1/* BEGIN_HEADER */ 2#include "mbedtls/hmac_drbg.h" 3#include "string.h" 4 5typedef struct 6{ 7 unsigned char *p; 8 size_t len; 9} entropy_ctx; 10 11static int mbedtls_test_entropy_func( void *data, unsigned char *buf, size_t len ) 12{ 13 entropy_ctx *ctx = (entropy_ctx *) data; 14 15 if( len > ctx->len ) 16 return( -1 ); 17 18 memcpy( buf, ctx->p, len ); 19 20 ctx->p += len; 21 ctx->len -= len; 22 23 return( 0 ); 24} 25/* END_HEADER */ 26 27/* BEGIN_DEPENDENCIES 28 * depends_on:MBEDTLS_HMAC_DRBG_C 29 * END_DEPENDENCIES 30 */ 31 32/* BEGIN_CASE */ 33void hmac_drbg_entropy_usage( int md_alg ) 34{ 35 unsigned char out[16]; 36 unsigned char buf[1024]; 37 const mbedtls_md_info_t *md_info; 38 mbedtls_hmac_drbg_context ctx; 39 entropy_ctx entropy; 40 size_t i, reps = 10; 41 size_t default_entropy_len; 42 size_t expected_consumed_entropy = 0; 43 44 mbedtls_hmac_drbg_init( &ctx ); 45 memset( buf, 0, sizeof( buf ) ); 46 memset( out, 0, sizeof( out ) ); 47 48 entropy.len = sizeof( buf ); 49 entropy.p = buf; 50 51 md_info = mbedtls_md_info_from_type( md_alg ); 52 TEST_ASSERT( md_info != NULL ); 53 if( mbedtls_md_get_size( md_info ) <= 20 ) 54 default_entropy_len = 16; 55 else if( mbedtls_md_get_size( md_info ) <= 28 ) 56 default_entropy_len = 24; 57 else 58 default_entropy_len = 32; 59 60 /* Set reseed interval before seed */ 61 mbedtls_hmac_drbg_set_reseed_interval( &ctx, 2 * reps ); 62 63 /* Init must use entropy */ 64 TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &entropy, 65 NULL, 0 ) == 0 ); 66 /* default_entropy_len of entropy, plus half as much for the nonce */ 67 expected_consumed_entropy += default_entropy_len * 3 / 2; 68 TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy ); 69 70 /* By default, PR is off, and reseed interval was set to 71 * 2 * reps so the next few calls should not use entropy */ 72 for( i = 0; i < reps; i++ ) 73 { 74 TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) - 4 ) == 0 ); 75 TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, out, sizeof( out ) - 4, 76 buf, 16 ) == 0 ); 77 } 78 TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy ); 79 80 /* While at it, make sure we didn't write past the requested length */ 81 TEST_ASSERT( out[sizeof( out ) - 4] == 0 ); 82 TEST_ASSERT( out[sizeof( out ) - 3] == 0 ); 83 TEST_ASSERT( out[sizeof( out ) - 2] == 0 ); 84 TEST_ASSERT( out[sizeof( out ) - 1] == 0 ); 85 86 /* There have been 2 * reps calls to random. The next call should reseed */ 87 TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 ); 88 expected_consumed_entropy += default_entropy_len; 89 TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy ); 90 91 /* Set reseed interval after seed */ 92 mbedtls_hmac_drbg_set_reseed_interval( &ctx, 4 * reps + 1); 93 94 /* The new few calls should not reseed */ 95 for( i = 0; i < (2 * reps); i++ ) 96 { 97 TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 ); 98 TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, out, sizeof( out ) , 99 buf, 16 ) == 0 ); 100 } 101 TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy ); 102 103 /* Now enable PR, so the next few calls should all reseed */ 104 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); 105 TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 ); 106 expected_consumed_entropy += default_entropy_len; 107 TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy ); 108 109 /* Finally, check setting entropy_len */ 110 mbedtls_hmac_drbg_set_entropy_len( &ctx, 42 ); 111 TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 ); 112 expected_consumed_entropy += 42; 113 TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy ); 114 115 mbedtls_hmac_drbg_set_entropy_len( &ctx, 13 ); 116 TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 ); 117 expected_consumed_entropy += 13; 118 TEST_EQUAL( sizeof( buf ) - entropy.len, expected_consumed_entropy ); 119 120exit: 121 mbedtls_hmac_drbg_free( &ctx ); 122} 123/* END_CASE */ 124 125/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */ 126void hmac_drbg_seed_file( int md_alg, char * path, int ret ) 127{ 128 const mbedtls_md_info_t *md_info; 129 mbedtls_hmac_drbg_context ctx; 130 131 mbedtls_hmac_drbg_init( &ctx ); 132 133 md_info = mbedtls_md_info_from_type( md_alg ); 134 TEST_ASSERT( md_info != NULL ); 135 136 TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, 137 mbedtls_test_rnd_std_rand, NULL, 138 NULL, 0 ) == 0 ); 139 140 TEST_ASSERT( mbedtls_hmac_drbg_write_seed_file( &ctx, path ) == ret ); 141 TEST_ASSERT( mbedtls_hmac_drbg_update_seed_file( &ctx, path ) == ret ); 142 143exit: 144 mbedtls_hmac_drbg_free( &ctx ); 145} 146/* END_CASE */ 147 148/* BEGIN_CASE */ 149void hmac_drbg_buf( int md_alg ) 150{ 151 unsigned char out[16]; 152 unsigned char buf[100]; 153 const mbedtls_md_info_t *md_info; 154 mbedtls_hmac_drbg_context ctx; 155 size_t i; 156 157 mbedtls_hmac_drbg_init( &ctx ); 158 memset( buf, 0, sizeof( buf ) ); 159 memset( out, 0, sizeof( out ) ); 160 161 md_info = mbedtls_md_info_from_type( md_alg ); 162 TEST_ASSERT( md_info != NULL ); 163 TEST_ASSERT( mbedtls_hmac_drbg_seed_buf( &ctx, md_info, buf, sizeof( buf ) ) == 0 ); 164 165 /* Make sure it never tries to reseed (would segfault otherwise) */ 166 mbedtls_hmac_drbg_set_reseed_interval( &ctx, 3 ); 167 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); 168 169 for( i = 0; i < 30; i++ ) 170 TEST_ASSERT( mbedtls_hmac_drbg_random( &ctx, out, sizeof( out ) ) == 0 ); 171 172exit: 173 mbedtls_hmac_drbg_free( &ctx ); 174} 175/* END_CASE */ 176 177/* BEGIN_CASE */ 178void hmac_drbg_no_reseed( int md_alg, data_t * entropy, 179 data_t * custom, data_t * add1, 180 data_t * add2, data_t * output ) 181{ 182 unsigned char data[1024]; 183 unsigned char my_output[512]; 184 entropy_ctx p_entropy; 185 const mbedtls_md_info_t *md_info; 186 mbedtls_hmac_drbg_context ctx; 187 188 mbedtls_hmac_drbg_init( &ctx ); 189 190 p_entropy.p = entropy->x; 191 p_entropy.len = entropy->len; 192 193 md_info = mbedtls_md_info_from_type( md_alg ); 194 TEST_ASSERT( md_info != NULL ); 195 196 /* Test the simplified buffer-based variant */ 197 memcpy( data, entropy->x, p_entropy.len ); 198 memcpy( data + p_entropy.len, custom->x, custom->len ); 199 TEST_ASSERT( mbedtls_hmac_drbg_seed_buf( &ctx, md_info, 200 data, p_entropy.len + custom->len ) == 0 ); 201 TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len, 202 add1->x, add1->len ) == 0 ); 203 TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len, 204 add2->x, add2->len ) == 0 ); 205 206 /* Reset context for second run */ 207 mbedtls_hmac_drbg_free( &ctx ); 208 209 TEST_ASSERT( memcmp( my_output, output->x, output->len ) == 0 ); 210 211 /* And now the normal entropy-based variant */ 212 TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &p_entropy, 213 custom->x, custom->len ) == 0 ); 214 TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len, 215 add1->x, add1->len ) == 0 ); 216 TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len, 217 add2->x, add2->len ) == 0 ); 218 TEST_ASSERT( memcmp( my_output, output->x, output->len ) == 0 ); 219 220exit: 221 mbedtls_hmac_drbg_free( &ctx ); 222} 223/* END_CASE */ 224 225/* BEGIN_CASE */ 226void hmac_drbg_nopr( int md_alg, data_t * entropy, data_t * custom, 227 data_t * add1, data_t * add2, data_t * add3, 228 data_t * output ) 229{ 230 unsigned char my_output[512]; 231 entropy_ctx p_entropy; 232 const mbedtls_md_info_t *md_info; 233 mbedtls_hmac_drbg_context ctx; 234 235 mbedtls_hmac_drbg_init( &ctx ); 236 237 p_entropy.p = entropy->x; 238 p_entropy.len = entropy->len; 239 240 md_info = mbedtls_md_info_from_type( md_alg ); 241 TEST_ASSERT( md_info != NULL ); 242 243 TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &p_entropy, 244 custom->x, custom->len ) == 0 ); 245 TEST_ASSERT( mbedtls_hmac_drbg_reseed( &ctx, add1->x, add1->len ) == 0 ); 246 TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len, 247 add2->x, add2->len ) == 0 ); 248 TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len, 249 add3->x, add3->len ) == 0 ); 250 251 TEST_ASSERT( memcmp( my_output, output->x, output->len ) == 0 ); 252 253exit: 254 mbedtls_hmac_drbg_free( &ctx ); 255} 256/* END_CASE */ 257 258/* BEGIN_CASE */ 259void hmac_drbg_pr( int md_alg, data_t * entropy, data_t * custom, 260 data_t * add1, data_t * add2, data_t * output ) 261{ 262 unsigned char my_output[512]; 263 entropy_ctx p_entropy; 264 const mbedtls_md_info_t *md_info; 265 mbedtls_hmac_drbg_context ctx; 266 267 mbedtls_hmac_drbg_init( &ctx ); 268 269 p_entropy.p = entropy->x; 270 p_entropy.len = entropy->len; 271 272 md_info = mbedtls_md_info_from_type( md_alg ); 273 TEST_ASSERT( md_info != NULL ); 274 275 TEST_ASSERT( mbedtls_hmac_drbg_seed( &ctx, md_info, mbedtls_test_entropy_func, &p_entropy, 276 custom->x, custom->len ) == 0 ); 277 mbedtls_hmac_drbg_set_prediction_resistance( &ctx, MBEDTLS_HMAC_DRBG_PR_ON ); 278 TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len, 279 add1->x, add1->len ) == 0 ); 280 TEST_ASSERT( mbedtls_hmac_drbg_random_with_add( &ctx, my_output, output->len, 281 add2->x, add2->len ) == 0 ); 282 283 TEST_ASSERT( memcmp( my_output, output->x, output->len ) == 0 ); 284 285exit: 286 mbedtls_hmac_drbg_free( &ctx ); 287} 288/* END_CASE */ 289 290/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ 291void hmac_drbg_selftest( ) 292{ 293 TEST_ASSERT( mbedtls_hmac_drbg_self_test( 1 ) == 0 ); 294} 295/* END_CASE */ 296