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