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