ec.c (22738B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifdef FREEBL_NO_DEPEND 6 #include "stubs.h" 7 #endif 8 9 #include "blapi.h" 10 #include "blapii.h" 11 #include "prerr.h" 12 #include "secerr.h" 13 #include "secmpi.h" 14 #include "secitem.h" 15 #include "mplogic.h" 16 #include "ec.h" 17 #include "ecl.h" 18 #include "verified/Hacl_P384.h" 19 #include "verified/Hacl_P521.h" 20 #include "secport.h" 21 #include "verified/Hacl_Ed25519.h" 22 23 #define EC_DOUBLECHECK PR_FALSE 24 25 SECStatus 26 ec_ED25519_pt_validate(const SECItem *px) 27 { 28 if (!px || !px->data || px->len != Ed25519_PUBLIC_KEYLEN) { 29 PORT_SetError(SEC_ERROR_INVALID_ARGS); 30 return SECFailure; 31 } 32 return SECSuccess; 33 } 34 35 SECStatus 36 ec_ED25519_scalar_validate(const SECItem *scalar) 37 { 38 if (!scalar || !scalar->data || scalar->len != Ed25519_PRIVATE_KEYLEN) { 39 PORT_SetError(SEC_ERROR_INVALID_ARGS); 40 return SECFailure; 41 } 42 43 return SECSuccess; 44 } 45 46 static const ECMethod kMethods[] = { 47 { ECCurve25519, 48 ec_Curve25519_pt_mul, 49 ec_Curve25519_pt_validate, 50 ec_Curve25519_scalar_validate, 51 NULL, 52 NULL }, 53 { 54 ECCurve_NIST_P256, 55 ec_secp256r1_pt_mul, 56 ec_secp256r1_pt_validate, 57 ec_secp256r1_scalar_validate, 58 ec_secp256r1_sign_digest, 59 ec_secp256r1_verify_digest, 60 }, 61 { 62 ECCurve_NIST_P384, 63 ec_secp384r1_pt_mul, 64 ec_secp384r1_pt_validate, 65 ec_secp384r1_scalar_validate, 66 ec_secp384r1_sign_digest, 67 ec_secp384r1_verify_digest, 68 }, 69 { 70 ECCurve_NIST_P521, 71 ec_secp521r1_pt_mul, 72 ec_secp521r1_pt_validate, 73 ec_secp521r1_scalar_validate, 74 ec_secp521r1_sign_digest, 75 ec_secp521r1_verify_digest, 76 }, 77 { ECCurve_Ed25519, 78 NULL, 79 ec_ED25519_pt_validate, 80 ec_ED25519_scalar_validate, 81 NULL, 82 NULL }, 83 }; 84 85 static const ECMethod * 86 ec_get_method_from_name(ECCurveName name) 87 { 88 unsigned long i; 89 for (i = 0; i < sizeof(kMethods) / sizeof(kMethods[0]); ++i) { 90 if (kMethods[i].name == name) { 91 return &kMethods[i]; 92 } 93 } 94 return NULL; 95 } 96 97 /* Generates a new EC key pair. The private key is a supplied 98 * value and the public key is the result of performing a scalar 99 * point multiplication of that value with the curve's base point. 100 */ 101 SECStatus 102 ec_NewKey(ECParams *ecParams, ECPrivateKey **privKey, 103 const unsigned char *privKeyBytes, int privKeyLen) 104 { 105 SECStatus rv = SECFailure; 106 PLArenaPool *arena; 107 ECPrivateKey *key; 108 int len; 109 110 if (!ecParams || ecParams->name == ECCurve_noName || 111 !privKey || !privKeyBytes || privKeyLen <= 0) { 112 PORT_SetError(SEC_ERROR_INVALID_ARGS); 113 return SECFailure; 114 } 115 116 if (ecParams->fieldID.type != ec_field_plain) { 117 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 118 return SECFailure; 119 } 120 121 /* Initialize an arena for the EC key. */ 122 if (!(arena = PORT_NewArena(NSS_FREEBL_DEFAULT_CHUNKSIZE))) 123 return SECFailure; 124 125 key = (ECPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(ECPrivateKey)); 126 if (!key) { 127 goto cleanup; 128 } 129 130 /* Set the version number (SEC 1 section C.4 says it should be 1) */ 131 SECITEM_AllocItem(arena, &key->version, 1); 132 key->version.data[0] = 1; 133 134 /* Copy all of the fields from the ECParams argument to the 135 * ECParams structure within the private key. 136 */ 137 key->ecParams.arena = arena; 138 key->ecParams.type = ecParams->type; 139 key->ecParams.fieldID.size = ecParams->fieldID.size; 140 key->ecParams.fieldID.type = ecParams->fieldID.type; 141 CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.fieldID.u.prime, 142 &ecParams->fieldID.u.prime)); 143 key->ecParams.fieldID.k1 = ecParams->fieldID.k1; 144 key->ecParams.fieldID.k2 = ecParams->fieldID.k2; 145 key->ecParams.fieldID.k3 = ecParams->fieldID.k3; 146 CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.a, 147 &ecParams->curve.a)); 148 CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.b, 149 &ecParams->curve.b)); 150 CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curve.seed, 151 &ecParams->curve.seed)); 152 CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.base, 153 &ecParams->base)); 154 CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.order, 155 &ecParams->order)); 156 key->ecParams.cofactor = ecParams->cofactor; 157 CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.DEREncoding, 158 &ecParams->DEREncoding)); 159 key->ecParams.name = ecParams->name; 160 CHECK_SEC_OK(SECITEM_CopyItem(arena, &key->ecParams.curveOID, 161 &ecParams->curveOID)); 162 163 SECITEM_AllocItem(arena, &key->publicValue, EC_GetPointSize(ecParams)); 164 len = ecParams->order.len; 165 SECITEM_AllocItem(arena, &key->privateValue, len); 166 167 /* Copy private key */ 168 if (privKeyLen >= len) { 169 memcpy(key->privateValue.data, privKeyBytes, len); 170 } else { 171 memset(key->privateValue.data, 0, (len - privKeyLen)); 172 memcpy(key->privateValue.data + (len - privKeyLen), privKeyBytes, privKeyLen); 173 } 174 175 /* Compute corresponding public key */ 176 177 /* Use curve specific code for point multiplication */ 178 if (ecParams->name == ECCurve_Ed25519) { 179 CHECK_SEC_OK(ED_DerivePublicKey(&key->privateValue, &key->publicValue)); 180 } else { 181 const ECMethod *method = ec_get_method_from_name(ecParams->name); 182 if (method == NULL || method->pt_mul == NULL) { 183 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 184 rv = SECFailure; 185 goto cleanup; 186 } 187 CHECK_SEC_OK(method->pt_mul(&key->publicValue, &key->privateValue, NULL)); 188 } 189 190 NSS_DECLASSIFY(key->publicValue.data, key->publicValue.len); /* Declassifying public key to avoid false positive */ 191 *privKey = key; 192 return SECSuccess; 193 194 cleanup: 195 PORT_FreeArena(arena, PR_TRUE); 196 return rv; 197 } 198 199 /* Generates a new EC key pair. The private key is a supplied 200 * random value (in seed) and the public key is the result of 201 * performing a scalar point multiplication of that value with 202 * the curve's base point. 203 */ 204 SECStatus 205 EC_NewKeyFromSeed(ECParams *ecParams, ECPrivateKey **privKey, 206 const unsigned char *seed, int seedlen) 207 { 208 return ec_NewKey(ecParams, privKey, seed, seedlen); 209 } 210 211 /* Generate a random private key using the algorithm A.4.1 or A.4.2 of ANSI X9.62, 212 * modified a la FIPS 186-2 Change Notice 1 to eliminate the bias in the 213 * random number generator. 214 */ 215 216 SECStatus 217 ec_GenerateRandomPrivateKey(ECParams *ecParams, SECItem *privKey) 218 { 219 SECStatus rv = SECFailure; 220 221 unsigned int len = EC_GetScalarSize(ecParams); 222 223 if (privKey->len != len || privKey->data == NULL) { 224 PORT_SetError(SEC_ERROR_INVALID_ARGS); 225 return SECFailure; 226 } 227 228 const ECMethod *method = ec_get_method_from_name(ecParams->name); 229 if (method == NULL || method->scalar_validate == NULL) { 230 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 231 return SECFailure; 232 } 233 234 uint8_t leading_coeff_mask; 235 switch (ecParams->name) { 236 case ECCurve_Ed25519: 237 case ECCurve25519: 238 case ECCurve_NIST_P256: 239 case ECCurve_NIST_P384: 240 leading_coeff_mask = 0xff; 241 break; 242 case ECCurve_NIST_P521: 243 leading_coeff_mask = 0x01; 244 break; 245 default: 246 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 247 return SECFailure; 248 } 249 250 /* The rejection sampling method from FIPS 186-5 A.4.2 */ 251 int count = 100; 252 do { 253 rv = RNG_GenerateGlobalRandomBytes(privKey->data, len); 254 if (rv != SECSuccess) { 255 PORT_SetError(SEC_ERROR_NEED_RANDOM); 256 return SECFailure; 257 } 258 privKey->data[0] &= leading_coeff_mask; 259 NSS_CLASSIFY(privKey->data, privKey->len); 260 rv = method->scalar_validate(privKey); 261 } while (rv != SECSuccess && --count > 0); 262 263 if (rv != SECSuccess) { // implies count == 0 264 PORT_SetError(SEC_ERROR_BAD_KEY); 265 } 266 267 return rv; 268 } 269 270 /* Generates a new EC key pair. The private key is a random value and 271 * the public key is the result of performing a scalar point multiplication 272 * of that value with the curve's base point. 273 */ 274 SECStatus 275 EC_NewKey(ECParams *ecParams, ECPrivateKey **privKey) 276 { 277 SECStatus rv = SECFailure; 278 SECItem privKeyRand = { siBuffer, NULL, 0 }; 279 280 if (!ecParams || ecParams->name == ECCurve_noName || !privKey) { 281 PORT_SetError(SEC_ERROR_INVALID_ARGS); 282 return SECFailure; 283 } 284 285 SECITEM_AllocItem(NULL, &privKeyRand, EC_GetScalarSize(ecParams)); 286 if (privKeyRand.data == NULL) { 287 PORT_SetError(SEC_ERROR_NO_MEMORY); 288 rv = SECFailure; 289 goto cleanup; 290 } 291 rv = ec_GenerateRandomPrivateKey(ecParams, &privKeyRand); 292 if (rv != SECSuccess || privKeyRand.data == NULL) { 293 goto cleanup; 294 } 295 /* generate public key */ 296 CHECK_SEC_OK(ec_NewKey(ecParams, privKey, privKeyRand.data, privKeyRand.len)); 297 298 cleanup: 299 if (privKeyRand.data) { 300 SECITEM_ZfreeItem(&privKeyRand, PR_FALSE); 301 } 302 #if EC_DEBUG 303 printf("EC_NewKey returning %s\n", 304 (rv == SECSuccess) ? "success" : "failure"); 305 #endif 306 307 return rv; 308 } 309 310 /* Validates an EC public key as described in Section 5.2.2 of 311 * X9.62. The ECDH primitive when used without the cofactor does 312 * not address small subgroup attacks, which may occur when the 313 * public key is not valid. These attacks can be prevented by 314 * validating the public key before using ECDH. 315 */ 316 SECStatus 317 EC_ValidatePublicKey(ECParams *ecParams, SECItem *publicValue) 318 { 319 if (!ecParams || ecParams->name == ECCurve_noName || 320 !publicValue || !publicValue->len) { 321 PORT_SetError(SEC_ERROR_INVALID_ARGS); 322 return SECFailure; 323 } 324 325 /* Uses curve specific code for point validation. */ 326 if (ecParams->fieldID.type != ec_field_plain) { 327 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 328 return SECFailure; 329 } 330 331 const ECMethod *method = ec_get_method_from_name(ecParams->name); 332 if (method == NULL || method->pt_validate == NULL) { 333 /* unknown curve */ 334 PORT_SetError(SEC_ERROR_INVALID_ARGS); 335 return SECFailure; 336 } 337 338 SECStatus rv = method->pt_validate(publicValue); 339 if (rv != SECSuccess) { 340 PORT_SetError(SEC_ERROR_BAD_KEY); 341 } 342 return rv; 343 } 344 345 /* 346 ** Performs an ECDH key derivation by computing the scalar point 347 ** multiplication of privateValue and publicValue (with or without the 348 ** cofactor) and returns the x-coordinate of the resulting elliptic 349 ** curve point in derived secret. If successful, derivedSecret->data 350 ** is set to the address of the newly allocated buffer containing the 351 ** derived secret, and derivedSecret->len is the size of the secret 352 ** produced. It is the caller's responsibility to free the allocated 353 ** buffer containing the derived secret. 354 */ 355 SECStatus 356 ECDH_Derive(SECItem *publicValue, 357 ECParams *ecParams, 358 SECItem *privateValue, 359 PRBool withCofactor, 360 SECItem *derivedSecret) 361 { 362 if (!publicValue || !publicValue->len || 363 !ecParams || ecParams->name == ECCurve_noName || 364 !privateValue || !privateValue->len || !derivedSecret) { 365 PORT_SetError(SEC_ERROR_INVALID_ARGS); 366 return SECFailure; 367 } 368 369 /* 370 * Make sure the point is on the requested curve to avoid 371 * certain small subgroup attacks. 372 */ 373 if (EC_ValidatePublicKey(ecParams, publicValue) != SECSuccess) { 374 PORT_SetError(SEC_ERROR_BAD_KEY); 375 return SECFailure; 376 } 377 378 /* Perform curve specific multiplication using ECMethod */ 379 if (ecParams->fieldID.type != ec_field_plain) { 380 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 381 return SECFailure; 382 } 383 384 const ECMethod *method = ec_get_method_from_name(ecParams->name); 385 if (method == NULL || method->pt_validate == NULL || 386 method->pt_mul == NULL) { 387 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 388 return SECFailure; 389 } 390 391 memset(derivedSecret, 0, sizeof(*derivedSecret)); 392 derivedSecret = SECITEM_AllocItem(NULL, derivedSecret, EC_GetScalarSize(ecParams)); 393 if (derivedSecret == NULL) { 394 PORT_SetError(SEC_ERROR_NO_MEMORY); 395 return SECFailure; 396 } 397 398 SECStatus rv = method->pt_mul(derivedSecret, privateValue, publicValue); 399 if (rv != SECSuccess) { 400 PORT_SetError(SEC_ERROR_BAD_KEY); 401 SECITEM_ZfreeItem(derivedSecret, PR_FALSE); 402 } 403 return rv; 404 } 405 406 /* Computes the ECDSA signature (a concatenation of two values r and s) 407 * on the digest using the given key and the random value kb (used in 408 * computing s). 409 */ 410 411 static SECStatus 412 ec_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, 413 const SECItem *digest, const unsigned char *kb, const int kblen) 414 { 415 ECParams *ecParams = NULL; 416 unsigned olen; /* length in bytes of the base point order */ 417 418 /* Check args */ 419 if (!key || !signature || !digest || !kb || (kblen <= 0)) { 420 PORT_SetError(SEC_ERROR_INVALID_ARGS); 421 return SECFailure; 422 } 423 424 ecParams = &(key->ecParams); 425 olen = ecParams->order.len; 426 if (signature->data == NULL) { 427 /* a call to get the signature length only */ 428 signature->len = 2 * olen; 429 return SECSuccess; 430 } 431 if (signature->len < 2 * olen) { 432 PORT_SetError(SEC_ERROR_OUTPUT_LEN); 433 return SECFailure; 434 } 435 436 /* Perform curve specific signature using ECMethod */ 437 if (ecParams->fieldID.type != ec_field_plain) { 438 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 439 return SECFailure; 440 } 441 442 const ECMethod *method = ec_get_method_from_name(ecParams->name); 443 if (method == NULL || method->sign_digest == NULL) { 444 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 445 return SECFailure; 446 } 447 448 SECStatus rv = method->sign_digest(key, signature, digest, kb, kblen); 449 if (rv != SECSuccess) { 450 PORT_SetError(SEC_ERROR_INVALID_ARGS); 451 } 452 453 #if EC_DEBUG 454 printf("ECDSA signing with seed %s\n", 455 (rv == SECSuccess) ? "succeeded" : "failed"); 456 #endif 457 return rv; 458 } 459 460 SECStatus 461 ECDSA_SignDigestWithSeed(ECPrivateKey *key, SECItem *signature, 462 const SECItem *digest, const unsigned char *kb, const int kblen) 463 { 464 #if EC_DEBUG || EC_DOUBLECHECK 465 SECItem *signature2 = SECITEM_AllocItem(NULL, NULL, signature->len); 466 SECStatus signSuccess = ec_SignDigestWithSeed(key, signature, digest, kb, kblen); 467 SECStatus signSuccessDouble = ec_SignDigestWithSeed(key, signature2, digest, kb, kblen); 468 int signaturesEqual = NSS_SecureMemcmp(signature->data, signature2->data, signature->len); 469 SECStatus rv; 470 471 if ((signaturesEqual == 0) && (signSuccess == SECSuccess) && (signSuccessDouble == SECSuccess)) { 472 rv = SECSuccess; 473 } else { 474 rv = SECFailure; 475 } 476 477 #if EC_DEBUG 478 printf("ECDSA signing with seed %s after signing twice\n", (rv == SECSuccess) ? "succeeded" : "failed"); 479 #endif 480 481 SECITEM_FreeItem(signature2, PR_TRUE); 482 return rv; 483 #else 484 return ec_SignDigestWithSeed(key, signature, digest, kb, kblen); 485 #endif 486 } 487 488 /* 489 ** Computes the ECDSA signature on the digest using the given key 490 ** and a random seed. 491 */ 492 SECStatus 493 ECDSA_SignDigest(ECPrivateKey *key, SECItem *signature, const SECItem *digest) 494 { 495 SECItem nonceRand = { siBuffer, NULL, 0 }; 496 497 if (!key) { 498 PORT_SetError(SEC_ERROR_INVALID_ARGS); 499 return SECFailure; 500 } 501 502 /* Generate random value k */ 503 SECITEM_AllocItem(NULL, &nonceRand, EC_GetScalarSize(&key->ecParams)); 504 if (nonceRand.data == NULL) { 505 PORT_SetError(SEC_ERROR_NO_MEMORY); 506 return SECFailure; 507 } 508 509 SECStatus rv = ec_GenerateRandomPrivateKey(&key->ecParams, &nonceRand); 510 if (rv != SECSuccess) { 511 goto cleanup; 512 } 513 514 /* Generate ECDSA signature with the specified k value */ 515 rv = ECDSA_SignDigestWithSeed(key, signature, digest, nonceRand.data, nonceRand.len); 516 NSS_DECLASSIFY(signature->data, signature->len); 517 518 cleanup: 519 SECITEM_ZfreeItem(&nonceRand, PR_FALSE); 520 521 #if EC_DEBUG 522 printf("ECDSA signing %s\n", 523 (rv == SECSuccess) ? "succeeded" : "failed"); 524 #endif 525 526 return rv; 527 } 528 529 /* 530 ** Checks the signature on the given digest using the key provided. 531 ** 532 ** The key argument must represent a valid EC public key (a point on 533 ** the relevant curve). If it is not a valid point, then the behavior 534 ** of this function is undefined. In cases where a public key might 535 ** not be valid, use EC_ValidatePublicKey to check. 536 */ 537 SECStatus 538 ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature, 539 const SECItem *digest) 540 { 541 SECStatus rv = SECFailure; 542 ECParams *ecParams = NULL; 543 544 /* Check args */ 545 if (!key || !signature || !digest) { 546 PORT_SetError(SEC_ERROR_INVALID_ARGS); 547 return SECFailure; 548 } 549 550 ecParams = &(key->ecParams); 551 552 /* Perform curve specific signature verification using ECMethod */ 553 if (ecParams->fieldID.type != ec_field_plain) { 554 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 555 return SECFailure; 556 } 557 558 const ECMethod *method = ec_get_method_from_name(ecParams->name); 559 if (method == NULL || method->verify_digest == NULL) { 560 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 561 return SECFailure; 562 } 563 564 rv = method->verify_digest(key, signature, digest); 565 if (rv != SECSuccess) { 566 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 567 } 568 569 #if EC_DEBUG 570 printf("ECDSA verification %s\n", 571 (rv == SECSuccess) ? "succeeded" : "failed"); 572 #endif 573 574 return rv; 575 } 576 577 /*EdDSA: Currently only Ed22519 is implemented.*/ 578 579 /* 580 ** Computes the EdDSA signature on the message using the given key. 581 */ 582 583 SECStatus 584 ec_ED25519_public_key_validate(const ECPublicKey *key) 585 { 586 if (!key || !(key->ecParams.name == ECCurve_Ed25519)) { 587 PORT_SetError(SEC_ERROR_INVALID_ARGS); 588 return SECFailure; 589 } 590 return ec_ED25519_pt_validate(&key->publicValue); 591 } 592 593 SECStatus 594 ec_ED25519_private_key_validate(const ECPrivateKey *key) 595 { 596 if (!key || !(key->ecParams.name == ECCurve_Ed25519)) { 597 598 PORT_SetError(SEC_ERROR_INVALID_ARGS); 599 return SECFailure; 600 } 601 return ec_ED25519_scalar_validate(&key->privateValue); 602 } 603 604 SECStatus 605 ED_SignMessage(ECPrivateKey *key, SECItem *signature, const SECItem *msg) 606 { 607 if (!msg || !signature || signature->len != Ed25519_SIGN_LEN) { 608 PORT_SetError(SEC_ERROR_INVALID_ARGS); 609 return SECFailure; 610 } 611 612 if (ec_ED25519_private_key_validate(key) != SECSuccess) { 613 return SECFailure; /* error code set by ec_ED25519_scalar_validate. */ 614 } 615 616 if (signature->data) { 617 Hacl_Ed25519_sign(signature->data, key->privateValue.data, msg->len, 618 msg->data); 619 } 620 signature->len = ED25519_SIGN_LEN; 621 BLAPI_CLEAR_STACK(2048); 622 return SECSuccess; 623 } 624 625 /* 626 ** Checks the signature on the given message using the key provided. 627 */ 628 629 SECStatus 630 ED_VerifyMessage(ECPublicKey *key, const SECItem *signature, 631 const SECItem *msg) 632 { 633 if (!msg || !signature || !signature->data || signature->len != Ed25519_SIGN_LEN) { 634 PORT_SetError(SEC_ERROR_INVALID_ARGS); 635 return SECFailure; 636 } 637 638 if (ec_ED25519_public_key_validate(key) != SECSuccess) { 639 return SECFailure; /* error code set by ec_ED25519_pt_validate. */ 640 } 641 642 bool rv = Hacl_Ed25519_verify(key->publicValue.data, msg->len, msg->data, 643 signature->data); 644 BLAPI_CLEAR_STACK(2048); 645 646 #if EC_DEBUG 647 printf("ED_VerifyMessage returning %s\n", 648 (rv) ? "success" : "failure"); 649 #endif 650 651 if (rv) { 652 return SECSuccess; 653 } 654 655 PORT_SetError(SEC_ERROR_BAD_SIGNATURE); 656 return SECFailure; 657 } 658 659 SECStatus 660 ED_DerivePublicKey(const SECItem *privateKey, SECItem *publicKey) 661 { 662 /* Currently supporting only Ed25519.*/ 663 if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != Ed25519_PUBLIC_KEYLEN) { 664 PORT_SetError(SEC_ERROR_INVALID_ARGS); 665 return SECFailure; 666 } 667 668 if (ec_ED25519_scalar_validate(privateKey) != SECSuccess) { 669 PORT_SetError(SEC_ERROR_INVALID_ARGS); 670 return SECFailure; 671 } 672 673 Hacl_Ed25519_secret_to_public(publicKey->data, privateKey->data); 674 return SECSuccess; 675 } 676 677 SECStatus 678 X25519_DerivePublicKey(const SECItem *privateKey, SECItem *publicKey) 679 { 680 SECStatus rv = SECFailure; 681 /* Currently supporting only X25519.*/ 682 if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != X25519_PUBLIC_KEYLEN) { 683 PORT_SetError(SEC_ERROR_INVALID_ARGS); 684 return SECFailure; 685 } 686 687 const ECMethod *method = ec_get_method_from_name(ECCurve25519); 688 if (method == NULL || method->pt_mul == NULL) { 689 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 690 return SECFailure; 691 } 692 693 rv = method->pt_mul(publicKey, (SECItem *)privateKey, NULL); 694 return rv; 695 } 696 697 SECStatus 698 EC_DerivePublicKey(const SECItem *privateKey, const ECParams *ecParams, SECItem *publicKey) 699 { 700 if (!privateKey || privateKey->len == 0 || !publicKey || publicKey->len != EC_GetPointSize(ecParams)) { 701 PORT_SetError(SEC_ERROR_INVALID_ARGS); 702 return SECFailure; 703 } 704 705 const ECMethod *method = ec_get_method_from_name(ecParams->name); 706 if (method == NULL || method->pt_mul == NULL) { 707 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 708 return SECFailure; 709 } 710 711 return method->pt_mul(publicKey, (SECItem *)privateKey, NULL); 712 } 713 714 /* Supported only for P-256, P-384 and P-521*/ 715 SECStatus 716 EC_DecompressPublicKey(const SECItem *publicCompressed, const ECParams *ecParams, SECItem *publicUncompressed) 717 { 718 /* I don't think that we need a special ECMethod extension for decompression. */ 719 switch (ecParams->name) { 720 case ECCurve_NIST_P256: 721 return ec_secp256r1_decompress(publicCompressed, publicUncompressed); 722 case ECCurve_NIST_P384: 723 return ec_secp384r1_decompress(publicCompressed, publicUncompressed); 724 case ECCurve_NIST_P521: 725 return ec_secp521r1_decompress(publicCompressed, publicUncompressed); 726 default: 727 PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE); 728 return SECFailure; 729 } 730 }