xref: /openbsd-src/lib/libcrypto/ec/ecx_methods.c (revision 94358d69ee05fa503294e6438e1b1bbf60aa9d02)
1 /*	$OpenBSD: ecx_methods.c,v 1.9 2023/07/22 19:33:25 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 /* Reimplementation of ASN1_buf_print() that adds a secondary indent of 4. */
296 static int
297 ecx_buf_print(BIO *bio, const uint8_t *buf, size_t buf_len, int indent)
298 {
299 	uint8_t u8;
300 	size_t octets = 0;
301 	const char *sep = ":", *nl = "";
302 	CBS cbs;
303 
304 	if (indent > 60)
305 		indent = 60;
306 	indent += 4;
307 	if (indent < 0)
308 		indent = 0;
309 
310 	CBS_init(&cbs, buf, buf_len);
311 	while (CBS_len(&cbs) > 0) {
312 		if (!CBS_get_u8(&cbs, &u8))
313 			return 0;
314 		if (octets++ % 15 == 0) {
315 			if (BIO_printf(bio, "%s%*s", nl, indent, "") < 0)
316 				return 0;
317 			nl = "\n";
318 		}
319 		if (CBS_len(&cbs) == 0)
320 			sep = "";
321 		if (BIO_printf(bio, "%02x%s", u8, sep) <= 0)
322 			return 0;
323 	}
324 
325 	if (BIO_printf(bio, "\n") <= 0)
326 		return 0;
327 
328 	return 1;
329 }
330 
331 static int
332 ecx_pub_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
333 {
334 	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
335 	const char *name;
336 
337 	if ((name = OBJ_nid2ln(pkey->ameth->pkey_id)) == NULL)
338 		return 0;
339 
340 	if (ecx_key == NULL || ecx_key->pub_key == NULL)
341 		return BIO_printf(bio, "%*s<INVALID PUBLIC KEY>\n",
342 		    indent, "") > 0;
343 
344 	if (BIO_printf(bio, "%*s%s Public-Key:\n", indent, "", name) <= 0)
345 		return 0;
346 	if (BIO_printf(bio, "%*spub:\n", indent, "") <= 0)
347 		return 0;
348 	if (!ecx_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len, indent))
349 		return 0;
350 
351 	return 1;
352 }
353 
354 static int
355 ecx_priv_decode(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8pki)
356 {
357 	struct ecx_key_st *ecx_key = NULL;
358 	ASN1_OCTET_STRING *aos = NULL;
359 	const X509_ALGOR *algor;
360 	int algor_type;
361 	const uint8_t *param;
362 	int param_len;
363 	int ret = 0;
364 
365 	if (!PKCS8_pkey_get0(NULL, &param, &param_len, &algor, p8pki))
366 		goto err;
367 	if ((aos = d2i_ASN1_OCTET_STRING(NULL, &param, param_len)) == NULL)
368 		goto err;
369 
370 	/* Ensure that parameters have not been specified in the encoding. */
371 	if (algor != NULL) {
372 		X509_ALGOR_get0(NULL, &algor_type, NULL, algor);
373 		if (algor_type != V_ASN1_UNDEF) {
374 			ECerror(EC_R_INVALID_ENCODING);
375 			goto err;
376 		}
377 	}
378 
379 	if (ASN1_STRING_get0_data(aos) == NULL ||
380 	    ASN1_STRING_length(aos) != ecx_key_len(pkey->ameth->pkey_id)) {
381 		ECerror(EC_R_INVALID_ENCODING);
382 		goto err;
383 	}
384 
385 	if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
386 		goto err;
387 	if (!ecx_key_set_priv(ecx_key, ASN1_STRING_get0_data(aos),
388 	    ASN1_STRING_length(aos)))
389 		goto err;
390 	if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
391 		goto err;
392 	ecx_key = NULL;
393 
394 	ret = 1;
395 
396  err:
397 	ASN1_OCTET_STRING_free(aos);
398 	ecx_key_free(ecx_key);
399 
400 	return ret;
401 }
402 
403 static int
404 ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8pki, const EVP_PKEY *pkey)
405 {
406 	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
407 	ASN1_OCTET_STRING *aos = NULL;
408 	ASN1_OBJECT *aobj;
409 	uint8_t *der = NULL;
410 	int der_len = 0;
411 	int ret = 0;
412 
413 	if (ecx_key == NULL || ecx_key->priv_key == NULL) {
414 		ECerror(EC_R_INVALID_PRIVATE_KEY);
415 		goto err;
416 	}
417 
418 	if ((aobj = OBJ_nid2obj(pkey->ameth->pkey_id)) == NULL)
419 		goto err;
420 
421 	if ((aos = ASN1_OCTET_STRING_new()) == NULL)
422 		goto err;
423 	if (!ASN1_OCTET_STRING_set(aos, ecx_key->priv_key,
424 	    ecx_key->priv_key_len))
425 		goto err;
426 	if ((der_len = i2d_ASN1_OCTET_STRING(aos, &der)) < 0)
427 		goto err;
428 	if (!PKCS8_pkey_set0(p8pki, aobj, 0, V_ASN1_UNDEF, NULL, der, der_len))
429 		goto err;
430 
431 	der = NULL;
432 	der_len = 0;
433 
434 	ret = 1;
435 
436  err:
437 	freezero(der, der_len);
438 	ASN1_OCTET_STRING_free(aos);
439 
440 	return ret;
441 }
442 
443 static int
444 ecx_priv_print(BIO *bio, const EVP_PKEY *pkey, int indent, ASN1_PCTX *ctx)
445 {
446 	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
447 	const char *name;
448 
449 	if ((name = OBJ_nid2ln(pkey->ameth->pkey_id)) == NULL)
450 		return 0;
451 
452 	if (ecx_key == NULL || ecx_key->priv_key == NULL)
453 		return BIO_printf(bio, "%*s<INVALID PRIVATE KEY>\n",
454 		    indent, "") > 0;
455 
456 	if (BIO_printf(bio, "%*s%s Private-Key:\n", indent, "", name) <= 0)
457 		return 0;
458 	if (BIO_printf(bio, "%*spriv:\n", indent, "") <= 0)
459 		return 0;
460 	if (!ecx_buf_print(bio, ecx_key->priv_key, ecx_key->priv_key_len, indent))
461 		return 0;
462 	if (BIO_printf(bio, "%*spub:\n", indent, "") <= 0)
463 		return 0;
464 	if (!ecx_buf_print(bio, ecx_key->pub_key, ecx_key->pub_key_len, indent))
465 		return 0;
466 
467 	return 1;
468 }
469 
470 static int
471 ecx_size(const EVP_PKEY *pkey)
472 {
473 	return ecx_key_len(pkey->ameth->pkey_id);
474 }
475 
476 static int
477 ecx_sig_size(const EVP_PKEY *pkey)
478 {
479 	switch (pkey->ameth->pkey_id) {
480 	case EVP_PKEY_ED25519:
481 		return ED25519_SIG_SIZE;
482 	}
483 	return 0;
484 }
485 
486 static int
487 ecx_bits(const EVP_PKEY *pkey)
488 {
489 	switch (pkey->ameth->pkey_id) {
490 	case EVP_PKEY_ED25519:
491 		return ED25519_BITS;
492 	case EVP_PKEY_X25519:
493 		return X25519_BITS;
494 	}
495 	return 0;
496 }
497 
498 static int
499 ecx_security_bits(const EVP_PKEY *pkey)
500 {
501 	switch (pkey->ameth->pkey_id) {
502 	case EVP_PKEY_ED25519:
503 		return ED25519_SECURITY_BITS;
504 	case EVP_PKEY_X25519:
505 		return X25519_SECURITY_BITS;
506 	}
507 	return 0;
508 }
509 
510 static int
511 ecx_param_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2)
512 {
513 	/* No parameters, so always equivalent. */
514 	return 1;
515 }
516 
517 static void
518 ecx_free(EVP_PKEY *pkey)
519 {
520 	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
521 
522 	ecx_key_free(ecx_key);
523 }
524 
525 static int
526 ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
527 {
528 	/* Not supported. */
529 	return -2;
530 }
531 
532 static int
533 ecx_sign_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
534 {
535 	switch (op) {
536 	case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
537 		/* PureEdDSA does its own hashing. */
538 		*(int *)arg2 = NID_undef;
539 		return 2;
540 	}
541 	return -2;
542 }
543 
544 static int
545 ecx_set_priv_key(EVP_PKEY *pkey, const uint8_t *priv, size_t len)
546 {
547 	struct ecx_key_st *ecx_key = NULL;
548 	int ret = 0;
549 
550 	if (priv == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) {
551 		ECerror(EC_R_INVALID_ENCODING);
552 		goto err;
553 	}
554 
555 	if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
556 		goto err;
557 	if (!ecx_key_set_priv(ecx_key, priv, len))
558 		goto err;
559 	if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
560 		goto err;
561 	ecx_key = NULL;
562 
563 	ret = 1;
564 
565  err:
566 	ecx_key_free(ecx_key);
567 
568 	return ret;
569 }
570 
571 static int
572 ecx_set_pub_key(EVP_PKEY *pkey, const uint8_t *pub, size_t len)
573 {
574 	struct ecx_key_st *ecx_key = NULL;
575 	int ret = 0;
576 
577 	if (pub == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) {
578 		ECerror(EC_R_INVALID_ENCODING);
579 		goto err;
580 	}
581 
582 	if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
583 		goto err;
584 	if (!ecx_key_set_pub(ecx_key, pub, len))
585 		goto err;
586 	if (!EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx_key))
587 		goto err;
588 	ecx_key = NULL;
589 
590 	ret = 1;
591 
592  err:
593 	ecx_key_free(ecx_key);
594 
595 	return ret;
596 }
597 
598 static int
599 ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *out_priv, size_t *out_len)
600 {
601 	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
602 	CBS cbs;
603 
604 	if (out_priv == NULL) {
605 		*out_len = ecx_key_len(pkey->ameth->pkey_id);
606 		return 1;
607 	}
608 
609 	if (ecx_key == NULL || ecx_key->priv_key == NULL)
610 		return 0;
611 
612 	CBS_init(&cbs, ecx_key->priv_key, ecx_key->priv_key_len);
613 	if (!CBS_write_bytes(&cbs, out_priv, *out_len, out_len))
614 		return 0;
615 
616 	return 1;
617 }
618 
619 static int
620 ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *out_pub, size_t *out_len)
621 {
622 	struct ecx_key_st *ecx_key = pkey->pkey.ecx;
623 	CBS cbs;
624 
625 	if (out_pub == NULL) {
626 		*out_len = ecx_key_len(pkey->ameth->pkey_id);
627 		return 1;
628 	}
629 
630 	if (ecx_key == NULL || ecx_key->pub_key == NULL)
631 		return 0;
632 
633 	CBS_init(&cbs, ecx_key->pub_key, ecx_key->pub_key_len);
634 	if (!CBS_write_bytes(&cbs, out_pub, *out_len, out_len))
635 		return 0;
636 
637 	return 1;
638 }
639 
640 static int
641 pkey_ecx_keygen(EVP_PKEY_CTX *pkey_ctx, EVP_PKEY *pkey)
642 {
643 	struct ecx_key_st *ecx_key = NULL;
644 	int ret = 0;
645 
646 	if ((ecx_key = ecx_key_new(pkey_ctx->pmeth->pkey_id)) == NULL)
647 		goto err;
648 	if (!ecx_key_generate(ecx_key))
649 		goto err;
650 	if (!EVP_PKEY_assign(pkey, pkey_ctx->pmeth->pkey_id, ecx_key))
651 		goto err;
652 	ecx_key = NULL;
653 
654 	ret = 1;
655 
656  err:
657 	ecx_key_free(ecx_key);
658 
659 	return ret;
660 }
661 
662 static int
663 pkey_ecx_derive(EVP_PKEY_CTX *pkey_ctx, unsigned char *out_key,
664     size_t *out_key_len)
665 {
666 	struct ecx_key_st *ecx_key, *ecx_peer_key;
667 
668 	if (pkey_ctx->pkey == NULL || pkey_ctx->peerkey == NULL) {
669 		ECerror(EC_R_KEYS_NOT_SET);
670 		return 0;
671 	}
672 
673 	if ((ecx_key = pkey_ctx->pkey->pkey.ecx) == NULL) {
674 		ECerror(EC_R_INVALID_PRIVATE_KEY);
675 		return 0;
676 	}
677 	if (ecx_key->priv_key == NULL) {
678 		ECerror(EC_R_INVALID_PRIVATE_KEY);
679 		return 0;
680 	}
681 
682 	if ((ecx_peer_key = pkey_ctx->peerkey->pkey.ecx) == NULL) {
683 		ECerror(EC_R_INVALID_PEER_KEY);
684 		return 0;
685 	}
686 
687 	if (out_key != NULL) {
688 		if (!X25519(out_key, ecx_key->priv_key, ecx_peer_key->pub_key))
689 			return 0;
690 	}
691 
692 	*out_key_len = X25519_KEYLEN;
693 
694 	return 1;
695 }
696 
697 static int
698 pkey_ecx_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2)
699 {
700 	if (op == EVP_PKEY_CTRL_PEER_KEY)
701 		return 1;
702 
703 	return -2;
704 }
705 
706 static int
707 ecx_item_verify(EVP_MD_CTX *md_ctx, const ASN1_ITEM *it, void *asn,
708    X509_ALGOR *algor, ASN1_BIT_STRING *abs, EVP_PKEY *pkey)
709 {
710 	const ASN1_OBJECT *aobj;
711 	int nid, param_type;
712 
713 	X509_ALGOR_get0(&aobj, &param_type, NULL, algor);
714 
715 	nid = OBJ_obj2nid(aobj);
716 
717 	if (nid != NID_ED25519 || param_type != V_ASN1_UNDEF) {
718 		ECerror(EC_R_INVALID_ENCODING);
719 		return -1;
720 	}
721 
722 	if (!EVP_DigestVerifyInit(md_ctx, NULL, NULL, NULL, pkey))
723 		return -1;
724 
725 	return 2;
726 }
727 
728 static int
729 ecx_item_sign(EVP_MD_CTX *md_ctx, const ASN1_ITEM *it, void *asn,
730     X509_ALGOR *algor1, X509_ALGOR *algor2, ASN1_BIT_STRING *abs)
731 {
732 	ASN1_OBJECT *aobj;
733 
734 	if ((aobj = OBJ_nid2obj(NID_ED25519)) == NULL)
735 		return 0;
736 
737 	if (!X509_ALGOR_set0(algor1, aobj, V_ASN1_UNDEF, NULL))
738 		return 0;
739 
740 	if (algor2 != NULL) {
741 		if (!X509_ALGOR_set0(algor2, aobj, V_ASN1_UNDEF, NULL))
742 			return 0;
743 	}
744 
745 	/* Tell ASN1_item_sign_ctx() that identifiers are set and it needs to sign. */
746 	return 3;
747 }
748 
749 static int
750 pkey_ecx_digestsign(EVP_MD_CTX *md_ctx, unsigned char *out_sig,
751     size_t *out_sig_len, const unsigned char *message, size_t message_len)
752 {
753 	struct ecx_key_st *ecx_key;
754 	EVP_PKEY_CTX *pkey_ctx;
755 
756 	pkey_ctx = EVP_MD_CTX_pkey_ctx(md_ctx);
757 	ecx_key = pkey_ctx->pkey->pkey.ecx;
758 
759 	if (out_sig == NULL) {
760 		*out_sig_len = ecx_sig_size(pkey_ctx->pkey);
761 		return 1;
762 	}
763 	if (*out_sig_len < ecx_sig_size(pkey_ctx->pkey)) {
764 		ECerror(EC_R_BUFFER_TOO_SMALL);
765 		return 0;
766 	}
767 
768 	if (ecx_key == NULL)
769 		return 0;
770 	if (ecx_key->priv_key == NULL || ecx_key->pub_key == NULL)
771 		return 0;
772 
773 	if (!ED25519_sign(out_sig, message, message_len, ecx_key->pub_key,
774 	    ecx_key->priv_key))
775 		return 0;
776 
777 	*out_sig_len = ecx_sig_size(pkey_ctx->pkey);
778 
779 	return 1;
780 }
781 
782 static int
783 pkey_ecx_digestverify(EVP_MD_CTX *md_ctx, const unsigned char *sig,
784    size_t sig_len, const unsigned char *message, size_t message_len)
785 {
786 	struct ecx_key_st *ecx_key;
787 	EVP_PKEY_CTX *pkey_ctx;
788 
789 	pkey_ctx = EVP_MD_CTX_pkey_ctx(md_ctx);
790 	ecx_key = pkey_ctx->pkey->pkey.ecx;
791 
792 	if (ecx_key == NULL || ecx_key->pub_key == NULL)
793 		return -1;
794 	if (sig_len != ecx_sig_size(pkey_ctx->pkey))
795 		return -1;
796 
797 	return ED25519_verify(message, message_len, sig, ecx_key->pub_key);
798 }
799 
800 static int
801 pkey_ecx_ed_ctrl(EVP_PKEY_CTX *pkey_ctx, int op, int arg1, void *arg2)
802 {
803 	switch (op) {
804 	case EVP_PKEY_CTRL_MD:
805 		/* PureEdDSA does its own hashing. */
806 		if (arg2 != NULL && (const EVP_MD *)arg2 != EVP_md_null()) {
807 			ECerror(EC_R_INVALID_DIGEST_TYPE);
808 			return 0;
809 		}
810 		return 1;
811 
812 	case EVP_PKEY_CTRL_DIGESTINIT:
813 		return 1;
814 	}
815 	return -2;
816 }
817 
818 const EVP_PKEY_ASN1_METHOD x25519_asn1_meth = {
819 	.pkey_id = EVP_PKEY_X25519,
820 	.pkey_base_id = EVP_PKEY_X25519,
821 	.pkey_flags = 0,
822 	.pem_str = "X25519",
823 	.info = "OpenSSL X25519 algorithm",
824 
825 	.pub_decode = ecx_pub_decode,
826 	.pub_encode = ecx_pub_encode,
827 	.pub_cmp = ecx_pub_cmp,
828 	.pub_print = ecx_pub_print,
829 
830 	.priv_decode = ecx_priv_decode,
831 	.priv_encode = ecx_priv_encode,
832 	.priv_print = ecx_priv_print,
833 
834 	.pkey_size = ecx_size,
835 	.pkey_bits = ecx_bits,
836 	.pkey_security_bits = ecx_security_bits,
837 
838 	.param_cmp = ecx_param_cmp,
839 
840 	.pkey_free = ecx_free,
841 	.pkey_ctrl = ecx_ctrl,
842 
843 	.set_priv_key = ecx_set_priv_key,
844 	.set_pub_key = ecx_set_pub_key,
845 	.get_priv_key = ecx_get_priv_key,
846 	.get_pub_key = ecx_get_pub_key,
847 };
848 
849 const EVP_PKEY_METHOD x25519_pkey_meth = {
850 	.pkey_id = EVP_PKEY_X25519,
851 	.keygen = pkey_ecx_keygen,
852 	.derive = pkey_ecx_derive,
853 	.ctrl = pkey_ecx_ctrl,
854 };
855 
856 const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth = {
857 	.pkey_id = EVP_PKEY_ED25519,
858 	.pkey_base_id = EVP_PKEY_ED25519,
859 	.pkey_flags = 0,
860 	.pem_str = "ED25519",
861 	.info = "OpenSSL ED25519 algorithm",
862 
863 	.pub_decode = ecx_pub_decode,
864 	.pub_encode = ecx_pub_encode,
865 	.pub_cmp = ecx_pub_cmp,
866 	.pub_print = ecx_pub_print,
867 
868 	.priv_decode = ecx_priv_decode,
869 	.priv_encode = ecx_priv_encode,
870 	.priv_print = ecx_priv_print,
871 
872 	.pkey_size = ecx_sig_size,
873 	.pkey_bits = ecx_bits,
874 	.pkey_security_bits = ecx_security_bits,
875 
876 	.param_cmp = ecx_param_cmp,
877 
878 	.pkey_free = ecx_free,
879 	.pkey_ctrl = ecx_sign_ctrl,
880 
881 	.item_verify = ecx_item_verify,
882 	.item_sign = ecx_item_sign,
883 
884 	.set_priv_key = ecx_set_priv_key,
885 	.set_pub_key = ecx_set_pub_key,
886 	.get_priv_key = ecx_get_priv_key,
887 	.get_pub_key = ecx_get_pub_key,
888 };
889 
890 const EVP_PKEY_METHOD ed25519_pkey_meth = {
891 	.pkey_id = EVP_PKEY_ED25519,
892 	.flags = EVP_PKEY_FLAG_SIGCTX_CUSTOM,
893 	.keygen = pkey_ecx_keygen,
894 	.ctrl = pkey_ecx_ed_ctrl,
895 	.digestsign = pkey_ecx_digestsign,
896 	.digestverify = pkey_ecx_digestverify,
897 };
898