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