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