]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ec/ecx_meth.c
Stop raising ERR_R_MALLOC_FAILURE in most places
[thirdparty/openssl.git] / crypto / ec / ecx_meth.c
1 /*
2 * Copyright 2006-2022 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
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
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
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
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
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
130 static int ecx_size(const EVP_PKEY *pkey)
131 {
132 return KEYLEN(pkey);
133 }
134
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
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
155 static void ecx_free(EVP_PKEY *pkey)
156 {
157 ossl_ecx_key_free(pkey->pkey.ecx);
158 }
159
160 /* "parameters" are always equal */
161 static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
162 {
163 return 1;
164 }
165
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) == 0)
184 return 0;
185 } else {
186 if (ecxkey == NULL) {
187 if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
188 return 0;
189 return 1;
190 }
191 if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
192 return 0;
193 }
194 if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
195 return 0;
196
197 if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
198 indent + 4) == 0)
199 return 0;
200 return 1;
201 }
202
203 static int ecx_priv_print(BIO *bp, const EVP_PKEY *pkey, int indent,
204 ASN1_PCTX *ctx)
205 {
206 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PRIVATE);
207 }
208
209 static int ecx_pub_print(BIO *bp, const EVP_PKEY *pkey, int indent,
210 ASN1_PCTX *ctx)
211 {
212 return ecx_key_print(bp, pkey, indent, ctx, KEY_OP_PUBLIC);
213 }
214
215 static int ecx_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
216 {
217 switch (op) {
218
219 case ASN1_PKEY_CTRL_SET1_TLS_ENCPT: {
220 ECX_KEY *ecx = ossl_ecx_key_op(NULL, arg2, arg1, pkey->ameth->pkey_id,
221 KEY_OP_PUBLIC, NULL, NULL);
222
223 if (ecx != NULL) {
224 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
225 return 1;
226 }
227 return 0;
228 }
229 case ASN1_PKEY_CTRL_GET1_TLS_ENCPT:
230 if (pkey->pkey.ecx != NULL) {
231 unsigned char **ppt = arg2;
232
233 *ppt = OPENSSL_memdup(pkey->pkey.ecx->pubkey, KEYLEN(pkey));
234 if (*ppt != NULL)
235 return KEYLEN(pkey);
236 }
237 return 0;
238
239 default:
240 return -2;
241
242 }
243 }
244
245 static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
246 {
247 switch (op) {
248 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
249 /* We currently only support Pure EdDSA which takes no digest */
250 *(int *)arg2 = NID_undef;
251 return 2;
252
253 default:
254 return -2;
255
256 }
257 }
258
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
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
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
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
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
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
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
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
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
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
530 static int ecd_size25519(const EVP_PKEY *pkey)
531 {
532 return ED25519_SIGSIZE;
533 }
534
535 static int ecd_size448(const EVP_PKEY *pkey)
536 {
537 return ED448_SIGSIZE;
538 }
539
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
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
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
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
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
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
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
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
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_PUBLIC, 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
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
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
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
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
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, NULL,
825 NULL) == 0)
826 return 0;
827 *siglen = ED25519_SIGSIZE;
828 return 1;
829 }
830
831 static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
832 size_t *siglen, const unsigned char *tbs,
833 size_t tbslen)
834 {
835 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
836
837 if (edkey == NULL) {
838 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
839 return 0;
840 }
841
842 if (sig == NULL) {
843 *siglen = ED448_SIGSIZE;
844 return 1;
845 }
846 if (*siglen < ED448_SIGSIZE) {
847 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
848 return 0;
849 }
850
851 if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
852 edkey->privkey, NULL, 0, edkey->propq) == 0)
853 return 0;
854 *siglen = ED448_SIGSIZE;
855 return 1;
856 }
857
858 static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
859 size_t siglen, const unsigned char *tbs,
860 size_t tbslen)
861 {
862 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
863
864 if (edkey == NULL) {
865 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
866 return 0;
867 }
868
869 if (siglen != ED25519_SIGSIZE)
870 return 0;
871
872 return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
873 edkey->libctx, edkey->propq);
874 }
875
876 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
877 size_t siglen, const unsigned char *tbs,
878 size_t tbslen)
879 {
880 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
881
882 if (edkey == NULL) {
883 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
884 return 0;
885 }
886
887 if (siglen != ED448_SIGSIZE)
888 return 0;
889
890 return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
891 NULL, 0, edkey->propq);
892 }
893
894 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
895 {
896 switch (type) {
897 case EVP_PKEY_CTRL_MD:
898 /* Only NULL allowed as digest */
899 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
900 return 1;
901 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
902 return 0;
903
904 case EVP_PKEY_CTRL_DIGESTINIT:
905 return 1;
906 }
907 return -2;
908 }
909
910 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
911 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
912 0, 0, 0, 0, 0, 0,
913 pkey_ecx_keygen,
914 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
915 pkey_ecd_ctrl,
916 0,
917 pkey_ecd_digestsign25519,
918 pkey_ecd_digestverify25519
919 };
920
921 static const EVP_PKEY_METHOD ed448_pkey_meth = {
922 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
923 0, 0, 0, 0, 0, 0,
924 pkey_ecx_keygen,
925 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
926 pkey_ecd_ctrl,
927 0,
928 pkey_ecd_digestsign448,
929 pkey_ecd_digestverify448
930 };
931
932 #ifdef S390X_EC_ASM
933 # include "s390x_arch.h"
934
935 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
936 {
937 static const unsigned char generator[] = {
938 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
939 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
940 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
941 };
942 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
943 ctx->propquery);
944 unsigned char *privkey = NULL, *pubkey;
945
946 if (key == NULL) {
947 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
948 goto err;
949 }
950
951 pubkey = key->pubkey;
952
953 privkey = ossl_ecx_key_allocate_privkey(key);
954 if (privkey == NULL) {
955 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
956 goto err;
957 }
958
959 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
960 goto err;
961
962 privkey[0] &= 248;
963 privkey[31] &= 127;
964 privkey[31] |= 64;
965
966 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
967 goto err;
968
969 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
970 return 1;
971 err:
972 ossl_ecx_key_free(key);
973 return 0;
974 }
975
976 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
977 {
978 static const unsigned char generator[] = {
979 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
980 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
981 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
982 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
983 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
984 };
985 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
986 ctx->propquery);
987 unsigned char *privkey = NULL, *pubkey;
988
989 if (key == NULL) {
990 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
991 goto err;
992 }
993
994 pubkey = key->pubkey;
995
996 privkey = ossl_ecx_key_allocate_privkey(key);
997 if (privkey == NULL) {
998 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
999 goto err;
1000 }
1001
1002 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1003 goto err;
1004
1005 privkey[0] &= 252;
1006 privkey[55] |= 128;
1007
1008 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1009 goto err;
1010
1011 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1012 return 1;
1013 err:
1014 ossl_ecx_key_free(key);
1015 return 0;
1016 }
1017
1018 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1019 {
1020 static const unsigned char generator_x[] = {
1021 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1022 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1023 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1024 };
1025 static const unsigned char generator_y[] = {
1026 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1027 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1028 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1029 };
1030 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1031 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1032 ctx->propquery);
1033 unsigned char *privkey = NULL, *pubkey;
1034 unsigned int sz;
1035 EVP_MD *md = NULL;
1036 int rv;
1037
1038 if (key == NULL) {
1039 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1040 goto err;
1041 }
1042
1043 pubkey = key->pubkey;
1044
1045 privkey = ossl_ecx_key_allocate_privkey(key);
1046 if (privkey == NULL) {
1047 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1048 goto err;
1049 }
1050
1051 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1052 goto err;
1053
1054 md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1055 if (md == NULL)
1056 goto err;
1057
1058 rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1059 EVP_MD_free(md);
1060 if (!rv)
1061 goto err;
1062
1063 buff[0] &= 248;
1064 buff[31] &= 63;
1065 buff[31] |= 64;
1066
1067 if (s390x_ed25519_mul(x_dst, pubkey,
1068 generator_x, generator_y, buff) != 1)
1069 goto err;
1070
1071 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1072
1073 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1074 return 1;
1075 err:
1076 ossl_ecx_key_free(key);
1077 return 0;
1078 }
1079
1080 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1081 {
1082 static const unsigned char generator_x[] = {
1083 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1084 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1085 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1086 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1087 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1088 };
1089 static const unsigned char generator_y[] = {
1090 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1091 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1092 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1093 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1094 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1095 };
1096 unsigned char x_dst[57], buff[114];
1097 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1098 ctx->propquery);
1099 unsigned char *privkey = NULL, *pubkey;
1100 EVP_MD_CTX *hashctx = NULL;
1101 EVP_MD *md = NULL;
1102 int rv;
1103
1104 if (key == NULL) {
1105 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1106 goto err;
1107 }
1108
1109 pubkey = key->pubkey;
1110
1111 privkey = ossl_ecx_key_allocate_privkey(key);
1112 if (privkey == NULL) {
1113 ERR_raise(ERR_LIB_EC, ERR_R_EC_LIB);
1114 goto err;
1115 }
1116
1117 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1118 goto err;
1119
1120 hashctx = EVP_MD_CTX_new();
1121 if (hashctx == NULL)
1122 goto err;
1123
1124 md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1125 if (md == NULL)
1126 goto err;
1127
1128 rv = EVP_DigestInit_ex(hashctx, md, NULL);
1129 EVP_MD_free(md);
1130 if (rv != 1)
1131 goto err;
1132
1133 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1134 goto err;
1135 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1136 goto err;
1137
1138 buff[0] &= -4;
1139 buff[55] |= 0x80;
1140 buff[56] = 0;
1141
1142 if (s390x_ed448_mul(x_dst, pubkey,
1143 generator_x, generator_y, buff) != 1)
1144 goto err;
1145
1146 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1147
1148 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1149 EVP_MD_CTX_free(hashctx);
1150 return 1;
1151 err:
1152 ossl_ecx_key_free(key);
1153 EVP_MD_CTX_free(hashctx);
1154 return 0;
1155 }
1156
1157 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1158 size_t *keylen)
1159 {
1160 const unsigned char *privkey, *pubkey;
1161
1162 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1163 || (key != NULL
1164 && s390x_x25519_mul(key, privkey, pubkey) == 0))
1165 return 0;
1166 *keylen = X25519_KEYLEN;
1167 return 1;
1168 }
1169
1170 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1171 size_t *keylen)
1172 {
1173 const unsigned char *privkey, *pubkey;
1174
1175 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1176 || (key != NULL
1177 && s390x_x448_mul(key, pubkey, privkey) == 0))
1178 return 0;
1179 *keylen = X448_KEYLEN;
1180 return 1;
1181 }
1182
1183 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1184 unsigned char *sig, size_t *siglen,
1185 const unsigned char *tbs,
1186 size_t tbslen)
1187 {
1188 union {
1189 struct {
1190 unsigned char sig[64];
1191 unsigned char priv[32];
1192 } ed25519;
1193 unsigned long long buff[512];
1194 } param;
1195 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1196 int rc;
1197
1198 if (edkey == NULL) {
1199 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1200 return 0;
1201 }
1202
1203 if (sig == NULL) {
1204 *siglen = ED25519_SIGSIZE;
1205 return 1;
1206 }
1207
1208 if (*siglen < ED25519_SIGSIZE) {
1209 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1210 return 0;
1211 }
1212
1213 memset(&param, 0, sizeof(param));
1214 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1215
1216 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1217 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1218 if (rc != 0)
1219 return 0;
1220
1221 s390x_flip_endian32(sig, param.ed25519.sig);
1222 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1223
1224 *siglen = ED25519_SIGSIZE;
1225 return 1;
1226 }
1227
1228 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1229 unsigned char *sig, size_t *siglen,
1230 const unsigned char *tbs,
1231 size_t tbslen)
1232 {
1233 union {
1234 struct {
1235 unsigned char sig[128];
1236 unsigned char priv[64];
1237 } ed448;
1238 unsigned long long buff[512];
1239 } param;
1240 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1241 int rc;
1242
1243 if (edkey == NULL) {
1244 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1245 return 0;
1246 }
1247
1248 if (sig == NULL) {
1249 *siglen = ED448_SIGSIZE;
1250 return 1;
1251 }
1252
1253 if (*siglen < ED448_SIGSIZE) {
1254 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1255 return 0;
1256 }
1257
1258 memset(&param, 0, sizeof(param));
1259 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1260
1261 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1262 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1263 if (rc != 0)
1264 return 0;
1265
1266 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1267 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1268 memcpy(sig, param.ed448.sig, 57);
1269 memcpy(sig + 57, param.ed448.sig + 64, 57);
1270
1271 *siglen = ED448_SIGSIZE;
1272 return 1;
1273 }
1274
1275 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1276 const unsigned char *sig,
1277 size_t siglen,
1278 const unsigned char *tbs,
1279 size_t tbslen)
1280 {
1281 union {
1282 struct {
1283 unsigned char sig[64];
1284 unsigned char pub[32];
1285 } ed25519;
1286 unsigned long long buff[512];
1287 } param;
1288 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1289
1290 if (edkey == NULL) {
1291 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1292 return 0;
1293 }
1294
1295 if (siglen != ED25519_SIGSIZE)
1296 return 0;
1297
1298 memset(&param, 0, sizeof(param));
1299 s390x_flip_endian32(param.ed25519.sig, sig);
1300 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1301 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1302
1303 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1304 &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1305 }
1306
1307 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1308 const unsigned char *sig,
1309 size_t siglen,
1310 const unsigned char *tbs,
1311 size_t tbslen)
1312 {
1313 union {
1314 struct {
1315 unsigned char sig[128];
1316 unsigned char pub[64];
1317 } ed448;
1318 unsigned long long buff[512];
1319 } param;
1320 const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1321
1322 if (edkey == NULL) {
1323 ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1324 return 0;
1325 }
1326
1327 if (siglen != ED448_SIGSIZE)
1328 return 0;
1329
1330 memset(&param, 0, sizeof(param));
1331 memcpy(param.ed448.sig, sig, 57);
1332 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1333 memcpy(param.ed448.sig + 64, sig + 57, 57);
1334 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1335 memcpy(param.ed448.pub, edkey->pubkey, 57);
1336 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1337
1338 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1339 &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1340 }
1341
1342 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1343 EVP_PKEY_X25519,
1344 0, 0, 0, 0, 0, 0, 0,
1345 s390x_pkey_ecx_keygen25519,
1346 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1347 s390x_pkey_ecx_derive25519,
1348 pkey_ecx_ctrl,
1349 0
1350 };
1351
1352 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1353 EVP_PKEY_X448,
1354 0, 0, 0, 0, 0, 0, 0,
1355 s390x_pkey_ecx_keygen448,
1356 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1357 s390x_pkey_ecx_derive448,
1358 pkey_ecx_ctrl,
1359 0
1360 };
1361 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1362 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1363 0, 0, 0, 0, 0, 0,
1364 s390x_pkey_ecd_keygen25519,
1365 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1366 pkey_ecd_ctrl,
1367 0,
1368 s390x_pkey_ecd_digestsign25519,
1369 s390x_pkey_ecd_digestverify25519
1370 };
1371
1372 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1373 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1374 0, 0, 0, 0, 0, 0,
1375 s390x_pkey_ecd_keygen448,
1376 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1377 pkey_ecd_ctrl,
1378 0,
1379 s390x_pkey_ecd_digestsign448,
1380 s390x_pkey_ecd_digestverify448
1381 };
1382 #endif
1383
1384 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1385 {
1386 #ifdef S390X_EC_ASM
1387 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1388 return &ecx25519_s390x_pkey_meth;
1389 #endif
1390 return &ecx25519_pkey_meth;
1391 }
1392
1393 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1394 {
1395 #ifdef S390X_EC_ASM
1396 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1397 return &ecx448_s390x_pkey_meth;
1398 #endif
1399 return &ecx448_pkey_meth;
1400 }
1401
1402 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1403 {
1404 #ifdef S390X_EC_ASM
1405 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1406 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1407 && OPENSSL_s390xcap_P.kdsa[0]
1408 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1409 return &ed25519_s390x_pkey_meth;
1410 #endif
1411 return &ed25519_pkey_meth;
1412 }
1413
1414 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1415 {
1416 #ifdef S390X_EC_ASM
1417 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1418 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1419 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1420 return &ed448_s390x_pkey_meth;
1421 #endif
1422 return &ed448_pkey_meth;
1423 }