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 { 131 unsigned char shift = 8 - ( grp.nbits % 8 ); 132 size_t i; 133 134 for( i = 0; i < rnd_info_A.length - 1; i++ ) 135 rnd_buf_A->x[i] = rnd_buf_A->x[i] << shift 136 | rnd_buf_A->x[i+1] >> ( 8 - shift ); 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 { 149 unsigned char shift = 8 - ( grp.nbits % 8 ); 150 size_t i; 151 152 for( i = 0; i < rnd_info_B.length - 1; i++ ) 153 rnd_buf_B->x[i] = rnd_buf_B->x[i] << shift 154 | rnd_buf_B->x[i+1] >> ( 8 - shift ); 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 { 283 mbedtls_ecdh_enable_restart( &srv ); 284 mbedtls_ecdh_enable_restart( &cli ); 285 } 286 287 /* server writes its parameters */ 288 memset( buf, 0x00, sizeof( buf ) ); 289 len = 0; 290 291 cnt_restart = 0; 292 do { 293 ret = mbedtls_ecdh_make_params( &srv, &len, buf, sizeof( buf ), 294 mbedtls_test_rnd_buffer_rand, 295 &rnd_info_A ); 296 } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); 297 298 TEST_ASSERT( ret == 0 ); 299 TEST_ASSERT( cnt_restart >= min_restart ); 300 TEST_ASSERT( cnt_restart <= max_restart ); 301 302 /* client read server params */ 303 vbuf = buf; 304 TEST_ASSERT( mbedtls_ecdh_read_params( &cli, &vbuf, buf + len ) == 0 ); 305 306 /* client writes its key share */ 307 memset( buf, 0x00, sizeof( buf ) ); 308 len = 0; 309 310 cnt_restart = 0; 311 do { 312 ret = mbedtls_ecdh_make_public( &cli, &len, buf, sizeof( buf ), 313 mbedtls_test_rnd_buffer_rand, 314 &rnd_info_B ); 315 } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); 316 317 TEST_ASSERT( ret == 0 ); 318 TEST_ASSERT( cnt_restart >= min_restart ); 319 TEST_ASSERT( cnt_restart <= max_restart ); 320 321 /* server reads client key share */ 322 TEST_ASSERT( mbedtls_ecdh_read_public( &srv, buf, len ) == 0 ); 323 324 /* server computes shared secret */ 325 memset( buf, 0, sizeof( buf ) ); 326 len = 0; 327 328 cnt_restart = 0; 329 do { 330 ret = mbedtls_ecdh_calc_secret( &srv, &len, buf, sizeof( buf ), 331 &mbedtls_test_rnd_pseudo_rand, 332 &rnd_info ); 333 } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); 334 335 TEST_ASSERT( ret == 0 ); 336 TEST_ASSERT( cnt_restart >= min_restart ); 337 TEST_ASSERT( cnt_restart <= max_restart ); 338 339 TEST_ASSERT( len == z->len ); 340 TEST_ASSERT( memcmp( buf, z->x, len ) == 0 ); 341 342 /* client computes shared secret */ 343 memset( buf, 0, sizeof( buf ) ); 344 len = 0; 345 346 cnt_restart = 0; 347 do { 348 ret = mbedtls_ecdh_calc_secret( &cli, &len, buf, sizeof( buf ), 349 &mbedtls_test_rnd_pseudo_rand, 350 &rnd_info ); 351 } while( ret == MBEDTLS_ERR_ECP_IN_PROGRESS && ++cnt_restart ); 352 353 TEST_ASSERT( ret == 0 ); 354 TEST_ASSERT( cnt_restart >= min_restart ); 355 TEST_ASSERT( cnt_restart <= max_restart ); 356 357 TEST_ASSERT( len == z->len ); 358 TEST_ASSERT( memcmp( buf, z->x, len ) == 0 ); 359 360exit: 361 mbedtls_ecp_group_free( &grp ); 362 mbedtls_ecdh_free( &srv ); 363 mbedtls_ecdh_free( &cli ); 364} 365/* END_CASE */ 366 367/* BEGIN_CASE */ 368void ecdh_exchange_calc_secret( int grp_id, 369 data_t *our_private_key, 370 data_t *their_point, 371 int ours_first, 372 data_t *expected ) 373{ 374 mbedtls_test_rnd_pseudo_info rnd_info; 375 mbedtls_ecp_keypair our_key; 376 mbedtls_ecp_keypair their_key; 377 mbedtls_ecdh_context ecdh; 378 unsigned char shared_secret[MBEDTLS_ECP_MAX_BYTES]; 379 size_t shared_secret_length = 0; 380 381 memset( &rnd_info, 0x00, sizeof( mbedtls_test_rnd_pseudo_info ) ); 382 mbedtls_ecdh_init( &ecdh ); 383 mbedtls_ecp_keypair_init( &our_key ); 384 mbedtls_ecp_keypair_init( &their_key ); 385 386 if( ! load_private_key( grp_id, our_private_key, &our_key, &rnd_info ) ) 387 goto exit; 388 if( ! load_public_key( grp_id, their_point, &their_key ) ) 389 goto exit; 390 391 /* Import the keys to the ECDH calculation. */ 392 if( ours_first ) 393 { 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 } 399 else 400 { 401 TEST_ASSERT( mbedtls_ecdh_get_params( 402 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 ); 403 TEST_ASSERT( mbedtls_ecdh_get_params( 404 &ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 ); 405 } 406 407 /* Perform the ECDH calculation. */ 408 TEST_ASSERT( mbedtls_ecdh_calc_secret( 409 &ecdh, 410 &shared_secret_length, 411 shared_secret, sizeof( shared_secret ), 412 &mbedtls_test_rnd_pseudo_rand, &rnd_info ) == 0 ); 413 TEST_ASSERT( shared_secret_length == expected->len ); 414 TEST_ASSERT( memcmp( expected->x, shared_secret, 415 shared_secret_length ) == 0 ); 416 417exit: 418 mbedtls_ecdh_free( &ecdh ); 419 mbedtls_ecp_keypair_free( &our_key ); 420 mbedtls_ecp_keypair_free( &their_key ); 421} 422/* END_CASE */ 423 424/* BEGIN_CASE */ 425void ecdh_exchange_get_params_fail( int our_grp_id, 426 data_t *our_private_key, 427 int their_grp_id, 428 data_t *their_point, 429 int ours_first, 430 int expected_ret ) 431{ 432 mbedtls_test_rnd_pseudo_info rnd_info; 433 mbedtls_ecp_keypair our_key; 434 mbedtls_ecp_keypair their_key; 435 mbedtls_ecdh_context ecdh; 436 437 memset( &rnd_info, 0x00, sizeof( mbedtls_test_rnd_pseudo_info ) ); 438 mbedtls_ecdh_init( &ecdh ); 439 mbedtls_ecp_keypair_init( &our_key ); 440 mbedtls_ecp_keypair_init( &their_key ); 441 442 if( ! load_private_key( our_grp_id, our_private_key, &our_key, &rnd_info ) ) 443 goto exit; 444 if( ! load_public_key( their_grp_id, their_point, &their_key ) ) 445 goto exit; 446 447 if( ours_first ) 448 { 449 TEST_ASSERT( mbedtls_ecdh_get_params( 450 &ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 0 ); 451 TEST_ASSERT( mbedtls_ecdh_get_params( 452 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 453 expected_ret ); 454 } 455 else 456 { 457 TEST_ASSERT( mbedtls_ecdh_get_params( 458 &ecdh, &their_key, MBEDTLS_ECDH_THEIRS ) == 0 ); 459 TEST_ASSERT( mbedtls_ecdh_get_params( 460 &ecdh, &our_key, MBEDTLS_ECDH_OURS ) == 461 expected_ret ); 462 } 463 464exit: 465 mbedtls_ecdh_free( &ecdh ); 466 mbedtls_ecp_keypair_free( &our_key ); 467 mbedtls_ecp_keypair_free( &their_key ); 468} 469/* END_CASE */ 470