summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/ec/ecx_methods.c
diff options
context:
space:
mode:
authorcvs2svn <admin@example.com>2025-04-14 17:32:06 +0000
committercvs2svn <admin@example.com>2025-04-14 17:32:06 +0000
commiteb8dd9dca1228af0cd132f515509051ecfabf6f6 (patch)
treeedb6da6af7e865d488dc1a29309f1e1ec226e603 /src/lib/libcrypto/ec/ecx_methods.c
parent247f0352e0ed72a4f476db9dc91f4d982bc83eb2 (diff)
downloadopenbsd-tb_20250414.tar.gz
openbsd-tb_20250414.tar.bz2
openbsd-tb_20250414.zip
This commit was manufactured by cvs2git to create tag 'tb_20250414'.tb_20250414
Diffstat (limited to 'src/lib/libcrypto/ec/ecx_methods.c')
-rw-r--r--src/lib/libcrypto/ec/ecx_methods.c973
1 files changed, 0 insertions, 973 deletions
diff --git a/src/lib/libcrypto/ec/ecx_methods.c b/src/lib/libcrypto/ec/ecx_methods.c
deleted file mode 100644
index 6b5759d4fa..0000000000
--- a/src/lib/libcrypto/ec/ecx_methods.c
+++ /dev/null
@@ -1,973 +0,0 @@
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
47static int
48ecx_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
60static struct ecx_key_st *
61ecx_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
78static void
79ecx_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
90static void
91ecx_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
101static int
102ecx_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
142static int
143ecx_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
182static int
183ecx_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
200static int
201ecx_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
243static int
244ecx_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
283static int
284ecx_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. */
298static int
299ecx_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
333static int
334ecx_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
356static int
357ecx_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
405static int
406ecx_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
445static int
446ecx_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
472static int
473ecx_size(const EVP_PKEY *pkey)
474{
475 return ecx_key_len(pkey->ameth->pkey_id);
476}
477
478static int
479ecx_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
488static int
489ecx_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
500static int
501ecx_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
512static int
513ecx_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
530static int
531ecx_param_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2)
532{
533 /* No parameters, so always equivalent. */
534 return 1;
535}
536
537static void
538ecx_free(EVP_PKEY *pkey)
539{
540 struct ecx_key_st *ecx_key = pkey->pkey.ecx;
541
542 ecx_key_free(ecx_key);
543}
544
545static int
546ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
547{
548 /* Not supported. */
549 return -2;
550}
551
552#ifndef OPENSSL_NO_CMS
553static int
554ecx_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
603static int
604ecx_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
619static int
620ecx_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
646static int
647ecx_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
673static int
674ecx_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
694static int
695ecx_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
715static int
716pkey_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
737static int
738pkey_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
772static int
773pkey_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
781static int
782ecx_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
803static int
804ecx_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
820static int
821pkey_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
853static int
854pkey_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
871static int
872pkey_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
892const 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
923const 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
930const 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
966const 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};