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