1/* BEGIN_HEADER */ 2#include "mbedtls/hmac_drbg.h" 3#include "string.h" 4 5typedef struct { 6 unsigned char *p; 7 size_t len; 8} entropy_ctx; 9 10static int mbedtls_test_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 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 61 /* Set reseed interval before seed */ 62 mbedtls_hmac_drbg_set_reseed_interval(&ctx, 2 * reps); 63 64 /* Init must use entropy */ 65 TEST_ASSERT(mbedtls_hmac_drbg_seed(&ctx, md_info, mbedtls_test_entropy_func, &entropy, 66 NULL, 0) == 0); 67 /* default_entropy_len of entropy, plus half as much for the nonce */ 68 expected_consumed_entropy += default_entropy_len * 3 / 2; 69 TEST_EQUAL(sizeof(buf) - entropy.len, expected_consumed_entropy); 70 71 /* By default, PR is off, and reseed interval was set to 72 * 2 * reps so the next few calls should not use entropy */ 73 for (i = 0; i < reps; i++) { 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 TEST_ASSERT(mbedtls_hmac_drbg_random(&ctx, out, sizeof(out)) == 0); 97 TEST_ASSERT(mbedtls_hmac_drbg_random_with_add(&ctx, out, sizeof(out), 98 buf, 16) == 0); 99 } 100 TEST_EQUAL(sizeof(buf) - entropy.len, expected_consumed_entropy); 101 102 /* Now enable PR, so the next few calls should all reseed */ 103 mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON); 104 TEST_ASSERT(mbedtls_hmac_drbg_random(&ctx, out, sizeof(out)) == 0); 105 expected_consumed_entropy += default_entropy_len; 106 TEST_EQUAL(sizeof(buf) - entropy.len, expected_consumed_entropy); 107 108 /* Finally, check setting entropy_len */ 109 mbedtls_hmac_drbg_set_entropy_len(&ctx, 42); 110 TEST_ASSERT(mbedtls_hmac_drbg_random(&ctx, out, sizeof(out)) == 0); 111 expected_consumed_entropy += 42; 112 TEST_EQUAL(sizeof(buf) - entropy.len, expected_consumed_entropy); 113 114 mbedtls_hmac_drbg_set_entropy_len(&ctx, 13); 115 TEST_ASSERT(mbedtls_hmac_drbg_random(&ctx, out, sizeof(out)) == 0); 116 expected_consumed_entropy += 13; 117 TEST_EQUAL(sizeof(buf) - entropy.len, expected_consumed_entropy); 118 119exit: 120 mbedtls_hmac_drbg_free(&ctx); 121} 122/* END_CASE */ 123 124/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */ 125void hmac_drbg_seed_file(int md_alg, char *path, int ret) 126{ 127 const mbedtls_md_info_t *md_info; 128 mbedtls_hmac_drbg_context ctx; 129 130 mbedtls_hmac_drbg_init(&ctx); 131 132 md_info = mbedtls_md_info_from_type(md_alg); 133 TEST_ASSERT(md_info != NULL); 134 135 TEST_ASSERT(mbedtls_hmac_drbg_seed(&ctx, md_info, 136 mbedtls_test_rnd_std_rand, NULL, 137 NULL, 0) == 0); 138 139 TEST_ASSERT(mbedtls_hmac_drbg_write_seed_file(&ctx, path) == ret); 140 TEST_ASSERT(mbedtls_hmac_drbg_update_seed_file(&ctx, path) == ret); 141 142exit: 143 mbedtls_hmac_drbg_free(&ctx); 144} 145/* END_CASE */ 146 147/* BEGIN_CASE */ 148void hmac_drbg_buf(int md_alg) 149{ 150 unsigned char out[16]; 151 unsigned char buf[100]; 152 const mbedtls_md_info_t *md_info; 153 mbedtls_hmac_drbg_context ctx; 154 size_t i; 155 156 mbedtls_hmac_drbg_init(&ctx); 157 memset(buf, 0, sizeof(buf)); 158 memset(out, 0, sizeof(out)); 159 160 md_info = mbedtls_md_info_from_type(md_alg); 161 TEST_ASSERT(md_info != NULL); 162 TEST_ASSERT(mbedtls_hmac_drbg_seed_buf(&ctx, md_info, buf, sizeof(buf)) == 0); 163 164 /* Make sure it never tries to reseed (would segfault otherwise) */ 165 mbedtls_hmac_drbg_set_reseed_interval(&ctx, 3); 166 mbedtls_hmac_drbg_set_prediction_resistance(&ctx, MBEDTLS_HMAC_DRBG_PR_ON); 167 168 for (i = 0; i < 30; i++) { 169 TEST_ASSERT(mbedtls_hmac_drbg_random(&ctx, out, sizeof(out)) == 0); 170 } 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