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