xref: /openbsd-src/lib/libcrypto/ec/ecx_methods.c (revision 68dd5bb1859285b71cb62a10bf107b8ad54064d9)
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, &param, &param_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, &param, &param_len, &algor, p8pki))
367 		goto err;
368 	if ((aos = d2i_ASN1_OCTET_STRING(NULL, &param, 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, &param_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