1 /* 2 * Copyright (C) 2021 - This file is part of libecc project 3 * 4 * Authors: 5 * Ryad BENADJILA <ryadbenadjila@gmail.com> 6 * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr> 7 * 8 * This software is licensed under a dual BSD and GPL v2 license. 9 * See LICENSE file at the root folder of the project. 10 */ 11 12 /* 13 * Source code for handling tests imported from the wycheproof project: 14 * https://github.com/google/wycheproof 15 * 16 * As this project primarily targets java cryptographic libraries, the 17 * json test files have been parsed to generate libecc friendly test cases. 18 * 19 * NOTE: we skip here all the tests related to ASN.1 format errors as libecc 20 * does not handle ASN.1 parsing at all. This explains the "skipped" tests from 21 * the wycheproof project. 22 * 23 */ 24 #include "libecc_wycheproof.h" 25 26 /* Parallelize self tests? */ 27 #ifdef WITH_OPENMP_SELF_TESTS 28 /* No openmp without stdlib ... */ 29 #ifndef WITH_STDLIB 30 #error "Sorry: no possible self tests parallelization (OpenMP) without stdlib! Please use WITH_STDLIB" 31 #endif 32 #include <omp.h> 33 #include <stdlib.h> 34 static omp_lock_t global_lock; 35 static volatile u8 global_lock_initialized = 0; 36 #define OPENMP_LOCK() do { \ 37 if(!global_lock_initialized){ \ 38 omp_init_lock(&global_lock); \ 39 global_lock_initialized = 1; \ 40 } \ 41 omp_set_lock(&global_lock); \ 42 } while(0) 43 #define OPENMP_EG(ret, err) do { \ 44 if(ret){ \ 45 ext_printf("OpenMP abort following error ... %s:%d\n", __FILE__, __LINE__); \ 46 exit(-1); \ 47 } \ 48 } while(0) 49 #define OPENMP_MUST_HAVE(cnd, ret, err) do { \ 50 ret = !!(cnd); \ 51 ret = -((~ret) & 1); \ 52 OPENMP_EG(ret, err); \ 53 } while(0) 54 #define OPENMP_UNLOCK() do { \ 55 omp_unset_lock(&global_lock); \ 56 } while(0) 57 #else 58 #define OPENMP_LOCK() 59 #define OPENMP_UNLOCK() 60 #define OPENMP_EG(ret, err) do { \ 61 EG(ret, err); \ 62 } while(0) 63 #define OPENMP_MUST_HAVE(cnd, ret, err) do { \ 64 MUST_HAVE(cnd, ret, err); \ 65 } while(0) 66 #endif 67 68 #include "libecc_wycheproof_tests.h" 69 70 /* Check all ECDSA test vectors */ 71 static unsigned int ecdsa_acceptable_invalid = 0; 72 static unsigned int ecdsa_acceptable_valid = 0; 73 static unsigned int ecdsa_all_performed = 0; 74 static int check_wycheproof_ecdsa(void) 75 { 76 #if defined(WITH_SIG_ECDSA) 77 int ret; 78 unsigned int i; 79 80 #ifdef WITH_OPENMP_SELF_TESTS 81 #pragma omp parallel 82 #pragma omp for schedule(static, 1) nowait 83 #endif 84 for(i = 0; i < NUM_WYCHEPROOF_ECDSA_TESTS; i++){ 85 const wycheproof_ecdsa_test *t = wycheproof_ecdsa_all_tests[i]; 86 ec_pub_key pub_key; 87 ec_params params; 88 89 if (t == NULL){ 90 continue; 91 } 92 93 ecdsa_all_performed++; 94 ret = local_memset(&pub_key, 0, sizeof(pub_key)); OPENMP_EG(ret, err); 95 ret = local_memset(¶ms, 0, sizeof(params)); OPENMP_EG(ret, err); 96 97 /* Import EC params from test case */ 98 ret = import_params(¶ms, t->curve); 99 if (ret) { 100 ext_printf("Error: ECDSA tests error importing params\n"); 101 ret = -1; 102 OPENMP_EG(ret, err); 103 } 104 105 /* Import the public key */ 106 ret = ec_pub_key_import_from_aff_buf(&pub_key, ¶ms, t->pubkey, (u8)(t->pubkeylen), t->sig_alg); 107 if (ret) { 108 ext_printf("Error: ECDSA tests error importing public key\n"); 109 ret = -1; 110 OPENMP_EG(ret, err); 111 } 112 113 114 ret = ec_verify(t->sig, (u8)(t->siglen), &pub_key, t->msg, t->msglen, t->sig_alg, t->hash, NULL, 0); 115 /* Valid result */ 116 if ((t->result == 1) && ret) { 117 ext_printf("[-] Error when verifying ECDSA test %d / %s (verification NOK while must be valid)\n", i, t->name); 118 ext_printf(" (comment = %s)\n", t->comment); 119 ret = -1; 120 OPENMP_EG(ret, err); 121 } 122 /* Invalid result */ 123 if ((t->result == -1) && !ret) { 124 ext_printf("[-] Error when verifying ECDSA test %d / %s (verification OK while must be invalid)\n", i, t->name); 125 ext_printf(" (comment = %s)\n", t->comment); 126 ret = -1; 127 OPENMP_EG(ret, err); 128 } 129 /* Acceptable result: only trigger an informational warning */ 130 if (t->result == 0) { 131 if(ret){ 132 ecdsa_acceptable_valid++; 133 } 134 else{ 135 ecdsa_acceptable_invalid++; 136 } 137 #ifdef VERBOSE_ACCEPTABLE 138 ext_printf("\t[~] ECDSA test %d / %s (verification %d while acceptable)\n", i, t->name, ret); 139 ext_printf("\t (comment = %s)\n", t->comment); 140 #endif 141 } 142 } 143 144 ret = 0; 145 #ifndef WITH_OPENMP_SELF_TESTS 146 err: 147 #endif 148 return ret; 149 #else 150 return 0; 151 #endif 152 } 153 154 /* Check all EDDSA test vectors */ 155 static unsigned int eddsa_acceptable_invalid = 0; 156 static unsigned int eddsa_acceptable_valid = 0; 157 static unsigned int eddsa_all_performed = 0; 158 static int check_wycheproof_eddsa(void) 159 { 160 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448) 161 int ret; 162 unsigned int i; 163 164 #ifdef WITH_OPENMP_SELF_TESTS 165 #pragma omp parallel 166 #pragma omp for schedule(static, 1) nowait 167 #endif 168 for(i = 0; i < NUM_WYCHEPROOF_EDDSA_TESTS; i++){ 169 const wycheproof_eddsa_test *t = wycheproof_eddsa_all_tests[i]; 170 ec_pub_key pub_key; 171 ec_pub_key pub_key_check; 172 ec_priv_key priv_key; 173 ec_params params; 174 int check; 175 u8 exported_pub_key[EDDSA_MAX_PUB_KEY_ENCODED_LEN]; 176 177 if (t == NULL){ 178 continue; 179 } 180 181 OPENMP_LOCK(); 182 eddsa_all_performed++; 183 OPENMP_UNLOCK(); 184 ret = local_memset(&pub_key, 0, sizeof(pub_key)); OPENMP_EG(ret, err); 185 ret = local_memset(&priv_key, 0, sizeof(priv_key)); OPENMP_EG(ret, err); 186 ret = local_memset(¶ms, 0, sizeof(params)); OPENMP_EG(ret, err); 187 188 /* Import EC params from test case */ 189 ret = import_params(¶ms, t->curve); 190 if (ret) { 191 ext_printf("Error: EDDSA tests error importing params\n"); 192 ret = -1; 193 OPENMP_EG(ret, err); 194 } 195 196 /* Import the public key */ 197 ret = eddsa_import_pub_key(&pub_key, t->pubkey, (u8)(t->pubkeylen), ¶ms, t->sig_alg); 198 if (ret) { 199 ext_printf("Error: EDDSA tests error importing public key\n"); 200 ret = -1; 201 OPENMP_EG(ret, err); 202 } 203 /* Import the private key */ 204 ret = eddsa_import_priv_key(&priv_key, t->privkey, (u8)(t->privkeylen), ¶ms, t->sig_alg); 205 if (ret) { 206 ext_printf("Error: EDDSA tests error importing private key\n"); 207 ret = -1; 208 OPENMP_EG(ret, err); 209 } 210 /* Derive private to public */ 211 ret = eddsa_init_pub_key(&pub_key_check, &priv_key); 212 if (ret) { 213 ext_printf("Error: EDDSA tests error deriving private to public key\n"); 214 ret = -1; 215 OPENMP_EG(ret, err); 216 } 217 /* Check */ 218 ret = eddsa_export_pub_key(&pub_key, exported_pub_key, (u8)(t->pubkeylen)); 219 if(ret){ 220 ext_printf("Error: EDDSA tests error when exporting public key\n"); 221 ret = -1; 222 OPENMP_EG(ret, err); 223 } 224 /* */ 225 ret = are_equal(t->pubkey, &exported_pub_key, (u8)(t->pubkeylen), &check); OPENMP_EG(ret, err); 226 if(!check){ 227 ext_printf("Error: EDDSA tests error when checking public key from private\n"); 228 ret = -1; 229 OPENMP_EG(ret, err); 230 } 231 232 ret = ec_verify(t->sig, (u8)(t->siglen), &pub_key, t->msg, t->msglen, t->sig_alg, t->hash, NULL, 0); 233 /* Valid result */ 234 if ((t->result == 1) && ret) { 235 ext_printf("[-] Error when verifying EDDSA test %d / %s (verification NOK while must be valid)\n", i, t->name); 236 ext_printf(" (comment = %s)\n", t->comment); 237 ret = -1; 238 OPENMP_EG(ret, err); 239 } 240 /* Invalid result */ 241 if ((t->result == -1) && !ret) { 242 ext_printf("[-] Error when verifying EDDSA test %d / %s (verification OK while must be invalid)\n", i, t->name); 243 ext_printf(" (comment = %s)\n", t->comment); 244 ret = -1; 245 OPENMP_EG(ret, err); 246 } 247 /* Acceptable result: only trigger an informational warning */ 248 if (t->result == 0) { 249 OPENMP_LOCK(); 250 if(ret){ 251 eddsa_acceptable_valid++; 252 } 253 else{ 254 eddsa_acceptable_invalid++; 255 } 256 #ifdef VERBOSE_ACCEPTABLE 257 ext_printf("\t[~] EDDSA test %d / %s (verification %d while acceptable)\n", i, t->name, ret); 258 ext_printf("\t (comment = %s)\n", t->comment); 259 #endif 260 OPENMP_UNLOCK(); 261 } 262 } 263 264 ret = 0; 265 #ifndef WITH_OPENMP_SELF_TESTS 266 err: 267 #endif 268 return ret; 269 #else 270 return 0; 271 #endif 272 } 273 274 /* Check all XDH test vectors */ 275 static unsigned int xdh_acceptable_invalid = 0; 276 static unsigned int xdh_acceptable_valid = 0; 277 static unsigned int xdh_all_performed = 0; 278 static int check_wycheproof_xdh(void) 279 { 280 #if defined(WITH_X25519) || defined(WITH_X448) 281 int ret; 282 unsigned int i; 283 284 #ifdef WITH_OPENMP_SELF_TESTS 285 #pragma omp parallel 286 #pragma omp for schedule(static, 1) nowait 287 #endif 288 for(i = 0; i < NUM_WYCHEPROOF_XDH_TESTS; i++){ 289 int check; 290 const wycheproof_xdh_test *t = wycheproof_xdh_all_tests[i]; 291 unsigned int alglen = 0; 292 /* Max size buffer */ 293 u8 pubkey_check[X448_SIZE]; 294 u8 sharedsecret_check[X448_SIZE]; 295 296 if (t == NULL){ 297 continue; 298 } 299 300 OPENMP_LOCK(); 301 xdh_all_performed++; 302 OPENMP_UNLOCK(); 303 304 #if defined(WITH_X25519) 305 if(t->xdh_alg == X25519){ 306 OPENMP_MUST_HAVE(((t->curve) == &wei25519_str_params), ret, err); 307 alglen = X25519_SIZE; 308 } 309 #endif 310 #if defined(WITH_X448) 311 if(t->xdh_alg == X448){ 312 OPENMP_MUST_HAVE(((t->curve) == &wei448_str_params), ret, err); 313 alglen = X448_SIZE; 314 } 315 #endif 316 if(alglen == 0){ 317 ext_printf("Error: XDH tests error, unkown algorithm\n"); 318 ret = -1; 319 OPENMP_EG(ret, err); 320 } 321 /* Reject bad lengths */ 322 if(t->privkeylen != alglen){ 323 if(t->result != -1){ 324 ext_printf("[-] Error: XDH tests error, unkown private key length %d with valid result\n", t->privkeylen); 325 ext_printf(" (comment = %s)\n", t->comment); 326 ret = -1; 327 OPENMP_EG(ret, err); 328 } 329 else{ 330 continue; 331 } 332 } 333 if(t->peerpubkeylen != alglen){ 334 if(t->result != -1){ 335 ext_printf("[-] Error: XDH tests error, unkown peer public key length %d with valid result\n", t->peerpubkeylen); 336 ext_printf(" (comment = %s)\n", t->comment); 337 ret = -1; 338 OPENMP_EG(ret, err); 339 } 340 else{ 341 continue; 342 } 343 } 344 if(t->sharedsecretlen != alglen){ 345 if(t->result != -1){ 346 ext_printf("[-] Error: XDH tests error, unkown shared secret length %d with valid result\n", t->sharedsecretlen); 347 ext_printf(" (comment = %s)\n", t->comment); 348 ret = -1; 349 OPENMP_EG(ret, err); 350 } 351 else{ 352 continue; 353 } 354 } 355 if((t->ourpubkeylen != 0) && (t->ourpubkeylen != alglen)){ 356 if(t->result != -1){ 357 ext_printf("[-] Error: XDH tests error, unkown our public key length %d with valid result\n", t->ourpubkeylen); 358 ext_printf(" (comment = %s)\n", t->comment); 359 ret = -1; 360 OPENMP_EG(ret, err); 361 } 362 else{ 363 continue; 364 } 365 } 366 #if defined(WITH_X25519) 367 if(t->xdh_alg == X25519){ 368 /* Derive our public key */ 369 ret = x25519_init_pub_key(t->privkey, pubkey_check); 370 if(ret){ 371 ext_printf("[-] Error: XDH tests error when deriving private key to public\n"); 372 ext_printf(" (comment = %s)\n", t->comment); 373 ret = -1; 374 OPENMP_EG(ret, err); 375 } 376 if(t->ourpubkeylen != 0){ 377 /* Check public key against the test one */ 378 ret = are_equal(t->ourpubkey, pubkey_check, alglen, &check); OPENMP_EG(ret, err); 379 if(!check){ 380 ext_printf("[-] Error: XDH tests error when checking our public key\n"); 381 ext_printf(" (comment = %s)\n", t->comment); 382 ret = -1; 383 OPENMP_EG(ret, err); 384 } 385 } 386 /* Derive the shared secret */ 387 ret = x25519_derive_secret(t->privkey, t->peerpubkey, sharedsecret_check); 388 if(ret){ 389 /* Handle "acceptable" results here (e.g. public key on twist) */ 390 if(t->result == 0){ 391 OPENMP_LOCK(); 392 xdh_acceptable_invalid++; 393 #ifdef VERBOSE_ACCEPTABLE 394 ext_printf("\t[~] XDH test %d / %s (shared secret derivation NOK while acceptable)\n", i, t->name); 395 ext_printf("\t (comment = %s)\n", t->comment); 396 #endif 397 OPENMP_UNLOCK(); 398 continue; 399 } 400 ext_printf("[-] Error: XDH tests error when deriving shared secret\n"); 401 ext_printf(" (comment = %s)\n", t->comment); 402 ret = -1; 403 OPENMP_EG(ret, err); 404 } 405 if(t->result == -1){ 406 ext_printf("[-] Error: XDH tests is OK while invalid\n"); 407 ext_printf(" (comment = %s)\n", t->comment); 408 ret = -1; 409 OPENMP_EG(ret, err); 410 } 411 /* Check the shared secret */ 412 ret = are_equal(t->sharedsecret, sharedsecret_check, alglen, &check); OPENMP_EG(ret, err); 413 if(!check){ 414 ext_printf("[-] Error: XDH tests error when checking shared secret\n"); 415 ext_printf(" (comment = %s)\n", t->comment); 416 ret = -1; 417 OPENMP_EG(ret, err); 418 } 419 } 420 #endif 421 #if defined(WITH_X448) 422 if(t->xdh_alg == X448){ 423 /* Derive our public key */ 424 ret = x448_init_pub_key(t->privkey, pubkey_check); 425 if(ret){ 426 ext_printf("[-] Error: XDH tests error when deriving private key to public\n"); 427 ext_printf(" (comment = %s)\n", t->comment); 428 ret = -1; 429 OPENMP_EG(ret, err); 430 } 431 if(t->ourpubkeylen != 0){ 432 /* Check public key against the test one */ 433 ret = are_equal(t->ourpubkey, pubkey_check, alglen, &check); OPENMP_EG(ret, err); 434 if(!check){ 435 ext_printf("[-] Error: XDH tests error when checking our public key\n"); 436 ext_printf(" (comment = %s)\n", t->comment); 437 ret = -1; 438 OPENMP_EG(ret, err); 439 } 440 } 441 /* Derive the shared secret */ 442 ret = x448_derive_secret(t->privkey, t->peerpubkey, sharedsecret_check); 443 if(ret){ 444 /* Handle "acceptable" results here (e.g. public key on twist) */ 445 if(t->result == 0){ 446 OPENMP_LOCK(); 447 xdh_acceptable_invalid++; 448 #ifdef VERBOSE_ACCEPTABLE 449 ext_printf("\t[~] XDH test %d / %s (shared secret derivation NOK while acceptable)\n", i, t->name); 450 ext_printf("\t (comment = %s)\n", t->comment); 451 #endif 452 OPENMP_UNLOCK(); 453 continue; 454 } 455 ext_printf("[-] Error: XDH tests error when deriving shared secret\n"); 456 ext_printf(" (comment = %s)\n", t->comment); 457 OPENMP_EG(ret, err); 458 } 459 if(t->result == -1){ 460 ext_printf("[-] Error: XDH tests is OK while invalid\n"); 461 ext_printf(" (comment = %s)\n", t->comment); 462 ret = -1; 463 OPENMP_EG(ret, err); 464 } 465 /* Check the shared secret */ 466 ret = are_equal(t->sharedsecret, sharedsecret_check, alglen, &check); OPENMP_EG(ret, err); 467 if(!check){ 468 ext_printf("[-] Error: XDH tests error when checking shared secret\n"); 469 ext_printf(" (comment = %s)\n", t->comment); 470 ret = -1; 471 OPENMP_EG(ret, err); 472 } 473 474 } 475 #endif 476 /* Log the acceptable results */ 477 if (t->result == 0) { 478 OPENMP_LOCK(); 479 xdh_acceptable_valid++; 480 #ifdef VERBOSE_ACCEPTABLE 481 ext_printf("\t[~] XDH test %d / %s (shared secret OK while acceptable)\n", i, t->name); 482 ext_printf("\t (comment = %s)\n", t->comment); 483 #endif 484 OPENMP_UNLOCK(); 485 } 486 } 487 ret = 0; 488 #ifndef WITH_OPENMP_SELF_TESTS 489 err: 490 #endif 491 return ret; 492 #else 493 return 0; 494 #endif 495 } 496 497 /* Point decompression routine */ 498 static int uncompress_ecc_point(const ec_params *params, const u8 *peerpubkey, u8 peerpubkeylen, u8 *serialized_pub_key, u8 serialized_pub_key_size, int compression) 499 { 500 int ret, sign, check; 501 fp x, tmp; 502 fp_t y; 503 x.magic = tmp.magic = 0; 504 505 MUST_HAVE((params != NULL) && (peerpubkey != NULL) && (serialized_pub_key != NULL), ret, err); 506 507 /* Uncompressed point size should be twice the x coordinate */ 508 MUST_HAVE((serialized_pub_key_size == (2 * peerpubkeylen)), ret, err); 509 510 /* Compression is either 02 or 03 */ 511 MUST_HAVE(((compression == 0x02) || (compression == 0x03)), ret, err); 512 513 /* Import our x coordinate */ 514 ret = fp_init_from_buf(&x, &(params->ec_fp), peerpubkey, peerpubkeylen); EG(ret, err); 515 ret = fp_init(&tmp, &(params->ec_fp)); EG(ret, err); 516 /* Compute the Weierstrass equation y^2 = x^3 + ax + b solutions */ 517 ret = aff_pt_y_from_x(&tmp, &x, &x, &(params->ec_curve)); EG(ret, err); 518 519 /* Choose the square root depending on the compression information */ 520 sign = (compression - 2); 521 522 ret = fp_cmp(&x, &tmp, &check); EG(ret, err); 523 524 y = ((check > 0) == sign) ? &x : &tmp; 525 526 /* Export the point to our buffer */ 527 ret = local_memcpy(&serialized_pub_key[0], &peerpubkey[0], (serialized_pub_key_size / 2)); EG(ret, err); 528 ret = fp_export_to_buf(&serialized_pub_key[(serialized_pub_key_size / 2)], (serialized_pub_key_size / 2), y); 529 530 err: 531 fp_uninit(&x); 532 fp_uninit(&tmp); 533 PTR_NULLIFY(y); 534 535 return ret; 536 } 537 538 /* Check all ECDH test vectors */ 539 static unsigned int ecdh_acceptable_invalid = 0; 540 static unsigned int ecdh_acceptable_valid = 0; 541 static unsigned int ecdh_all_performed = 0; 542 static int check_wycheproof_ecdh(void) 543 { 544 #if defined(WITH_ECCCDH) 545 int ret; 546 unsigned int i; 547 548 #ifdef WITH_OPENMP_SELF_TESTS 549 #pragma omp parallel 550 #pragma omp for schedule(static, 1) nowait 551 #endif 552 for(i = 0; i < NUM_WYCHEPROOF_ECDH_TESTS; i++){ 553 int check; 554 const wycheproof_ecdh_test *t = wycheproof_ecdh_all_tests[i]; 555 ec_pub_key peerpub_key; 556 ec_pub_key ourpub_key; 557 ec_pub_key ourpub_key_check; 558 ec_priv_key priv_key; 559 ec_params params; 560 u8 sharedsecret_check[EC_PRIV_KEY_MAX_SIZE]; 561 u8 sharedsecretsize; 562 u8 serialized_pub_key[EC_PUB_KEY_MAX_SIZE]; 563 u8 serialized_pub_key_check[EC_PUB_KEY_MAX_SIZE]; 564 u8 serialized_pub_key_size; 565 566 if (t == NULL){ 567 continue; 568 } 569 570 OPENMP_LOCK(); 571 ecdh_all_performed++; 572 OPENMP_UNLOCK(); 573 574 ret = local_memset(&peerpub_key, 0, sizeof(peerpub_key)); OPENMP_EG(ret, err); 575 ret = local_memset(&ourpub_key, 0, sizeof(ourpub_key)); OPENMP_EG(ret, err); 576 ret = local_memset(&ourpub_key_check, 0, sizeof(ourpub_key_check)); OPENMP_EG(ret, err); 577 ret = local_memset(&priv_key, 0, sizeof(priv_key)); OPENMP_EG(ret, err); 578 ret = local_memset(¶ms, 0, sizeof(params)); OPENMP_EG(ret, err); 579 ret = local_memset(sharedsecret_check, 0, sizeof(sharedsecret_check)); OPENMP_EG(ret, err); 580 ret = local_memset(serialized_pub_key, 0, sizeof(serialized_pub_key)); OPENMP_EG(ret, err); 581 582 /* Import EC params from test case */ 583 ret = import_params(¶ms, t->curve); 584 if (ret) { 585 ext_printf("Error: ECDH tests error importing params\n"); 586 ret = -1; 587 OPENMP_EG(ret, err); 588 } 589 590 /* Get the sizes */ 591 ret = ecccdh_shared_secret_size(¶ms, &sharedsecretsize); 592 if (ret) { 593 ext_printf("Error: ECDH tests error getting shared secret size\n"); 594 ret = -1; 595 OPENMP_EG(ret, err); 596 } 597 OPENMP_MUST_HAVE((sharedsecretsize <= sizeof(sharedsecret_check)), ret, err); 598 ret = ecccdh_serialized_pub_key_size(¶ms, &serialized_pub_key_size); 599 if (ret) { 600 ext_printf("Error: ECDH tests error getting serialized public key size\n"); 601 ret = -1; 602 OPENMP_EG(ret, err); 603 } 604 OPENMP_MUST_HAVE((serialized_pub_key_size <= sizeof(serialized_pub_key)), ret, err); 605 OPENMP_MUST_HAVE((serialized_pub_key_size <= sizeof(serialized_pub_key_check)), ret, err); 606 607 /* Import the private key */ 608 ret = ec_priv_key_import_from_buf(&priv_key, ¶ms, t->privkey, (u8)(t->privkeylen), t->ecdh_alg); 609 if (ret) { 610 ext_printf("Error: ECDH tests error importing private key\n"); 611 ret = -1; 612 OPENMP_EG(ret, err); 613 } 614 615 if(t->ourpubkeylen != 0){ 616 /* Import our public key if it exists */ 617 ret = ec_pub_key_import_from_aff_buf(&ourpub_key, ¶ms, t->ourpubkey, (u8)(t->ourpubkeylen), t->ecdh_alg); 618 if (ret && (t->result >= 0)) { 619 ext_printf("[-] Error: ECDH tests error when importing our public key\n"); 620 ext_printf(" (comment = %s)\n", t->comment); 621 ret = -1; 622 OPENMP_EG(ret, err); 623 } 624 /* Derive our private key to public */ 625 ret = ecccdh_init_pub_key(&ourpub_key_check, &priv_key); 626 if (ret) { 627 ext_printf("Error: ECDH tests error deriving our private key to public\n"); 628 ret = -1; 629 OPENMP_EG(ret, err); 630 } 631 /* Check if we get the same public key by serializing them */ 632 ret = ecccdh_serialize_pub_key(&ourpub_key, serialized_pub_key, serialized_pub_key_size); 633 if (ret){ 634 ext_printf("Error: ECDH tests error serializing public key\n"); 635 ret = -1; 636 OPENMP_EG(ret, err); 637 } 638 ret = ecccdh_serialize_pub_key(&ourpub_key_check, serialized_pub_key_check, serialized_pub_key_size); 639 if (ret){ 640 ext_printf("Error: ECDH tests error serializing public key\n"); 641 ret = -1; 642 OPENMP_EG(ret, err); 643 } 644 ret = are_equal(serialized_pub_key, serialized_pub_key_check, serialized_pub_key_size, &check); OPENMP_EG(ret, err); 645 if(!check){ 646 ext_printf("[-] Error: ECDH tests error when checking our public key\n"); 647 ext_printf(" (comment = %s)\n", t->comment); 648 ret = -1; 649 OPENMP_EG(ret, err); 650 } 651 } 652 653 /* Do we have to uncompress our point? */ 654 if(t->compressed > 0){ 655 /* Uncompress the point */ 656 ret = uncompress_ecc_point(¶ms, t->peerpubkey, (u8)(t->peerpubkeylen), serialized_pub_key, serialized_pub_key_size, t->compressed); 657 if ((ret) && (t->result >= 0)) { 658 ext_printf("[-] Error: ECDH tests error when uncompressing public key\n"); 659 ext_printf(" (comment = %s)\n", t->comment); 660 ret = -1; 661 OPENMP_EG(ret, err); 662 } 663 } 664 else{ 665 /* No point compression is used, copy our raw buffer as public key */ 666 if((t->peerpubkeylen != serialized_pub_key_size) && (t->result >= 0)){ 667 ext_printf("[-] Error: ECDH tests error when checking our public key size, got %d instead of %d\n", t->peerpubkeylen, serialized_pub_key_size); 668 ext_printf(" (comment = %s)\n", t->comment); 669 ret = -1; 670 OPENMP_EG(ret, err); 671 } 672 ret = local_memcpy(serialized_pub_key, t->peerpubkey, serialized_pub_key_size); OPENMP_EG(ret, err); 673 } 674 /* Now derive the shared secret */ 675 ret = ecccdh_derive_secret(&priv_key, serialized_pub_key, serialized_pub_key_size, sharedsecret_check, sharedsecretsize); 676 if ((ret) && (t->result >= 0)) { 677 ext_printf("[-] Error: ECDH tests error when deriving secret while acceptable or valid\n"); 678 ext_printf(" (comment = %s)\n", t->comment); 679 ret = -1; 680 OPENMP_EG(ret, err); 681 } 682 if((!ret) && (t->result == -1)){ 683 ext_printf("Error: ECDH tests error, secret derived OK while invalid\n"); 684 ext_printf(" (comment = %s)\n", t->comment); 685 ret = -1; 686 OPENMP_EG(ret, err); 687 } 688 if(t->result == -1){ 689 continue; 690 } 691 if(sharedsecretsize != t->sharedsecretlen){ 692 ext_printf("Error: ECDH tests error, bad shared secret size %d instead of %d\n", sharedsecretsize, t->sharedsecretlen); 693 ext_printf(" (comment = %s)\n", t->comment); 694 ret = -1; 695 OPENMP_EG(ret, err); 696 } 697 /* Compare */ 698 ret = are_equal(sharedsecret_check, t->sharedsecret, sharedsecretsize, &check); OPENMP_EG(ret, err); 699 if(!check){ 700 ext_printf("[-] Error: ECDH tests error when checking the computed shared secret, they differ\n"); 701 ext_printf(" (comment = %s)\n", t->comment); 702 ret = -1; 703 OPENMP_EG(ret, err); 704 } 705 /* Log the acceptable results */ 706 if (t->result == 0) { 707 OPENMP_LOCK(); 708 ecdh_acceptable_valid++; 709 #ifdef VERBOSE_ACCEPTABLE 710 ext_printf("\t[~] ECDH test %d / %s (shared secret OK while acceptable)\n", i, t->name); 711 ext_printf("\t (comment = %s)\n", t->comment); 712 #endif 713 OPENMP_UNLOCK(); 714 } 715 716 } 717 ret = 0; 718 #ifndef WITH_OPENMP_SELF_TESTS 719 err: 720 #endif 721 return ret; 722 #else 723 return 0; 724 #endif 725 } 726 727 /* Check all HMAC test vectors */ 728 static unsigned int hmac_acceptable_invalid = 0; 729 static unsigned int hmac_acceptable_valid = 0; 730 static unsigned int hmac_all_performed = 0; 731 static int check_wycheproof_hmac(void) 732 { 733 #if defined(WITH_HMAC) 734 int ret; 735 unsigned int i; 736 737 #ifdef WITH_OPENMP_SELF_TESTS 738 #pragma omp parallel 739 #pragma omp for schedule(static, 1) nowait 740 #endif 741 for(i = 0; i < NUM_WYCHEPROOF_HMAC_TESTS; i++){ 742 int check; 743 const wycheproof_hmac_test *t = wycheproof_hmac_all_tests[i]; 744 u8 hmac_res[MAX_DIGEST_SIZE]; 745 u8 hlen; 746 747 if (t == NULL){ 748 continue; 749 } 750 751 OPENMP_LOCK(); 752 hmac_all_performed++; 753 OPENMP_UNLOCK(); 754 755 ret = local_memset(&hmac_res, 0, sizeof(hmac_res)); OPENMP_EG(ret, err); 756 757 hlen = sizeof(hmac_res); 758 ret = hmac(t->key, t->keylen, t->hash, t->msg, t->msglen, hmac_res, &hlen); 759 if (ret) { 760 ext_printf("[-] Error: HMAC tests error when performin HMAC\n"); 761 ext_printf(" (comment = %s)\n", t->comment); 762 ret = -1; 763 OPENMP_EG(ret, err); 764 } 765 if((hlen < t->taglen) && (t->result >= 0)){ 766 ext_printf("[-] Error: HMAC tests error: size error %d < %d\n", hlen, t->taglen); 767 ext_printf(" (comment = %s)\n", t->comment); 768 ret = -1; 769 OPENMP_EG(ret, err); 770 } 771 /* Compare */ 772 ret = are_equal(hmac_res, t->tag, t->taglen, &check); OPENMP_EG(ret, err); 773 if((!check) && (t->result >= 0)){ 774 ext_printf("[-] Error: HMAC tests error when checking the computed tag, they differ\n"); 775 ext_printf(" (comment = %s)\n", t->comment); 776 ret = -1; 777 OPENMP_EG(ret, err); 778 } 779 /* Log the acceptable results */ 780 if (t->result == 0) { 781 OPENMP_LOCK(); 782 hmac_acceptable_valid++; 783 #ifdef VERBOSE_ACCEPTABLE 784 ext_printf("\t[~] HMAC test %d / %s (shared secret OK while acceptable)\n", i, t->name); 785 ext_printf("\t (comment = %s)\n", t->comment); 786 #endif 787 OPENMP_UNLOCK(); 788 } 789 } 790 ret = 0; 791 #ifndef WITH_OPENMP_SELF_TESTS 792 err: 793 #endif 794 return ret; 795 #else 796 return 0; 797 #endif 798 } 799 800 int main(int argc, char *argv[]) 801 { 802 FORCE_USED_VAR(argc); 803 FORCE_USED_VAR(argv); 804 805 /**********************/ 806 ext_printf("==== Checking ECDH =========== Imported = %d, Skipped = %d (valid = %d, invalid = %d, acceptable = %d)\n", NUM_WYCHEPROOF_ECDH_TESTS_IMPORTED, NUM_WYCHEPROOF_ECDH_TESTS_SKIPPED, NUM_WYCHEPROOF_ECDH_TESTS_VALID, NUM_WYCHEPROOF_ECDH_TESTS_INVALID, NUM_WYCHEPROOF_ECDH_TESTS_ACCEPTABLE); 807 if(check_wycheproof_ecdh()){ 808 goto err; 809 } 810 ext_printf("[+][%d] All ECDH tests went OK! (%d acceptable/valid, %d acceptable/invalid)\n", ecdh_all_performed, ecdh_acceptable_valid, ecdh_acceptable_invalid); 811 /**********************/ 812 ext_printf("==== Checking XDH =========== Imported = %d, Skipped = %d (valid = %d, invalid = %d, acceptable = %d)\n", NUM_WYCHEPROOF_XDH_TESTS_IMPORTED, NUM_WYCHEPROOF_XDH_TESTS_SKIPPED, NUM_WYCHEPROOF_XDH_TESTS_VALID, NUM_WYCHEPROOF_XDH_TESTS_INVALID, NUM_WYCHEPROOF_XDH_TESTS_ACCEPTABLE); 813 if(check_wycheproof_xdh()){ 814 goto err; 815 } 816 ext_printf("[+][%d] All XDH tests went OK! (%d acceptable/valid, %d acceptable/invalid)\n", xdh_all_performed, xdh_acceptable_valid, xdh_acceptable_invalid); 817 /**********************/ 818 ext_printf("==== Checking ECDSA =========== Imported = %d, Skipped = %d (valid = %d, invalid = %d, acceptable = %d)\n", NUM_WYCHEPROOF_ECDSA_TESTS_IMPORTED, NUM_WYCHEPROOF_ECDSA_TESTS_SKIPPED, NUM_WYCHEPROOF_ECDSA_TESTS_VALID, NUM_WYCHEPROOF_ECDSA_TESTS_INVALID, NUM_WYCHEPROOF_ECDSA_TESTS_ACCEPTABLE); 819 if(check_wycheproof_ecdsa()){ 820 goto err; 821 } 822 ext_printf("[+][%d] All ECDSA tests went OK! (%d acceptable/valid, %d acceptable/invalid)\n", ecdsa_all_performed, ecdsa_acceptable_valid, ecdsa_acceptable_invalid); 823 /**********************/ 824 ext_printf("==== Checking EDDSA =========== Imported = %d, Skipped = %d (valid = %d, invalid = %d, acceptable = %d)\n", NUM_WYCHEPROOF_EDDSA_TESTS_IMPORTED, NUM_WYCHEPROOF_EDDSA_TESTS_SKIPPED, NUM_WYCHEPROOF_EDDSA_TESTS_VALID, NUM_WYCHEPROOF_EDDSA_TESTS_INVALID, NUM_WYCHEPROOF_EDDSA_TESTS_ACCEPTABLE); 825 if(check_wycheproof_eddsa()){ 826 goto err; 827 } 828 ext_printf("[+][%d] All EDDSA tests went OK! (%d acceptable/valid, %d acceptable/invalid)\n", eddsa_all_performed, eddsa_acceptable_valid, eddsa_acceptable_invalid); 829 /**********************/ 830 ext_printf("==== Checking HMAC =========== Imported = %d, Skipped = %d (valid = %d, invalid = %d, acceptable = %d)\n", NUM_WYCHEPROOF_HMAC_TESTS_IMPORTED, NUM_WYCHEPROOF_HMAC_TESTS_SKIPPED, NUM_WYCHEPROOF_HMAC_TESTS_VALID, NUM_WYCHEPROOF_HMAC_TESTS_INVALID, NUM_WYCHEPROOF_HMAC_TESTS_ACCEPTABLE); 831 if(check_wycheproof_hmac()){ 832 goto err; 833 } 834 ext_printf("[+][%d] All HMAC tests went OK! (%d acceptable/valid, %d acceptable/invalid)\n", hmac_all_performed, hmac_acceptable_valid, hmac_acceptable_invalid); 835 836 err: 837 return 0; 838 } 839