1 /* 2 * Copyright (C) 2017 - 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 * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr> 8 * 9 * Contributors: 10 * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr> 11 * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr> 12 * 13 * This software is licensed under a dual BSD and GPL v2 license. 14 * See LICENSE file at the root folder of the project. 15 */ 16 #include <libecc/utils/utils.h> 17 #include <libecc/external_deps/rand.h> 18 #include <libecc/external_deps/time.h> 19 #include <libecc/external_deps/print.h> 20 #include "ec_self_tests_core.h" 21 22 /* Parallelize self tests? */ 23 #ifdef WITH_OPENMP_SELF_TESTS 24 /* No openmp without stdlib ... */ 25 #ifndef WITH_STDLIB 26 #error "Sorry: no possible self tests parallelization (OpenMP) without stdlib! Please use WITH_STDLIB" 27 #endif 28 #include <omp.h> 29 #include <stdlib.h> 30 static omp_lock_t global_lock; 31 static volatile u8 global_lock_initialized = 0; 32 #define OPENMP_LOCK() do { \ 33 if(!global_lock_initialized){ \ 34 omp_init_lock(&global_lock); \ 35 global_lock_initialized = 1; \ 36 } \ 37 omp_set_lock(&global_lock); \ 38 } while(0) 39 #define OPENMP_UNLOCK() do { \ 40 omp_unset_lock(&global_lock); \ 41 } while(0) 42 #define OPENMP_EG(ret, err) do { \ 43 if(ret){ \ 44 ext_printf("OpenMP abort following error ... %s:%d\n", __FILE__, __LINE__); \ 45 exit(-1); \ 46 } \ 47 } while(0) 48 #else 49 #define OPENMP_LOCK() 50 #define OPENMP_UNLOCK() 51 #define OPENMP_EG(ret, err) do { \ 52 EG(ret, err); \ 53 } while(0) 54 #endif 55 56 ATTRIBUTE_WARN_UNUSED_RET static int ec_gen_import_export_kp(ec_key_pair *kp, const ec_params *params, 57 const ec_test_case *c) 58 { 59 u8 pub_key_buf[EC_STRUCTURED_PUB_KEY_MAX_EXPORT_SIZE]; 60 u8 priv_key_buf[EC_STRUCTURED_PRIV_KEY_MAX_EXPORT_SIZE]; 61 u8 pub_key_buf_len, priv_key_buf_len; 62 ec_key_pair imported_kp; 63 int ret; 64 65 MUST_HAVE(c != NULL, ret, err); 66 67 ret = local_memset(pub_key_buf, 0, sizeof(pub_key_buf)); EG(ret, err); 68 ret = local_memset(priv_key_buf, 0, sizeof(priv_key_buf)); EG(ret, err); 69 ret = local_memset(&imported_kp, 0, sizeof(imported_kp)); EG(ret, err); 70 71 /* Generate key pair */ 72 ret = ec_key_pair_gen(kp, params, c->sig_type); 73 if (ret) { 74 ext_printf("Error generating key pair\n"); 75 goto err; 76 } 77 pub_key_buf_len = EC_STRUCTURED_PUB_KEY_EXPORT_SIZE(&(kp->pub_key)); 78 priv_key_buf_len = EC_STRUCTURED_PRIV_KEY_EXPORT_SIZE(&(kp->priv_key)); 79 80 /* Export public and private keys in buffers */ 81 ret = ec_structured_pub_key_export_to_buf(&(kp->pub_key), pub_key_buf, 82 pub_key_buf_len); 83 if (ret) { 84 ext_printf("Error exporting public key\n"); 85 goto err; 86 } 87 ret = ec_structured_priv_key_export_to_buf(&(kp->priv_key), 88 priv_key_buf, 89 priv_key_buf_len); 90 if (ret) { 91 ext_printf("Error exporting private key\n"); 92 goto err; 93 } 94 95 /* Import public and private key */ 96 ret = ec_structured_pub_key_import_from_buf(&(imported_kp.pub_key), 97 params, 98 pub_key_buf, 99 pub_key_buf_len, 100 c->sig_type); 101 if (ret) { 102 ext_printf("Error importing public key\n"); 103 goto err; 104 } 105 ret = ec_structured_priv_key_import_from_buf(&(imported_kp.priv_key), 106 params, priv_key_buf, 107 priv_key_buf_len, 108 c->sig_type); 109 if (ret) { 110 ext_printf("Error importing private key\n"); 111 goto err; 112 } 113 ret = 0; 114 115 err: 116 return ret; 117 } 118 119 /* This function randomly splits the message input in small chunks to 120 * test the signature init / multiple updates / finalize mechanism for 121 * algorithms that support them. 122 */ 123 ATTRIBUTE_WARN_UNUSED_RET static int random_split_ec_sign(u8 *sig, u8 siglen, const ec_key_pair *key_pair, 124 const u8 *m, u32 mlen, 125 int (*rand) (nn_t out, nn_src_t q), 126 ec_alg_type sig_type, hash_alg_type hash_type, const u8 *adata, u16 adata_len) 127 { 128 struct ec_sign_context ctx; 129 int ret; 130 u32 consumed; 131 132 ret = local_memset(&ctx, 0, sizeof(ctx)); EG(ret, err); 133 134 MUST_HAVE(sig != NULL, ret, err); 135 MUST_HAVE(key_pair != NULL, ret, err); 136 MUST_HAVE(m != NULL, ret, err); 137 /* note: adata == NULL is allowed */ 138 139 ret = _ec_sign_init(&ctx, key_pair, rand, sig_type, hash_type, adata, adata_len); 140 if (ret) { 141 goto err; 142 } 143 /* We randomly split the input message in chunks and proceed with updates */ 144 consumed = 0; 145 while(consumed < mlen){ 146 u32 toconsume = 0; 147 ret = get_random((u8 *)&toconsume, sizeof(toconsume)); 148 if (ret) { 149 ext_printf("Error when getting random\n"); 150 goto err; 151 } 152 toconsume = (toconsume % (mlen - consumed)); 153 if(((mlen - consumed) == 1) && (toconsume == 0)){ 154 toconsume = 1; 155 } 156 ret = ec_sign_update(&ctx, &m[consumed], toconsume); 157 if (ret) { 158 goto err; 159 } 160 consumed += toconsume; 161 } 162 163 ret = ec_sign_finalize(&ctx, sig, siglen); 164 165 err: 166 return ret; 167 } 168 169 /* This function randomly splits the message input in small chunks to 170 * test the verification init / multiple updates / finalize mechanism for 171 * algorithms that support them. 172 */ 173 ATTRIBUTE_WARN_UNUSED_RET static int random_split_ec_verify(const u8 *sig, u8 siglen, const ec_pub_key *pub_key, 174 const u8 *m, u32 mlen, 175 ec_alg_type sig_type, hash_alg_type hash_type, const u8 *adata, u16 adata_len) 176 { 177 int ret; 178 struct ec_verify_context ctx; 179 u32 consumed; 180 181 ret = local_memset(&ctx, 0, sizeof(ctx)); EG(ret, err); 182 183 ret = ec_verify_init(&ctx, pub_key, sig, siglen, sig_type, hash_type, adata, adata_len); 184 if (ret) { 185 goto err; 186 } 187 188 /* We randomly split the input message in chunks and proceed with updates */ 189 consumed = 0; 190 while(consumed < mlen){ 191 u32 toconsume = 0; 192 ret = get_random((u8 *)&toconsume, sizeof(toconsume)); 193 if (ret) { 194 ext_printf("Error when getting random\n"); 195 goto err; 196 } 197 toconsume = (toconsume % (mlen - consumed)); 198 if(((mlen - consumed) == 1) && (toconsume == 0)){ 199 toconsume = 1; 200 } 201 ret = ec_verify_update(&ctx, &m[consumed], toconsume); 202 if (ret) { 203 goto err; 204 } 205 consumed += toconsume; 206 } 207 208 ret = ec_verify_finalize(&ctx); 209 210 err: 211 return ret; 212 } 213 214 215 /* Reduce pressure on the stack for small targets 216 * by letting the user override this value. 217 */ 218 #ifndef MAX_MSG_LEN 219 #if WORDSIZE == 16 220 /* For wordsize 16 bits, avoid overflows */ 221 #define MAX_MSG_LEN 1024 222 #else 223 #define MAX_MSG_LEN 8192 224 #endif 225 #endif 226 #ifndef MAX_BATCH_SIG_SIZE 227 #define MAX_BATCH_SIG_SIZE 20 228 #endif 229 230 /* 231 * ECC generic self tests (sign/verify on random values 232 * with import/export) 233 */ 234 ATTRIBUTE_WARN_UNUSED_RET static int ec_import_export_test(const ec_test_case *c) 235 { 236 ec_key_pair kp; 237 ec_params params; 238 int ret, check; 239 240 MUST_HAVE(c != NULL, ret, err); 241 242 ret = local_memset(&kp, 0, sizeof(kp)); EG(ret, err); 243 ret = local_memset(¶ms, 0, sizeof(params)); EG(ret, err); 244 245 /* Import EC params from test case */ 246 ret = import_params(¶ms, c->ec_str_p); 247 if (ret) { 248 ext_printf("Error importing params\n"); 249 goto err; 250 } 251 252 /* Generate, import/export a key pair */ 253 ret = ec_gen_import_export_kp(&kp, ¶ms, c); 254 if (ret) { 255 ext_printf("Error at key pair generation/import/export\n"); 256 goto err; 257 } 258 259 /* Perform test */ 260 { 261 u16 msglen; 262 u8 siglen; 263 u8 msg[MAX_MSG_LEN]; 264 u8 sig[EC_MAX_SIGLEN]; 265 u8 check_type = 0; 266 u8 sig_tmp1[EC_MAX_SIGLEN]; 267 u8 sig_tmp2[EC_MAX_SIGLEN]; 268 FORCE_USED_VAR(check_type); 269 270 ret = ec_get_sig_len(¶ms, c->sig_type, c->hash_type, 271 (u8 *)&siglen); 272 if (ret) { 273 ext_printf("Error computing effective sig size\n"); 274 goto err; 275 } 276 277 /* Generate a random message to sign */ 278 ret = get_random((u8 *)&msglen, sizeof(msglen)); 279 if (ret) { 280 ext_printf("Error when getting random\n"); 281 goto err; 282 } 283 msglen = msglen % MAX_MSG_LEN; 284 ret = get_random(msg, msglen); 285 if (ret) { 286 ext_printf("Error when getting random\n"); 287 goto err; 288 } 289 290 ret = _ec_sign(sig, siglen, &kp, msg, msglen, 291 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); 292 if (ret) { 293 ext_printf("Error when signing\n"); 294 goto err; 295 } 296 ret = local_memset(sig_tmp1, 0, sizeof(sig_tmp1)); EG(ret, err); 297 ret = local_memset(sig_tmp2, 0, sizeof(sig_tmp2)); EG(ret, err); 298 /* If the algorithm supports streaming mode, test it against direct mode */ 299 ret = is_sign_streaming_mode_supported(c->sig_type, &check); EG(ret, err); 300 if(check){ 301 MUST_HAVE(siglen <= LOCAL_MAX(sizeof(sig_tmp1), sizeof(sig_tmp2)), ret, err); 302 ret = generic_ec_sign(sig_tmp1, siglen, &kp, msg, msglen, 303 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); 304 if(ret){ 305 ext_printf("Error when signing\n"); 306 ret = -1; 307 goto err; 308 } 309 ret = random_split_ec_sign(sig_tmp2, siglen, &kp, msg, msglen, 310 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); 311 if(ret){ 312 ext_printf("Error when signing\n"); 313 ret = -1; 314 goto err; 315 } 316 /* Verify signature equality only in case of deterministic signatures */ 317 ret = is_sign_deterministic(c->sig_type, &check); EG(ret, err); 318 if(check){ 319 ret = are_equal(sig, sig_tmp1, siglen, &check); EG(ret, err); 320 if(!check){ 321 ext_printf("Error when signing: streaming and non streaming modes results differ "\ 322 "for deterministic signature scheme!\n"); 323 ret = -1; 324 goto err; 325 } 326 ret = are_equal(sig, sig_tmp2, siglen, &check); EG(ret, err); 327 if(!check){ 328 ext_printf("Error when signing: streaming and non streaming modes results differ "\ 329 "for deterministic signature scheme!\n"); 330 ret = -1; 331 goto err; 332 } 333 } 334 } 335 336 ret = ec_verify(sig, siglen, &(kp.pub_key), msg, msglen, 337 c->sig_type, c->hash_type, c->adata, c->adata_len); 338 if (ret) { 339 ext_printf("Error when verifying signature\n"); 340 goto err; 341 } 342 /* If the algorithm supports streaming mode, test it against direct mode */ 343 ret = is_verify_streaming_mode_supported(c->sig_type, &check); EG(ret, err); 344 if(check){ 345 ret = is_sign_streaming_mode_supported(c->sig_type, &check); EG(ret, err); 346 if(check){ 347 ret = ec_verify(sig_tmp2, siglen, &(kp.pub_key), msg, msglen, 348 c->sig_type, c->hash_type, c->adata, c->adata_len); 349 } 350 else{ 351 ret = ec_verify(sig, siglen, &(kp.pub_key), msg, msglen, 352 c->sig_type, c->hash_type, c->adata, c->adata_len); 353 } 354 if (ret) { 355 ext_printf("Error when verifying signature ec_verify\n"); 356 goto err; 357 } 358 ret = is_sign_streaming_mode_supported(c->sig_type, &check); EG(ret, err); 359 if(check){ 360 ret = random_split_ec_verify(sig_tmp1, siglen, &(kp.pub_key), msg, msglen, 361 c->sig_type, c->hash_type, c->adata, c->adata_len); 362 } 363 else{ 364 ret = random_split_ec_verify(sig, siglen, &(kp.pub_key), msg, msglen, 365 c->sig_type, c->hash_type, c->adata, c->adata_len); 366 } 367 if (ret) { 368 ext_printf("Error when verifying signature random_split_ec_verify\n"); 369 goto err; 370 } 371 } 372 /* Also test the "single" signature batch verification */ 373 ret = is_verify_batch_mode_supported(c->sig_type, &check); EG(ret, err); 374 if(check){ 375 const u8 *signatures[] = { sig }; 376 const u8 signatures_len[] = { siglen }; 377 const u8 *messages[] = { msg }; 378 const u32 messages_len[] = { msglen }; 379 const ec_pub_key *pub_keys[] = { &(kp.pub_key) }; 380 const u8 *adatas[] = { c->adata }; 381 const u16 adatas_len[] = { c->adata_len }; 382 ret = ec_verify_batch(signatures, signatures_len, pub_keys, messages, messages_len, 383 1, c->sig_type, c->hash_type, adatas, adatas_len, NULL, NULL); 384 if(ret){ 385 ext_printf("Error when verifying signature ec_verify_batch with batch 1\n"); 386 goto err; 387 } 388 } 389 check_type = 0; 390 #if defined(WITH_SIG_ECDSA) 391 if(c->sig_type == ECDSA){ 392 check_type = 1; 393 } 394 #endif 395 #if defined(WITH_SIG_DECDSA) 396 if(c->sig_type == DECDSA){ 397 check_type = 1; 398 } 399 #endif 400 /* Try a public key recovery from the signature and the message. 401 * This is only possible for ECDSA. 402 */ 403 if(check_type){ 404 struct ec_sign_context sig_ctx; 405 u8 digest[MAX_DIGEST_SIZE] = { 0 }; 406 u8 digestlen; 407 ec_pub_key pub_key1; 408 ec_pub_key pub_key2; 409 nn_src_t cofactor = &(params.ec_gen_cofactor); 410 int cofactorisone; 411 const u8 *input[2] = { (const u8*)msg , NULL}; 412 u32 ilens[2] = { msglen , 0 }; 413 /* Initialize our signature context only for the hash */ 414 ret = ec_sign_init(&sig_ctx, &kp, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err); 415 /* Perform the hash of the data ourselves */ 416 ret = hash_mapping_callbacks_sanity_check(sig_ctx.h); EG(ret, err); 417 ret = sig_ctx.h->hfunc_scattered(input, ilens, digest); EG(ret, err); 418 digestlen = sig_ctx.h->digest_size; 419 MUST_HAVE(digestlen <= sizeof(digest), ret, err); 420 /* Check the cofactor */ 421 ret = nn_isone(cofactor, &cofactorisone); EG(ret, err); 422 /* Compute the two possible public keys */ 423 ret = __ecdsa_public_key_from_sig(&pub_key1, &pub_key2, ¶ms, sig, siglen, digest, digestlen, c->sig_type); 424 if(ret){ 425 ret = 0; 426 check = -1; 427 goto pubkey_recovery_warning; 428 } 429 /* Check equality with one of the two keys */ 430 ret = prj_pt_cmp(&(pub_key1.y), &(kp.pub_key.y), &check); EG(ret, err); 431 if(check){ 432 ret = prj_pt_cmp(&(pub_key2.y), &(kp.pub_key.y), &check); EG(ret, err); 433 } 434 pubkey_recovery_warning: 435 if(check && cofactorisone){ 436 OPENMP_LOCK(); 437 ext_printf("[~] Warning: ECDSA recovered public key differs from real one ..."); 438 ext_printf("This can happen with very low probability. Please check the trace:\n"); 439 pub_key_print("pub_key1", &pub_key1); 440 pub_key_print("pub_key2", &pub_key2); 441 pub_key_print("pub_key", &(kp.pub_key)); 442 buf_print("digest", digest, digestlen); 443 buf_print("sig", sig, siglen); 444 OPENMP_UNLOCK(); 445 } 446 } 447 #ifdef USE_CRYPTOFUZZ 448 check_type = 0; 449 /* Specific case where we have access to raw signature API */ 450 #if defined(WITH_SIG_ECDSA) 451 if(c->sig_type == ECDSA){ 452 check_type = 1; 453 } 454 #endif 455 #if defined(WITH_SIG_ECGDSA) 456 if(c->sig_type == ECGDSA){ 457 check_type = 1; 458 } 459 #endif 460 #if defined(WITH_SIG_ECRDSA) 461 if(c->sig_type == ECRDSA){ 462 check_type = 1; 463 } 464 #endif 465 if(check_type){ 466 struct ec_sign_context sig_ctx; 467 struct ec_verify_context verif_ctx; 468 u8 digest[MAX_DIGEST_SIZE] = { 0 }; 469 u8 digestlen; 470 const u8 *input[2] = { (const u8*)msg , NULL}; 471 u32 ilens[2] = { msglen , 0 }; 472 /* Initialize our signature context */ 473 ret = ec_sign_init(&sig_ctx, &kp, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err); 474 /* Perform the hash of the data ourselves */ 475 ret = hash_mapping_callbacks_sanity_check(sig_ctx.h); EG(ret, err); 476 ret = sig_ctx.h->hfunc_scattered(input, ilens, digest); EG(ret, err); 477 digestlen = sig_ctx.h->digest_size; 478 MUST_HAVE(digestlen <= sizeof(digest), ret, err); 479 /* Raw signing of data */ 480 #if defined(WITH_SIG_ECDSA) 481 if(c->sig_type == ECDSA){ 482 ret = ecdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, NULL, 0); EG(ret, err); 483 } 484 #endif 485 #if defined(WITH_SIG_ECGDSA) 486 if(c->sig_type == ECGDSA){ 487 ret = ecgdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, NULL, 0); EG(ret, err); 488 } 489 #endif 490 #if defined(WITH_SIG_ECRDSA) 491 if(c->sig_type == ECRDSA){ 492 ret = ecrdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, NULL, 0); EG(ret, err); 493 } 494 #endif 495 /* Now verify signature */ 496 ret = ec_verify_init(&verif_ctx, &(kp.pub_key), sig, siglen, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err); 497 #if defined(WITH_SIG_ECDSA) 498 if(c->sig_type == ECDSA){ 499 ret = ecdsa_verify_raw(&verif_ctx, digest, digestlen); EG(ret, err); 500 } 501 #endif 502 #if defined(WITH_SIG_ECGDSA) 503 if(c->sig_type == ECGDSA){ 504 ret = ecgdsa_verify_raw(&verif_ctx, digest, digestlen); EG(ret, err); 505 } 506 #endif 507 #if defined(WITH_SIG_ECRDSA) 508 if(c->sig_type == ECRDSA){ 509 ret = ecrdsa_verify_raw(&verif_ctx, digest, digestlen); EG(ret, err); 510 } 511 #endif 512 } 513 #endif 514 } 515 516 /* Perform test specific to batch verification */ 517 ret = is_verify_batch_mode_supported(c->sig_type, &check); EG(ret, err); 518 if(check){ 519 u16 msglen; 520 u8 siglen; 521 ec_key_pair keypairs[MAX_BATCH_SIG_SIZE]; 522 const ec_pub_key *pubkeys[MAX_BATCH_SIG_SIZE]; 523 u8 msg[MAX_BATCH_SIG_SIZE * MAX_MSG_LEN]; 524 const u8 *messages[MAX_BATCH_SIG_SIZE]; 525 u32 messages_len[MAX_BATCH_SIG_SIZE]; 526 u8 sig[MAX_BATCH_SIG_SIZE * EC_MAX_SIGLEN]; 527 const u8 *signatures[MAX_BATCH_SIG_SIZE]; 528 u8 signatures_len[MAX_BATCH_SIG_SIZE]; 529 const u8 *adata[MAX_BATCH_SIG_SIZE]; 530 u16 adata_len[MAX_BATCH_SIG_SIZE]; 531 u8 check_type = 0; 532 u32 num_batch, i, current; 533 534 FORCE_USED_VAR(check_type); 535 536 gen_num_batch: 537 ret = get_random((u8 *)&num_batch, sizeof(num_batch)); 538 if(ret){ 539 ext_printf("Error when getting random\n"); 540 goto err; 541 } 542 num_batch = (num_batch % MAX_BATCH_SIG_SIZE); 543 if(num_batch == 0){ 544 goto gen_num_batch; 545 } 546 547 ret = ec_get_sig_len(¶ms, c->sig_type, c->hash_type, 548 (u8 *)&siglen); 549 if (ret) { 550 ext_printf("Error computing effective sig size\n"); 551 goto err; 552 } 553 554 /* Generate random messages to sign */ 555 current = 0; 556 for(i = 0; i < num_batch; i++){ 557 /* Generate, import/export a key pair */ 558 ret = ec_gen_import_export_kp(&keypairs[i], ¶ms, c); 559 pubkeys[i] = &(keypairs[i].pub_key); 560 if (ret) { 561 ext_printf("Error at key pair generation/import/export\n"); 562 goto err; 563 } 564 ret = get_random((u8 *)&msglen, sizeof(msglen)); 565 if (ret) { 566 ext_printf("Error when getting random\n"); 567 goto err; 568 } 569 msglen = msglen % MAX_MSG_LEN; 570 messages_len[i] = msglen; 571 messages[i] = &msg[current]; 572 ret = get_random(&msg[current], msglen); 573 if (ret) { 574 ext_printf("Error when getting random\n"); 575 goto err; 576 } 577 current += msglen; 578 579 signatures[i] = &sig[i * siglen]; 580 signatures_len[i] = siglen; 581 adata_len[i] = c->adata_len; 582 adata[i] = c->adata; 583 ret = _ec_sign(&sig[i * siglen], siglen, &keypairs[i], messages[i], messages_len[i], 584 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); 585 if (ret) { 586 ext_printf("Error when signing\n"); 587 goto err; 588 } 589 } 590 /* Test */ 591 ret = ec_verify_batch(signatures, signatures_len, pubkeys, messages, messages_len, 592 num_batch, c->sig_type, c->hash_type, adata, adata_len, NULL, NULL); 593 if(ret){ 594 ext_printf("Error when verifying signature ec_verify_batch no memory for batch size %" PRIu32 "\n", num_batch); 595 goto err; 596 } 597 { 598 u32 scratch_pad_area_len = 0; 599 /* We need 2 * n + 1 scratch pad storage, compute this with max */ 600 verify_batch_scratch_pad scratch_pad_area[(2 * MAX_BATCH_SIG_SIZE) + 1]; 601 602 ret = ec_verify_batch(signatures, signatures_len, pubkeys, messages, messages_len, 603 num_batch, c->sig_type, c->hash_type, adata, adata_len, NULL, &scratch_pad_area_len); 604 if(ret){ 605 ext_printf("Error when getting scratch_pad_area length for ec_verify_batch optimized for batch size %" PRIu32 "\n", num_batch); 606 goto err; 607 } 608 MUST_HAVE((scratch_pad_area_len <= sizeof(scratch_pad_area)), ret, err); 609 610 scratch_pad_area_len = sizeof(scratch_pad_area); 611 ret = ec_verify_batch(signatures, signatures_len, pubkeys, messages, messages_len, 612 num_batch, c->sig_type, c->hash_type, adata, adata_len, scratch_pad_area, &scratch_pad_area_len); 613 if(ret){ 614 ext_printf("Error when verifying signature ec_verify_batch optimized for batch size %" PRIu32 "\n", num_batch); 615 goto err; 616 } 617 } 618 } 619 620 ret = 0; 621 622 err: 623 return ret; 624 } 625 626 /* 627 * Those functions respectively perform signature and verification tests 628 * based the content of a given test case. 629 */ 630 ATTRIBUTE_WARN_UNUSED_RET static int ec_test_sign(u8 *sig, u8 siglen, ec_key_pair *kp, 631 const ec_test_case *c) 632 { 633 /* If the algorithm supports streaming, we check that both the streaming and 634 * non streaming modes produce the same result. 635 */ 636 int ret, check; 637 638 MUST_HAVE(sig != NULL, ret, err); 639 MUST_HAVE(c != NULL, ret, err); 640 641 ret = _ec_sign(sig, siglen, kp, (const u8 *)(c->msg), c->msglen, 642 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err); 643 ret = is_sign_streaming_mode_supported(c->sig_type, &check); EG(ret, err); 644 if(check){ 645 u8 sig_tmp[EC_MAX_SIGLEN]; 646 MUST_HAVE(siglen <= sizeof(sig_tmp), ret, err); 647 ret = generic_ec_sign(sig_tmp, siglen, kp, (const u8 *)(c->msg), c->msglen, 648 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err); 649 ret = are_equal(sig, sig_tmp, siglen, &check); EG(ret, err); 650 if(!check){ 651 ret = -1; 652 goto err; 653 } 654 /* Now test the random split version */ 655 ret = random_split_ec_sign(sig_tmp, siglen, kp, (const u8 *)(c->msg), c->msglen, 656 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err); 657 ret = are_equal(sig, sig_tmp, siglen, &check); EG(ret, err); 658 if(!check){ 659 ret = -1; 660 goto err; 661 } 662 } 663 664 ret = 0; 665 err: 666 return ret; 667 } 668 669 ATTRIBUTE_WARN_UNUSED_RET static int ec_test_verify(u8 *sig, u8 siglen, const ec_pub_key *pub_key, 670 const ec_test_case *c) 671 { 672 /* If the algorithm supports streaming, we check that both the streaming and 673 * non streaming modes produce the same result. 674 */ 675 int ret, check; 676 677 MUST_HAVE(sig != NULL, ret, err); 678 MUST_HAVE(c != NULL, ret, err); 679 680 ret = ec_verify(sig, siglen, pub_key, (const u8 *)(c->msg), c->msglen, 681 c->sig_type, c->hash_type, c->adata, c->adata_len); 682 if(ret){ 683 ret = -1; 684 goto err; 685 } 686 ret = is_verify_streaming_mode_supported(c->sig_type, &check); EG(ret, err); 687 if(check){ 688 ret = ec_verify(sig, siglen, pub_key, (const u8 *)(c->msg), c->msglen, 689 c->sig_type, c->hash_type, c->adata, c->adata_len); 690 if(ret){ 691 ret = -1; 692 goto err; 693 } 694 /* Now test the random split version */ 695 ret = random_split_ec_verify(sig, siglen, pub_key, (const u8 *)(c->msg), c->msglen, 696 c->sig_type, c->hash_type, c->adata, c->adata_len); 697 if(ret){ 698 ret = -1; 699 goto err; 700 } 701 } 702 /* Also test the "single" signature batch verification */ 703 ret = is_verify_batch_mode_supported(c->sig_type, &check); EG(ret, err); 704 if(check){ 705 const u8 *signatures[] = { sig }; 706 const u8 signatures_len[] = { siglen }; 707 const u8 *messages[] = { (const u8*)c->msg }; 708 const u32 messages_len[] = { c->msglen }; 709 const ec_pub_key *pub_keys[] = { pub_key }; 710 const u8 *adatas[] = { c->adata }; 711 const u16 adatas_len[] = { c->adata_len }; 712 ret = ec_verify_batch(signatures, signatures_len, pub_keys, messages, messages_len, 713 1, c->sig_type, c->hash_type, adatas, adatas_len, NULL, NULL); 714 if(ret){ 715 ret = -1; 716 goto err; 717 } 718 } 719 720 ret = 0; 721 err: 722 return ret; 723 } 724 725 /* 726 * ECC generic self tests (sign/verify on known test vectors). Returns 727 * 0 if given test succeeded, or a non-zero value otherwise. In that 728 * case, the value encodes the information on what went wrong as 729 * described above. 730 */ 731 ATTRIBUTE_WARN_UNUSED_RET static int ec_sig_known_vector_tests_one(const ec_test_case *c) 732 { 733 test_err_kind failed_test = TEST_KEY_IMPORT_ERROR; 734 u8 sig[EC_MAX_SIGLEN]; 735 ec_params params; 736 ec_key_pair kp; 737 u8 siglen; 738 int ret; 739 int check = 0; 740 741 MUST_HAVE((c != NULL), ret, err); 742 743 ret = local_memset(&kp, 0, sizeof(kp)); EG(ret, err); 744 ret = local_memset(¶ms, 0, sizeof(params)); EG(ret, err); 745 ret = local_memset(sig, 0, sizeof(sig)); EG(ret, err); 746 747 ret = import_params(¶ms, c->ec_str_p); 748 if (ret) { 749 ext_printf("Error importing params\n"); 750 goto err; 751 } 752 753 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448) 754 /* In the specific case of EdDSA, we perform a specific key derivation */ 755 #if defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_EDDSA448) 756 if((c->sig_type == EDDSA25519) || (c->sig_type == EDDSA25519CTX) || (c->sig_type == EDDSA25519PH) || \ 757 (c->sig_type == EDDSA448) || (c->sig_type == EDDSA448PH)){ 758 #endif 759 #if defined(WITH_SIG_EDDSA25519) && !defined(WITH_SIG_EDDSA448) 760 if((c->sig_type == EDDSA25519) || (c->sig_type == EDDSA25519CTX) || (c->sig_type == EDDSA25519PH)){ 761 #endif 762 #if !defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_EDDSA448) 763 if((c->sig_type == EDDSA448) || (c->sig_type == EDDSA448PH)){ 764 #endif 765 /* Import the key pair using the EdDSA dedicated function */ 766 if(eddsa_import_key_pair_from_priv_key_buf(&kp, c->priv_key, c->priv_key_len, ¶ms, c->sig_type)){ 767 ret = -1; 768 failed_test = TEST_KEY_IMPORT_ERROR; 769 goto err; 770 } 771 } 772 else 773 #endif /* !(defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_EDDSA448)) */ 774 { 775 /* Regular import if not EdDSA */ 776 ret = ec_key_pair_import_from_priv_key_buf(&kp, ¶ms, c->priv_key, 777 c->priv_key_len, 778 c->sig_type); 779 if (ret) { 780 failed_test = TEST_KEY_IMPORT_ERROR; 781 goto err; 782 } 783 } 784 785 siglen = c->exp_siglen; 786 ret = ec_test_sign(sig, siglen, &kp, c); 787 if (ret) { 788 failed_test = TEST_SIG_ERROR; 789 goto err; 790 } 791 792 ret = are_equal(sig, c->exp_sig, siglen, &check); EG(ret, err); 793 if (!check) { 794 ret = -1; 795 failed_test = TEST_SIG_COMP_ERROR; 796 goto err; 797 } 798 799 ret = ec_test_verify(sig, siglen, &(kp.pub_key), c); 800 if (ret) { 801 failed_test = TEST_VERIF_ERROR; 802 goto err; 803 } 804 805 check = 0; 806 #if defined(WITH_SIG_ECDSA) 807 if(c->sig_type == ECDSA){ 808 check = 1; 809 } 810 #endif 811 #if defined(WITH_SIG_DECDSA) 812 if(c->sig_type == DECDSA){ 813 check = 1; 814 } 815 #endif 816 /* Try a public key recovery from the signature and the message. 817 * This is only possible for ECDSA. 818 */ 819 if(check){ 820 struct ec_sign_context sig_ctx; 821 u8 digest[MAX_DIGEST_SIZE] = { 0 }; 822 u8 digestlen; 823 ec_pub_key pub_key1; 824 ec_pub_key pub_key2; 825 nn_src_t cofactor = &(params.ec_gen_cofactor); 826 int cofactorisone; 827 const u8 *input[2] = { (const u8*)(c->msg) , NULL}; 828 u32 ilens[2] = { c->msglen , 0 }; 829 /* Initialize our signature context only for the hash */ 830 ret = ec_sign_init(&sig_ctx, &kp, c->sig_type, c->hash_type, c->adata, c->adata_len); EG(ret, err); 831 /* Perform the hash of the data ourselves */ 832 ret = hash_mapping_callbacks_sanity_check(sig_ctx.h); EG(ret, err); 833 ret = sig_ctx.h->hfunc_scattered(input, ilens, digest); EG(ret, err); 834 digestlen = sig_ctx.h->digest_size; 835 MUST_HAVE(digestlen <= sizeof(digest), ret, err); 836 /* Check the cofactor */ 837 ret = nn_isone(cofactor, &cofactorisone); EG(ret, err); 838 /* Compute the two possible public keys */ 839 ret = __ecdsa_public_key_from_sig(&pub_key1, &pub_key2, ¶ms, sig, siglen, digest, digestlen, c->sig_type); 840 if(ret){ 841 ret = 0; 842 check = -1; 843 goto pubkey_recovery_warning; 844 } 845 /* Check equality with one of the two keys */ 846 ret = prj_pt_cmp(&(pub_key1.y), &(kp.pub_key.y), &check); EG(ret, err); 847 if(check){ 848 ret = prj_pt_cmp(&(pub_key2.y), &(kp.pub_key.y), &check); EG(ret, err); 849 } 850 pubkey_recovery_warning: 851 if(check && cofactorisone){ 852 OPENMP_LOCK(); 853 ext_printf("[~] Warning: ECDSA recovered public key differs from real one ..."); 854 ext_printf("This can happen with very low probability. Please check the trace:\n"); 855 pub_key_print("pub_key1", &pub_key1); 856 pub_key_print("pub_key2", &pub_key2); 857 pub_key_print("pub_key", &(kp.pub_key)); 858 buf_print("digest", digest, digestlen); 859 buf_print("sig", sig, siglen); 860 OPENMP_UNLOCK(); 861 } 862 } 863 #ifdef USE_CRYPTOFUZZ 864 check = 0; 865 /* Specific case where we have access to raw signature API */ 866 #if defined(WITH_SIG_ECDSA) 867 if(c->sig_type == ECDSA){ 868 check = 1; 869 } 870 #endif 871 #if defined(WITH_SIG_ECGDSA) 872 if(c->sig_type == ECGDSA){ 873 check = 1; 874 } 875 #endif 876 #if defined(WITH_SIG_ECRDSA) 877 if(c->sig_type == ECRDSA){ 878 check = 1; 879 } 880 #endif 881 /* Specific case where we have access to raw signature API */ 882 if(check){ 883 struct ec_sign_context sig_ctx; 884 struct ec_verify_context verif_ctx; 885 u8 digest[MAX_DIGEST_SIZE] = { 0 }; 886 u8 digestlen; 887 const u8 *input[2] = { (const u8*)(c->msg) , NULL}; 888 u32 ilens[2] = { c->msglen , 0 }; 889 u8 nonce[LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8))] = { 0 }; 890 nn n_nonce; 891 bitcnt_t q_bit_len; 892 u8 noncelen; 893 /* Initialize our signature context */ 894 if(ec_sign_init(&sig_ctx, &kp, c->sig_type, c->hash_type, c->adata, c->adata_len)){ 895 ret = -1; 896 failed_test = TEST_SIG_ERROR; 897 goto err; 898 } 899 /* Perform the hash of the data ourselves */ 900 if(hash_mapping_callbacks_sanity_check(sig_ctx.h)){ 901 ret = -1; 902 failed_test = TEST_SIG_ERROR; 903 goto err; 904 } 905 ret = sig_ctx.h->hfunc_scattered(input, ilens, digest); EG(ret, err); 906 digestlen = sig_ctx.h->digest_size; 907 MUST_HAVE(digestlen <= sizeof(digest), ret, err); 908 /* Import the fixed nonce */ 909 q_bit_len = kp.priv_key.params->ec_gen_order_bitlen; 910 if(c->nn_random(&n_nonce, &(kp.priv_key.params->ec_gen_order))){ 911 ret = -1; 912 failed_test = TEST_SIG_ERROR; 913 goto err; 914 } 915 ret = nn_export_to_buf(nonce, (u16)BYTECEIL(q_bit_len), &n_nonce); EG(ret, err); 916 if((unsigned int)BYTECEIL(q_bit_len) > sizeof(nonce)){ 917 ret = -1; 918 failed_test = TEST_SIG_ERROR; 919 goto err; 920 } 921 noncelen = (u8)(BYTECEIL(q_bit_len)); 922 /* Force used variable to avoid warnings */ 923 FORCE_USED_VAR(noncelen); 924 /* NOTE: the MUST_HAVE is protected by a preprocessing check 925 * to avoid -Werror=type-limits errors: 926 * "error: comparison is always true due to limited range of data type" 927 */ 928 #if LOCAL_MIN(255, BIT_LEN_WORDS(NN_MAX_BIT_LEN) * (WORDSIZE / 8)) < 255 929 MUST_HAVE((u32)noncelen <= sizeof(nonce), ret, err); 930 #endif 931 /* Raw signing of data */ 932 #if defined(WITH_SIG_ECDSA) 933 if(c->sig_type == ECDSA){ 934 if(ecdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, nonce, noncelen)){ 935 ret = -1; 936 failed_test = TEST_SIG_ERROR; 937 goto err; 938 } 939 } 940 #endif 941 #if defined(WITH_SIG_ECGDSA) 942 if(c->sig_type == ECGDSA){ 943 if(ecgdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, nonce, noncelen)){ 944 ret = -1; 945 failed_test = TEST_SIG_ERROR; 946 goto err; 947 } 948 } 949 #endif 950 #if defined(WITH_SIG_ECRDSA) 951 if(c->sig_type == ECRDSA){ 952 if(ecrdsa_sign_raw(&sig_ctx, digest, digestlen, sig, siglen, nonce, noncelen)){ 953 ret = -1; 954 failed_test = TEST_SIG_ERROR; 955 goto err; 956 } 957 } 958 #endif 959 /* Check computed signature against expected one */ 960 ret = are_equal(sig, c->exp_sig, siglen, &check); EG(ret, err); 961 if (!check) { 962 failed_test = TEST_SIG_COMP_ERROR; 963 ret = -1; 964 goto err; 965 } 966 /* Now verify signature */ 967 if(ec_verify_init(&verif_ctx, &(kp.pub_key), sig, siglen, c->sig_type, c->hash_type, c->adata, c->adata_len)){ 968 ret = -1; 969 failed_test = TEST_VERIF_ERROR; 970 goto err; 971 } 972 /* Raw verification of data */ 973 #if defined(WITH_SIG_ECDSA) 974 if(c->sig_type == ECDSA){ 975 if(ecdsa_verify_raw(&verif_ctx, digest, digestlen)){ 976 ret = -1; 977 failed_test = TEST_VERIF_ERROR; 978 goto err; 979 } 980 } 981 #endif 982 #if defined(WITH_SIG_ECGDSA) 983 if(c->sig_type == ECGDSA){ 984 if(ecgdsa_verify_raw(&verif_ctx, digest, digestlen)){ 985 ret = -1; 986 failed_test = TEST_VERIF_ERROR; 987 goto err; 988 } 989 } 990 #endif 991 #if defined(WITH_SIG_ECRDSA) 992 if(c->sig_type == ECRDSA){ 993 if(ecrdsa_verify_raw(&verif_ctx, digest, digestlen)){ 994 ret = -1; 995 failed_test = TEST_VERIF_ERROR; 996 goto err; 997 } 998 } 999 #endif 1000 } 1001 #endif 1002 ret = 0; 1003 1004 err: 1005 if (ret) { 1006 u32 ret_; 1007 ret = encode_error_value(c, failed_test, &ret_); EG(ret, err); 1008 ret = (int)ret_; 1009 } 1010 1011 return ret; 1012 } 1013 1014 #if defined(WITH_ECCCDH) || defined(WITH_X25519) || defined(WITH_X448) 1015 /* 1016 * ECC generic self tests (ecdh on known test vectors). Returns 1017 * 0 if given test succeeded, or a non-zero value otherwise. In that 1018 * case, the value encodes the information on what went wrong as 1019 * described above. 1020 */ 1021 ATTRIBUTE_WARN_UNUSED_RET static int ecdh_known_vector_tests_one(const ecdh_test_case *c) 1022 { 1023 test_err_kind failed_test = TEST_KEY_IMPORT_ERROR; 1024 ec_params params; 1025 ec_key_pair kp; 1026 int ret, check; 1027 1028 MUST_HAVE((c != NULL), ret, err); 1029 1030 ret = local_memset(&kp, 0, sizeof(kp)); EG(ret, err); 1031 ret = local_memset(¶ms, 0, sizeof(params)); EG(ret, err); 1032 1033 ret = import_params(¶ms, c->ec_str_p); 1034 if (ret) { 1035 ext_printf("Error importing params\n"); 1036 goto err; 1037 } 1038 1039 /* Check what ECDH test we have to perform */ 1040 switch(c->ecdh_type){ 1041 #if defined(WITH_ECCCDH) 1042 case ECCCDH:{ 1043 u8 serialized_pub_key[EC_PUB_KEY_MAX_SIZE]; 1044 u8 serialized_pub_key_len; 1045 /* This maximum size is way bigger than expected, but we ensure 1046 * that there is enough room for our shared secret. 1047 */ 1048 u8 shared_secret[EC_PUB_KEY_MAX_SIZE]; 1049 u8 shared_secret_len; 1050 1051 ret = local_memset(serialized_pub_key, 0, sizeof(serialized_pub_key)); EG(ret, err); 1052 ret = local_memset(shared_secret, 0, sizeof(shared_secret)); EG(ret, err); 1053 1054 /* Import our ECDH key pair */ 1055 ret = ecccdh_import_key_pair_from_priv_key_buf(&kp, ¶ms, c->our_priv_key, 1056 c->our_priv_key_len); 1057 if (ret) { 1058 failed_test = TEST_KEY_IMPORT_ERROR; 1059 ret = -1; 1060 goto err; 1061 } 1062 /* Serialize our public key */ 1063 ret = ecccdh_serialized_pub_key_size(¶ms, &serialized_pub_key_len); EG(ret, err); 1064 MUST_HAVE((sizeof(serialized_pub_key) >= serialized_pub_key_len), ret, err); 1065 ret = ecccdh_serialize_pub_key(&(kp.pub_key), serialized_pub_key, serialized_pub_key_len); 1066 if (ret) { 1067 failed_test = TEST_ECDH_ERROR; 1068 ret = -1; 1069 goto err; 1070 } 1071 /* Check it against the expected one */ 1072 MUST_HAVE((serialized_pub_key_len == c->exp_our_pub_key_len), ret, err); 1073 ret = are_equal(serialized_pub_key, c->exp_our_pub_key, serialized_pub_key_len, &check); EG(ret, err); 1074 if (!check) { 1075 failed_test = TEST_ECDH_COMP_ERROR; 1076 ret = -1; 1077 goto err; 1078 } 1079 /* Now derive the shared secret */ 1080 ret = ecccdh_shared_secret_size(¶ms, &shared_secret_len); EG(ret, err); 1081 MUST_HAVE((sizeof(shared_secret) >= shared_secret_len), ret, err); 1082 ret = ecccdh_derive_secret(&(kp.priv_key), c->peer_pub_key, c->peer_pub_key_len, shared_secret, shared_secret_len); 1083 if (ret) { 1084 failed_test = TEST_ECDH_ERROR; 1085 ret = -1; 1086 goto err; 1087 } 1088 /* Check it against the expected one */ 1089 MUST_HAVE((shared_secret_len == c->exp_shared_secret_len), ret, err); 1090 ret = are_equal(shared_secret, c->exp_shared_secret, shared_secret_len, &check); EG(ret, err); 1091 if (!check) { 1092 failed_test = TEST_ECDH_COMP_ERROR; 1093 ret = -1; 1094 goto err; 1095 } 1096 1097 break; 1098 } 1099 #endif 1100 #if defined(WITH_X25519) 1101 case X25519:{ 1102 u8 pub_key[X25519_SIZE]; 1103 u8 shared_secret[X25519_SIZE]; 1104 1105 ret = local_memset(pub_key, 0, sizeof(pub_key)); EG(ret, err); 1106 ret = local_memset(shared_secret, 0, sizeof(shared_secret)); EG(ret, err); 1107 1108 /* Compute our public key */ 1109 MUST_HAVE((c->our_priv_key_len == X25519_SIZE), ret, err); 1110 ret = x25519_init_pub_key(c->our_priv_key, pub_key); 1111 if (ret) { 1112 failed_test = TEST_KEY_IMPORT_ERROR; 1113 ret = -1; 1114 goto err; 1115 } 1116 /* Check it against the expected one */ 1117 MUST_HAVE((c->exp_our_pub_key_len == X25519_SIZE), ret, err); 1118 ret = are_equal(pub_key, c->exp_our_pub_key, X25519_SIZE, &check); EG(ret, err); 1119 if (!check) { 1120 failed_test = TEST_ECDH_COMP_ERROR; 1121 ret = -1; 1122 goto err; 1123 } 1124 /* Now derive the shared secret */ 1125 MUST_HAVE((c->peer_pub_key_len == X25519_SIZE), ret, err); 1126 ret = x25519_derive_secret(c->our_priv_key, c->peer_pub_key, shared_secret); 1127 if (ret) { 1128 failed_test = TEST_ECDH_ERROR; 1129 ret = -1; 1130 goto err; 1131 } 1132 /* Check it against the expected one */ 1133 MUST_HAVE((c->exp_shared_secret_len == X25519_SIZE), ret, err); 1134 ret = are_equal(shared_secret, c->exp_shared_secret, X25519_SIZE, &check); EG(ret, err); 1135 if (!check) { 1136 failed_test = TEST_ECDH_COMP_ERROR; 1137 ret = -1; 1138 goto err; 1139 } 1140 1141 break; 1142 } 1143 #endif 1144 #if defined(WITH_X448) 1145 case X448:{ 1146 u8 pub_key[X448_SIZE]; 1147 u8 shared_secret[X448_SIZE]; 1148 1149 ret = local_memset(pub_key, 0, sizeof(pub_key)); EG(ret, err); 1150 ret = local_memset(shared_secret, 0, sizeof(shared_secret)); EG(ret, err); 1151 1152 /* Compute our public key */ 1153 MUST_HAVE((c->our_priv_key_len == X448_SIZE), ret, err); 1154 ret = x448_init_pub_key(c->our_priv_key, pub_key); 1155 if (ret) { 1156 failed_test = TEST_KEY_IMPORT_ERROR; 1157 ret = -1; 1158 goto err; 1159 } 1160 /* Check it against the expected one */ 1161 MUST_HAVE((c->exp_our_pub_key_len == X448_SIZE), ret, err); 1162 ret = are_equal(pub_key, c->exp_our_pub_key, X448_SIZE, &check); EG(ret, err); 1163 if (!check) { 1164 failed_test = TEST_ECDH_COMP_ERROR; 1165 ret = -1; 1166 goto err; 1167 } 1168 /* Now derive the shared secret */ 1169 MUST_HAVE((c->peer_pub_key_len == X448_SIZE), ret, err); 1170 ret = x448_derive_secret(c->our_priv_key, c->peer_pub_key, shared_secret); 1171 if (ret) { 1172 failed_test = TEST_ECDH_ERROR; 1173 ret = -1; 1174 goto err; 1175 } 1176 /* Check it against the expected one */ 1177 MUST_HAVE((c->exp_shared_secret_len == X448_SIZE), ret, err); 1178 ret = are_equal(shared_secret, c->exp_shared_secret, X448_SIZE, &check); EG(ret, err); 1179 if (!check) { 1180 failed_test = TEST_ECDH_COMP_ERROR; 1181 ret = -1; 1182 goto err; 1183 } 1184 1185 break; 1186 } 1187 #endif 1188 default:{ 1189 ext_printf("Error: not an ECDH test\n"); 1190 ret = -1; 1191 goto err; 1192 } 1193 } 1194 1195 err: 1196 if (ret) { 1197 u32 ret_; 1198 ret = ecdh_encode_error_value(c, failed_test, &ret_); EG(ret, err); 1199 ret = (int)ret_; 1200 } 1201 1202 return ret; 1203 } 1204 #endif 1205 1206 ATTRIBUTE_WARN_UNUSED_RET int perform_known_test_vectors_test(const char *sig, const char *hash, const char *curve) 1207 { 1208 unsigned int i; 1209 int ret = 0; 1210 1211 ext_printf("======= Known test vectors test =================\n"); 1212 #ifdef WITH_OPENMP_SELF_TESTS 1213 #pragma omp parallel 1214 #pragma omp for schedule(static, 1) nowait 1215 #endif 1216 for (i = 0; i < EC_FIXED_VECTOR_NUM_TESTS; i++) { 1217 int check; 1218 const ec_test_case *cur_test; 1219 cur_test = ec_fixed_vector_tests[i]; 1220 if(cur_test == NULL){ 1221 continue; 1222 } 1223 /* If this is a dummy test case, skip it! */ 1224 if(cur_test->sig_type == UNKNOWN_ALG){ 1225 continue; 1226 } 1227 /* Filter out */ 1228 if(sig != NULL){ 1229 const ec_sig_mapping *sig_map; 1230 ret = get_sig_by_type(cur_test->sig_type, &sig_map); OPENMP_EG(ret, err); 1231 if(sig_map == NULL){ 1232 continue; 1233 } 1234 ret = are_str_equal(sig_map->name, sig, &check); OPENMP_EG(ret, err); 1235 if(!check){ 1236 continue; 1237 } 1238 } 1239 if(hash != NULL){ 1240 const hash_mapping *hash_map; 1241 ret = get_hash_by_type(cur_test->hash_type, &hash_map); OPENMP_EG(ret, err); 1242 if(hash_map == NULL){ 1243 continue; 1244 } 1245 ret = are_str_equal(hash_map->name, hash, &check); OPENMP_EG(ret, err); 1246 if(!check){ 1247 continue; 1248 } 1249 } 1250 if(curve != NULL){ 1251 if(cur_test->ec_str_p == NULL){ 1252 continue; 1253 } 1254 ret = are_str_equal((const char*)cur_test->ec_str_p->name->buf, curve, &check); OPENMP_EG(ret, err); 1255 if(!check){ 1256 continue; 1257 } 1258 } 1259 ret = ec_sig_known_vector_tests_one(cur_test); 1260 OPENMP_LOCK(); 1261 ext_printf("[%s] %30s selftests: known test vectors " 1262 "sig/verif %s\n", ret ? "-" : "+", 1263 cur_test->name, ret ? "failed" : "ok"); 1264 check = 0; 1265 #if defined(WITH_SIG_ECDSA) 1266 if(cur_test->sig_type == ECDSA){ 1267 check = 1; 1268 } 1269 #endif 1270 #if defined(WITH_SIG_DECDSA) 1271 if(cur_test->sig_type == DECDSA){ 1272 check = 1; 1273 } 1274 #endif 1275 if(check){ 1276 ext_printf("\t(ECDSA public key recovery also checked!)\n"); 1277 } 1278 #ifdef USE_CRYPTOFUZZ 1279 #if defined(WITH_SIG_ECDSA) 1280 if(cur_test->sig_type == ECDSA){ 1281 ext_printf("\t(RAW ECDSA for CRYPTOFUZZ also checked!)\n"); 1282 } 1283 #endif 1284 #if defined(WITH_SIG_ECGDSA) 1285 if(cur_test->sig_type == ECGDSA){ 1286 ext_printf("\t(RAW ECGDSA for CRYPTOFUZZ also checked!)\n"); 1287 } 1288 #endif 1289 #if defined(WITH_SIG_ECRDSA) 1290 if(cur_test->sig_type == ECRDSA){ 1291 ext_printf("\t(RAW ECRDSA for CRYPTOFUZZ also checked!)\n"); 1292 } 1293 #endif 1294 #endif 1295 OPENMP_UNLOCK(); 1296 OPENMP_EG(ret, err); 1297 } 1298 #if defined(WITH_ECCCDH) || defined(WITH_X25519) || defined(WITH_X448) 1299 /* Now take care of ECDH */ 1300 if((sig == NULL) && (hash == NULL)){ 1301 #ifdef WITH_OPENMP_SELF_TESTS 1302 #pragma omp parallel 1303 #pragma omp for schedule(static, 1) nowait 1304 #endif 1305 for (i = 0; i < ECDH_FIXED_VECTOR_NUM_TESTS; i++) { 1306 int check; 1307 const ecdh_test_case *ecdh_cur_test; 1308 ecdh_cur_test = ecdh_fixed_vector_tests[i]; 1309 if(ecdh_cur_test == NULL){ 1310 continue; 1311 } 1312 /* If this is not an ECDH test case, skip it! */ 1313 if(ecdh_cur_test->ecdh_type == UNKNOWN_ALG){ 1314 continue; 1315 } 1316 if(curve != NULL){ 1317 if(ecdh_cur_test->ec_str_p == NULL){ 1318 continue; 1319 } 1320 ret = are_str_equal((const char*)ecdh_cur_test->ec_str_p->name->buf, curve, &check); OPENMP_EG(ret, err); 1321 if(!check){ 1322 continue; 1323 } 1324 } 1325 ret = ecdh_known_vector_tests_one(ecdh_cur_test); 1326 OPENMP_LOCK(); 1327 ext_printf("[%s] %30s selftests: known test vectors " 1328 "ecdh %s\n", ret ? "-" : "+", 1329 ecdh_cur_test->name, ret ? "failed" : "ok"); 1330 OPENMP_EG(ret, err); 1331 OPENMP_UNLOCK(); 1332 } 1333 } 1334 #endif 1335 1336 #ifndef WITH_OPENMP_SELF_TESTS 1337 err: 1338 #endif 1339 return ret; 1340 } 1341 1342 ATTRIBUTE_WARN_UNUSED_RET static int rand_sig_verif_test_one(const ec_sig_mapping *sig, 1343 const hash_mapping *hash, 1344 const ec_mapping *ec) 1345 { 1346 char test_name[MAX_CURVE_NAME_LEN + MAX_HASH_ALG_NAME_LEN + 1347 MAX_SIG_ALG_NAME_LEN + 2]; 1348 const unsigned int tn_size = sizeof(test_name) - 1; /* w/o trailing 0 */ 1349 const char *crv_name; 1350 ec_test_case t; 1351 int ret, check; 1352 u32 len; 1353 1354 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_SM2) || defined(WITH_SIG_BIGN) || defined(WITH_SIG_DBIGN) 1355 u8 rand_adata[255]; 1356 ret = local_memset(rand_adata, 0, sizeof(rand_adata)); EG(ret, err); 1357 /* The case of EDDSA25519CTX and SM2 needs a non NULL context (ancillary data). 1358 * Create a random string of size <= 255 for this. 1359 */ 1360 /* 1361 * In the case of BIGN and DBIGN, the ancillary data have a structure containing the OID as well 1362 * as an optional generation token. 1363 */ 1364 #endif 1365 ret = local_memset(test_name, 0, sizeof(test_name)); EG(ret, err); 1366 1367 MUST_HAVE((sig != NULL), ret, err); 1368 MUST_HAVE((hash != NULL), ret, err); 1369 MUST_HAVE((ec != NULL), ret, err); 1370 1371 crv_name = (const char *)PARAM_BUF_PTR((ec->params)->name); 1372 1373 /* Generate the test name */ 1374 ret = local_memset(test_name, 0, tn_size + 1); EG(ret, err); 1375 ret = local_strncpy(test_name, sig->name, tn_size); EG(ret, err); 1376 ret = local_strlen(test_name, &len); EG(ret, err); 1377 ret = local_strncat(test_name, "-", tn_size - len); EG(ret, err); 1378 ret = local_strlen(test_name, &len); EG(ret, err); 1379 ret = local_strncat(test_name, hash->name, tn_size - len); EG(ret, err); 1380 ret = local_strlen(test_name, &len); EG(ret, err); 1381 ret = local_strncat(test_name, "/", tn_size - len); EG(ret, err); 1382 ret = local_strlen(test_name, &len); EG(ret, err); 1383 ret = local_strncat(test_name, crv_name, tn_size - len); EG(ret, err); 1384 1385 /* Create a test */ 1386 t.name = test_name; 1387 t.ec_str_p = ec->params; 1388 t.priv_key = NULL; 1389 t.priv_key_len = 0; 1390 t.nn_random = NULL; 1391 t.hash_type = hash->type; 1392 t.msg = NULL; 1393 t.msglen = 0; 1394 t.sig_type = sig->type; 1395 t.exp_sig = NULL; 1396 t.exp_siglen = 0; 1397 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_SM2) 1398 #if defined(WITH_SIG_EDDSA25519) && !defined(WITH_SIG_SM2) 1399 if(sig->type == EDDSA25519CTX) 1400 #endif 1401 #if !defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_SM2) 1402 if(sig->type == SM2) 1403 #endif 1404 #if defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_SM2) 1405 if((sig->type == EDDSA25519CTX) || (sig->type == SM2)) 1406 #endif 1407 { 1408 u8 rand_len = 0; 1409 ret = get_random((u8 *)&rand_len, sizeof(rand_len)); EG(ret, err); 1410 ret = get_random((u8 *)rand_adata, (u16)(rand_len % sizeof(rand_adata))); EG(ret, err); 1411 t.adata = rand_adata; 1412 t.adata_len = rand_len; 1413 } 1414 else 1415 #endif 1416 { 1417 #if defined(WITH_SIG_BIGN) || defined(WITH_SIG_DBIGN) 1418 #if defined(WITH_SIG_BIGN) && !defined(WITH_SIG_DBIGN) 1419 if(sig->type == BIGN) 1420 #endif 1421 #if !defined(WITH_SIG_BIGN) && defined(WITH_SIG_DBIGN) 1422 if(sig->type == DBIGN) 1423 #endif 1424 #if defined(WITH_SIG_BIGN) && defined(WITH_SIG_DBIGN) 1425 if((sig->type == BIGN) || (sig->type == DBIGN)) 1426 #endif 1427 { 1428 u16 oid_len = 0; 1429 u16 t_len = 0; 1430 ret = get_random((u8 *)rand_adata, sizeof(rand_adata)); EG(ret, err); 1431 1432 ret = get_random((u8 *)&oid_len, sizeof(oid_len)); EG(ret, err); 1433 ret = get_random((u8 *)&t_len, sizeof(oid_len)); EG(ret, err); 1434 1435 oid_len = (u8)(oid_len % (sizeof(rand_adata) - 4)); 1436 t_len = (u8)(t_len % (sizeof(rand_adata) - 4 - oid_len)); 1437 rand_adata[0] = (u8)(oid_len >> 8); 1438 rand_adata[1] = (u8)(oid_len & 0xff); 1439 rand_adata[2] = (u8)(t_len >> 8); 1440 rand_adata[3] = (u8)(t_len & 0xff); 1441 t.adata = rand_adata; 1442 t.adata_len = (u8)(oid_len + t_len + 4); 1443 } 1444 else 1445 #endif 1446 { 1447 t.adata = NULL; 1448 t.adata_len = 0; 1449 } 1450 } 1451 1452 /* Execute the test */ 1453 ret = ec_import_export_test(&t); 1454 OPENMP_LOCK(); 1455 ext_printf("[%s] %34s randtests: random import/export " 1456 "with sig/verif %s\n", ret ? "-" : "+", t.name, 1457 ret ? "failed" : "ok"); 1458 check = 0; 1459 #if defined(WITH_SIG_ECDSA) 1460 if(t.sig_type == ECDSA){ 1461 check = 1; 1462 } 1463 #endif 1464 #if defined(WITH_SIG_DECDSA) 1465 if(t.sig_type == DECDSA){ 1466 check = 1; 1467 } 1468 #endif 1469 if(check){ 1470 ext_printf("\t(ECDSA public key recovery also checked!)\n"); 1471 } 1472 1473 #ifdef USE_CRYPTOFUZZ 1474 #if defined(WITH_SIG_ECDSA) 1475 if(t.sig_type == ECDSA){ 1476 ext_printf("\t(RAW ECDSA for CRYPTOFUZZ also checked!)\n"); 1477 } 1478 #endif 1479 #if defined(WITH_SIG_ECGDSA) 1480 if(t.sig_type == ECGDSA){ 1481 ext_printf("\t(RAW ECGDSA for CRYPTOFUZZ also checked!)\n"); 1482 } 1483 #endif 1484 #if defined(WITH_SIG_ECRDSA) 1485 if(t.sig_type == ECRDSA){ 1486 ext_printf("\t(RAW ECRDSA for CRYPTOFUZZ also checked!)\n"); 1487 } 1488 #endif 1489 #endif 1490 OPENMP_UNLOCK(); 1491 1492 err: 1493 return ret; 1494 } 1495 1496 ATTRIBUTE_WARN_UNUSED_RET int perform_random_sig_verif_test(const char *sig, const char *hash, const char *curve) 1497 { 1498 unsigned int num_sig_maps, num_hash_maps; 1499 int ret = 0; 1500 1501 /* Compute number of sig and hash maps */ 1502 for (num_sig_maps = 0; ec_sig_maps[num_sig_maps].type != UNKNOWN_ALG; num_sig_maps++) {} 1503 for (num_hash_maps = 0; hash_maps[num_hash_maps].type != UNKNOWN_HASH_ALG; num_hash_maps++) {} 1504 1505 /* 1506 * Perform basic sign/verify tests on all the cipher suites 1507 * (combination of sign algo/hash function/curve) 1508 */ 1509 ext_printf("======= Random sig/verif test ===================\n"); 1510 for (unsigned int i = 0; i < num_sig_maps; i++) { 1511 #ifdef WITH_OPENMP_SELF_TESTS 1512 #pragma omp parallel for collapse(2) 1513 #endif 1514 for (unsigned int j = 0; j < num_hash_maps; j++) { 1515 for (unsigned int k = 0; k < EC_CURVES_NUM; k++) { 1516 int check; 1517 if(sig != NULL){ 1518 ret = are_str_equal(ec_sig_maps[i].name, sig, &check); OPENMP_EG(ret, err); 1519 if(!check){ 1520 continue; 1521 } 1522 } 1523 if(hash != NULL){ 1524 ret = are_str_equal(hash_maps[j].name, hash, &check); OPENMP_EG(ret, err); 1525 if(!check){ 1526 continue; 1527 } 1528 } 1529 if(curve != NULL){ 1530 ret = are_str_equal((const char*)ec_maps[k].params->name->buf, curve, &check); OPENMP_EG(ret, err); 1531 if(!check){ 1532 continue; 1533 } 1534 } 1535 /* If we have EDDSA25519 or EDDSA448, we only accept specific hash functions. 1536 * Skip the other tests. 1537 */ 1538 #ifdef WITH_SIG_EDDSA25519 1539 if((ec_sig_maps[i].type == EDDSA25519) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){ 1540 continue; 1541 } 1542 if((ec_sig_maps[i].type == EDDSA25519CTX) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){ 1543 continue; 1544 } 1545 if((ec_sig_maps[i].type == EDDSA25519PH) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){ 1546 continue; 1547 } 1548 #endif 1549 #ifdef WITH_SIG_EDDSA448 1550 if((ec_sig_maps[i].type == EDDSA448) && ((hash_maps[j].type != SHAKE256) || (ec_maps[k].type != WEI448))){ 1551 continue; 1552 } 1553 if((ec_sig_maps[i].type == EDDSA448PH) && ((hash_maps[j].type != SHAKE256) || (ec_maps[k].type != WEI448))){ 1554 continue; 1555 } 1556 #endif 1557 ret = rand_sig_verif_test_one(&ec_sig_maps[i], 1558 &hash_maps[j], 1559 &ec_maps[k]); 1560 OPENMP_EG(ret, err); 1561 } 1562 } 1563 } 1564 1565 #ifndef WITH_OPENMP_SELF_TESTS 1566 err: 1567 #endif 1568 return ret; 1569 } 1570 1571 #define PERF_NUM_OP 300 1572 #define PERF_BATCH_VERIFICATION 16 1573 1574 /* 1575 * ECC generic performance test: Returns the number of signatures 1576 * and verifications per second 1577 */ 1578 ATTRIBUTE_WARN_UNUSED_RET static int ec_performance_test(const ec_test_case *c, 1579 unsigned int *n_perf_sign, 1580 unsigned int *n_perf_verif, 1581 unsigned int *n_perf_batch_verif, 1582 unsigned char *batch_verify_ok) 1583 { 1584 ec_key_pair kp; 1585 ec_params params; 1586 int ret, check; 1587 1588 MUST_HAVE(c != NULL, ret, err); 1589 MUST_HAVE(n_perf_sign != NULL, ret, err); 1590 MUST_HAVE(n_perf_verif != NULL, ret, err); 1591 MUST_HAVE((n_perf_batch_verif != NULL) && (batch_verify_ok != NULL), ret, err); 1592 1593 ret = local_memset(&kp, 0, sizeof(kp)); EG(ret, err); 1594 1595 /* Import EC params from test case */ 1596 ret = import_params(¶ms, c->ec_str_p); 1597 if (ret) { 1598 ext_printf("Error when importing parameters\n"); 1599 goto err; 1600 } 1601 1602 /* Generate, import/export a key pair */ 1603 ret = ec_gen_import_export_kp(&kp, ¶ms, c); 1604 if (ret) { 1605 ext_printf("Error at key pair generation/import/export\n"); 1606 goto err; 1607 } 1608 1609 /* Perform test */ 1610 { 1611 u8 sig[EC_MAX_SIGLEN]; 1612 u8 siglen; 1613 u8 msg[MAX_BLOCK_SIZE]; 1614 u16 msglen; 1615 u8 hash_digest_size, hash_block_size; 1616 /* Time related variables */ 1617 u64 time1, time2, cumulated_time_sign, cumulated_time_verify, cumulated_time_batch_verify; 1618 unsigned int i; 1619 1620 ret = local_memset(sig, 0, sizeof(sig)); EG(ret, err); 1621 ret = local_memset(msg, 0, sizeof(msg)); EG(ret, err); 1622 1623 ret = ec_get_sig_len(¶ms, c->sig_type, c->hash_type, 1624 (u8 *)&siglen); 1625 if (ret) { 1626 ext_printf("Error computing effective sig size\n"); 1627 goto err; 1628 } 1629 1630 /* 1631 * Random tests to measure performance: We do it on small 1632 * messages to "absorb" the hash function cost 1633 */ 1634 ret = get_hash_sizes(c->hash_type, &hash_digest_size, 1635 &hash_block_size); 1636 if (ret) { 1637 ext_printf("Error when getting hash size\n"); 1638 goto err; 1639 } 1640 cumulated_time_sign = cumulated_time_verify = cumulated_time_batch_verify = 0; 1641 for (i = 0; i < PERF_NUM_OP; i++) { 1642 /* Generate a random message to sign */ 1643 ret = get_random((u8 *)&msglen, sizeof(msglen)); 1644 if (ret) { 1645 ext_printf("Error when getting random\n"); 1646 goto err; 1647 } 1648 msglen = (u16)(msglen % hash_block_size); 1649 ret = get_random(msg, msglen); 1650 if (ret) { 1651 ext_printf("Error when getting random\n"); 1652 goto err; 1653 } 1654 1655 /***** Signature **********/ 1656 ret = get_ms_time(&time1); 1657 if (ret) { 1658 ext_printf("Error when getting time\n"); 1659 goto err; 1660 } 1661 ret = _ec_sign(sig, siglen, &kp, msg, msglen, 1662 c->nn_random, c->sig_type, c->hash_type, c->adata, c->adata_len); 1663 if (ret) { 1664 ext_printf("Error when signing\n"); 1665 goto err; 1666 } 1667 ret = get_ms_time(&time2); 1668 if (ret) { 1669 ext_printf("Error when getting time\n"); 1670 goto err; 1671 } 1672 if (time2 < time1) { 1673 ext_printf("Error: time error (t2 < t1)\n"); 1674 goto err; 1675 } 1676 cumulated_time_sign += (time2 - time1); 1677 1678 /***** Verification **********/ 1679 ret = get_ms_time(&time1); 1680 if (ret) { 1681 ext_printf("Error when getting time\n"); 1682 goto err; 1683 } 1684 ret = ec_verify(sig, siglen, &(kp.pub_key), msg, msglen, 1685 c->sig_type, c->hash_type, c->adata, c->adata_len); 1686 if (ret) { 1687 ext_printf("Error when verifying signature\n"); 1688 goto err; 1689 } 1690 ret = get_ms_time(&time2); 1691 if (ret) { 1692 ext_printf("Error when getting time\n"); 1693 goto err; 1694 } 1695 if (time2 < time1) { 1696 ext_printf("Error: time error (time2 < time1)\n"); 1697 goto err; 1698 } 1699 cumulated_time_verify += (time2 - time1); 1700 1701 /***** Batch verification **********/ 1702 ret = is_verify_batch_mode_supported(c->sig_type, &check); EG(ret, err); 1703 if(check){ 1704 unsigned int j; 1705 const u8 *signatures[PERF_BATCH_VERIFICATION]; 1706 u8 signatures_len[PERF_BATCH_VERIFICATION]; 1707 const u8 *messages[PERF_BATCH_VERIFICATION]; 1708 u32 messages_len[PERF_BATCH_VERIFICATION]; 1709 const ec_pub_key *pub_keys[PERF_BATCH_VERIFICATION]; 1710 const u8 *adatas[PERF_BATCH_VERIFICATION]; 1711 u16 adatas_len[PERF_BATCH_VERIFICATION]; 1712 /* We need 2 * n + 1 scratch pad storage, compute this with max */ 1713 verify_batch_scratch_pad scratch_pad_area[(2 * PERF_BATCH_VERIFICATION) + 1]; 1714 u32 scratch_pad_area_len = sizeof(scratch_pad_area); 1715 1716 for(j = 0; j < PERF_BATCH_VERIFICATION; j++){ 1717 signatures[j] = sig; 1718 signatures_len[j] = siglen; 1719 messages[j] = msg; 1720 messages_len[j] = msglen; 1721 pub_keys[j] = &(kp.pub_key); 1722 adatas[j] = c->adata; 1723 adatas_len[j] = c->adata_len; 1724 } 1725 ret = get_ms_time(&time1); 1726 if (ret) { 1727 ext_printf("Error when getting time\n"); 1728 goto err; 1729 } 1730 ret = ec_verify_batch(signatures, signatures_len, pub_keys, messages, messages_len, 1731 PERF_BATCH_VERIFICATION, c->sig_type, c->hash_type, adatas, adatas_len, scratch_pad_area, &scratch_pad_area_len); 1732 if(ret){ 1733 ext_printf("Error when verifying signature ec_verify_batch with batch %d\n", PERF_BATCH_VERIFICATION); 1734 goto err; 1735 } 1736 ret = get_ms_time(&time2); 1737 if (ret) { 1738 ext_printf("Error when getting time\n"); 1739 goto err; 1740 } 1741 if (time2 < time1) { 1742 ext_printf("Error: time error (time2 < time1)\n"); 1743 goto err; 1744 } 1745 cumulated_time_batch_verify += (time2 - time1); 1746 (*batch_verify_ok) = 1; 1747 } 1748 else{ 1749 (*batch_verify_ok) = 0; 1750 } 1751 } 1752 1753 if (n_perf_sign != NULL) { 1754 (*n_perf_sign) = (unsigned int)((PERF_NUM_OP * 1000ULL) / cumulated_time_sign); 1755 } 1756 if (n_perf_verif != NULL) { 1757 (*n_perf_verif) = (unsigned int)((PERF_NUM_OP * 1000ULL) / cumulated_time_verify); 1758 } 1759 if (n_perf_batch_verif != NULL) { 1760 if((*batch_verify_ok) == 1){ 1761 (*n_perf_batch_verif) = (unsigned int)((PERF_NUM_OP * PERF_BATCH_VERIFICATION * 1000ULL) / cumulated_time_batch_verify); 1762 } 1763 else{ 1764 (*n_perf_batch_verif) = 0; 1765 } 1766 } 1767 } 1768 ret = 0; 1769 err: 1770 return ret; 1771 } 1772 1773 1774 ATTRIBUTE_WARN_UNUSED_RET static int perf_test_one(const ec_sig_mapping *sig, const hash_mapping *hash, 1775 const ec_mapping *ec) 1776 { 1777 char test_name[MAX_CURVE_NAME_LEN + MAX_HASH_ALG_NAME_LEN + 1778 MAX_SIG_ALG_NAME_LEN + 2]; 1779 const unsigned int tn_size = sizeof(test_name) - 1; /* w/o trailing 0 */ 1780 unsigned int n_perf_sign = 0, n_perf_verif = 0, n_perf_batch_verif = 0; 1781 unsigned char batch_verify_ok = 0; 1782 const char *crv_name; 1783 ec_test_case t; 1784 int ret; 1785 u32 len; 1786 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_SM2) || defined(WITH_SIG_BIGN) || defined(WITH_SIG_DBIGN) 1787 u8 rand_adata[255]; 1788 ret = local_memset(rand_adata, 0, sizeof(rand_adata)); EG(ret, err); 1789 /* The case of EDDSA25519CTX and SM2 needs a non NULL context (ancillary data). 1790 * Create a random string of size <= 255 for this. 1791 */ 1792 /* 1793 * In the case of BIGN and DBIGN, the ancillary data have a structure containing the OID as well 1794 * as an optional generation token. 1795 */ 1796 #endif 1797 MUST_HAVE((sig != NULL), ret, err); 1798 MUST_HAVE((hash != NULL), ret, err); 1799 MUST_HAVE((ec != NULL), ret, err); 1800 1801 ret = local_memset(test_name, 0, sizeof(test_name)); EG(ret, err); 1802 1803 crv_name = (const char *)PARAM_BUF_PTR((ec->params)->name); 1804 1805 /* Generate the test name */ 1806 ret = local_memset(test_name, 0, tn_size + 1); EG(ret, err); 1807 ret = local_strncpy(test_name, sig->name, tn_size); EG(ret, err); 1808 ret = local_strlen(test_name, &len); EG(ret, err); 1809 ret = local_strncat(test_name, "-", tn_size - len); EG(ret, err); 1810 ret = local_strlen(test_name, &len); EG(ret, err); 1811 ret = local_strncat(test_name, hash->name, tn_size - len); EG(ret, err); 1812 ret = local_strlen(test_name, &len); EG(ret, err); 1813 ret = local_strncat(test_name, "/", tn_size - len); EG(ret, err); 1814 ret = local_strlen(test_name, &len); EG(ret, err); 1815 ret = local_strncat(test_name, crv_name, tn_size - len); EG(ret, err); 1816 1817 /* Create a test */ 1818 t.name = test_name; 1819 t.ec_str_p = ec->params; 1820 t.priv_key = NULL; 1821 t.priv_key_len = 0; 1822 t.nn_random = NULL; 1823 t.hash_type = hash->type; 1824 t.msg = NULL; 1825 t.msglen = 0; 1826 t.sig_type = sig->type; 1827 t.exp_sig = NULL; 1828 t.exp_siglen = 0; 1829 #if defined(WITH_SIG_EDDSA25519) || defined(WITH_SIG_SM2) 1830 #if defined(WITH_SIG_EDDSA25519) && !defined(WITH_SIG_SM2) 1831 if(sig->type == EDDSA25519CTX) 1832 #endif 1833 #if !defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_SM2) 1834 if(sig->type == SM2) 1835 #endif 1836 #if defined(WITH_SIG_EDDSA25519) && defined(WITH_SIG_SM2) 1837 if((sig->type == EDDSA25519CTX) || (sig->type == SM2)) 1838 #endif 1839 { 1840 u8 rand_len = 0; 1841 ret = get_random((u8 *)&rand_len, sizeof(rand_len)); EG(ret, err); 1842 ret = get_random((u8 *)rand_adata, (u16)(rand_len % sizeof(rand_adata))); EG(ret, err); 1843 t.adata = rand_adata; 1844 t.adata_len = rand_len; 1845 } 1846 else 1847 #endif 1848 { 1849 #if defined(WITH_SIG_BIGN) || defined(WITH_SIG_DBIGN) 1850 #if defined(WITH_SIG_BIGN) && !defined(WITH_SIG_DBIGN) 1851 if(sig->type == BIGN) 1852 #endif 1853 #if !defined(WITH_SIG_BIGN) && defined(WITH_SIG_DBIGN) 1854 if(sig->type == DBIGN) 1855 #endif 1856 #if defined(WITH_SIG_BIGN) && defined(WITH_SIG_DBIGN) 1857 if((sig->type == BIGN) || (sig->type == DBIGN)) 1858 #endif 1859 { 1860 u16 oid_len = 0; 1861 u16 t_len = 0; 1862 ret = get_random((u8 *)rand_adata, sizeof(rand_adata)); EG(ret, err); 1863 1864 ret = get_random((u8 *)&oid_len, sizeof(oid_len)); EG(ret, err); 1865 ret = get_random((u8 *)&t_len, sizeof(oid_len)); EG(ret, err); 1866 1867 oid_len = (u8)(oid_len % (sizeof(rand_adata) - 4)); 1868 t_len = (u8)(t_len % (sizeof(rand_adata) - 4 - oid_len)); 1869 rand_adata[0] = (u8)(oid_len >> 8); 1870 rand_adata[1] = (u8)(oid_len & 0xff); 1871 rand_adata[2] = (u8)(t_len >> 8); 1872 rand_adata[3] = (u8)(t_len & 0xff); 1873 t.adata = rand_adata; 1874 t.adata_len = (u8)(oid_len + t_len + 4); 1875 } 1876 else 1877 #endif 1878 { 1879 t.adata = NULL; 1880 t.adata_len = 0; 1881 } 1882 } 1883 1884 /* Sign and verify some random data during some time */ 1885 ret = ec_performance_test(&t, &n_perf_sign, &n_perf_verif, &n_perf_batch_verif, &batch_verify_ok); 1886 OPENMP_LOCK(); 1887 if(batch_verify_ok == 1){ 1888 ext_printf("[%s] %30s perf: %u sign/s and %u verif/s, %u batch verif/s (for %u batch)\n", 1889 ret ? "-" : "+", t.name, n_perf_sign, n_perf_verif, n_perf_batch_verif, (unsigned int)PERF_BATCH_VERIFICATION); 1890 if ((n_perf_sign == 0) || (n_perf_verif == 0) || (n_perf_batch_verif == 0)) { 1891 ext_printf("\t(0 is less than one sig/verif per sec)\n"); 1892 } 1893 } 1894 else{ 1895 ext_printf("[%s] %30s perf: %u sign/s and %u verif/s\n", 1896 ret ? "-" : "+", t.name, n_perf_sign, n_perf_verif); 1897 if ((n_perf_sign == 0) || (n_perf_verif == 0)) { 1898 ext_printf("\t(0 is less than one sig/verif per sec)\n"); 1899 } 1900 } 1901 OPENMP_UNLOCK(); 1902 1903 err: 1904 return ret; 1905 } 1906 1907 ATTRIBUTE_WARN_UNUSED_RET int perform_performance_test(const char *sig, const char *hash, const char *curve) 1908 { 1909 unsigned int i, j, k; 1910 int ret, check; 1911 1912 /* Perform performance tests like "openssl speed" command */ 1913 ext_printf("======= Performance test ========================\n"); 1914 #ifdef WITH_OPENMP_SELF_TESTS 1915 ext_printf("== NOTE: OpenMP parallelization is not applied to performance tests ...\n"); 1916 ext_printf("== (because of CPU/cores shared ressources such as caches, BPU, etc.)\n"); 1917 #endif 1918 for (i = 0; ec_sig_maps[i].type != UNKNOWN_ALG; i++) { 1919 for (j = 0; hash_maps[j].type != UNKNOWN_HASH_ALG; j++) { 1920 for (k = 0; k < EC_CURVES_NUM; k++) { 1921 if(sig != NULL){ 1922 ret = are_str_equal(ec_sig_maps[i].name, sig, &check); OPENMP_EG(ret, err); 1923 if(!check){ 1924 continue; 1925 } 1926 } 1927 if(hash != NULL){ 1928 ret = are_str_equal(hash_maps[j].name, hash, &check); OPENMP_EG(ret, err); 1929 if(!check){ 1930 continue; 1931 } 1932 } 1933 if(curve != NULL){ 1934 ret = are_str_equal((const char*)ec_maps[k].params->name->buf, curve, &check); OPENMP_EG(ret, err); 1935 if(!check){ 1936 continue; 1937 } 1938 } 1939 /* If we have EDDSA25519 or EDDSA448, we only accept specific hash functions. 1940 * Skip the other tests. 1941 */ 1942 #ifdef WITH_SIG_EDDSA25519 1943 if((ec_sig_maps[i].type == EDDSA25519) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){ 1944 continue; 1945 } 1946 if((ec_sig_maps[i].type == EDDSA25519CTX) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){ 1947 continue; 1948 } 1949 if((ec_sig_maps[i].type == EDDSA25519PH) && ((hash_maps[j].type != SHA512) || (ec_maps[k].type != WEI25519))){ 1950 continue; 1951 } 1952 #endif 1953 #ifdef WITH_SIG_EDDSA448 1954 if((ec_sig_maps[i].type == EDDSA448) && ((hash_maps[j].type != SHAKE256) || (ec_maps[k].type != WEI448))){ 1955 continue; 1956 } 1957 if((ec_sig_maps[i].type == EDDSA448PH) && ((hash_maps[j].type != SHAKE256) || (ec_maps[k].type != WEI448))){ 1958 continue; 1959 } 1960 #endif 1961 ret = perf_test_one(&ec_sig_maps[i], 1962 &hash_maps[j], 1963 &ec_maps[k]); 1964 if (ret) { 1965 goto err; 1966 } 1967 } 1968 } 1969 } 1970 1971 return 0; 1972 1973 err: 1974 return -1; 1975 } 1976