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