1 /*
2 * Copyright 2006-2023 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 /*
11 * ECDSA low level APIs are deprecated for public use, but still ok for
12 * internal use.
13 */
14 #include "internal/deprecated.h"
15
16 #include <stdio.h>
17 #include <openssl/x509.h>
18 #include <openssl/ec.h>
19 #include <openssl/core_names.h>
20 #include <openssl/param_build.h>
21 #include <openssl/rand.h>
22 #include "internal/cryptlib.h"
23 #include "internal/provider.h"
24 #include "crypto/asn1.h"
25 #include "crypto/evp.h"
26 #include "crypto/ecx.h"
27 #include "ec_local.h"
28 #include "curve448/curve448_local.h"
29 #include "ecx_backend.h"
30
ecx_pub_encode(X509_PUBKEY * pk,const EVP_PKEY * pkey)31 static int ecx_pub_encode(X509_PUBKEY *pk, const EVP_PKEY *pkey)
32 {
33 const ECX_KEY *ecxkey = pkey->pkey.ecx;
34 unsigned char *penc;
35
36 if (ecxkey == NULL) {
37 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
38 return 0;
39 }
40
41 penc = OPENSSL_memdup(ecxkey->pubkey, KEYLEN(pkey));
42 if (penc == NULL)
43 return 0;
44
45 if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
46 V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
47 OPENSSL_free(penc);
48 ERR_raise(ERR_LIB_EC, ERR_R_X509_LIB);
49 return 0;
50 }
51 return 1;
52 }
53
ecx_pub_decode(EVP_PKEY * pkey,const X509_PUBKEY * pubkey)54 static int ecx_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
55 {
56 const unsigned char *p;
57 int pklen;
58 X509_ALGOR *palg;
59 ECX_KEY *ecx;
60 int ret = 0;
61
62 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
63 return 0;
64 ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id,
65 KEY_OP_PUBLIC, NULL, NULL);
66 if (ecx != NULL) {
67 ret = 1;
68 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
69 }
70 return ret;
71 }
72
ecx_pub_cmp(const EVP_PKEY * a,const EVP_PKEY * b)73 static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
74 {
75 const ECX_KEY *akey = a->pkey.ecx;
76 const ECX_KEY *bkey = b->pkey.ecx;
77
78 if (akey == NULL || bkey == NULL)
79 return -2;
80
81 return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
82 }
83
ecx_priv_decode_ex(EVP_PKEY * pkey,const PKCS8_PRIV_KEY_INFO * p8,OSSL_LIB_CTX * libctx,const char * propq)84 static int ecx_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
85 OSSL_LIB_CTX *libctx, const char *propq)
86 {
87 int ret = 0;
88 ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq);
89
90 if (ecx != NULL) {
91 ret = 1;
92 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
93 }
94
95 return ret;
96 }
97
ecx_priv_encode(PKCS8_PRIV_KEY_INFO * p8,const EVP_PKEY * pkey)98 static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
99 {
100 const ECX_KEY *ecxkey = pkey->pkey.ecx;
101 ASN1_OCTET_STRING oct;
102 unsigned char *penc = NULL;
103 int penclen;
104
105 if (ecxkey == NULL || ecxkey->privkey == NULL) {
106 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
107 return 0;
108 }
109
110 oct.data = ecxkey->privkey;
111 oct.length = KEYLEN(pkey);
112 oct.flags = 0;
113
114 penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
115 if (penclen < 0) {
116 ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
117 return 0;
118 }
119
120 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
121 V_ASN1_UNDEF, NULL, penc, penclen)) {
122 OPENSSL_clear_free(penc, penclen);
123 ERR_raise(ERR_LIB_EC, ERR_R_ASN1_LIB);
124 return 0;
125 }
126
127 return 1;
128 }
129
ecx_size(const EVP_PKEY * pkey)130 static int ecx_size(const EVP_PKEY *pkey)
131 {
132 return KEYLEN(pkey);
133 }
134
ecx_bits(const EVP_PKEY * pkey)135 static int ecx_bits(const EVP_PKEY *pkey)
136 {
137 if (IS25519(pkey->ameth->pkey_id)) {
138 return X25519_BITS;
139 } else if (ISX448(pkey->ameth->pkey_id)) {
140 return X448_BITS;
141 } else {
142 return ED448_BITS;
143 }
144 }
145
ecx_security_bits(const EVP_PKEY * pkey)146 static int ecx_security_bits(const EVP_PKEY *pkey)
147 {
148 if (IS25519(pkey->ameth->pkey_id)) {
149 return X25519_SECURITY_BITS;
150 } else {
151 return X448_SECURITY_BITS;
152 }
153 }
154
ecx_free(EVP_PKEY * pkey)155 static void ecx_free(EVP_PKEY *pkey)
156 {
157 ossl_ecx_key_free(pkey->pkey.ecx);
158 }
159
160 /* "parameters" are always equal */
ecx_cmp_parameters(const EVP_PKEY * a,const EVP_PKEY * b)161 static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
162 {
163 return 1;
164 }
165
ecx_key_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx,ecx_key_op_t op)166 static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
167 ASN1_PCTX *ctx, ecx_key_op_t op)
168 {
169 const ECX_KEY *ecxkey = pkey->pkey.ecx;
170 const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
171
172 if (op == KEY_OP_PRIVATE) {
173 if (ecxkey == NULL || ecxkey->privkey == NULL) {
174 if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
175 return 0;
176 return 1;
177 }
178 if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
179 return 0;
180 if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
181 return 0;
182 if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
183 indent + 4)
184 == 0)
185 return 0;
186 } else {
187 if (ecxkey == NULL) {
188 if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
189 return 0;
190 return 1;
191 }
192 if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
193 return 0;
194 }
195 if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
196 return 0;
197
198 if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
199 indent + 4)
200 == 0)
201 return 0;
202 return 1;
203 }
204
ecx_priv_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)205 static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
206 ASN1_PCTX *ctx)
207 {
208 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
209 }
210
ecx_pub_print(BIO * bp,const EVP_PKEY * pkey,int indent,ASN1_PCTX * ctx)211 static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
212 ASN1_PCTX *ctx)
213 {
214 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
215 }
216
ecx_ctrl(EVP_PKEY * pkey,int op,long arg1,void * arg2)217 static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
218 {
219 switch (op) {
220
221 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: {
222 ECX_KEY *ecx = ossl_ecx_key_op(NULL, arg2, arg1, pkey->ameth->pkey_id,
223 KEY_OP_PUBLIC, NULL, NULL);
224
225 if (ecx != NULL) {
226 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
227 return 1;
228 }
229 return 0;
230 }
231 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
232 if (pkey->pkey.ecx != NULL) {
233 unsigned char **ppt = arg2;
234
235 *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
236 if (*ppt != NULL)
237 return KEYLEN(pkey);
238 }
239 return 0;
240
241 default:
242 return -2;
243 }
244 }
245
ecd_ctrl(EVP_PKEY * pkey,int op,long arg1,void * arg2)246 static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
247 {
248 switch (op) {
249 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
250 /* We currently only support Pure EdDSA which takes no digest */
251 *(int *)arg2 = NID_undef;
252 return 2;
253
254 default:
255 return -2;
256 }
257 }
258
ecx_set_priv_key(EVP_PKEY * pkey,const unsigned char * priv,size_t len)259 static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
260 size_t len)
261 {
262 OSSL_LIB_CTX *libctx = NULL;
263 ECX_KEY *ecx = NULL;
264
265 if (pkey->keymgmt != NULL)
266 libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
267
268 ecx = ossl_ecx_key_op(NULL, priv, len, pkey->ameth->pkey_id,
269 KEY_OP_PRIVATE, libctx, NULL);
270
271 if (ecx != NULL) {
272 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
273 return 1;
274 }
275 return 0;
276 }
277
ecx_set_pub_key(EVP_PKEY * pkey,const unsigned char * pub,size_t len)278 static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
279 {
280 OSSL_LIB_CTX *libctx = NULL;
281 ECX_KEY *ecx = NULL;
282
283 if (pkey->keymgmt != NULL)
284 libctx = ossl_provider_libctx(EVP_KEYMGMT_get0_provider(pkey->keymgmt));
285
286 ecx = ossl_ecx_key_op(NULL, pub, len, pkey->ameth->pkey_id,
287 KEY_OP_PUBLIC, libctx, NULL);
288
289 if (ecx != NULL) {
290 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
291 return 1;
292 }
293 return 0;
294 }
295
ecx_get_priv_key(const EVP_PKEY * pkey,unsigned char * priv,size_t * len)296 static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
297 size_t *len)
298 {
299 const ECX_KEY *key = pkey->pkey.ecx;
300
301 if (priv == NULL) {
302 *len = KEYLENID(pkey->ameth->pkey_id);
303 return 1;
304 }
305
306 if (key == NULL
307 || key->privkey == NULL
308 || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
309 return 0;
310
311 *len = KEYLENID(pkey->ameth->pkey_id);
312 memcpy(priv, key->privkey, *len);
313
314 return 1;
315 }
316
ecx_get_pub_key(const EVP_PKEY * pkey,unsigned char * pub,size_t * len)317 static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
318 size_t *len)
319 {
320 const ECX_KEY *key = pkey->pkey.ecx;
321
322 if (pub == NULL) {
323 *len = KEYLENID(pkey->ameth->pkey_id);
324 return 1;
325 }
326
327 if (key == NULL
328 || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
329 return 0;
330
331 *len = KEYLENID(pkey->ameth->pkey_id);
332 memcpy(pub, key->pubkey, *len);
333
334 return 1;
335 }
336
ecx_pkey_dirty_cnt(const EVP_PKEY * pkey)337 static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey)
338 {
339 /*
340 * We provide no mechanism to "update" an ECX key once it has been set,
341 * therefore we do not have to maintain a dirty count.
342 */
343 return 1;
344 }
345
ecx_pkey_export_to(const EVP_PKEY * from,void * to_keydata,OSSL_FUNC_keymgmt_import_fn * importer,OSSL_LIB_CTX * libctx,const char * propq)346 static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
347 OSSL_FUNC_keymgmt_import_fn *importer,
348 OSSL_LIB_CTX *libctx, const char *propq)
349 {
350 const ECX_KEY *key = from->pkey.ecx;
351 OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
352 OSSL_PARAM *params = NULL;
353 int selection = 0;
354 int rv = 0;
355
356 if (tmpl == NULL)
357 return 0;
358
359 /* A key must at least have a public part */
360 if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
361 key->pubkey, key->keylen))
362 goto err;
363 selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
364
365 if (key->privkey != NULL) {
366 if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
367 OSSL_PKEY_PARAM_PRIV_KEY,
368 key->privkey, key->keylen))
369 goto err;
370 selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
371 }
372
373 params = OSSL_PARAM_BLD_to_param(tmpl);
374
375 /* We export, the provider imports */
376 rv = importer(to_keydata, selection, params);
377
378 err:
379 OSSL_PARAM_BLD_free(tmpl);
380 OSSL_PARAM_free(params);
381 return rv;
382 }
383
ecx_generic_import_from(const OSSL_PARAM params[],void * vpctx,int keytype)384 static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
385 int keytype)
386 {
387 EVP_PKEY_CTX *pctx = vpctx;
388 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
389 ECX_KEY *ecx = ossl_ecx_key_new(pctx->libctx, KEYNID2TYPE(keytype), 0,
390 pctx->propquery);
391
392 if (ecx == NULL) {
393 ERR_raise(ERR_LIB_DH, ERR_R_EC_LIB);
394 return 0;
395 }
396
397 if (!ossl_ecx_key_fromdata(ecx, params, 1)
398 || !EVP_PKEY_assign(pkey, keytype, ecx)) {
399 ossl_ecx_key_free(ecx);
400 return 0;
401 }
402 return 1;
403 }
404
ecx_pkey_copy(EVP_PKEY * to,EVP_PKEY * from)405 static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
406 {
407 ECX_KEY *ecx = from->pkey.ecx, *dupkey = NULL;
408 int ret;
409
410 if (ecx != NULL) {
411 dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL);
412 if (dupkey == NULL)
413 return 0;
414 }
415
416 ret = EVP_PKEY_assign(to, from->type, dupkey);
417 if (!ret)
418 ossl_ecx_key_free(dupkey);
419 return ret;
420 }
421
x25519_import_from(const OSSL_PARAM params[],void * vpctx)422 static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
423 {
424 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
425 }
426
427 const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = {
428 EVP_PKEY_X25519,
429 EVP_PKEY_X25519,
430 0,
431 "X25519",
432 "OpenSSL X25519 algorithm",
433
434 ecx_pub_decode,
435 ecx_pub_encode,
436 ecx_pub_cmp,
437 ecx_pub_print,
438
439 NULL,
440 ecx_priv_encode,
441 ecx_priv_print,
442
443 ecx_size,
444 ecx_bits,
445 ecx_security_bits,
446
447 0, 0, 0, 0,
448 ecx_cmp_parameters,
449 0, 0,
450
451 ecx_free,
452 ecx_ctrl,
453 NULL,
454 NULL,
455
456 NULL,
457 NULL,
458 NULL,
459
460 NULL,
461 NULL,
462 NULL,
463
464 ecx_set_priv_key,
465 ecx_set_pub_key,
466 ecx_get_priv_key,
467 ecx_get_pub_key,
468 ecx_pkey_dirty_cnt,
469 ecx_pkey_export_to,
470 x25519_import_from,
471 ecx_pkey_copy,
472
473 ecx_priv_decode_ex
474 };
475
x448_import_from(const OSSL_PARAM params[],void * vpctx)476 static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
477 {
478 return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
479 }
480
481 const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = {
482 EVP_PKEY_X448,
483 EVP_PKEY_X448,
484 0,
485 "X448",
486 "OpenSSL X448 algorithm",
487
488 ecx_pub_decode,
489 ecx_pub_encode,
490 ecx_pub_cmp,
491 ecx_pub_print,
492
493 NULL,
494 ecx_priv_encode,
495 ecx_priv_print,
496
497 ecx_size,
498 ecx_bits,
499 ecx_security_bits,
500
501 0, 0, 0, 0,
502 ecx_cmp_parameters,
503 0, 0,
504
505 ecx_free,
506 ecx_ctrl,
507 NULL,
508 NULL,
509
510 NULL,
511 NULL,
512 NULL,
513
514 NULL,
515 NULL,
516 NULL,
517
518 ecx_set_priv_key,
519 ecx_set_pub_key,
520 ecx_get_priv_key,
521 ecx_get_pub_key,
522 ecx_pkey_dirty_cnt,
523 ecx_pkey_export_to,
524 x448_import_from,
525 ecx_pkey_copy,
526
527 ecx_priv_decode_ex
528 };
529
ecd_size25519(const EVP_PKEY * pkey)530 static int ecd_size25519(const EVP_PKEY *pkey)
531 {
532 return ED25519_SIGSIZE;
533 }
534
ecd_size448(const EVP_PKEY * pkey)535 static int ecd_size448(const EVP_PKEY *pkey)
536 {
537 return ED448_SIGSIZE;
538 }
539
ecd_item_verify(EVP_MD_CTX * ctx,const ASN1_ITEM * it,const void * asn,const X509_ALGOR * sigalg,const ASN1_BIT_STRING * str,EVP_PKEY * pkey)540 static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
541 const void *asn, const X509_ALGOR *sigalg,
542 const ASN1_BIT_STRING *str, EVP_PKEY *pkey)
543 {
544 const ASN1_OBJECT *obj;
545 int ptype;
546 int nid;
547
548 /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
549 X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
550 nid = OBJ_obj2nid(obj);
551 if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
552 ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
553 return 0;
554 }
555
556 if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
557 return 0;
558
559 return 2;
560 }
561
ecd_item_sign(X509_ALGOR * alg1,X509_ALGOR * alg2,int nid)562 static int ecd_item_sign(X509_ALGOR *alg1, X509_ALGOR *alg2, int nid)
563 {
564 /* Note that X509_ALGOR_set0(..., ..., V_ASN1_UNDEF, ...) cannot fail */
565 /* Set algorithms identifiers */
566 (void)X509_ALGOR_set0(alg1, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
567 if (alg2 != NULL)
568 (void)X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
569 /* Algorithm identifiers set: carry on as normal */
570 return 3;
571 }
572
ecd_item_sign25519(EVP_MD_CTX * ctx,const ASN1_ITEM * it,const void * asn,X509_ALGOR * alg1,X509_ALGOR * alg2,ASN1_BIT_STRING * str)573 static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
574 const void *asn,
575 X509_ALGOR *alg1, X509_ALGOR *alg2,
576 ASN1_BIT_STRING *str)
577 {
578 return ecd_item_sign(alg1, alg2, NID_ED25519);
579 }
580
ecd_sig_info_set25519(X509_SIG_INFO * siginf,const X509_ALGOR * alg,const ASN1_STRING * sig)581 static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
582 const ASN1_STRING *sig)
583 {
584 X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
585 X509_SIG_INFO_TLS);
586 return 1;
587 }
588
ecd_item_sign448(EVP_MD_CTX * ctx,const ASN1_ITEM * it,const void * asn,X509_ALGOR * alg1,X509_ALGOR * alg2,ASN1_BIT_STRING * str)589 static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
590 const void *asn,
591 X509_ALGOR *alg1, X509_ALGOR *alg2,
592 ASN1_BIT_STRING *str)
593 {
594 return ecd_item_sign(alg1, alg2, NID_ED448);
595 }
596
ecd_sig_info_set448(X509_SIG_INFO * siginf,const X509_ALGOR * alg,const ASN1_STRING * sig)597 static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
598 const ASN1_STRING *sig)
599 {
600 X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
601 X509_SIG_INFO_TLS);
602 return 1;
603 }
604
ed25519_import_from(const OSSL_PARAM params[],void * vpctx)605 static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
606 {
607 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
608 }
609
610 const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
611 EVP_PKEY_ED25519,
612 EVP_PKEY_ED25519,
613 0,
614 "ED25519",
615 "OpenSSL ED25519 algorithm",
616
617 ecx_pub_decode,
618 ecx_pub_encode,
619 ecx_pub_cmp,
620 ecx_pub_print,
621
622 NULL,
623 ecx_priv_encode,
624 ecx_priv_print,
625
626 ecd_size25519,
627 ecx_bits,
628 ecx_security_bits,
629
630 0, 0, 0, 0,
631 ecx_cmp_parameters,
632 0, 0,
633
634 ecx_free,
635 ecd_ctrl,
636 NULL,
637 NULL,
638 ecd_item_verify,
639 ecd_item_sign25519,
640 ecd_sig_info_set25519,
641
642 NULL,
643 NULL,
644 NULL,
645
646 ecx_set_priv_key,
647 ecx_set_pub_key,
648 ecx_get_priv_key,
649 ecx_get_pub_key,
650 ecx_pkey_dirty_cnt,
651 ecx_pkey_export_to,
652 ed25519_import_from,
653 ecx_pkey_copy,
654
655 ecx_priv_decode_ex
656 };
657
ed448_import_from(const OSSL_PARAM params[],void * vpctx)658 static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
659 {
660 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
661 }
662
663 const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
664 EVP_PKEY_ED448,
665 EVP_PKEY_ED448,
666 0,
667 "ED448",
668 "OpenSSL ED448 algorithm",
669
670 ecx_pub_decode,
671 ecx_pub_encode,
672 ecx_pub_cmp,
673 ecx_pub_print,
674
675 NULL,
676 ecx_priv_encode,
677 ecx_priv_print,
678
679 ecd_size448,
680 ecx_bits,
681 ecx_security_bits,
682
683 0, 0, 0, 0,
684 ecx_cmp_parameters,
685 0, 0,
686
687 ecx_free,
688 ecd_ctrl,
689 NULL,
690 NULL,
691 ecd_item_verify,
692 ecd_item_sign448,
693 ecd_sig_info_set448,
694
695 NULL,
696 NULL,
697 NULL,
698
699 ecx_set_priv_key,
700 ecx_set_pub_key,
701 ecx_get_priv_key,
702 ecx_get_pub_key,
703 ecx_pkey_dirty_cnt,
704 ecx_pkey_export_to,
705 ed448_import_from,
706 ecx_pkey_copy,
707
708 ecx_priv_decode_ex
709 };
710
pkey_ecx_keygen(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)711 static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
712 {
713 ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
714 KEY_OP_KEYGEN, NULL, NULL);
715
716 if (ecx != NULL) {
717 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
718 return 1;
719 }
720 return 0;
721 }
722
validate_ecx_derive(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen,const unsigned char ** privkey,const unsigned char ** pubkey)723 static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
724 size_t *keylen,
725 const unsigned char **privkey,
726 const unsigned char **pubkey)
727 {
728 const ECX_KEY *ecxkey, *peerkey;
729
730 if (ctx->pkey == NULL || ctx->peerkey == NULL) {
731 ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
732 return 0;
733 }
734 ecxkey = evp_pkey_get_legacy(ctx->pkey);
735 peerkey = evp_pkey_get_legacy(ctx->peerkey);
736 if (ecxkey == NULL || ecxkey->privkey == NULL) {
737 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
738 return 0;
739 }
740 if (peerkey == NULL) {
741 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
742 return 0;
743 }
744 *privkey = ecxkey->privkey;
745 *pubkey = peerkey->pubkey;
746
747 return 1;
748 }
749
pkey_ecx_derive25519(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)750 static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
751 size_t *keylen)
752 {
753 const unsigned char *privkey, *pubkey;
754
755 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
756 || (key != NULL
757 && ossl_x25519(key, privkey, pubkey) == 0))
758 return 0;
759 *keylen = X25519_KEYLEN;
760 return 1;
761 }
762
pkey_ecx_derive448(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)763 static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
764 size_t *keylen)
765 {
766 const unsigned char *privkey, *pubkey;
767
768 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
769 || (key != NULL
770 && ossl_x448(key, privkey, pubkey) == 0))
771 return 0;
772 *keylen = X448_KEYLEN;
773 return 1;
774 }
775
pkey_ecx_ctrl(EVP_PKEY_CTX * ctx,int type,int p1,void * p2)776 static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
777 {
778 /* Only need to handle peer key for derivation */
779 if (type == EVP_PKEY_CTRL_PEER_KEY)
780 return 1;
781 return -2;
782 }
783
784 static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
785 EVP_PKEY_X25519,
786 0, 0, 0, 0, 0, 0, 0,
787 pkey_ecx_keygen,
788 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
789 pkey_ecx_derive25519,
790 pkey_ecx_ctrl,
791 0
792 };
793
794 static const EVP_PKEY_METHOD ecx448_pkey_meth = {
795 EVP_PKEY_X448,
796 0, 0, 0, 0, 0, 0, 0,
797 pkey_ecx_keygen,
798 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
799 pkey_ecx_derive448,
800 pkey_ecx_ctrl,
801 0
802 };
803
pkey_ecd_digestsign25519(EVP_MD_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)804 static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
805 size_t *siglen, const unsigned char *tbs,
806 size_t tbslen)
807 {
808 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
809
810 if (edkey == NULL) {
811 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
812 return 0;
813 }
814
815 if (sig == NULL) {
816 *siglen = ED25519_SIGSIZE;
817 return 1;
818 }
819 if (*siglen < ED25519_SIGSIZE) {
820 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
821 return 0;
822 }
823
824 if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey,
825 0, 0, 0,
826 NULL, 0,
827 NULL, NULL)
828 == 0)
829 return 0;
830 *siglen = ED25519_SIGSIZE;
831 return 1;
832 }
833
pkey_ecd_digestsign448(EVP_MD_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)834 static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
835 size_t *siglen, const unsigned char *tbs,
836 size_t tbslen)
837 {
838 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
839
840 if (edkey == NULL) {
841 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
842 return 0;
843 }
844
845 if (sig == NULL) {
846 *siglen = ED448_SIGSIZE;
847 return 1;
848 }
849 if (*siglen < ED448_SIGSIZE) {
850 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
851 return 0;
852 }
853
854 if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
855 edkey->privkey, NULL, 0, 0, edkey->propq)
856 == 0)
857 return 0;
858 *siglen = ED448_SIGSIZE;
859 return 1;
860 }
861
pkey_ecd_digestverify25519(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)862 static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
863 size_t siglen, const unsigned char *tbs,
864 size_t tbslen)
865 {
866 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
867
868 if (edkey == NULL) {
869 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
870 return 0;
871 }
872
873 if (siglen != ED25519_SIGSIZE)
874 return 0;
875
876 return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
877 0, 0, 0,
878 NULL, 0,
879 edkey->libctx, edkey->propq);
880 }
881
pkey_ecd_digestverify448(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)882 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
883 size_t siglen, const unsigned char *tbs,
884 size_t tbslen)
885 {
886 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
887
888 if (edkey == NULL) {
889 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
890 return 0;
891 }
892
893 if (siglen != ED448_SIGSIZE)
894 return 0;
895
896 return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
897 NULL, 0, 0, edkey->propq);
898 }
899
pkey_ecd_ctrl(EVP_PKEY_CTX * ctx,int type,int p1,void * p2)900 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
901 {
902 switch (type) {
903 case EVP_PKEY_CTRL_MD:
904 /* Only NULL allowed as digest */
905 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
906 return 1;
907 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
908 return 0;
909
910 case EVP_PKEY_CTRL_DIGESTINIT:
911 return 1;
912 }
913 return -2;
914 }
915
916 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
917 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
918 0, 0, 0, 0, 0, 0,
919 pkey_ecx_keygen,
920 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
921 pkey_ecd_ctrl,
922 0,
923 pkey_ecd_digestsign25519,
924 pkey_ecd_digestverify25519
925 };
926
927 static const EVP_PKEY_METHOD ed448_pkey_meth = {
928 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
929 0, 0, 0, 0, 0, 0,
930 pkey_ecx_keygen,
931 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
932 pkey_ecd_ctrl,
933 0,
934 pkey_ecd_digestsign448,
935 pkey_ecd_digestverify448
936 };
937
938 #ifdef S390X_EC_ASM
939 #include "s390x_arch.h"
940
s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)941 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
942 {
943 static const unsigned char generator[] = {
944 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
945 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
946 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
947 };
948 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
949 ctx->propquery);
950 unsigned char *privkey = NULL, *pubkey;
951
952 if (key == NULL) {
953 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
954 goto err;
955 }
956
957 pubkey = key->pubkey;
958
959 privkey = ossl_ecx_key_allocate_privkey(key);
960 if (privkey == NULL) {
961 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
962 goto err;
963 }
964
965 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
966 goto err;
967
968 privkey[0] &= 248;
969 privkey[31] &= 127;
970 privkey[31] |= 64;
971
972 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
973 goto err;
974
975 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
976 return 1;
977 err:
978 ossl_ecx_key_free(key);
979 return 0;
980 }
981
s390x_pkey_ecx_keygen448(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)982 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
983 {
984 static const unsigned char generator[] = {
985 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
986 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
988 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
989 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
990 };
991 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
992 ctx->propquery);
993 unsigned char *privkey = NULL, *pubkey;
994
995 if (key == NULL) {
996 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
997 goto err;
998 }
999
1000 pubkey = key->pubkey;
1001
1002 privkey = ossl_ecx_key_allocate_privkey(key);
1003 if (privkey == NULL) {
1004 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1005 goto err;
1006 }
1007
1008 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1009 goto err;
1010
1011 privkey[0] &= 252;
1012 privkey[55] |= 128;
1013
1014 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1015 goto err;
1016
1017 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1018 return 1;
1019 err:
1020 ossl_ecx_key_free(key);
1021 return 0;
1022 }
1023
s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)1024 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1025 {
1026 static const unsigned char generator_x[] = {
1027 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1028 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1029 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1030 };
1031 static const unsigned char generator_y[] = {
1032 0x58,
1033 0x66,
1034 0x66,
1035 0x66,
1036 0x66,
1037 0x66,
1038 0x66,
1039 0x66,
1040 0x66,
1041 0x66,
1042 0x66,
1043 0x66,
1044 0x66,
1045 0x66,
1046 0x66,
1047 0x66,
1048 0x66,
1049 0x66,
1050 0x66,
1051 0x66,
1052 0x66,
1053 0x66,
1054 0x66,
1055 0x66,
1056 0x66,
1057 0x66,
1058 0x66,
1059 0x66,
1060 0x66,
1061 0x66,
1062 0x66,
1063 0x66,
1064 };
1065 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1066 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1067 ctx->propquery);
1068 unsigned char *privkey = NULL, *pubkey;
1069 unsigned int sz;
1070 EVP_MD *md = NULL;
1071 int rv;
1072
1073 if (key == NULL) {
1074 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1075 goto err;
1076 }
1077
1078 pubkey = key->pubkey;
1079
1080 privkey = ossl_ecx_key_allocate_privkey(key);
1081 if (privkey == NULL) {
1082 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1083 goto err;
1084 }
1085
1086 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1087 goto err;
1088
1089 md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1090 if (md == NULL)
1091 goto err;
1092
1093 rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1094 EVP_MD_free(md);
1095 if (!rv)
1096 goto err;
1097
1098 buff[0] &= 248;
1099 buff[31] &= 63;
1100 buff[31] |= 64;
1101
1102 if (s390x_ed25519_mul(x_dst, pubkey,
1103 generator_x, generator_y, buff)
1104 != 1)
1105 goto err;
1106
1107 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1108
1109 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1110 return 1;
1111 err:
1112 ossl_ecx_key_free(key);
1113 return 0;
1114 }
1115
s390x_pkey_ecd_keygen448(EVP_PKEY_CTX * ctx,EVP_PKEY * pkey)1116 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1117 {
1118 static const unsigned char generator_x[] = {
1119 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1120 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1121 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1122 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1123 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1124 };
1125 static const unsigned char generator_y[] = {
1126 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1127 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1128 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1129 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1130 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1131 };
1132 unsigned char x_dst[57], buff[114];
1133 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1134 ctx->propquery);
1135 unsigned char *privkey = NULL, *pubkey;
1136 EVP_MD_CTX *hashctx = NULL;
1137 EVP_MD *md = NULL;
1138 int rv;
1139
1140 if (key == NULL) {
1141 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1142 goto err;
1143 }
1144
1145 pubkey = key->pubkey;
1146
1147 privkey = ossl_ecx_key_allocate_privkey(key);
1148 if (privkey == NULL) {
1149 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1150 goto err;
1151 }
1152
1153 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1154 goto err;
1155
1156 hashctx = EVP_MD_CTX_new();
1157 if (hashctx == NULL)
1158 goto err;
1159
1160 md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1161 if (md == NULL)
1162 goto err;
1163
1164 rv = EVP_DigestInit_ex(hashctx, md, NULL);
1165 EVP_MD_free(md);
1166 if (rv != 1)
1167 goto err;
1168
1169 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1170 goto err;
1171 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1172 goto err;
1173
1174 buff[0] &= -4;
1175 buff[55] |= 0x80;
1176 buff[56] = 0;
1177
1178 if (s390x_ed448_mul(x_dst, pubkey,
1179 generator_x, generator_y, buff)
1180 != 1)
1181 goto err;
1182
1183 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1184
1185 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1186 EVP_MD_CTX_free(hashctx);
1187 return 1;
1188 err:
1189 ossl_ecx_key_free(key);
1190 EVP_MD_CTX_free(hashctx);
1191 return 0;
1192 }
1193
s390x_pkey_ecx_derive25519(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)1194 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1195 size_t *keylen)
1196 {
1197 const unsigned char *privkey, *pubkey;
1198
1199 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1200 || (key != NULL
1201 && s390x_x25519_mul(key, privkey, pubkey) == 0))
1202 return 0;
1203 *keylen = X25519_KEYLEN;
1204 return 1;
1205 }
1206
s390x_pkey_ecx_derive448(EVP_PKEY_CTX * ctx,unsigned char * key,size_t * keylen)1207 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1208 size_t *keylen)
1209 {
1210 const unsigned char *privkey, *pubkey;
1211
1212 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1213 || (key != NULL
1214 && s390x_x448_mul(key, pubkey, privkey) == 0))
1215 return 0;
1216 *keylen = X448_KEYLEN;
1217 return 1;
1218 }
1219
s390x_pkey_ecd_digestsign25519(EVP_MD_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)1220 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1221 unsigned char *sig, size_t *siglen,
1222 const unsigned char *tbs,
1223 size_t tbslen)
1224 {
1225 union {
1226 struct {
1227 unsigned char sig[64];
1228 unsigned char priv[32];
1229 } ed25519;
1230 unsigned long long buff[512];
1231 } param;
1232 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1233 int rc;
1234
1235 if (edkey == NULL) {
1236 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1237 return 0;
1238 }
1239
1240 if (sig == NULL) {
1241 *siglen = ED25519_SIGSIZE;
1242 return 1;
1243 }
1244
1245 if (*siglen < ED25519_SIGSIZE) {
1246 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1247 return 0;
1248 }
1249
1250 memset(¶m, 0, sizeof(param));
1251 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1252
1253 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, ¶m.ed25519, tbs, tbslen);
1254 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1255 if (rc != 0)
1256 return 0;
1257
1258 s390x_flip_endian32(sig, param.ed25519.sig);
1259 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1260
1261 *siglen = ED25519_SIGSIZE;
1262 return 1;
1263 }
1264
s390x_pkey_ecd_digestsign448(EVP_MD_CTX * ctx,unsigned char * sig,size_t * siglen,const unsigned char * tbs,size_t tbslen)1265 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1266 unsigned char *sig, size_t *siglen,
1267 const unsigned char *tbs,
1268 size_t tbslen)
1269 {
1270 union {
1271 struct {
1272 unsigned char sig[128];
1273 unsigned char priv[64];
1274 } ed448;
1275 unsigned long long buff[512];
1276 } param;
1277 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1278 int rc;
1279
1280 if (edkey == NULL) {
1281 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1282 return 0;
1283 }
1284
1285 if (sig == NULL) {
1286 *siglen = ED448_SIGSIZE;
1287 return 1;
1288 }
1289
1290 if (*siglen < ED448_SIGSIZE) {
1291 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1292 return 0;
1293 }
1294
1295 memset(¶m, 0, sizeof(param));
1296 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1297
1298 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, ¶m.ed448, tbs, tbslen);
1299 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1300 if (rc != 0)
1301 return 0;
1302
1303 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1304 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1305 memcpy(sig, param.ed448.sig, 57);
1306 memcpy(sig + 57, param.ed448.sig + 64, 57);
1307
1308 *siglen = ED448_SIGSIZE;
1309 return 1;
1310 }
1311
s390x_pkey_ecd_digestverify25519(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)1312 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1313 const unsigned char *sig,
1314 size_t siglen,
1315 const unsigned char *tbs,
1316 size_t tbslen)
1317 {
1318 union {
1319 struct {
1320 unsigned char sig[64];
1321 unsigned char pub[32];
1322 } ed25519;
1323 unsigned long long buff[512];
1324 } param;
1325 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1326
1327 if (edkey == NULL) {
1328 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1329 return 0;
1330 }
1331
1332 if (siglen != ED25519_SIGSIZE)
1333 return 0;
1334
1335 memset(¶m, 0, sizeof(param));
1336 s390x_flip_endian32(param.ed25519.sig, sig);
1337 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1338 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1339
1340 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1341 ¶m.ed25519, tbs, tbslen)
1342 == 0
1343 ? 1
1344 : 0;
1345 }
1346
s390x_pkey_ecd_digestverify448(EVP_MD_CTX * ctx,const unsigned char * sig,size_t siglen,const unsigned char * tbs,size_t tbslen)1347 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1348 const unsigned char *sig,
1349 size_t siglen,
1350 const unsigned char *tbs,
1351 size_t tbslen)
1352 {
1353 union {
1354 struct {
1355 unsigned char sig[128];
1356 unsigned char pub[64];
1357 } ed448;
1358 unsigned long long buff[512];
1359 } param;
1360 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1361
1362 if (edkey == NULL) {
1363 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1364 return 0;
1365 }
1366
1367 if (siglen != ED448_SIGSIZE)
1368 return 0;
1369
1370 memset(¶m, 0, sizeof(param));
1371 memcpy(param.ed448.sig, sig, 57);
1372 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1373 memcpy(param.ed448.sig + 64, sig + 57, 57);
1374 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1375 memcpy(param.ed448.pub, edkey->pubkey, 57);
1376 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1377
1378 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1379 ¶m.ed448, tbs, tbslen)
1380 == 0
1381 ? 1
1382 : 0;
1383 }
1384
1385 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1386 EVP_PKEY_X25519,
1387 0, 0, 0, 0, 0, 0, 0,
1388 s390x_pkey_ecx_keygen25519,
1389 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1390 s390x_pkey_ecx_derive25519,
1391 pkey_ecx_ctrl,
1392 0
1393 };
1394
1395 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1396 EVP_PKEY_X448,
1397 0, 0, 0, 0, 0, 0, 0,
1398 s390x_pkey_ecx_keygen448,
1399 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1400 s390x_pkey_ecx_derive448,
1401 pkey_ecx_ctrl,
1402 0
1403 };
1404 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1405 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1406 0, 0, 0, 0, 0, 0,
1407 s390x_pkey_ecd_keygen25519,
1408 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1409 pkey_ecd_ctrl,
1410 0,
1411 s390x_pkey_ecd_digestsign25519,
1412 s390x_pkey_ecd_digestverify25519
1413 };
1414
1415 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1416 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1417 0, 0, 0, 0, 0, 0,
1418 s390x_pkey_ecd_keygen448,
1419 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1420 pkey_ecd_ctrl,
1421 0,
1422 s390x_pkey_ecd_digestsign448,
1423 s390x_pkey_ecd_digestverify448
1424 };
1425 #endif
1426
ossl_ecx25519_pkey_method(void)1427 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1428 {
1429 #ifdef S390X_EC_ASM
1430 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1431 return &ecx25519_s390x_pkey_meth;
1432 #endif
1433 return &ecx25519_pkey_meth;
1434 }
1435
ossl_ecx448_pkey_method(void)1436 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1437 {
1438 #ifdef S390X_EC_ASM
1439 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1440 return &ecx448_s390x_pkey_meth;
1441 #endif
1442 return &ecx448_pkey_meth;
1443 }
1444
ossl_ed25519_pkey_method(void)1445 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1446 {
1447 #ifdef S390X_EC_ASM
1448 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1449 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1450 && OPENSSL_s390xcap_P.kdsa[0]
1451 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1452 return &ed25519_s390x_pkey_meth;
1453 #endif
1454 return &ed25519_pkey_meth;
1455 }
1456
ossl_ed448_pkey_method(void)1457 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1458 {
1459 #ifdef S390X_EC_ASM
1460 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1461 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1462 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1463 return &ed448_s390x_pkey_meth;
1464 #endif
1465 return &ed448_pkey_meth;
1466 }
1467