xref: /openbsd-src/lib/libcrypto/ec/ecx_methods.c (revision f2a19305cfc49ea4d1a5feb55cd6c283c6f1e031)
1 /*	$OpenBSD: ecx_methods.c,v 1.13 2024/04/02 04:04:07 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_param_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2)
514 {
515 	/* No parameters, so always equivalent. */
516 	return 1;
517 }
518 
519 static void
520 ecx_free(EVP_PKEY *pkey)
521 {
522 	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
523 
524 	ecx_key_free(ecx_key);
525 }
526 
527 static int
528 ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
529 {
530 	/* Not supported. */
531 	return -2;
532 }
533 
534 #ifndef OPENSSL_NO_CMS
535 static int
536 ecx_cms_sign_or_verify(EVP_PKEY *pkey, long verify, CMS_SignerInfo *si)
537 {
538 	X509_ALGOR *digestAlgorithm, *signatureAlgorithm;
539 
540 	if (verify != 0 && verify != 1)
541 		return -1;
542 
543 	/* Check that we have an Ed25519 public key. */
544 	if (EVP_PKEY_id(pkey) != NID_ED25519)
545 		return -1;
546 
547 	CMS_SignerInfo_get0_algs(si, NULL, NULL, &digestAlgorithm,
548 	    &signatureAlgorithm);
549 
550 	/* RFC 8419, section 2.3: digestAlgorithm MUST be SHA-512. */
551 	if (digestAlgorithm == NULL)
552 		return -1;
553 	if (OBJ_obj2nid(digestAlgorithm->algorithm) != NID_sha512)
554 		return -1;
555 
556 	/*
557 	 * RFC 8419, section 2.4: signatureAlgorithm MUST be Ed25519, and the
558 	 * parameters MUST be absent. For verification check that this is the
559 	 * case, for signing set the signatureAlgorithm accordingly.
560 	 */
561 	if (verify) {
562 		const ASN1_OBJECT *obj;
563 		int param_type;
564 
565 		if (signatureAlgorithm == NULL)
566 			return -1;
567 
568 		X509_ALGOR_get0(&obj, &param_type, NULL, signatureAlgorithm);
569 		if (OBJ_obj2nid(obj) != NID_ED25519)
570 			return -1;
571 		if (param_type != V_ASN1_UNDEF)
572 			return -1;
573 
574 		return 1;
575 	}
576 
577 	if (!X509_ALGOR_set0_by_nid(signatureAlgorithm, NID_ED25519,
578 	    V_ASN1_UNDEF, NULL))
579 		return -1;
580 
581 	return 1;
582 }
583 #endif
584 
585 static int
586 ecx_sign_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
587 {
588 	switch (op) {
589 #ifndef OPENSSL_NO_CMS
590 	case ASN1_PKEY_CTRL_CMS_SIGN:
591 		return ecx_cms_sign_or_verify(pkey, arg1, arg2);
592 #endif
593 	case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
594 		/* PureEdDSA does its own hashing. */
595 		*(int *)arg2 = NID_undef;
596 		return 2;
597 	}
598 	return -2;
599 }
600 
601 static int
602 ecx_set_priv_key(EVP_PKEY *pkey, const uint8_t *priv, size_t len)
603 {
604 	struct ecx_key_st *ecx_key = NULL;
605 	int ret = 0;
606 
607 	if (priv == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) {
608 		ECerror(EC_R_INVALID_ENCODING);
609 		goto err;
610 	}
611 
612 	if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
613 		goto err;
614 	if (!ecx_key_set_priv(ecx_key, priv, len))
615 		goto err;
616 	if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
617 		goto err;
618 	ecx_key = NULL;
619 
620 	ret = 1;
621 
622  err:
623 	ecx_key_free(ecx_key);
624 
625 	return ret;
626 }
627 
628 static int
629 ecx_set_pub_key(EVP_PKEY *pkey, const uint8_t *pub, size_t len)
630 {
631 	struct ecx_key_st *ecx_key = NULL;
632 	int ret = 0;
633 
634 	if (pub == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) {
635 		ECerror(EC_R_INVALID_ENCODING);
636 		goto err;
637 	}
638 
639 	if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
640 		goto err;
641 	if (!ecx_key_set_pub(ecx_key, pub, len))
642 		goto err;
643 	if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
644 		goto err;
645 	ecx_key = NULL;
646 
647 	ret = 1;
648 
649  err:
650 	ecx_key_free(ecx_key);
651 
652 	return ret;
653 }
654 
655 static int
656 ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *out_priv, size_t *out_len)
657 {
658 	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
659 	CBS cbs;
660 
661 	if (out_priv == NULL) {
662 		*out_len = ecx_key_len(pkey->ameth->pkey_id);
663 		return 1;
664 	}
665 
666 	if (ecx_key == NULL || ecx_key->priv_key == NULL)
667 		return 0;
668 
669 	CBS_init(&cbs, ecx_key->priv_key, ecx_key->priv_key_len);
670 	if (!CBS_write_bytes(&cbs, out_priv, *out_len, out_len))
671 		return 0;
672 
673 	return 1;
674 }
675 
676 static int
677 ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *out_pub, size_t *out_len)
678 {
679 	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
680 	CBS cbs;
681 
682 	if (out_pub == NULL) {
683 		*out_len = ecx_key_len(pkey->ameth->pkey_id);
684 		return 1;
685 	}
686 
687 	if (ecx_key == NULL || ecx_key->pub_key == NULL)
688 		return 0;
689 
690 	CBS_init(&cbs, ecx_key->pub_key, ecx_key->pub_key_len);
691 	if (!CBS_write_bytes(&cbs, out_pub, *out_len, out_len))
692 		return 0;
693 
694 	return 1;
695 }
696 
697 static int
698 pkey_ecx_keygen(EVP_PKEY_CTX *pkey_ctx, EVP_PKEY *pkey)
699 {
700 	struct ecx_key_st *ecx_key = NULL;
701 	int ret = 0;
702 
703 	if ((ecx_key = ecx_key_new(pkey_ctx->pmeth->pkey_id)) == NULL)
704 		goto err;
705 	if (!ecx_key_generate(ecx_key))
706 		goto err;
707 	if (!EVP_PKEY_assign(pkey, pkey_ctx->pmeth->pkey_id, ecx_key))
708 		goto err;
709 	ecx_key = NULL;
710 
711 	ret = 1;
712 
713  err:
714 	ecx_key_free(ecx_key);
715 
716 	return ret;
717 }
718 
719 static int
720 pkey_ecx_derive(EVP_PKEY_CTX *pkey_ctx, unsigned char *out_key,
721     size_t *out_key_len)
722 {
723 	struct ecx_key_st *ecx_key, *ecx_peer_key;
724 
725 	if (pkey_ctx->pkey == NULL || pkey_ctx->peerkey == NULL) {
726 		ECerror(EC_R_KEYS_NOT_SET);
727 		return 0;
728 	}
729 
730 	if ((ecx_key = pkey_ctx->pkey->pkey.ecx) == NULL) {
731 		ECerror(EC_R_INVALID_PRIVATE_KEY);
732 		return 0;
733 	}
734 	if (ecx_key->priv_key == NULL) {
735 		ECerror(EC_R_INVALID_PRIVATE_KEY);
736 		return 0;
737 	}
738 
739 	if ((ecx_peer_key = pkey_ctx->peerkey->pkey.ecx) == NULL) {
740 		ECerror(EC_R_INVALID_PEER_KEY);
741 		return 0;
742 	}
743 
744 	if (out_key != NULL) {
745 		if (!X25519(out_key, ecx_key->priv_key, ecx_peer_key->pub_key))
746 			return 0;
747 	}
748 
749 	*out_key_len = X25519_KEYLEN;
750 
751 	return 1;
752 }
753 
754 static int
755 pkey_ecx_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2)
756 {
757 	if (op == EVP_PKEY_CTRL_PEER_KEY)
758 		return 1;
759 
760 	return -2;
761 }
762 
763 static int
764 ecx_item_verify(EVP_MD_CTX *md_ctx, const ASN1_ITEM *it, void *asn,
765    X509_ALGOR *algor, ASN1_BIT_STRING *abs, EVP_PKEY *pkey)
766 {
767 	const ASN1_OBJECT *aobj;
768 	int nid, param_type;
769 
770 	X509_ALGOR_get0(&aobj, &param_type, NULL, algor);
771 
772 	nid = OBJ_obj2nid(aobj);
773 
774 	if (nid != NID_ED25519 || param_type != V_ASN1_UNDEF) {
775 		ECerror(EC_R_INVALID_ENCODING);
776 		return -1;
777 	}
778 
779 	if (!EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, pkey))
780 		return -1;
781 
782 	return 2;
783 }
784 
785 static int
786 ecx_item_sign(EVP_MD_CTX *md_ctx, const ASN1_ITEM *it, void *asn,
787     X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *abs)
788 {
789 	if (!X509_ALGOR_set0_by_nid(algor1, NID_ED25519, V_ASN1_UNDEF, NULL))
790 		return 0;
791 
792 	if (algor2 != NULL) {
793 		if (!X509_ALGOR_set0_by_nid(algor2, NID_ED25519, V_ASN1_UNDEF,
794 		    NULL))
795 			return 0;
796 	}
797 
798 	/* Tell ASN1_item_sign_ctx() that identifiers are set and it needs to sign. */
799 	return 3;
800 }
801 
802 static int
803 pkey_ecx_digestsign(EVP_MD_CTX *md_ctx, unsigned char *out_sig,
804     size_t *out_sig_len, const unsigned char *message, size_t message_len)
805 {
806 	struct ecx_key_st *ecx_key;
807 	EVP_PKEY_CTX *pkey_ctx;
808 
809 	pkey_ctx = EVP_MD_CTX_pkey_ctx(md_ctx);
810 	ecx_key = pkey_ctx->pkey->pkey.ecx;
811 
812 	if (out_sig == NULL) {
813 		*out_sig_len = ecx_sig_size(pkey_ctx->pkey);
814 		return 1;
815 	}
816 	if (*out_sig_len < ecx_sig_size(pkey_ctx->pkey)) {
817 		ECerror(EC_R_BUFFER_TOO_SMALL);
818 		return 0;
819 	}
820 
821 	if (ecx_key == NULL)
822 		return 0;
823 	if (ecx_key->priv_key == NULL || ecx_key->pub_key == NULL)
824 		return 0;
825 
826 	if (!ED25519_sign(out_sig, message, message_len, ecx_key->pub_key,
827 	    ecx_key->priv_key))
828 		return 0;
829 
830 	*out_sig_len = ecx_sig_size(pkey_ctx->pkey);
831 
832 	return 1;
833 }
834 
835 static int
836 pkey_ecx_digestverify(EVP_MD_CTX *md_ctx, const unsigned char *sig,
837    size_t sig_len, const unsigned char *message, size_t message_len)
838 {
839 	struct ecx_key_st *ecx_key;
840 	EVP_PKEY_CTX *pkey_ctx;
841 
842 	pkey_ctx = EVP_MD_CTX_pkey_ctx(md_ctx);
843 	ecx_key = pkey_ctx->pkey->pkey.ecx;
844 
845 	if (ecx_key == NULL || ecx_key->pub_key == NULL)
846 		return -1;
847 	if (sig_len != ecx_sig_size(pkey_ctx->pkey))
848 		return -1;
849 
850 	return ED25519_verify(message, message_len, sig, ecx_key->pub_key);
851 }
852 
853 static int
854 pkey_ecx_ed_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2)
855 {
856 	switch (op) {
857 	case EVP_PKEY_CTRL_MD:
858 		/* PureEdDSA does its own hashing. */
859 		if (arg2 != NULL && (const EVP_MD *)arg2 != EVP_md_null()) {
860 			ECerror(EC_R_INVALID_DIGEST_TYPE);
861 			return 0;
862 		}
863 		return 1;
864 
865 #ifndef OPENSSL_NO_CMS
866 	case EVP_PKEY_CTRL_CMS_SIGN:
867 #endif
868 	case EVP_PKEY_CTRL_DIGESTINIT:
869 		return 1;
870 	}
871 	return -2;
872 }
873 
874 const EVP_PKEY_ASN1_METHOD x25519_asn1_meth = {
875 	.base_method = &x25519_asn1_meth,
876 	.pkey_id = EVP_PKEY_X25519,
877 	.pkey_flags = 0,
878 	.pem_str = "X25519",
879 	.info = "OpenSSL X25519 algorithm",
880 
881 	.pub_decode = ecx_pub_decode,
882 	.pub_encode = ecx_pub_encode,
883 	.pub_cmp = ecx_pub_cmp,
884 	.pub_print = ecx_pub_print,
885 
886 	.priv_decode = ecx_priv_decode,
887 	.priv_encode = ecx_priv_encode,
888 	.priv_print = ecx_priv_print,
889 
890 	.pkey_size = ecx_size,
891 	.pkey_bits = ecx_bits,
892 	.pkey_security_bits = ecx_security_bits,
893 
894 	.param_cmp = ecx_param_cmp,
895 
896 	.pkey_free = ecx_free,
897 	.pkey_ctrl = ecx_ctrl,
898 
899 	.set_priv_key = ecx_set_priv_key,
900 	.set_pub_key = ecx_set_pub_key,
901 	.get_priv_key = ecx_get_priv_key,
902 	.get_pub_key = ecx_get_pub_key,
903 };
904 
905 const EVP_PKEY_METHOD x25519_pkey_meth = {
906 	.pkey_id = EVP_PKEY_X25519,
907 	.keygen = pkey_ecx_keygen,
908 	.derive = pkey_ecx_derive,
909 	.ctrl = pkey_ecx_ctrl,
910 };
911 
912 const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
913 	.base_method = &ed25519_asn1_meth,
914 	.pkey_id = EVP_PKEY_ED25519,
915 	.pkey_flags = 0,
916 	.pem_str = "ED25519",
917 	.info = "OpenSSL ED25519 algorithm",
918 
919 	.pub_decode = ecx_pub_decode,
920 	.pub_encode = ecx_pub_encode,
921 	.pub_cmp = ecx_pub_cmp,
922 	.pub_print = ecx_pub_print,
923 
924 	.priv_decode = ecx_priv_decode,
925 	.priv_encode = ecx_priv_encode,
926 	.priv_print = ecx_priv_print,
927 
928 	.pkey_size = ecx_sig_size,
929 	.pkey_bits = ecx_bits,
930 	.pkey_security_bits = ecx_security_bits,
931 
932 	.param_cmp = ecx_param_cmp,
933 
934 	.pkey_free = ecx_free,
935 	.pkey_ctrl = ecx_sign_ctrl,
936 
937 	.item_verify = ecx_item_verify,
938 	.item_sign = ecx_item_sign,
939 
940 	.set_priv_key = ecx_set_priv_key,
941 	.set_pub_key = ecx_set_pub_key,
942 	.get_priv_key = ecx_get_priv_key,
943 	.get_pub_key = ecx_get_pub_key,
944 };
945 
946 const EVP_PKEY_METHOD ed25519_pkey_meth = {
947 	.pkey_id = EVP_PKEY_ED25519,
948 	.flags = EVP_PKEY_FLAG_SIGCTX_CUSTOM,
949 	.keygen = pkey_ecx_keygen,
950 	.ctrl = pkey_ecx_ed_ctrl,
951 	.digestsign = pkey_ecx_digestsign,
952 	.digestverify = pkey_ecx_digestverify,
953 };
954