test_suite_ctr_drbg.function 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /* BEGIN_HEADER */
  2. #include "mbedtls/entropy.h"
  3. #include "mbedtls/ctr_drbg.h"
  4. #include "string.h"
  5. /* Modes for ctr_drbg_validate */
  6. enum reseed_mode {
  7. RESEED_NEVER, /* never reseed */
  8. RESEED_FIRST, /* instantiate, reseed, generate, generate */
  9. RESEED_SECOND, /* instantiate, generate, reseed, generate */
  10. RESEED_ALWAYS /* prediction resistance, no explicit reseed */
  11. };
  12. static size_t test_offset_idx = 0;
  13. static size_t test_max_idx = 0;
  14. static int mbedtls_test_entropy_func(void *data, unsigned char *buf, size_t len)
  15. {
  16. const unsigned char *p = (unsigned char *) data;
  17. if (test_offset_idx + len > test_max_idx) {
  18. return MBEDTLS_ERR_ENTROPY_SOURCE_FAILED;
  19. }
  20. memcpy(buf, p + test_offset_idx, len);
  21. test_offset_idx += len;
  22. return 0;
  23. }
  24. static void ctr_drbg_validate_internal(int reseed_mode, data_t *nonce,
  25. int entropy_len_arg, data_t *entropy,
  26. data_t *reseed,
  27. data_t *add1, data_t *add2,
  28. data_t *result)
  29. {
  30. mbedtls_ctr_drbg_context ctx;
  31. unsigned char buf[64];
  32. size_t entropy_chunk_len = (size_t) entropy_len_arg;
  33. TEST_ASSERT(entropy_chunk_len <= sizeof(buf));
  34. test_offset_idx = 0;
  35. mbedtls_ctr_drbg_init(&ctx);
  36. test_max_idx = entropy->len;
  37. /* CTR_DRBG_Instantiate(entropy[:entropy->len], nonce, perso, <ignored>)
  38. * where nonce||perso = nonce[nonce->len] */
  39. mbedtls_ctr_drbg_set_entropy_len(&ctx, entropy_chunk_len);
  40. mbedtls_ctr_drbg_set_nonce_len(&ctx, 0);
  41. TEST_ASSERT(mbedtls_ctr_drbg_seed(
  42. &ctx,
  43. mbedtls_test_entropy_func, entropy->x,
  44. nonce->x, nonce->len) == 0);
  45. if (reseed_mode == RESEED_ALWAYS) {
  46. mbedtls_ctr_drbg_set_prediction_resistance(
  47. &ctx,
  48. MBEDTLS_CTR_DRBG_PR_ON);
  49. }
  50. if (reseed_mode == RESEED_FIRST) {
  51. /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
  52. * reseed[:reseed->len]) */
  53. TEST_ASSERT(mbedtls_ctr_drbg_reseed(
  54. &ctx,
  55. reseed->x, reseed->len) == 0);
  56. }
  57. /* CTR_DRBG_Generate(result->len * 8 bits, add1[:add1->len]) -> buf */
  58. /* Then reseed if prediction resistance is enabled. */
  59. TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(
  60. &ctx,
  61. buf, result->len,
  62. add1->x, add1->len) == 0);
  63. if (reseed_mode == RESEED_SECOND) {
  64. /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
  65. * reseed[:reseed->len]) */
  66. TEST_ASSERT(mbedtls_ctr_drbg_reseed(
  67. &ctx,
  68. reseed->x, reseed->len) == 0);
  69. }
  70. /* CTR_DRBG_Generate(result->len * 8 bits, add2->x[:add2->len]) -> buf */
  71. /* Then reseed if prediction resistance is enabled. */
  72. TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(
  73. &ctx,
  74. buf, result->len,
  75. add2->x, add2->len) == 0);
  76. TEST_ASSERT(memcmp(buf, result->x, result->len) == 0);
  77. exit:
  78. mbedtls_ctr_drbg_free(&ctx);
  79. }
  80. /* END_HEADER */
  81. /* BEGIN_DEPENDENCIES
  82. * depends_on:MBEDTLS_CTR_DRBG_C
  83. * END_DEPENDENCIES
  84. */
  85. /* BEGIN_CASE */
  86. void ctr_drbg_special_behaviours()
  87. {
  88. mbedtls_ctr_drbg_context ctx;
  89. unsigned char output[512];
  90. unsigned char additional[512];
  91. mbedtls_ctr_drbg_init(&ctx);
  92. memset(output, 0, sizeof(output));
  93. memset(additional, 0, sizeof(additional));
  94. TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx,
  95. output, MBEDTLS_CTR_DRBG_MAX_REQUEST + 1,
  96. additional, 16) ==
  97. MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG);
  98. TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx,
  99. output, 16,
  100. additional, MBEDTLS_CTR_DRBG_MAX_INPUT + 1) ==
  101. MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
  102. TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional,
  103. MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + 1) ==
  104. MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
  105. mbedtls_ctr_drbg_set_entropy_len(&ctx, ~0);
  106. TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, additional,
  107. MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) ==
  108. MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG);
  109. exit:
  110. mbedtls_ctr_drbg_free(&ctx);
  111. }
  112. /* END_CASE */
  113. /* BEGIN_CASE */
  114. void ctr_drbg_validate_no_reseed(data_t *add_init, data_t *entropy,
  115. data_t *add1, data_t *add2,
  116. data_t *result_string)
  117. {
  118. data_t empty = { 0, 0 };
  119. ctr_drbg_validate_internal(RESEED_NEVER, add_init,
  120. entropy->len, entropy,
  121. &empty, add1, add2,
  122. result_string);
  123. goto exit; // goto is needed to avoid warning ( no test assertions in func)
  124. }
  125. /* END_CASE */
  126. /* BEGIN_CASE */
  127. void ctr_drbg_validate_pr(data_t *add_init, data_t *entropy,
  128. data_t *add1, data_t *add2,
  129. data_t *result_string)
  130. {
  131. data_t empty = { 0, 0 };
  132. ctr_drbg_validate_internal(RESEED_ALWAYS, add_init,
  133. entropy->len / 3, entropy,
  134. &empty, add1, add2,
  135. result_string);
  136. goto exit; // goto is needed to avoid warning ( no test assertions in func)
  137. }
  138. /* END_CASE */
  139. /* BEGIN_CASE */
  140. void ctr_drbg_validate_reseed_between(data_t *add_init, data_t *entropy,
  141. data_t *add1, data_t *add_reseed,
  142. data_t *add2, data_t *result_string)
  143. {
  144. ctr_drbg_validate_internal(RESEED_SECOND, add_init,
  145. entropy->len / 2, entropy,
  146. add_reseed, add1, add2,
  147. result_string);
  148. goto exit; // goto is needed to avoid warning ( no test assertions in func)
  149. }
  150. /* END_CASE */
  151. /* BEGIN_CASE */
  152. void ctr_drbg_validate_reseed_first(data_t *add_init, data_t *entropy,
  153. data_t *add1, data_t *add_reseed,
  154. data_t *add2, data_t *result_string)
  155. {
  156. ctr_drbg_validate_internal(RESEED_FIRST, add_init,
  157. entropy->len / 2, entropy,
  158. add_reseed, add1, add2,
  159. result_string);
  160. goto exit; // goto is needed to avoid warning ( no test assertions in func)
  161. }
  162. /* END_CASE */
  163. /* BEGIN_CASE */
  164. void ctr_drbg_entropy_strength(int expected_bit_strength)
  165. {
  166. unsigned char entropy[/*initial entropy*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN +
  167. /*nonce*/ MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN +
  168. /*reseed*/ MBEDTLS_CTR_DRBG_ENTROPY_LEN];
  169. mbedtls_ctr_drbg_context ctx;
  170. size_t last_idx;
  171. size_t byte_strength = expected_bit_strength / 8;
  172. mbedtls_ctr_drbg_init(&ctx);
  173. test_offset_idx = 0;
  174. test_max_idx = sizeof(entropy);
  175. memset(entropy, 0, sizeof(entropy));
  176. /* The initial seeding must grab at least byte_strength bytes of entropy
  177. * for the entropy input and byte_strength/2 bytes for a nonce. */
  178. TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx,
  179. mbedtls_test_entropy_func, entropy,
  180. NULL, 0) == 0);
  181. TEST_ASSERT(test_offset_idx >= (byte_strength * 3 + 1) / 2);
  182. last_idx = test_offset_idx;
  183. /* A reseed must grab at least byte_strength bytes of entropy. */
  184. TEST_ASSERT(mbedtls_ctr_drbg_reseed(&ctx, NULL, 0) == 0);
  185. TEST_ASSERT(test_offset_idx - last_idx >= byte_strength);
  186. exit:
  187. mbedtls_ctr_drbg_free(&ctx);
  188. }
  189. /* END_CASE */
  190. /* BEGIN_CASE */
  191. void ctr_drbg_entropy_usage(int entropy_nonce_len)
  192. {
  193. unsigned char out[16];
  194. unsigned char add[16];
  195. unsigned char entropy[1024];
  196. mbedtls_ctr_drbg_context ctx;
  197. size_t i, reps = 10;
  198. size_t expected_idx = 0;
  199. mbedtls_ctr_drbg_init(&ctx);
  200. test_offset_idx = 0;
  201. test_max_idx = sizeof(entropy);
  202. memset(entropy, 0, sizeof(entropy));
  203. memset(out, 0, sizeof(out));
  204. memset(add, 0, sizeof(add));
  205. if (entropy_nonce_len >= 0) {
  206. TEST_ASSERT(mbedtls_ctr_drbg_set_nonce_len(&ctx, entropy_nonce_len) == 0);
  207. }
  208. /* Set reseed interval before seed */
  209. mbedtls_ctr_drbg_set_reseed_interval(&ctx, 2 * reps);
  210. /* Init must use entropy */
  211. TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_entropy_func, entropy, NULL, 0) == 0);
  212. expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
  213. if (entropy_nonce_len >= 0) {
  214. expected_idx += entropy_nonce_len;
  215. } else {
  216. expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_NONCE_LEN;
  217. }
  218. TEST_EQUAL(test_offset_idx, expected_idx);
  219. /* By default, PR is off, and reseed interval was set to
  220. * 2 * reps so the next few calls should not use entropy */
  221. for (i = 0; i < reps; i++) {
  222. TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out) - 4) == 0);
  223. TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx, out, sizeof(out) - 4,
  224. add, sizeof(add)) == 0);
  225. }
  226. TEST_EQUAL(test_offset_idx, expected_idx);
  227. /* While at it, make sure we didn't write past the requested length */
  228. TEST_ASSERT(out[sizeof(out) - 4] == 0);
  229. TEST_ASSERT(out[sizeof(out) - 3] == 0);
  230. TEST_ASSERT(out[sizeof(out) - 2] == 0);
  231. TEST_ASSERT(out[sizeof(out) - 1] == 0);
  232. /* There have been 2 * reps calls to random. The next call should reseed */
  233. TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
  234. expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
  235. TEST_EQUAL(test_offset_idx, expected_idx);
  236. /* Set reseed interval after seed */
  237. mbedtls_ctr_drbg_set_reseed_interval(&ctx, 4 * reps + 1);
  238. /* The next few calls should not reseed */
  239. for (i = 0; i < (2 * reps); i++) {
  240. TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
  241. TEST_ASSERT(mbedtls_ctr_drbg_random_with_add(&ctx, out, sizeof(out),
  242. add, sizeof(add)) == 0);
  243. }
  244. TEST_EQUAL(test_offset_idx, expected_idx);
  245. /* Call update with too much data (sizeof(entropy) > MAX(_SEED)_INPUT).
  246. * Make sure it's detected as an error and doesn't cause memory
  247. * corruption. */
  248. TEST_ASSERT(mbedtls_ctr_drbg_update(
  249. &ctx, entropy, sizeof(entropy)) != 0);
  250. /* Now enable PR, so the next few calls should all reseed */
  251. mbedtls_ctr_drbg_set_prediction_resistance(&ctx, MBEDTLS_CTR_DRBG_PR_ON);
  252. TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
  253. expected_idx += MBEDTLS_CTR_DRBG_ENTROPY_LEN;
  254. TEST_EQUAL(test_offset_idx, expected_idx);
  255. /* Finally, check setting entropy_len */
  256. mbedtls_ctr_drbg_set_entropy_len(&ctx, 42);
  257. TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
  258. expected_idx += 42;
  259. TEST_EQUAL(test_offset_idx, expected_idx);
  260. mbedtls_ctr_drbg_set_entropy_len(&ctx, 13);
  261. TEST_ASSERT(mbedtls_ctr_drbg_random(&ctx, out, sizeof(out)) == 0);
  262. expected_idx += 13;
  263. TEST_EQUAL(test_offset_idx, expected_idx);
  264. exit:
  265. mbedtls_ctr_drbg_free(&ctx);
  266. }
  267. /* END_CASE */
  268. /* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
  269. void ctr_drbg_seed_file(char *path, int ret)
  270. {
  271. mbedtls_ctr_drbg_context ctx;
  272. mbedtls_ctr_drbg_init(&ctx);
  273. TEST_ASSERT(mbedtls_ctr_drbg_seed(&ctx, mbedtls_test_rnd_std_rand,
  274. NULL, NULL, 0) == 0);
  275. TEST_ASSERT(mbedtls_ctr_drbg_write_seed_file(&ctx, path) == ret);
  276. TEST_ASSERT(mbedtls_ctr_drbg_update_seed_file(&ctx, path) == ret);
  277. exit:
  278. mbedtls_ctr_drbg_free(&ctx);
  279. }
  280. /* END_CASE */
  281. /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
  282. void ctr_drbg_selftest()
  283. {
  284. TEST_ASSERT(mbedtls_ctr_drbg_self_test(1) == 0);
  285. }
  286. /* END_CASE */