1/* BEGIN_HEADER */ 2#include "mbedtls/ecdh.h" 3 4static int load_public_key(int grp_id, data_t *point, 5 mbedtls_ecp_keypair *ecp) 6{ 7 int ok = 0; 8 TEST_ASSERT(mbedtls_ecp_group_load(&ecp->grp, grp_id) == 0); 9 TEST_ASSERT(mbedtls_ecp_point_read_binary(&ecp->grp, 10 &ecp->Q, 11 point->x, 12 point->len) == 0); 13 TEST_ASSERT(mbedtls_ecp_check_pubkey(&ecp->grp, 14 &ecp->Q) == 0); 15 ok = 1; 16exit: 17 return ok; 18} 19 20static int load_private_key(int grp_id, data_t *private_key, 21 mbedtls_ecp_keypair *ecp, 22 mbedtls_test_rnd_pseudo_info *rnd_info) 23{ 24 int ok = 0; 25 TEST_ASSERT(mbedtls_ecp_read_key(grp_id, ecp, 26 private_key->x, 27 private_key->len) == 0); 28 TEST_ASSERT(mbedtls_ecp_check_privkey(&ecp->grp, &ecp->d) == 0); 29 /* Calculate the public key from the private key. */ 30 TEST_ASSERT(mbedtls_ecp_mul(&ecp->grp, &ecp->Q, &ecp->d, 31 &ecp->grp.G, 32 &mbedtls_test_rnd_pseudo_rand, 33 rnd_info) == 0); 34 ok = 1; 35exit: 36 return ok; 37} 38 39/* END_HEADER */ 40 41/* BEGIN_DEPENDENCIES 42 * depends_on:MBEDTLS_ECDH_C 43 * END_DEPENDENCIES 44 */ 45 46/* BEGIN_CASE */ 47void ecdh_invalid_param() 48{ 49 mbedtls_ecdh_context ctx; 50 mbedtls_ecp_keypair kp; 51 int invalid_side = 42; 52 53 mbedtls_ecdh_init(&ctx); 54 mbedtls_ecp_keypair_init(&kp); 55 56 TEST_EQUAL(MBEDTLS_ERR_ECP_BAD_INPUT_DATA, 57 mbedtls_ecdh_get_params(&ctx, &kp, 58 invalid_side)); 59 60exit: 61 return; 62} 63/* END_CASE */ 64 65/* BEGIN_CASE */ 66void ecdh_primitive_random(int id) 67{ 68 mbedtls_ecp_group grp; 69 mbedtls_ecp_point qA, qB; 70 mbedtls_mpi dA, dB, zA, zB; 71 mbedtls_test_rnd_pseudo_info rnd_info; 72 73 mbedtls_ecp_group_init(&grp); 74 mbedtls_ecp_point_init(&qA); mbedtls_ecp_point_init(&qB); 75 mbedtls_mpi_init(&dA); mbedtls_mpi_init(&dB); 76 mbedtls_mpi_init(&zA); mbedtls_mpi_init(&zB); 77 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info)); 78 79 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0); 80 81 TEST_ASSERT(mbedtls_ecdh_gen_public(&grp, &dA, &qA, 82 &mbedtls_test_rnd_pseudo_rand, 83 &rnd_info) == 0); 84 TEST_ASSERT(mbedtls_ecdh_gen_public(&grp, &dB, &qB, 85 &mbedtls_test_rnd_pseudo_rand, 86 &rnd_info) == 0); 87 TEST_ASSERT(mbedtls_ecdh_compute_shared(&grp, &zA, &qB, &dA, 88 &mbedtls_test_rnd_pseudo_rand, 89 &rnd_info) == 0); 90 TEST_ASSERT(mbedtls_ecdh_compute_shared(&grp, &zB, &qA, &dB, 91 &mbedtls_test_rnd_pseudo_rand, 92 &rnd_info) == 0); 93 94 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&zA, &zB) == 0); 95 96exit: 97 mbedtls_ecp_group_free(&grp); 98 mbedtls_ecp_point_free(&qA); mbedtls_ecp_point_free(&qB); 99 mbedtls_mpi_free(&dA); mbedtls_mpi_free(&dB); 100 mbedtls_mpi_free(&zA); mbedtls_mpi_free(&zB); 101} 102/* END_CASE */ 103 104/* BEGIN_CASE */ 105void ecdh_primitive_testvec(int id, data_t *rnd_buf_A, char *xA_str, 106 char *yA_str, data_t *rnd_buf_B, 107 char *xB_str, char *yB_str, char *z_str) 108{ 109 mbedtls_ecp_group grp; 110 mbedtls_ecp_point qA, qB; 111 mbedtls_mpi dA, dB, zA, zB, check; 112 mbedtls_test_rnd_buf_info rnd_info_A, rnd_info_B; 113 mbedtls_test_rnd_pseudo_info rnd_info; 114 115 mbedtls_ecp_group_init(&grp); 116 mbedtls_ecp_point_init(&qA); mbedtls_ecp_point_init(&qB); 117 mbedtls_mpi_init(&dA); mbedtls_mpi_init(&dB); 118 mbedtls_mpi_init(&zA); mbedtls_mpi_init(&zB); mbedtls_mpi_init(&check); 119 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info)); 120 121 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0); 122 123 rnd_info_A.buf = rnd_buf_A->x; 124 rnd_info_A.length = rnd_buf_A->len; 125 rnd_info_A.fallback_f_rng = mbedtls_test_rnd_std_rand; 126 rnd_info_A.fallback_p_rng = NULL; 127 128 /* Fix rnd_buf_A->x by shifting it left if necessary */ 129 if (grp.nbits % 8 != 0) { 130 unsigned char shift = 8 - (grp.nbits % 8); 131 size_t i; 132 133 for (i = 0; i < rnd_info_A.length - 1; i++) { 134 rnd_buf_A->x[i] = rnd_buf_A->x[i] << shift 135 | rnd_buf_A->x[i+1] >> (8 - shift); 136 } 137 138 rnd_buf_A->x[rnd_info_A.length-1] <<= shift; 139 } 140 141 rnd_info_B.buf = rnd_buf_B->x; 142 rnd_info_B.length = rnd_buf_B->len; 143 rnd_info_B.fallback_f_rng = mbedtls_test_rnd_std_rand; 144 rnd_info_B.fallback_p_rng = NULL; 145 146 /* Fix rnd_buf_B->x by shifting it left if necessary */ 147 if (grp.nbits % 8 != 0) { 148 unsigned char shift = 8 - (grp.nbits % 8); 149 size_t i; 150 151 for (i = 0; i < rnd_info_B.length - 1; i++) { 152 rnd_buf_B->x[i] = rnd_buf_B->x[i] << shift 153 | rnd_buf_B->x[i+1] >> (8 - shift); 154 } 155 156 rnd_buf_B->x[rnd_info_B.length-1] <<= shift; 157 } 158 159 TEST_ASSERT(mbedtls_ecdh_gen_public(&grp, &dA, &qA, 160 mbedtls_test_rnd_buffer_rand, 161 &rnd_info_A) == 0); 162 TEST_ASSERT(!mbedtls_ecp_is_zero(&qA)); 163 TEST_ASSERT(mbedtls_test_read_mpi(&check, xA_str) == 0); 164 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&qA.X, &check) == 0); 165 TEST_ASSERT(mbedtls_test_read_mpi(&check, yA_str) == 0); 166 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&qA.Y, &check) == 0); 167 168 TEST_ASSERT(mbedtls_ecdh_gen_public(&grp, &dB, &qB, 169 mbedtls_test_rnd_buffer_rand, 170 &rnd_info_B) == 0); 171 TEST_ASSERT(!mbedtls_ecp_is_zero(&qB)); 172 TEST_ASSERT(mbedtls_test_read_mpi(&check, xB_str) == 0); 173 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&qB.X, &check) == 0); 174 TEST_ASSERT(mbedtls_test_read_mpi(&check, yB_str) == 0); 175 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&qB.Y, &check) == 0); 176 177 TEST_ASSERT(mbedtls_test_read_mpi(&check, z_str) == 0); 178 TEST_ASSERT(mbedtls_ecdh_compute_shared(&grp, &zA, &qB, &dA, 179 &mbedtls_test_rnd_pseudo_rand, 180 &rnd_info) == 0); 181 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&zA, &check) == 0); 182 TEST_ASSERT(mbedtls_ecdh_compute_shared(&grp, &zB, &qA, &dB, 183 &mbedtls_test_rnd_pseudo_rand, 184 &rnd_info) == 0); 185 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&zB, &check) == 0); 186 187exit: 188 mbedtls_ecp_group_free(&grp); 189 mbedtls_ecp_point_free(&qA); mbedtls_ecp_point_free(&qB); 190 mbedtls_mpi_free(&dA); mbedtls_mpi_free(&dB); 191 mbedtls_mpi_free(&zA); mbedtls_mpi_free(&zB); mbedtls_mpi_free(&check); 192} 193/* END_CASE */ 194 195/* BEGIN_CASE */ 196void ecdh_exchange(int id) 197{ 198 mbedtls_ecdh_context srv, cli; 199 unsigned char buf[1000]; 200 const unsigned char *vbuf; 201 size_t len; 202 mbedtls_test_rnd_pseudo_info rnd_info; 203 unsigned char res_buf[1000]; 204 size_t res_len; 205 206 mbedtls_ecdh_init(&srv); 207 mbedtls_ecdh_init(&cli); 208 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info)); 209 210 TEST_ASSERT(mbedtls_ecdh_setup(&srv, id) == 0); 211 212 memset(buf, 0x00, sizeof(buf)); vbuf = buf; 213 TEST_ASSERT(mbedtls_ecdh_make_params(&srv, &len, buf, 1000, 214 &mbedtls_test_rnd_pseudo_rand, 215 &rnd_info) == 0); 216 TEST_ASSERT(mbedtls_ecdh_read_params(&cli, &vbuf, buf + len) == 0); 217 218 memset(buf, 0x00, sizeof(buf)); 219 TEST_ASSERT(mbedtls_ecdh_make_public(&cli, &len, buf, 1000, 220 &mbedtls_test_rnd_pseudo_rand, 221 &rnd_info) == 0); 222 TEST_ASSERT(mbedtls_ecdh_read_public(&srv, buf, len) == 0); 223 224 TEST_ASSERT(mbedtls_ecdh_calc_secret(&srv, &len, buf, 1000, 225 &mbedtls_test_rnd_pseudo_rand, 226 &rnd_info) == 0); 227 TEST_ASSERT(mbedtls_ecdh_calc_secret(&cli, &res_len, res_buf, 1000, 228 &mbedtls_test_rnd_pseudo_rand, 229 &rnd_info) == 0); 230 TEST_ASSERT(len == res_len); 231 TEST_ASSERT(memcmp(buf, res_buf, len) == 0); 232 233exit: 234 mbedtls_ecdh_free(&srv); 235 mbedtls_ecdh_free(&cli); 236} 237/* END_CASE */ 238 239/* BEGIN_CASE depends_on:MBEDTLS_ECP_RESTARTABLE */ 240void ecdh_restart(int id, data_t *dA, data_t *dB, data_t *z, 241 int enable, int max_ops, int min_restart, int max_restart) 242{ 243 int ret; 244 mbedtls_ecdh_context srv, cli; 245 unsigned char buf[1000]; 246 const unsigned char *vbuf; 247 size_t len; 248 mbedtls_test_rnd_buf_info rnd_info_A, rnd_info_B; 249 mbedtls_test_rnd_pseudo_info rnd_info; 250 int cnt_restart; 251 mbedtls_ecp_group grp; 252 253 mbedtls_ecp_group_init(&grp); 254 mbedtls_ecdh_init(&srv); 255 mbedtls_ecdh_init(&cli); 256 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info)); 257 258 rnd_info_A.fallback_f_rng = mbedtls_test_rnd_std_rand; 259 rnd_info_A.fallback_p_rng = NULL; 260 rnd_info_A.buf = dA->x; 261 rnd_info_A.length = dA->len; 262 263 rnd_info_B.fallback_f_rng = mbedtls_test_rnd_std_rand; 264 rnd_info_B.fallback_p_rng = NULL; 265 rnd_info_B.buf = dB->x; 266 rnd_info_B.length = dB->len; 267 268 /* The ECDH context is not guaranteed to have an mbedtls_ecp_group structure 269 * in every configuration, therefore we load it separately. */ 270 TEST_ASSERT(mbedtls_ecp_group_load(&grp, id) == 0); 271 272 /* Otherwise we would have to fix the random buffer, 273 * as in ecdh_primitive_testvec. */ 274 TEST_ASSERT(grp.nbits % 8 == 0); 275 276 TEST_ASSERT(mbedtls_ecdh_setup(&srv, id) == 0); 277 278 /* set up restart parameters */ 279 mbedtls_ecp_set_max_ops(max_ops); 280 281 if (enable) { 282 mbedtls_ecdh_enable_restart(&srv); 283 mbedtls_ecdh_enable_restart(&cli); 284 } 285 286 /* server writes its parameters */ 287 memset(buf, 0x00, sizeof(buf)); 288 len = 0; 289 290 cnt_restart = 0; 291 do { 292 ret = mbedtls_ecdh_make_params(&srv, &len, buf, sizeof(buf), 293 mbedtls_test_rnd_buffer_rand, 294 &rnd_info_A); 295 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart); 296 297 TEST_ASSERT(ret == 0); 298 TEST_ASSERT(cnt_restart >= min_restart); 299 TEST_ASSERT(cnt_restart <= max_restart); 300 301 /* client read server params */ 302 vbuf = buf; 303 TEST_ASSERT(mbedtls_ecdh_read_params(&cli, &vbuf, buf + len) == 0); 304 305 /* client writes its key share */ 306 memset(buf, 0x00, sizeof(buf)); 307 len = 0; 308 309 cnt_restart = 0; 310 do { 311 ret = mbedtls_ecdh_make_public(&cli, &len, buf, sizeof(buf), 312 mbedtls_test_rnd_buffer_rand, 313 &rnd_info_B); 314 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart); 315 316 TEST_ASSERT(ret == 0); 317 TEST_ASSERT(cnt_restart >= min_restart); 318 TEST_ASSERT(cnt_restart <= max_restart); 319 320 /* server reads client key share */ 321 TEST_ASSERT(mbedtls_ecdh_read_public(&srv, buf, len) == 0); 322 323 /* server computes shared secret */ 324 memset(buf, 0, sizeof(buf)); 325 len = 0; 326 327 cnt_restart = 0; 328 do { 329 ret = mbedtls_ecdh_calc_secret(&srv, &len, buf, sizeof(buf), 330 &mbedtls_test_rnd_pseudo_rand, 331 &rnd_info); 332 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart); 333 334 TEST_ASSERT(ret == 0); 335 TEST_ASSERT(cnt_restart >= min_restart); 336 TEST_ASSERT(cnt_restart <= max_restart); 337 338 TEST_ASSERT(len == z->len); 339 TEST_ASSERT(memcmp(buf, z->x, len) == 0); 340 341 /* client computes shared secret */ 342 memset(buf, 0, sizeof(buf)); 343 len = 0; 344 345 cnt_restart = 0; 346 do { 347 ret = mbedtls_ecdh_calc_secret(&cli, &len, buf, sizeof(buf), 348 &mbedtls_test_rnd_pseudo_rand, 349 &rnd_info); 350 } while (ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart); 351 352 TEST_ASSERT(ret == 0); 353 TEST_ASSERT(cnt_restart >= min_restart); 354 TEST_ASSERT(cnt_restart <= max_restart); 355 356 TEST_ASSERT(len == z->len); 357 TEST_ASSERT(memcmp(buf, z->x, len) == 0); 358 359exit: 360 mbedtls_ecp_group_free(&grp); 361 mbedtls_ecdh_free(&srv); 362 mbedtls_ecdh_free(&cli); 363} 364/* END_CASE */ 365 366/* BEGIN_CASE */ 367void ecdh_exchange_calc_secret(int grp_id, 368 data_t *our_private_key, 369 data_t *their_point, 370 int ours_first, 371 data_t *expected) 372{ 373 mbedtls_test_rnd_pseudo_info rnd_info; 374 mbedtls_ecp_keypair our_key; 375 mbedtls_ecp_keypair their_key; 376 mbedtls_ecdh_context ecdh; 377 unsigned char shared_secret[MBEDTLS_ECP_MAX_BYTES]; 378 size_t shared_secret_length = 0; 379 380 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info)); 381 mbedtls_ecdh_init(&ecdh); 382 mbedtls_ecp_keypair_init(&our_key); 383 mbedtls_ecp_keypair_init(&their_key); 384 385 if (!load_private_key(grp_id, our_private_key, &our_key, &rnd_info)) { 386 goto exit; 387 } 388 if (!load_public_key(grp_id, their_point, &their_key)) { 389 goto exit; 390 } 391 392 /* Import the keys to the ECDH calculation. */ 393 if (ours_first) { 394 TEST_ASSERT(mbedtls_ecdh_get_params( 395 &ecdh, &our_key, MBEDTLS_ECDH_OURS) == 0); 396 TEST_ASSERT(mbedtls_ecdh_get_params( 397 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS) == 0); 398 } else { 399 TEST_ASSERT(mbedtls_ecdh_get_params( 400 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS) == 0); 401 TEST_ASSERT(mbedtls_ecdh_get_params( 402 &ecdh, &our_key, MBEDTLS_ECDH_OURS) == 0); 403 } 404 405 /* Perform the ECDH calculation. */ 406 TEST_ASSERT(mbedtls_ecdh_calc_secret( 407 &ecdh, 408 &shared_secret_length, 409 shared_secret, sizeof(shared_secret), 410 &mbedtls_test_rnd_pseudo_rand, &rnd_info) == 0); 411 TEST_ASSERT(shared_secret_length == expected->len); 412 TEST_ASSERT(memcmp(expected->x, shared_secret, 413 shared_secret_length) == 0); 414 415exit: 416 mbedtls_ecdh_free(&ecdh); 417 mbedtls_ecp_keypair_free(&our_key); 418 mbedtls_ecp_keypair_free(&their_key); 419} 420/* END_CASE */ 421 422/* BEGIN_CASE */ 423void ecdh_exchange_get_params_fail(int our_grp_id, 424 data_t *our_private_key, 425 int their_grp_id, 426 data_t *their_point, 427 int ours_first, 428 int expected_ret) 429{ 430 mbedtls_test_rnd_pseudo_info rnd_info; 431 mbedtls_ecp_keypair our_key; 432 mbedtls_ecp_keypair their_key; 433 mbedtls_ecdh_context ecdh; 434 435 memset(&rnd_info, 0x00, sizeof(mbedtls_test_rnd_pseudo_info)); 436 mbedtls_ecdh_init(&ecdh); 437 mbedtls_ecp_keypair_init(&our_key); 438 mbedtls_ecp_keypair_init(&their_key); 439 440 if (!load_private_key(our_grp_id, our_private_key, &our_key, &rnd_info)) { 441 goto exit; 442 } 443 if (!load_public_key(their_grp_id, their_point, &their_key)) { 444 goto exit; 445 } 446 447 if (ours_first) { 448 TEST_ASSERT(mbedtls_ecdh_get_params( 449 &ecdh, &our_key, MBEDTLS_ECDH_OURS) == 0); 450 TEST_ASSERT(mbedtls_ecdh_get_params( 451 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS) == 452 expected_ret); 453 } else { 454 TEST_ASSERT(mbedtls_ecdh_get_params( 455 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS) == 0); 456 TEST_ASSERT(mbedtls_ecdh_get_params( 457 &ecdh, &our_key, MBEDTLS_ECDH_OURS) == 458 expected_ret); 459 } 460 461exit: 462 mbedtls_ecdh_free(&ecdh); 463 mbedtls_ecp_keypair_free(&our_key); 464 mbedtls_ecp_keypair_free(&their_key); 465} 466/* END_CASE */ 467