1 /* $OpenBSD: ecx_methods.c,v 1.4 2022/11/26 16:08:52 tb Exp $ */ 2 /* 3 * Copyright (c) 2022 Joel Sing <jsing@openbsd.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <string.h> 19 20 #include <openssl/curve25519.h> 21 #include <openssl/ec.h> 22 #include <openssl/err.h> 23 #include <openssl/evp.h> 24 #include <openssl/x509.h> 25 26 #include "asn1_local.h" 27 #include "bytestring.h" 28 #include "curve25519_internal.h" 29 #include "evp_local.h" 30 31 /* 32 * EVP PKEY and PKEY ASN.1 methods Ed25519 and X25519. 33 * 34 * RFC 7748 - Elliptic Curves for Security. 35 * RFC 8032 - Edwards-Curve Digital Signature Algorithm (EdDSA). 36 */ 37 38 #define ED25519_BITS 253 39 #define ED25519_SECURITY_BITS 128 40 #define ED25519_SIG_SIZE 64 41 42 #define X25519_BITS 253 43 #define X25519_SECURITY_BITS 128 44 45 static int 46 ecx_key_len(int nid) 47 { 48 switch (nid) { 49 case NID_ED25519: 50 return ED25519_KEYLEN; 51 case NID_X25519: 52 return X25519_KEYLEN; 53 } 54 55 return 0; 56 } 57 58 static struct ecx_key_st * 59 ecx_key_new(int nid) 60 { 61 struct ecx_key_st *ecx_key; 62 int key_len; 63 64 if ((key_len = ecx_key_len(nid)) == 0) 65 return NULL; 66 67 if ((ecx_key = calloc(1, sizeof(*ecx_key))) == NULL) 68 return NULL; 69 70 ecx_key->nid = nid; 71 ecx_key->key_len = key_len; 72 73 return ecx_key; 74 } 75 76 static void 77 ecx_key_clear(struct ecx_key_st *ecx_key) 78 { 79 freezero(ecx_key->priv_key, ecx_key->priv_key_len); 80 ecx_key->priv_key = NULL; 81 ecx_key->priv_key_len = 0; 82 83 freezero(ecx_key->pub_key, ecx_key->pub_key_len); 84 ecx_key->pub_key = NULL; 85 ecx_key->pub_key_len = 0; 86 } 87 88 static void 89 ecx_key_free(struct ecx_key_st *ecx_key) 90 { 91 if (ecx_key == NULL) 92 return; 93 94 ecx_key_clear(ecx_key); 95 96 freezero(ecx_key, sizeof(*ecx_key)); 97 } 98 99 static int 100 ecx_key_generate(struct ecx_key_st *ecx_key) 101 { 102 uint8_t *pub_key = NULL, *priv_key = NULL; 103 int ret = 0; 104 105 ecx_key_clear(ecx_key); 106 107 if ((pub_key = calloc(1, ecx_key->key_len)) == NULL) 108 goto err; 109 if ((priv_key = calloc(1, ecx_key->key_len)) == NULL) 110 goto err; 111 112 switch (ecx_key->nid) { 113 case NID_ED25519: 114 ED25519_keypair(pub_key, priv_key); 115 break; 116 case NID_X25519: 117 X25519_keypair(pub_key, priv_key); 118 break; 119 default: 120 goto err; 121 } 122 123 ecx_key->priv_key = priv_key; 124 ecx_key->priv_key_len = ecx_key->key_len; 125 priv_key = NULL; 126 127 ecx_key->pub_key = pub_key; 128 ecx_key->pub_key_len = ecx_key->key_len; 129 pub_key = NULL; 130 131 ret = 1; 132 133 err: 134 freezero(pub_key, ecx_key->key_len); 135 freezero(priv_key, ecx_key->key_len); 136 137 return ret; 138 } 139 140 static int 141 ecx_key_set_priv(struct ecx_key_st *ecx_key, const uint8_t *priv_key, 142 size_t priv_key_len) 143 { 144 uint8_t *pub_key = NULL; 145 CBS cbs; 146 147 ecx_key_clear(ecx_key); 148 149 if (priv_key_len != ecx_key->key_len) 150 goto err; 151 152 if ((pub_key = calloc(1, ecx_key->key_len)) == NULL) 153 goto err; 154 155 switch (ecx_key->nid) { 156 case NID_ED25519: 157 ED25519_public_from_private(pub_key, priv_key); 158 break; 159 case NID_X25519: 160 X25519_public_from_private(pub_key, priv_key); 161 break; 162 default: 163 goto err; 164 } 165 166 CBS_init(&cbs, priv_key, priv_key_len); 167 if (!CBS_stow(&cbs, &ecx_key->priv_key, &ecx_key->priv_key_len)) 168 goto err; 169 170 ecx_key->pub_key = pub_key; 171 ecx_key->pub_key_len = ecx_key->key_len; 172 pub_key = NULL; 173 174 err: 175 freezero(pub_key, ecx_key->key_len); 176 177 return 1; 178 } 179 180 static int 181 ecx_key_set_pub(struct ecx_key_st *ecx_key, const uint8_t *pub_key, 182 size_t pub_key_len) 183 { 184 CBS cbs; 185 186 ecx_key_clear(ecx_key); 187 188 if (pub_key_len != ecx_key->key_len) 189 return 0; 190 191 CBS_init(&cbs, pub_key, pub_key_len); 192 if (!CBS_stow(&cbs, &ecx_key->pub_key, &ecx_key->pub_key_len)) 193 return 0; 194 195 return 1; 196 } 197 198 static int 199 ecx_pub_decode(EVP_PKEY *pkey, X509_PUBKEY *xpubkey) 200 { 201 struct ecx_key_st *ecx_key = NULL; 202 X509_ALGOR *algor; 203 int algor_type; 204 const uint8_t *param; 205 int param_len; 206 int ret = 0; 207 208 if (!X509_PUBKEY_get0_param(NULL, ¶m, ¶m_len, &algor, xpubkey)) 209 goto err; 210 211 /* Ensure that parameters have not been specified in the encoding. */ 212 if (algor != NULL) { 213 X509_ALGOR_get0(NULL, &algor_type, NULL, algor); 214 if (algor_type != V_ASN1_UNDEF) { 215 ECerror(EC_R_INVALID_ENCODING); 216 goto err; 217 } 218 } 219 220 if (param == NULL || param_len != ecx_key_len(pkey->ameth->pkey_id)) { 221 ECerror(EC_R_INVALID_ENCODING); 222 goto err; 223 } 224 225 if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL) 226 goto err; 227 if (!ecx_key_set_pub(ecx_key, param, param_len)) 228 goto err; 229 if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key)) 230 goto err; 231 ecx_key = NULL; 232 233 ret = 1; 234 235 err: 236 ecx_key_free(ecx_key); 237 238 return ret; 239 } 240 241 static int 242 ecx_pub_encode(X509_PUBKEY *xpubkey, const EVP_PKEY *pkey) 243 { 244 const struct ecx_key_st *ecx_key = pkey->pkey.ecx; 245 uint8_t *pub_key = NULL; 246 size_t pub_key_len = 0; 247 ASN1_OBJECT *aobj; 248 CBS cbs; 249 int ret = 0; 250 251 if (ecx_key == NULL) { 252 ECerror(EC_R_INVALID_KEY); 253 goto err; 254 } 255 256 if (ecx_key->pub_key_len != ecx_key->key_len) 257 goto err; 258 259 if ((aobj = OBJ_nid2obj(pkey->ameth->pkey_id)) == NULL) 260 goto err; 261 262 CBS_init(&cbs, ecx_key->pub_key, ecx_key->pub_key_len); 263 if (!CBS_stow(&cbs, &pub_key, &pub_key_len)) 264 goto err; 265 266 if (!X509_PUBKEY_set0_param(xpubkey, aobj, V_ASN1_UNDEF, NULL, 267 pub_key, pub_key_len)) 268 goto err; 269 270 pub_key = NULL; 271 pub_key_len = 0; 272 273 ret = 1; 274 275 err: 276 free(pub_key); 277 278 return ret; 279 } 280 281 static int 282 ecx_pub_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2) 283 { 284 if (pkey1->pkey.ecx == NULL || pkey1->pkey.ecx->pub_key == NULL) 285 return -2; 286 if (pkey2->pkey.ecx == NULL || pkey2->pkey.ecx->pub_key == NULL) 287 return -2; 288 if (pkey1->pkey.ecx->pub_key_len != pkey2->pkey.ecx->pub_key_len) 289 return -2; 290 291 return timingsafe_memcmp(pkey1->pkey.ecx->pub_key, pkey2->pkey.ecx->pub_key, 292 pkey1->pkey.ecx->pub_key_len) == 0; 293 } 294 295 static int 296 ecx_pub_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) 297 { 298 struct ecx_key_st *ecx_key = pkey->pkey.ecx; 299 const char *name; 300 301 if ((name = OBJ_nid2ln(pkey->ameth->pkey_id)) == NULL) 302 return 0; 303 304 if (ecx_key == NULL || ecx_key->pub_key == NULL) 305 return BIO_printf(bio, "%*s<INVALID PUBLIC KEY>\n", 306 indent, "") > 0; 307 308 if (BIO_printf(bio, "%*s%s Public-Key:\n", indent, "", name) <= 0) 309 return 0; 310 if (BIO_printf(bio, "%*spub:\n", indent, "") <= 0) 311 return 0; 312 if (ASN1_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len, 313 indent + 4) == 0) 314 return 0; 315 316 return 1; 317 } 318 319 static int 320 ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8pki) 321 { 322 struct ecx_key_st *ecx_key = NULL; 323 ASN1_OCTET_STRING *aos = NULL; 324 const X509_ALGOR *algor; 325 int algor_type; 326 const uint8_t *param; 327 int param_len; 328 int ret = 0; 329 330 if (!PKCS8_pkey_get0(NULL, ¶m, ¶m_len, &algor, p8pki)) 331 goto err; 332 if ((aos = d2i_ASN1_OCTET_STRING(NULL, ¶m, param_len)) == NULL) 333 goto err; 334 335 /* Ensure that parameters have not been specified in the encoding. */ 336 if (algor != NULL) { 337 X509_ALGOR_get0(NULL, &algor_type, NULL, algor); 338 if (algor_type != V_ASN1_UNDEF) { 339 ECerror(EC_R_INVALID_ENCODING); 340 goto err; 341 } 342 } 343 344 if (ASN1_STRING_get0_data(aos) == NULL || 345 ASN1_STRING_length(aos) != ecx_key_len(pkey->ameth->pkey_id)) { 346 ECerror(EC_R_INVALID_ENCODING); 347 goto err; 348 } 349 350 if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL) 351 goto err; 352 if (!ecx_key_set_priv(ecx_key, ASN1_STRING_get0_data(aos), 353 ASN1_STRING_length(aos))) 354 goto err; 355 if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key)) 356 goto err; 357 ecx_key = NULL; 358 359 ret = 1; 360 361 err: 362 ASN1_OCTET_STRING_free(aos); 363 ecx_key_free(ecx_key); 364 365 return ret; 366 } 367 368 static int 369 ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8pki, const EVP_PKEY *pkey) 370 { 371 struct ecx_key_st *ecx_key = pkey->pkey.ecx; 372 ASN1_OCTET_STRING *aos = NULL; 373 ASN1_OBJECT *aobj; 374 uint8_t *der = NULL; 375 int der_len = 0; 376 int ret = 0; 377 378 if (ecx_key == NULL || ecx_key->priv_key == NULL) { 379 ECerror(EC_R_INVALID_PRIVATE_KEY); 380 goto err; 381 } 382 383 if ((aobj = OBJ_nid2obj(pkey->ameth->pkey_id)) == NULL) 384 goto err; 385 386 if ((aos = ASN1_OCTET_STRING_new()) == NULL) 387 goto err; 388 if (!ASN1_OCTET_STRING_set(aos, ecx_key->priv_key, 389 ecx_key->priv_key_len)) 390 goto err; 391 if ((der_len = i2d_ASN1_OCTET_STRING(aos, &der)) < 0) 392 goto err; 393 if (!PKCS8_pkey_set0(p8pki, aobj, 0, V_ASN1_UNDEF, NULL, der, der_len)) 394 goto err; 395 396 der = NULL; 397 der_len = 0; 398 399 ret = 1; 400 401 err: 402 freezero(der, der_len); 403 ASN1_OCTET_STRING_free(aos); 404 405 return ret; 406 } 407 408 static int 409 ecx_priv_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx) 410 { 411 struct ecx_key_st *ecx_key = pkey->pkey.ecx; 412 const char *name; 413 414 if ((name = OBJ_nid2ln(pkey->ameth->pkey_id)) == NULL) 415 return 0; 416 417 if (ecx_key == NULL || ecx_key->priv_key == NULL) 418 return BIO_printf(bio, "%*s<INVALID PRIVATE KEY>\n", 419 indent, "") > 0; 420 421 if (BIO_printf(bio, "%*s%s Private-Key:\n", indent, "", name) <= 0) 422 return 0; 423 if (BIO_printf(bio, "%*spriv:\n", indent, "") <= 0) 424 return 0; 425 if (ASN1_buf_print(bio, ecx_key->priv_key, ecx_key->priv_key_len, 426 indent + 4) == 0) 427 return 0; 428 if (BIO_printf(bio, "%*spub:\n", indent, "") <= 0) 429 return 0; 430 if (ASN1_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len, 431 indent + 4) == 0) 432 return 0; 433 434 return 1; 435 } 436 437 static int 438 ecx_size(const EVP_PKEY *pkey) 439 { 440 return ecx_key_len(pkey->ameth->pkey_id); 441 } 442 443 static int 444 ecx_sig_size(const EVP_PKEY *pkey) 445 { 446 switch (pkey->ameth->pkey_id) { 447 case EVP_PKEY_ED25519: 448 return ED25519_SIG_SIZE; 449 } 450 return 0; 451 } 452 453 static int 454 ecx_bits(const EVP_PKEY *pkey) 455 { 456 switch (pkey->ameth->pkey_id) { 457 case EVP_PKEY_ED25519: 458 return ED25519_BITS; 459 case EVP_PKEY_X25519: 460 return X25519_BITS; 461 } 462 return 0; 463 } 464 465 static int 466 ecx_security_bits(const EVP_PKEY *pkey) 467 { 468 switch (pkey->ameth->pkey_id) { 469 case EVP_PKEY_ED25519: 470 return ED25519_SECURITY_BITS; 471 case EVP_PKEY_X25519: 472 return X25519_SECURITY_BITS; 473 } 474 return 0; 475 } 476 477 static int 478 ecx_param_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2) 479 { 480 /* No parameters, so always equivalent. */ 481 return 1; 482 } 483 484 static void 485 ecx_free(EVP_PKEY *pkey) 486 { 487 struct ecx_key_st *ecx_key = pkey->pkey.ecx; 488 489 return ecx_key_free(ecx_key); 490 } 491 492 static int 493 ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) 494 { 495 /* Not supported. */ 496 return -2; 497 } 498 499 static int 500 ecx_sign_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2) 501 { 502 switch (op) { 503 case ASN1_PKEY_CTRL_DEFAULT_MD_NID: 504 /* PureEdDSA does its own hashing. */ 505 *(int *)arg2 = NID_undef; 506 return 2; 507 } 508 return -2; 509 } 510 511 static int 512 ecx_set_priv_key(EVP_PKEY *pkey, const uint8_t *priv, size_t len) 513 { 514 struct ecx_key_st *ecx_key = NULL; 515 int ret = 0; 516 517 if (priv == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) { 518 ECerror(EC_R_INVALID_ENCODING); 519 goto err; 520 } 521 522 if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL) 523 goto err; 524 if (!ecx_key_set_priv(ecx_key, priv, len)) 525 goto err; 526 if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key)) 527 goto err; 528 ecx_key = NULL; 529 530 ret = 1; 531 532 err: 533 ecx_key_free(ecx_key); 534 535 return ret; 536 } 537 538 static int 539 ecx_set_pub_key(EVP_PKEY *pkey, const uint8_t *pub, size_t len) 540 { 541 struct ecx_key_st *ecx_key = NULL; 542 int ret = 0; 543 544 if (pub == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) { 545 ECerror(EC_R_INVALID_ENCODING); 546 goto err; 547 } 548 549 if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL) 550 goto err; 551 if (!ecx_key_set_pub(ecx_key, pub, len)) 552 goto err; 553 if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key)) 554 goto err; 555 ecx_key = NULL; 556 557 ret = 1; 558 559 err: 560 ecx_key_free(ecx_key); 561 562 return ret; 563 } 564 565 static int 566 ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *out_priv, size_t *out_len) 567 { 568 struct ecx_key_st *ecx_key = pkey->pkey.ecx; 569 CBS cbs; 570 571 if (out_priv == NULL) { 572 *out_len = ecx_key_len(pkey->ameth->pkey_id); 573 return 1; 574 } 575 576 if (ecx_key == NULL || ecx_key->priv_key == NULL) 577 return 0; 578 579 CBS_init(&cbs, ecx_key->priv_key, ecx_key->priv_key_len); 580 if (!CBS_write_bytes(&cbs, out_priv, *out_len, out_len)) 581 return 0; 582 583 return 1; 584 } 585 586 static int 587 ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *out_pub, size_t *out_len) 588 { 589 struct ecx_key_st *ecx_key = pkey->pkey.ecx; 590 CBS cbs; 591 592 if (out_pub == NULL) { 593 *out_len = ecx_key_len(pkey->ameth->pkey_id); 594 return 1; 595 } 596 597 if (ecx_key == NULL || ecx_key->pub_key == NULL) 598 return 0; 599 600 CBS_init(&cbs, ecx_key->pub_key, ecx_key->pub_key_len); 601 if (!CBS_write_bytes(&cbs, out_pub, *out_len, out_len)) 602 return 0; 603 604 return 1; 605 } 606 607 static int 608 pkey_ecx_keygen(EVP_PKEY_CTX *pkey_ctx, EVP_PKEY *pkey) 609 { 610 struct ecx_key_st *ecx_key = NULL; 611 int ret = 0; 612 613 if ((ecx_key = ecx_key_new(pkey_ctx->pmeth->pkey_id)) == NULL) 614 goto err; 615 if (!ecx_key_generate(ecx_key)) 616 goto err; 617 if (!EVP_PKEY_assign(pkey, pkey_ctx->pmeth->pkey_id, ecx_key)) 618 goto err; 619 ecx_key = NULL; 620 621 ret = 1; 622 623 err: 624 ecx_key_free(ecx_key); 625 626 return ret; 627 } 628 629 static int 630 pkey_ecx_derive(EVP_PKEY_CTX *pkey_ctx, unsigned char *out_key, 631 size_t *out_key_len) 632 { 633 struct ecx_key_st *ecx_key, *ecx_peer_key; 634 635 if (pkey_ctx->pkey == NULL || pkey_ctx->peerkey == NULL) { 636 ECerror(EC_R_KEYS_NOT_SET); 637 return 0; 638 } 639 640 if ((ecx_key = pkey_ctx->pkey->pkey.ecx) == NULL) { 641 ECerror(EC_R_INVALID_PRIVATE_KEY); 642 return 0; 643 } 644 if (ecx_key->priv_key == NULL) { 645 ECerror(EC_R_INVALID_PRIVATE_KEY); 646 return 0; 647 } 648 649 if ((ecx_peer_key = pkey_ctx->peerkey->pkey.ecx) == NULL) { 650 ECerror(EC_R_INVALID_PEER_KEY); 651 return 0; 652 } 653 654 if (out_key != NULL) { 655 if (!X25519(out_key, ecx_key->priv_key, ecx_peer_key->pub_key)) 656 return 0; 657 } 658 659 *out_key_len = X25519_KEYLEN; 660 661 return 1; 662 } 663 664 static int 665 pkey_ecx_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2) 666 { 667 if (op == EVP_PKEY_CTRL_PEER_KEY) 668 return 1; 669 670 return -2; 671 } 672 673 static int 674 ecx_item_verify(EVP_MD_CTX *md_ctx, const ASN1_ITEM *it, void *asn, 675 X509_ALGOR *algor, ASN1_BIT_STRING *abs, EVP_PKEY *pkey) 676 { 677 const ASN1_OBJECT *aobj; 678 int nid, param_type; 679 680 X509_ALGOR_get0(&aobj, ¶m_type, NULL, algor); 681 682 nid = OBJ_obj2nid(aobj); 683 684 if (nid != NID_ED25519 || param_type != V_ASN1_UNDEF) { 685 ECerror(EC_R_INVALID_ENCODING); 686 return 0; 687 } 688 689 if (!EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, pkey)) 690 return 0; 691 692 return 2; 693 } 694 695 static int 696 ecx_item_sign(EVP_MD_CTX *md_ctx, const ASN1_ITEM *it, void *asn, 697 X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *abs) 698 { 699 ASN1_OBJECT *aobj; 700 701 if ((aobj = OBJ_nid2obj(NID_ED25519)) == NULL) 702 return 0; 703 704 if (!X509_ALGOR_set0(algor1, aobj, V_ASN1_UNDEF, NULL)) 705 return 0; 706 707 if (algor2 != NULL) { 708 if (!X509_ALGOR_set0(algor2, aobj, V_ASN1_UNDEF, NULL)) 709 return 0; 710 } 711 712 /* Tell ASN1_item_sign_ctx() that identifiers are set and it needs to sign. */ 713 return 3; 714 } 715 716 static int 717 pkey_ecx_digestsign(EVP_MD_CTX *md_ctx, unsigned char *out_sig, 718 size_t *out_sig_len, const unsigned char *message, size_t message_len) 719 { 720 struct ecx_key_st *ecx_key; 721 EVP_PKEY_CTX *pkey_ctx; 722 723 pkey_ctx = EVP_MD_CTX_pkey_ctx(md_ctx); 724 ecx_key = pkey_ctx->pkey->pkey.ecx; 725 726 if (out_sig == NULL) { 727 *out_sig_len = ecx_sig_size(pkey_ctx->pkey); 728 return 1; 729 } 730 if (*out_sig_len < ecx_sig_size(pkey_ctx->pkey)) { 731 ECerror(EC_R_BUFFER_TOO_SMALL); 732 return 0; 733 } 734 735 if (ecx_key == NULL) 736 return 0; 737 if (ecx_key->priv_key == NULL || ecx_key->pub_key == NULL) 738 return 0; 739 740 if (!ED25519_sign(out_sig, message, message_len, ecx_key->pub_key, 741 ecx_key->priv_key)) 742 return 0; 743 744 return 1; 745 } 746 747 static int 748 pkey_ecx_digestverify(EVP_MD_CTX *md_ctx, const unsigned char *sig, 749 size_t sig_len, const unsigned char *message, size_t message_len) 750 { 751 struct ecx_key_st *ecx_key; 752 EVP_PKEY_CTX *pkey_ctx; 753 754 pkey_ctx = EVP_MD_CTX_pkey_ctx(md_ctx); 755 ecx_key = pkey_ctx->pkey->pkey.ecx; 756 757 if (ecx_key == NULL || ecx_key->pub_key == NULL) 758 return 0; 759 if (sig_len != ecx_sig_size(pkey_ctx->pkey)) 760 return 0; 761 762 return ED25519_verify(message, message_len, sig, ecx_key->pub_key); 763 } 764 765 static int 766 pkey_ecx_ed_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2) 767 { 768 switch (op) { 769 case EVP_PKEY_CTRL_MD: 770 /* PureEdDSA does its own hashing. */ 771 if (arg2 != NULL && (const EVP_MD *)arg2 != EVP_md_null()) { 772 ECerror(EC_R_INVALID_DIGEST_TYPE); 773 return 0; 774 } 775 return 1; 776 777 case EVP_PKEY_CTRL_DIGESTINIT: 778 return 1; 779 } 780 return -2; 781 } 782 783 const EVP_PKEY_ASN1_METHOD x25519_asn1_meth = { 784 .pkey_id = EVP_PKEY_X25519, 785 .pkey_base_id = EVP_PKEY_X25519, 786 .pkey_flags = 0, 787 .pem_str = "X25519", 788 .info = "OpenSSL X25519 algorithm", 789 790 .pub_decode = ecx_pub_decode, 791 .pub_encode = ecx_pub_encode, 792 .pub_cmp = ecx_pub_cmp, 793 .pub_print = ecx_pub_print, 794 795 .priv_decode = ecx_priv_decode, 796 .priv_encode = ecx_priv_encode, 797 .priv_print = ecx_priv_print, 798 799 .pkey_size = ecx_size, 800 .pkey_bits = ecx_bits, 801 .pkey_security_bits = ecx_security_bits, 802 803 .param_cmp = ecx_param_cmp, 804 805 .pkey_free = ecx_free, 806 .pkey_ctrl = ecx_ctrl, 807 808 .set_priv_key = ecx_set_priv_key, 809 .set_pub_key = ecx_set_pub_key, 810 .get_priv_key = ecx_get_priv_key, 811 .get_pub_key = ecx_get_pub_key, 812 }; 813 814 const EVP_PKEY_METHOD x25519_pkey_meth = { 815 .pkey_id = EVP_PKEY_X25519, 816 .keygen = pkey_ecx_keygen, 817 .derive = pkey_ecx_derive, 818 .ctrl = pkey_ecx_ctrl, 819 }; 820 821 const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = { 822 .pkey_id = EVP_PKEY_ED25519, 823 .pkey_base_id = EVP_PKEY_ED25519, 824 .pkey_flags = 0, 825 .pem_str = "ED25519", 826 .info = "OpenSSL ED25519 algorithm", 827 828 .pub_decode = ecx_pub_decode, 829 .pub_encode = ecx_pub_encode, 830 .pub_cmp = ecx_pub_cmp, 831 .pub_print = ecx_pub_print, 832 833 .priv_decode = ecx_priv_decode, 834 .priv_encode = ecx_priv_encode, 835 .priv_print = ecx_priv_print, 836 837 .pkey_size = ecx_sig_size, 838 .pkey_bits = ecx_bits, 839 .pkey_security_bits = ecx_security_bits, 840 841 .param_cmp = ecx_param_cmp, 842 843 .pkey_free = ecx_free, 844 .pkey_ctrl = ecx_sign_ctrl, 845 846 .item_verify = ecx_item_verify, 847 .item_sign = ecx_item_sign, 848 849 .set_priv_key = ecx_set_priv_key, 850 .set_pub_key = ecx_set_pub_key, 851 .get_priv_key = ecx_get_priv_key, 852 .get_pub_key = ecx_get_pub_key, 853 }; 854 855 const EVP_PKEY_METHOD ed25519_pkey_meth = { 856 .pkey_id = EVP_PKEY_ED25519, 857 .flags = EVP_PKEY_FLAG_SIGCTX_CUSTOM, 858 .keygen = pkey_ecx_keygen, 859 .ctrl = pkey_ecx_ed_ctrl, 860 .digestsign = pkey_ecx_digestsign, 861 .digestverify = pkey_ecx_digestverify, 862 }; 863