test_suite_ctr_drbg.function 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  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. {
  8. RESEED_NEVER, /* never reseed */
  9. RESEED_FIRST, /* instantiate, reseed, generate, generate */
  10. RESEED_SECOND, /* instantiate, generate, reseed, generate */
  11. RESEED_ALWAYS /* prediction resistance, no explicit reseed */
  12. };
  13. static size_t test_offset_idx = 0;
  14. static size_t test_max_idx = 0;
  15. static int mbedtls_test_entropy_func( void *data, unsigned char *buf, size_t len )
  16. {
  17. const unsigned char *p = (unsigned char *) data;
  18. if( test_offset_idx + len > test_max_idx )
  19. return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED );
  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. TEST_ASSERT( mbedtls_ctr_drbg_seed(
  41. &ctx,
  42. mbedtls_test_entropy_func, entropy->x,
  43. nonce->x, nonce->len ) == 0 );
  44. if( reseed_mode == RESEED_ALWAYS )
  45. mbedtls_ctr_drbg_set_prediction_resistance(
  46. &ctx,
  47. MBEDTLS_CTR_DRBG_PR_ON );
  48. if( reseed_mode == RESEED_FIRST )
  49. {
  50. /* CTR_DRBG_Reseed(entropy[idx:idx+entropy->len],
  51. * reseed[:reseed->len]) */
  52. TEST_ASSERT( mbedtls_ctr_drbg_reseed(
  53. &ctx,
  54. reseed->x, reseed->len ) == 0 );
  55. }
  56. /* CTR_DRBG_Generate(result->len * 8 bits, add1[:add1->len]) -> buf */
  57. /* Then reseed if prediction resistance is enabled. */
  58. TEST_ASSERT( mbedtls_ctr_drbg_random_with_add(
  59. &ctx,
  60. buf, result->len,
  61. add1->x, add1->len ) == 0 );
  62. if( reseed_mode == RESEED_SECOND )
  63. {
  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_usage( )
  165. {
  166. unsigned char out[16];
  167. unsigned char add[16];
  168. unsigned char entropy[1024];
  169. mbedtls_ctr_drbg_context ctx;
  170. size_t i, reps = 10;
  171. size_t last_idx;
  172. mbedtls_ctr_drbg_init( &ctx );
  173. test_offset_idx = 0;
  174. test_max_idx = sizeof( entropy );
  175. memset( entropy, 0, sizeof( entropy ) );
  176. memset( out, 0, sizeof( out ) );
  177. memset( add, 0, sizeof( add ) );
  178. /* Set reseed interval before seed */
  179. mbedtls_ctr_drbg_set_reseed_interval( &ctx, 2 * reps );
  180. /* Init must use entropy */
  181. last_idx = test_offset_idx;
  182. TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, mbedtls_test_entropy_func, entropy, NULL, 0 ) == 0 );
  183. TEST_ASSERT( last_idx < test_offset_idx );
  184. /* By default, PR is off, and reseed interval was set to
  185. * 2 * reps so the next few calls should not use entropy */
  186. last_idx = test_offset_idx;
  187. for( i = 0; i < reps; i++ )
  188. {
  189. TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 );
  190. TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, out, sizeof( out ) - 4,
  191. add, sizeof( add ) ) == 0 );
  192. }
  193. TEST_ASSERT( last_idx == test_offset_idx );
  194. /* While at it, make sure we didn't write past the requested length */
  195. TEST_ASSERT( out[sizeof( out ) - 4] == 0 );
  196. TEST_ASSERT( out[sizeof( out ) - 3] == 0 );
  197. TEST_ASSERT( out[sizeof( out ) - 2] == 0 );
  198. TEST_ASSERT( out[sizeof( out ) - 1] == 0 );
  199. /* There have been 2 * reps calls to random. The next call should reseed */
  200. TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
  201. TEST_ASSERT( last_idx < test_offset_idx );
  202. /* Set reseed interval after seed */
  203. mbedtls_ctr_drbg_set_reseed_interval( &ctx, 4 * reps + 1 );
  204. /* The next few calls should not reseed */
  205. last_idx = test_offset_idx;
  206. for( i = 0; i < (2 * reps); i++ )
  207. {
  208. TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
  209. TEST_ASSERT( mbedtls_ctr_drbg_random_with_add( &ctx, out, sizeof( out ) ,
  210. add, sizeof( add ) ) == 0 );
  211. }
  212. TEST_ASSERT( last_idx == test_offset_idx );
  213. /* Call update with too much data (sizeof entropy > MAX(_SEED)_INPUT).
  214. * Make sure it's detected as an error and doesn't cause memory
  215. * corruption. */
  216. TEST_ASSERT( mbedtls_ctr_drbg_update_ret(
  217. &ctx, entropy, sizeof( entropy ) ) != 0 );
  218. /* Now enable PR, so the next few calls should all reseed */
  219. mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON );
  220. TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
  221. TEST_ASSERT( last_idx < test_offset_idx );
  222. /* Finally, check setting entropy_len */
  223. mbedtls_ctr_drbg_set_entropy_len( &ctx, 42 );
  224. last_idx = test_offset_idx;
  225. TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
  226. TEST_ASSERT( test_offset_idx - last_idx == 42 );
  227. mbedtls_ctr_drbg_set_entropy_len( &ctx, 13 );
  228. last_idx = test_offset_idx;
  229. TEST_ASSERT( mbedtls_ctr_drbg_random( &ctx, out, sizeof( out ) ) == 0 );
  230. TEST_ASSERT( test_offset_idx - last_idx == 13 );
  231. exit:
  232. mbedtls_ctr_drbg_free( &ctx );
  233. }
  234. /* END_CASE */
  235. /* BEGIN_CASE depends_on:MBEDTLS_FS_IO */
  236. void ctr_drbg_seed_file( char * path, int ret )
  237. {
  238. mbedtls_ctr_drbg_context ctx;
  239. mbedtls_ctr_drbg_init( &ctx );
  240. TEST_ASSERT( mbedtls_ctr_drbg_seed( &ctx, rnd_std_rand, NULL, NULL, 0 ) == 0 );
  241. TEST_ASSERT( mbedtls_ctr_drbg_write_seed_file( &ctx, path ) == ret );
  242. TEST_ASSERT( mbedtls_ctr_drbg_update_seed_file( &ctx, path ) == ret );
  243. exit:
  244. mbedtls_ctr_drbg_free( &ctx );
  245. }
  246. /* END_CASE */
  247. /* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */
  248. void ctr_drbg_selftest( )
  249. {
  250. TEST_ASSERT( mbedtls_ctr_drbg_self_test( 1 ) == 0 );
  251. }
  252. /* END_CASE */