summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorjsing <>2022-11-10 16:37:52 +0000
committerjsing <>2022-11-10 16:37:52 +0000
commit8bbca4710a981e94365a52a3aad374c251e1d0a5 (patch)
treea195899b53d4926967b849934341c4be077ceb67 /src/lib
parent313fb25a243cac7bb2c5d40518041217e06a9d16 (diff)
downloadopenbsd-8bbca4710a981e94365a52a3aad374c251e1d0a5.tar.gz
openbsd-8bbca4710a981e94365a52a3aad374c251e1d0a5.tar.bz2
openbsd-8bbca4710a981e94365a52a3aad374c251e1d0a5.zip
Implement EVP interfaces for Ed25519 and X25519.
ok beck@ tb@
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/Makefile4
-rw-r--r--src/lib/libcrypto/asn1/ameth_lib.c6
-rw-r--r--src/lib/libcrypto/ec/ec.h4
-rw-r--r--src/lib/libcrypto/ec/ec_err.c4
-rw-r--r--src/lib/libcrypto/ec/ecx_methods.c862
-rw-r--r--src/lib/libcrypto/evp/evp.h11
-rw-r--r--src/lib/libcrypto/evp/evp_locl.h12
-rw-r--r--src/lib/libcrypto/evp/pmeth_lib.c6
8 files changed, 902 insertions, 7 deletions
diff --git a/src/lib/libcrypto/Makefile b/src/lib/libcrypto/Makefile
index b25ea5f948..084d6c1786 100644
--- a/src/lib/libcrypto/Makefile
+++ b/src/lib/libcrypto/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.85 2022/11/10 16:00:34 joshua Exp $ 1# $OpenBSD: Makefile,v 1.86 2022/11/10 16:37:51 jsing Exp $
2 2
3LIB= crypto 3LIB= crypto
4LIBREBUILD=y 4LIBREBUILD=y
@@ -33,6 +33,7 @@ CFLAGS+= -I${LCRYPTO_SRC}/asn1
33CFLAGS+= -I${LCRYPTO_SRC}/bio 33CFLAGS+= -I${LCRYPTO_SRC}/bio
34CFLAGS+= -I${LCRYPTO_SRC}/bn 34CFLAGS+= -I${LCRYPTO_SRC}/bn
35CFLAGS+= -I${LCRYPTO_SRC}/bytestring 35CFLAGS+= -I${LCRYPTO_SRC}/bytestring
36CFLAGS+= -I${LCRYPTO_SRC}/curve25519
36CFLAGS+= -I${LCRYPTO_SRC}/dh 37CFLAGS+= -I${LCRYPTO_SRC}/dh
37CFLAGS+= -I${LCRYPTO_SRC}/dsa 38CFLAGS+= -I${LCRYPTO_SRC}/dsa
38CFLAGS+= -I${LCRYPTO_SRC}/ec 39CFLAGS+= -I${LCRYPTO_SRC}/ec
@@ -361,6 +362,7 @@ SRCS+= ecp_nistp521.c
361SRCS+= ecp_nistputil.c 362SRCS+= ecp_nistputil.c
362SRCS+= ecp_oct.c 363SRCS+= ecp_oct.c
363SRCS+= ecp_smpl.c 364SRCS+= ecp_smpl.c
365SRCS+= ecx_methods.c
364 366
365# ecdh/ 367# ecdh/
366SRCS+= ecdh_kdf.c 368SRCS+= ecdh_kdf.c
diff --git a/src/lib/libcrypto/asn1/ameth_lib.c b/src/lib/libcrypto/asn1/ameth_lib.c
index cca1dcce7d..143c010dfa 100644
--- a/src/lib/libcrypto/asn1/ameth_lib.c
+++ b/src/lib/libcrypto/asn1/ameth_lib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ameth_lib.c,v 1.28 2022/11/09 18:17:16 jsing Exp $ */ 1/* $OpenBSD: ameth_lib.c,v 1.29 2022/11/10 16:37:51 jsing Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2006. 3 * project 2006.
4 */ 4 */
@@ -75,11 +75,13 @@ extern const EVP_PKEY_ASN1_METHOD cmac_asn1_meth;
75extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth; 75extern const EVP_PKEY_ASN1_METHOD dh_asn1_meth;
76extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[]; 76extern const EVP_PKEY_ASN1_METHOD dsa_asn1_meths[];
77extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth; 77extern const EVP_PKEY_ASN1_METHOD eckey_asn1_meth;
78extern const EVP_PKEY_ASN1_METHOD ed25519_asn1_meth;
78extern const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth; 79extern const EVP_PKEY_ASN1_METHOD gostimit_asn1_meth;
79extern const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[]; 80extern const EVP_PKEY_ASN1_METHOD gostr01_asn1_meths[];
80extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth; 81extern const EVP_PKEY_ASN1_METHOD hmac_asn1_meth;
81extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[]; 82extern const EVP_PKEY_ASN1_METHOD rsa_asn1_meths[];
82extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth; 83extern const EVP_PKEY_ASN1_METHOD rsa_pss_asn1_meth;
84extern const EVP_PKEY_ASN1_METHOD x25519_asn1_meth;
83 85
84static const EVP_PKEY_ASN1_METHOD *asn1_methods[] = { 86static const EVP_PKEY_ASN1_METHOD *asn1_methods[] = {
85 &cmac_asn1_meth, 87 &cmac_asn1_meth,
@@ -90,6 +92,7 @@ static const EVP_PKEY_ASN1_METHOD *asn1_methods[] = {
90 &dsa_asn1_meths[3], 92 &dsa_asn1_meths[3],
91 &dsa_asn1_meths[4], 93 &dsa_asn1_meths[4],
92 &eckey_asn1_meth, 94 &eckey_asn1_meth,
95 &ed25519_asn1_meth,
93 &gostimit_asn1_meth, 96 &gostimit_asn1_meth,
94 &gostr01_asn1_meths[0], 97 &gostr01_asn1_meths[0],
95 &gostr01_asn1_meths[1], 98 &gostr01_asn1_meths[1],
@@ -98,6 +101,7 @@ static const EVP_PKEY_ASN1_METHOD *asn1_methods[] = {
98 &rsa_asn1_meths[0], 101 &rsa_asn1_meths[0],
99 &rsa_asn1_meths[1], 102 &rsa_asn1_meths[1],
100 &rsa_pss_asn1_meth, 103 &rsa_pss_asn1_meth,
104 &x25519_asn1_meth,
101}; 105};
102 106
103static const size_t asn1_methods_count = 107static const size_t asn1_methods_count =
diff --git a/src/lib/libcrypto/ec/ec.h b/src/lib/libcrypto/ec/ec.h
index 52c8f2f329..9a7c5de8a5 100644
--- a/src/lib/libcrypto/ec/ec.h
+++ b/src/lib/libcrypto/ec/ec.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec.h,v 1.28 2022/07/12 14:42:49 kn Exp $ */ 1/* $OpenBSD: ec.h,v 1.29 2022/11/10 16:37:51 jsing Exp $ */
2/* 2/*
3 * Originally written by Bodo Moeller for the OpenSSL project. 3 * Originally written by Bodo Moeller for the OpenSSL project.
4 */ 4 */
@@ -1289,6 +1289,8 @@ void ERR_load_EC_strings(void);
1289#define EC_R_INVALID_FIELD 103 1289#define EC_R_INVALID_FIELD 103
1290#define EC_R_INVALID_FORM 104 1290#define EC_R_INVALID_FORM 104
1291#define EC_R_INVALID_GROUP_ORDER 122 1291#define EC_R_INVALID_GROUP_ORDER 122
1292#define EC_R_INVALID_KEY 165
1293#define EC_R_INVALID_PEER_KEY 152
1292#define EC_R_INVALID_PENTANOMIAL_BASIS 132 1294#define EC_R_INVALID_PENTANOMIAL_BASIS 132
1293#define EC_R_INVALID_PRIVATE_KEY 123 1295#define EC_R_INVALID_PRIVATE_KEY 123
1294#define EC_R_INVALID_TRINOMIAL_BASIS 137 1296#define EC_R_INVALID_TRINOMIAL_BASIS 137
diff --git a/src/lib/libcrypto/ec/ec_err.c b/src/lib/libcrypto/ec/ec_err.c
index d8ead9636c..2ff8e9974e 100644
--- a/src/lib/libcrypto/ec/ec_err.c
+++ b/src/lib/libcrypto/ec/ec_err.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ec_err.c,v 1.13 2022/07/12 14:42:49 kn Exp $ */ 1/* $OpenBSD: ec_err.c,v 1.14 2022/11/10 16:37:52 jsing Exp $ */
2/* ==================================================================== 2/* ====================================================================
3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved. 3 * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
4 * 4 *
@@ -96,6 +96,8 @@ static ERR_STRING_DATA EC_str_reasons[] =
96 {ERR_REASON(EC_R_INVALID_FIELD), "invalid field"}, 96 {ERR_REASON(EC_R_INVALID_FIELD), "invalid field"},
97 {ERR_REASON(EC_R_INVALID_FORM), "invalid form"}, 97 {ERR_REASON(EC_R_INVALID_FORM), "invalid form"},
98 {ERR_REASON(EC_R_INVALID_GROUP_ORDER), "invalid group order"}, 98 {ERR_REASON(EC_R_INVALID_GROUP_ORDER), "invalid group order"},
99 {ERR_REASON(EC_R_INVALID_KEY), "invalid key"},
100 {ERR_REASON(EC_R_INVALID_PEER_KEY), "invalid peer key"},
99 {ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"}, 101 {ERR_REASON(EC_R_INVALID_PENTANOMIAL_BASIS), "invalid pentanomial basis"},
100 {ERR_REASON(EC_R_INVALID_PRIVATE_KEY), "invalid private key"}, 102 {ERR_REASON(EC_R_INVALID_PRIVATE_KEY), "invalid private key"},
101 {ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS), "invalid trinomial basis"}, 103 {ERR_REASON(EC_R_INVALID_TRINOMIAL_BASIS), "invalid trinomial basis"},
diff --git a/src/lib/libcrypto/ec/ecx_methods.c b/src/lib/libcrypto/ec/ecx_methods.c
new file mode 100644
index 0000000000..741cb2de6b
--- /dev/null
+++ b/src/lib/libcrypto/ec/ecx_methods.c
@@ -0,0 +1,862 @@
1/* $OpenBSD: ecx_methods.c,v 1.1 2022/11/10 16:37:52 jsing 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_locl.h"
27#include "bytestring.h"
28#include "curve25519_internal.h"
29#include "evp_locl.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
45static int
46ecx_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
58static struct ecx_key_st *
59ecx_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
76static void
77ecx_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
88static void
89ecx_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
99static int
100ecx_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
140static int
141ecx_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
180static int
181ecx_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
198static int
199ecx_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
241static int
242ecx_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
281static int
282ecx_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
295static int
296ecx_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
319static int
320ecx_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
368static int
369ecx_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
408static int
409ecx_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
437static int
438ecx_size(const EVP_PKEY *pkey)
439{
440 return ecx_key_len(pkey->ameth->pkey_id);
441}
442
443static int
444ecx_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
453static int
454ecx_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
465static int
466ecx_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
477static int
478ecx_param_cmp(const EVP_PKEY *pkey1, const EVP_PKEY *pkey2)
479{
480 /* No parameters, so always equivalent. */
481 return 1;
482}
483
484static void
485ecx_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
492static int
493ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
494{
495 /* Not supported. */
496 return -2;
497}
498
499static int
500ecx_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
511static int
512ecx_set_priv_key(EVP_PKEY *pkey, const uint8_t *priv, size_t len)
513{
514 struct ecx_key_st *ecx_key;
515 int ret = 0;
516
517 if (priv == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) {
518 ECerror(EC_R_INVALID_ENCODING);
519 return 0;
520 }
521
522 if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
523 return 0;
524 if (!ecx_key_set_priv(ecx_key, priv, len))
525 return 0;
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
538static int
539ecx_set_pub_key(EVP_PKEY *pkey, const uint8_t *pub, size_t len)
540{
541 struct ecx_key_st *ecx_key;
542 int ret = 0;
543
544 if (pub == NULL || len != ecx_key_len(pkey->ameth->pkey_id)) {
545 ECerror(EC_R_INVALID_ENCODING);
546 return 0;
547 }
548
549 if ((ecx_key = ecx_key_new(pkey->ameth->pkey_id)) == NULL)
550 return 0;
551 if (!ecx_key_set_pub(ecx_key, pub, len))
552 return 0;
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
565static int
566ecx_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
586static int
587ecx_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
607static int
608pkey_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
629static int
630pkey_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
664static int
665pkey_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
673static int
674ecx_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
695static int
696ecx_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
716static int
717pkey_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
747static int
748pkey_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
765static int
766pkey_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
783const 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
814const 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
821const 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
855const 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};
diff --git a/src/lib/libcrypto/evp/evp.h b/src/lib/libcrypto/evp/evp.h
index f4702ab433..f8bab26b3f 100644
--- a/src/lib/libcrypto/evp/evp.h
+++ b/src/lib/libcrypto/evp/evp.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: evp.h,v 1.110 2022/11/10 15:17:30 jsing Exp $ */ 1/* $OpenBSD: evp.h,v 1.111 2022/11/10 16:37:52 jsing Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -115,6 +115,10 @@
115#define EVP_PKEY_HKDF NID_hkdf 115#define EVP_PKEY_HKDF NID_hkdf
116#define EVP_PKEY_GOSTR12_256 NID_id_tc26_gost3410_2012_256 116#define EVP_PKEY_GOSTR12_256 NID_id_tc26_gost3410_2012_256
117#define EVP_PKEY_GOSTR12_512 NID_id_tc26_gost3410_2012_512 117#define EVP_PKEY_GOSTR12_512 NID_id_tc26_gost3410_2012_512
118#if defined(LIBRESSL_NEXT_API) || defined(LIBRESSL_INTERNAL)
119#define EVP_PKEY_ED25519 NID_ED25519
120#define EVP_PKEY_X25519 NID_X25519
121#endif
118 122
119#ifdef __cplusplus 123#ifdef __cplusplus
120extern "C" { 124extern "C" {
@@ -297,6 +301,11 @@ extern "C" {
297/* Length of tag for TLS */ 301/* Length of tag for TLS */
298#define EVP_CHACHAPOLY_TLS_TAG_LEN 16 302#define EVP_CHACHAPOLY_TLS_TAG_LEN 16
299 303
304#if defined(LIBRESSL_NEXT_API) || defined(LIBRESSL_INTERNAL)
305#define ED25519_KEYLEN 32
306#define X25519_KEYLEN 32
307#endif
308
300typedef struct evp_cipher_info_st { 309typedef struct evp_cipher_info_st {
301 const EVP_CIPHER *cipher; 310 const EVP_CIPHER *cipher;
302 unsigned char iv[EVP_MAX_IV_LENGTH]; 311 unsigned char iv[EVP_MAX_IV_LENGTH];
diff --git a/src/lib/libcrypto/evp/evp_locl.h b/src/lib/libcrypto/evp/evp_locl.h
index dd7d2522e6..37fc55eb9c 100644
--- a/src/lib/libcrypto/evp/evp_locl.h
+++ b/src/lib/libcrypto/evp/evp_locl.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: evp_locl.h,v 1.29 2022/11/10 15:17:30 jsing Exp $ */ 1/* $OpenBSD: evp_locl.h,v 1.30 2022/11/10 16:37:52 jsing Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2000. 3 * project 2000.
4 */ 4 */
@@ -74,6 +74,15 @@ typedef int evp_verify_method(int type, const unsigned char *m,
74 unsigned int m_length, const unsigned char *sigbuf, unsigned int siglen, 74 unsigned int m_length, const unsigned char *sigbuf, unsigned int siglen,
75 void *key); 75 void *key);
76 76
77struct ecx_key_st {
78 int nid;
79 int key_len;
80 uint8_t *priv_key;
81 size_t priv_key_len;
82 uint8_t *pub_key;
83 size_t pub_key_len;
84};
85
77/* Type needs to be a bit field 86/* Type needs to be a bit field
78 * Sub-type needs to be for variations on the method, as in, can it do 87 * Sub-type needs to be for variations on the method, as in, can it do
79 * arbitrary encryption.... */ 88 * arbitrary encryption.... */
@@ -96,6 +105,7 @@ struct evp_pkey_st {
96#endif 105#endif
97#ifndef OPENSSL_NO_EC 106#ifndef OPENSSL_NO_EC
98 struct ec_key_st *ec; /* ECC */ 107 struct ec_key_st *ec; /* ECC */
108 struct ecx_key_st *ecx; /* ECX */
99#endif 109#endif
100#ifndef OPENSSL_NO_GOST 110#ifndef OPENSSL_NO_GOST
101 struct gost_key_st *gost; /* GOST */ 111 struct gost_key_st *gost; /* GOST */
diff --git a/src/lib/libcrypto/evp/pmeth_lib.c b/src/lib/libcrypto/evp/pmeth_lib.c
index 0a0451fd92..19610dfbad 100644
--- a/src/lib/libcrypto/evp/pmeth_lib.c
+++ b/src/lib/libcrypto/evp/pmeth_lib.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: pmeth_lib.c,v 1.24 2022/11/09 18:25:36 jsing Exp $ */ 1/* $OpenBSD: pmeth_lib.c,v 1.25 2022/11/10 16:37:52 jsing Exp $ */
2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL 2/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project 2006. 3 * project 2006.
4 */ 4 */
@@ -82,24 +82,28 @@ extern const EVP_PKEY_METHOD cmac_pkey_meth;
82extern const EVP_PKEY_METHOD dh_pkey_meth; 82extern const EVP_PKEY_METHOD dh_pkey_meth;
83extern const EVP_PKEY_METHOD dsa_pkey_meth; 83extern const EVP_PKEY_METHOD dsa_pkey_meth;
84extern const EVP_PKEY_METHOD ec_pkey_meth; 84extern const EVP_PKEY_METHOD ec_pkey_meth;
85extern const EVP_PKEY_METHOD ed25519_pkey_meth;
85extern const EVP_PKEY_METHOD gostimit_pkey_meth; 86extern const EVP_PKEY_METHOD gostimit_pkey_meth;
86extern const EVP_PKEY_METHOD gostr01_pkey_meth; 87extern const EVP_PKEY_METHOD gostr01_pkey_meth;
87extern const EVP_PKEY_METHOD hkdf_pkey_meth; 88extern const EVP_PKEY_METHOD hkdf_pkey_meth;
88extern const EVP_PKEY_METHOD hmac_pkey_meth; 89extern const EVP_PKEY_METHOD hmac_pkey_meth;
89extern const EVP_PKEY_METHOD rsa_pkey_meth; 90extern const EVP_PKEY_METHOD rsa_pkey_meth;
90extern const EVP_PKEY_METHOD rsa_pss_pkey_meth; 91extern const EVP_PKEY_METHOD rsa_pss_pkey_meth;
92extern const EVP_PKEY_METHOD x25519_pkey_meth;
91 93
92static const EVP_PKEY_METHOD *pkey_methods[] = { 94static const EVP_PKEY_METHOD *pkey_methods[] = {
93 &cmac_pkey_meth, 95 &cmac_pkey_meth,
94 &dh_pkey_meth, 96 &dh_pkey_meth,
95 &dsa_pkey_meth, 97 &dsa_pkey_meth,
96 &ec_pkey_meth, 98 &ec_pkey_meth,
99 &ed25519_pkey_meth,
97 &gostimit_pkey_meth, 100 &gostimit_pkey_meth,
98 &gostr01_pkey_meth, 101 &gostr01_pkey_meth,
99 &hkdf_pkey_meth, 102 &hkdf_pkey_meth,
100 &hmac_pkey_meth, 103 &hmac_pkey_meth,
101 &rsa_pkey_meth, 104 &rsa_pkey_meth,
102 &rsa_pss_pkey_meth, 105 &rsa_pss_pkey_meth,
106 &x25519_pkey_meth,
103}; 107};
104 108
105static const size_t pkey_methods_count = 109static const size_t pkey_methods_count =