]> git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/ec/ecx_meth.c
Implement EVP_PKEY_dup() function
[thirdparty/openssl.git] / crypto / ec / ecx_meth.c
1 /*
2 * Copyright 2006-2021 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 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
44 return 0;
45 }
46
47 if (!X509_PUBKEY_set0_param(pk, OBJ_nid2obj(pkey->ameth->pkey_id),
48 V_ASN1_UNDEF, NULL, penc, KEYLEN(pkey))) {
49 OPENSSL_free(penc);
50 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
51 return 0;
52 }
53 return 1;
54 }
55
56 static int ecx_pub_decode(EVP_PKEY *pkey, const X509_PUBKEY *pubkey)
57 {
58 const unsigned char *p;
59 int pklen;
60 X509_ALGOR *palg;
61 ECX_KEY *ecx;
62 int ret = 0;
63
64 if (!X509_PUBKEY_get0_param(NULL, &p, &pklen, &palg, pubkey))
65 return 0;
66 ecx = ossl_ecx_key_op(palg, p, pklen, pkey->ameth->pkey_id,
67 KEY_OP_PUBLIC, NULL, NULL);
68 if (ecx != NULL) {
69 ret = 1;
70 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
71 }
72 return ret;
73 }
74
75 static int ecx_pub_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
76 {
77 const ECX_KEY *akey = a->pkey.ecx;
78 const ECX_KEY *bkey = b->pkey.ecx;
79
80 if (akey == NULL || bkey == NULL)
81 return -2;
82
83 return CRYPTO_memcmp(akey->pubkey, bkey->pubkey, KEYLEN(a)) == 0;
84 }
85
86 static int ecx_priv_decode_ex(EVP_PKEY *pkey, const PKCS8_PRIV_KEY_INFO *p8,
87 OSSL_LIB_CTX *libctx, const char *propq)
88 {
89 int ret = 0;
90 ECX_KEY *ecx = ossl_ecx_key_from_pkcs8(p8, libctx, propq);
91
92 if (ecx != NULL) {
93 ret = 1;
94 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
95 }
96
97 return ret;
98 }
99
100 static int ecx_priv_encode(PKCS8_PRIV_KEY_INFO *p8, const EVP_PKEY *pkey)
101 {
102 const ECX_KEY *ecxkey = pkey->pkey.ecx;
103 ASN1_OCTET_STRING oct;
104 unsigned char *penc = NULL;
105 int penclen;
106
107 if (ecxkey == NULL || ecxkey->privkey == NULL) {
108 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
109 return 0;
110 }
111
112 oct.data = ecxkey->privkey;
113 oct.length = KEYLEN(pkey);
114 oct.flags = 0;
115
116 penclen = i2d_ASN1_OCTET_STRING(&oct, &penc);
117 if (penclen < 0) {
118 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
119 return 0;
120 }
121
122 if (!PKCS8_pkey_set0(p8, OBJ_nid2obj(pkey->ameth->pkey_id), 0,
123 V_ASN1_UNDEF, NULL, penc, penclen)) {
124 OPENSSL_clear_free(penc, penclen);
125 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
126 return 0;
127 }
128
129 return 1;
130 }
131
132 static int ecx_size(const EVP_PKEY *pkey)
133 {
134 return KEYLEN(pkey);
135 }
136
137 static int ecx_bits(const EVP_PKEY *pkey)
138 {
139 if (IS25519(pkey->ameth->pkey_id)) {
140 return X25519_BITS;
141 } else if(ISX448(pkey->ameth->pkey_id)) {
142 return X448_BITS;
143 } else {
144 return ED448_BITS;
145 }
146 }
147
148 static int ecx_security_bits(const EVP_PKEY *pkey)
149 {
150 if (IS25519(pkey->ameth->pkey_id)) {
151 return X25519_SECURITY_BITS;
152 } else {
153 return X448_SECURITY_BITS;
154 }
155 }
156
157 static void ecx_free(EVP_PKEY *pkey)
158 {
159 ossl_ecx_key_free(pkey->pkey.ecx);
160 }
161
162 /* "parameters" are always equal */
163 static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
164 {
165 return 1;
166 }
167
168 static int ecx_key_print(BIO *bp, const EVP_PKEY *pkey, int indent,
169 ASN1_PCTX *ctx, ecx_key_op_t op)
170 {
171 const ECX_KEY *ecxkey = pkey->pkey.ecx;
172 const char *nm = OBJ_nid2ln(pkey->ameth->pkey_id);
173
174 if (op == KEY_OP_PRIVATE) {
175 if (ecxkey == NULL || ecxkey->privkey == NULL) {
176 if (BIO_printf(bp, "%*s<INVALID PRIVATE KEY>\n", indent, "") <= 0)
177 return 0;
178 return 1;
179 }
180 if (BIO_printf(bp, "%*s%s Private-Key:\n", indent, "", nm) <= 0)
181 return 0;
182 if (BIO_printf(bp, "%*spriv:\n", indent, "") <= 0)
183 return 0;
184 if (ASN1_buf_print(bp, ecxkey->privkey, KEYLEN(pkey),
185 indent + 4) == 0)
186 return 0;
187 } else {
188 if (ecxkey == NULL) {
189 if (BIO_printf(bp, "%*s<INVALID PUBLIC KEY>\n", indent, "") <= 0)
190 return 0;
191 return 1;
192 }
193 if (BIO_printf(bp, "%*s%s Public-Key:\n", indent, "", nm) <= 0)
194 return 0;
195 }
196 if (BIO_printf(bp, "%*spub:\n", indent, "") <= 0)
197 return 0;
198
199 if (ASN1_buf_print(bp, ecxkey->pubkey, KEYLEN(pkey),
200 indent + 4) == 0)
201 return 0;
202 return 1;
203 }
204
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
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
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 }
246
247 static int ecd_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
248 {
249 switch (op) {
250 case ASN1_PKEY_CTRL_DEFAULT_MD_NID:
251 /* We currently only support Pure EdDSA which takes no digest */
252 *(int *)arg2 = NID_undef;
253 return 2;
254
255 default:
256 return -2;
257
258 }
259 }
260
261 static int ecx_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv,
262 size_t len)
263 {
264 OSSL_LIB_CTX *libctx = NULL;
265 ECX_KEY *ecx = NULL;
266
267 if (pkey->keymgmt != NULL)
268 libctx = ossl_provider_libctx(EVP_KEYMGMT_provider(pkey->keymgmt));
269
270 ecx = ossl_ecx_key_op(NULL, priv, len, pkey->ameth->pkey_id,
271 KEY_OP_PRIVATE, libctx, NULL);
272
273 if (ecx != NULL) {
274 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
275 return 1;
276 }
277 return 0;
278 }
279
280 static int ecx_set_pub_key(EVP_PKEY *pkey, const unsigned char *pub, size_t len)
281 {
282 OSSL_LIB_CTX *libctx = NULL;
283 ECX_KEY *ecx = NULL;
284
285 if (pkey->keymgmt != NULL)
286 libctx = ossl_provider_libctx(EVP_KEYMGMT_provider(pkey->keymgmt));
287
288 ecx = ossl_ecx_key_op(NULL, pub, len, pkey->ameth->pkey_id,
289 KEY_OP_PUBLIC, libctx, NULL);
290
291 if (ecx != NULL) {
292 EVP_PKEY_assign(pkey, pkey->ameth->pkey_id, ecx);
293 return 1;
294 }
295 return 0;
296 }
297
298 static int ecx_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv,
299 size_t *len)
300 {
301 const ECX_KEY *key = pkey->pkey.ecx;
302
303 if (priv == NULL) {
304 *len = KEYLENID(pkey->ameth->pkey_id);
305 return 1;
306 }
307
308 if (key == NULL
309 || key->privkey == NULL
310 || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
311 return 0;
312
313 *len = KEYLENID(pkey->ameth->pkey_id);
314 memcpy(priv, key->privkey, *len);
315
316 return 1;
317 }
318
319 static int ecx_get_pub_key(const EVP_PKEY *pkey, unsigned char *pub,
320 size_t *len)
321 {
322 const ECX_KEY *key = pkey->pkey.ecx;
323
324 if (pub == NULL) {
325 *len = KEYLENID(pkey->ameth->pkey_id);
326 return 1;
327 }
328
329 if (key == NULL
330 || *len < (size_t)KEYLENID(pkey->ameth->pkey_id))
331 return 0;
332
333 *len = KEYLENID(pkey->ameth->pkey_id);
334 memcpy(pub, key->pubkey, *len);
335
336 return 1;
337 }
338
339 static size_t ecx_pkey_dirty_cnt(const EVP_PKEY *pkey)
340 {
341 /*
342 * We provide no mechanism to "update" an ECX key once it has been set,
343 * therefore we do not have to maintain a dirty count.
344 */
345 return 1;
346 }
347
348 static int ecx_pkey_export_to(const EVP_PKEY *from, void *to_keydata,
349 EVP_KEYMGMT *to_keymgmt, OSSL_LIB_CTX *libctx,
350 const char *propq)
351 {
352 const ECX_KEY *key = from->pkey.ecx;
353 OSSL_PARAM_BLD *tmpl = OSSL_PARAM_BLD_new();
354 OSSL_PARAM *params = NULL;
355 int selection = 0;
356 int rv = 0;
357
358 if (tmpl == NULL)
359 return 0;
360
361 /* A key must at least have a public part */
362 if (!OSSL_PARAM_BLD_push_octet_string(tmpl, OSSL_PKEY_PARAM_PUB_KEY,
363 key->pubkey, key->keylen))
364 goto err;
365 selection |= OSSL_KEYMGMT_SELECT_PUBLIC_KEY;
366
367 if (key->privkey != NULL) {
368 if (!OSSL_PARAM_BLD_push_octet_string(tmpl,
369 OSSL_PKEY_PARAM_PRIV_KEY,
370 key->privkey, key->keylen))
371 goto err;
372 selection |= OSSL_KEYMGMT_SELECT_PRIVATE_KEY;
373 }
374
375 params = OSSL_PARAM_BLD_to_param(tmpl);
376
377 /* We export, the provider imports */
378 rv = evp_keymgmt_import(to_keymgmt, to_keydata, selection, params);
379
380 err:
381 OSSL_PARAM_BLD_free(tmpl);
382 OSSL_PARAM_BLD_free_params(params);
383 return rv;
384 }
385
386 static int ecx_generic_import_from(const OSSL_PARAM params[], void *vpctx,
387 int keytype)
388 {
389 EVP_PKEY_CTX *pctx = vpctx;
390 EVP_PKEY *pkey = EVP_PKEY_CTX_get0_pkey(pctx);
391 ECX_KEY *ecx = ossl_ecx_key_new(pctx->libctx, KEYNID2TYPE(keytype), 0,
392 pctx->propquery);
393
394 if (ecx == NULL) {
395 ERR_raise(ERR_LIB_DH, ERR_R_MALLOC_FAILURE);
396 return 0;
397 }
398
399 if (!ossl_ecx_key_fromdata(ecx, params, 1)
400 || !EVP_PKEY_assign(pkey, keytype, ecx)) {
401 ossl_ecx_key_free(ecx);
402 return 0;
403 }
404 return 1;
405 }
406
407 static int ecx_pkey_copy(EVP_PKEY *to, EVP_PKEY *from)
408 {
409 ECX_KEY *ecx = from->pkey.ecx;
410 int ret;
411
412 /* We can do just up-ref as ECX keys are immutable */
413 if (ecx != NULL && !ossl_ecx_key_up_ref(ecx))
414 return 0;
415
416 ret = EVP_PKEY_assign(to, from->type, ecx);
417 if (!ret)
418 ossl_ecx_key_free(ecx);
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_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
563 const void *asn,
564 X509_ALGOR *alg1, X509_ALGOR *alg2,
565 ASN1_BIT_STRING *str)
566 {
567 /* Set algorithms identifiers */
568 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
569 if (alg2)
570 X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
571 /* Algorithm identifiers set: carry on as normal */
572 return 3;
573 }
574
575 static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
576 const ASN1_STRING *sig)
577 {
578 X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
579 X509_SIG_INFO_TLS);
580 return 1;
581 }
582
583 static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
584 const void *asn,
585 X509_ALGOR *alg1, X509_ALGOR *alg2,
586 ASN1_BIT_STRING *str)
587 {
588 /* Set algorithm identifier */
589 X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
590 if (alg2 != NULL)
591 X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
592 /* Algorithm identifier set: carry on as normal */
593 return 3;
594 }
595
596 static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
597 const ASN1_STRING *sig)
598 {
599 X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
600 X509_SIG_INFO_TLS);
601 return 1;
602 }
603
604 static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
605 {
606 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
607 }
608
609 const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
610 EVP_PKEY_ED25519,
611 EVP_PKEY_ED25519,
612 0,
613 "ED25519",
614 "OpenSSL ED25519 algorithm",
615
616 ecx_pub_decode,
617 ecx_pub_encode,
618 ecx_pub_cmp,
619 ecx_pub_print,
620
621 NULL,
622 ecx_priv_encode,
623 ecx_priv_print,
624
625 ecd_size25519,
626 ecx_bits,
627 ecx_security_bits,
628
629 0, 0, 0, 0,
630 ecx_cmp_parameters,
631 0, 0,
632
633 ecx_free,
634 ecd_ctrl,
635 NULL,
636 NULL,
637 ecd_item_verify,
638 ecd_item_sign25519,
639 ecd_sig_info_set25519,
640
641 NULL,
642 NULL,
643 NULL,
644
645 ecx_set_priv_key,
646 ecx_set_pub_key,
647 ecx_get_priv_key,
648 ecx_get_pub_key,
649 ecx_pkey_dirty_cnt,
650 ecx_pkey_export_to,
651 ed25519_import_from,
652 ecx_pkey_copy,
653
654 ecx_priv_decode_ex
655 };
656
657 static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
658 {
659 return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
660 }
661
662 const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
663 EVP_PKEY_ED448,
664 EVP_PKEY_ED448,
665 0,
666 "ED448",
667 "OpenSSL ED448 algorithm",
668
669 ecx_pub_decode,
670 ecx_pub_encode,
671 ecx_pub_cmp,
672 ecx_pub_print,
673
674 NULL,
675 ecx_priv_encode,
676 ecx_priv_print,
677
678 ecd_size448,
679 ecx_bits,
680 ecx_security_bits,
681
682 0, 0, 0, 0,
683 ecx_cmp_parameters,
684 0, 0,
685
686 ecx_free,
687 ecd_ctrl,
688 NULL,
689 NULL,
690 ecd_item_verify,
691 ecd_item_sign448,
692 ecd_sig_info_set448,
693
694 NULL,
695 NULL,
696 NULL,
697
698 ecx_set_priv_key,
699 ecx_set_pub_key,
700 ecx_get_priv_key,
701 ecx_get_pub_key,
702 ecx_pkey_dirty_cnt,
703 ecx_pkey_export_to,
704 ed448_import_from,
705 ecx_pkey_copy,
706
707 ecx_priv_decode_ex
708 };
709
710 static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
711 {
712 ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
713 KEY_OP_PUBLIC, NULL, NULL);
714
715 if (ecx != NULL) {
716 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
717 return 1;
718 }
719 return 0;
720 }
721
722 static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
723 size_t *keylen,
724 const unsigned char **privkey,
725 const unsigned char **pubkey)
726 {
727 const ECX_KEY *ecxkey, *peerkey;
728
729 if (ctx->pkey == NULL || ctx->peerkey == NULL) {
730 ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
731 return 0;
732 }
733 ecxkey = ctx->pkey->pkey.ecx;
734 peerkey = EVP_PKEY_get0(ctx->peerkey);
735 if (ecxkey == NULL || ecxkey->privkey == NULL) {
736 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
737 return 0;
738 }
739 if (peerkey == NULL) {
740 ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
741 return 0;
742 }
743 *privkey = ecxkey->privkey;
744 *pubkey = peerkey->pubkey;
745
746 return 1;
747 }
748
749 static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
750 size_t *keylen)
751 {
752 const unsigned char *privkey, *pubkey;
753
754 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
755 || (key != NULL
756 && ossl_x25519(key, privkey, pubkey) == 0))
757 return 0;
758 *keylen = X25519_KEYLEN;
759 return 1;
760 }
761
762 static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
763 size_t *keylen)
764 {
765 const unsigned char *privkey, *pubkey;
766
767 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
768 || (key != NULL
769 && ossl_x448(key, privkey, pubkey) == 0))
770 return 0;
771 *keylen = X448_KEYLEN;
772 return 1;
773 }
774
775 static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
776 {
777 /* Only need to handle peer key for derivation */
778 if (type == EVP_PKEY_CTRL_PEER_KEY)
779 return 1;
780 return -2;
781 }
782
783 static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
784 EVP_PKEY_X25519,
785 0, 0, 0, 0, 0, 0, 0,
786 pkey_ecx_keygen,
787 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
788 pkey_ecx_derive25519,
789 pkey_ecx_ctrl,
790 0
791 };
792
793 static const EVP_PKEY_METHOD ecx448_pkey_meth = {
794 EVP_PKEY_X448,
795 0, 0, 0, 0, 0, 0, 0,
796 pkey_ecx_keygen,
797 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
798 pkey_ecx_derive448,
799 pkey_ecx_ctrl,
800 0
801 };
802
803 static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
804 size_t *siglen, const unsigned char *tbs,
805 size_t tbslen)
806 {
807 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
808
809 if (sig == NULL) {
810 *siglen = ED25519_SIGSIZE;
811 return 1;
812 }
813 if (*siglen < ED25519_SIGSIZE) {
814 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
815 return 0;
816 }
817
818 if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
819 NULL) == 0)
820 return 0;
821 *siglen = ED25519_SIGSIZE;
822 return 1;
823 }
824
825 static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
826 size_t *siglen, const unsigned char *tbs,
827 size_t tbslen)
828 {
829 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
830
831 if (sig == NULL) {
832 *siglen = ED448_SIGSIZE;
833 return 1;
834 }
835 if (*siglen < ED448_SIGSIZE) {
836 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
837 return 0;
838 }
839
840 if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
841 edkey->privkey, NULL, 0, edkey->propq) == 0)
842 return 0;
843 *siglen = ED448_SIGSIZE;
844 return 1;
845 }
846
847 static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
848 size_t siglen, const unsigned char *tbs,
849 size_t tbslen)
850 {
851 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
852
853 if (siglen != ED25519_SIGSIZE)
854 return 0;
855
856 return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
857 edkey->libctx, edkey->propq);
858 }
859
860 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
861 size_t siglen, const unsigned char *tbs,
862 size_t tbslen)
863 {
864 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
865
866 if (siglen != ED448_SIGSIZE)
867 return 0;
868
869 return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
870 NULL, 0, edkey->propq);
871 }
872
873 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
874 {
875 switch (type) {
876 case EVP_PKEY_CTRL_MD:
877 /* Only NULL allowed as digest */
878 if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
879 return 1;
880 ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
881 return 0;
882
883 case EVP_PKEY_CTRL_DIGESTINIT:
884 return 1;
885 }
886 return -2;
887 }
888
889 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
890 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
891 0, 0, 0, 0, 0, 0,
892 pkey_ecx_keygen,
893 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
894 pkey_ecd_ctrl,
895 0,
896 pkey_ecd_digestsign25519,
897 pkey_ecd_digestverify25519
898 };
899
900 static const EVP_PKEY_METHOD ed448_pkey_meth = {
901 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
902 0, 0, 0, 0, 0, 0,
903 pkey_ecx_keygen,
904 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
905 pkey_ecd_ctrl,
906 0,
907 pkey_ecd_digestsign448,
908 pkey_ecd_digestverify448
909 };
910
911 #ifdef S390X_EC_ASM
912 # include "s390x_arch.h"
913
914 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
915 {
916 static const unsigned char generator[] = {
917 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
918 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
920 };
921 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
922 ctx->propquery);
923 unsigned char *privkey = NULL, *pubkey;
924
925 if (key == NULL) {
926 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
927 goto err;
928 }
929
930 pubkey = key->pubkey;
931
932 privkey = ossl_ecx_key_allocate_privkey(key);
933 if (privkey == NULL) {
934 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
935 goto err;
936 }
937
938 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN) <= 0)
939 goto err;
940
941 privkey[0] &= 248;
942 privkey[31] &= 127;
943 privkey[31] |= 64;
944
945 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
946 goto err;
947
948 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
949 return 1;
950 err:
951 ossl_ecx_key_free(key);
952 return 0;
953 }
954
955 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
956 {
957 static const unsigned char generator[] = {
958 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
959 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
960 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
961 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
962 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
963 };
964 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
965 ctx->propquery);
966 unsigned char *privkey = NULL, *pubkey;
967
968 if (key == NULL) {
969 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
970 goto err;
971 }
972
973 pubkey = key->pubkey;
974
975 privkey = ossl_ecx_key_allocate_privkey(key);
976 if (privkey == NULL) {
977 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
978 goto err;
979 }
980
981 if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN) <= 0)
982 goto err;
983
984 privkey[0] &= 252;
985 privkey[55] |= 128;
986
987 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
988 goto err;
989
990 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
991 return 1;
992 err:
993 ossl_ecx_key_free(key);
994 return 0;
995 }
996
997 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
998 {
999 static const unsigned char generator_x[] = {
1000 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1001 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1002 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1003 };
1004 static const unsigned char generator_y[] = {
1005 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1006 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1007 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1008 };
1009 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1010 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1011 ctx->propquery);
1012 unsigned char *privkey = NULL, *pubkey;
1013 unsigned int sz;
1014 EVP_MD *md = NULL;
1015 int rv;
1016
1017 if (key == NULL) {
1018 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1019 goto err;
1020 }
1021
1022 pubkey = key->pubkey;
1023
1024 privkey = ossl_ecx_key_allocate_privkey(key);
1025 if (privkey == NULL) {
1026 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1027 goto err;
1028 }
1029
1030 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN) <= 0)
1031 goto err;
1032
1033 md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1034 if (md == NULL)
1035 goto err;
1036
1037 rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1038 EVP_MD_free(md);
1039 if (!rv)
1040 goto err;
1041
1042 buff[0] &= 248;
1043 buff[31] &= 63;
1044 buff[31] |= 64;
1045
1046 if (s390x_ed25519_mul(x_dst, pubkey,
1047 generator_x, generator_y, buff) != 1)
1048 goto err;
1049
1050 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1051
1052 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1053 return 1;
1054 err:
1055 ossl_ecx_key_free(key);
1056 return 0;
1057 }
1058
1059 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1060 {
1061 static const unsigned char generator_x[] = {
1062 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1063 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1064 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1065 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1066 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1067 };
1068 static const unsigned char generator_y[] = {
1069 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1070 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1071 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1072 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1073 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1074 };
1075 unsigned char x_dst[57], buff[114];
1076 ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1077 ctx->propquery);
1078 unsigned char *privkey = NULL, *pubkey;
1079 EVP_MD_CTX *hashctx = NULL;
1080 EVP_MD *md = NULL;
1081 int rv;
1082
1083 if (key == NULL) {
1084 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1085 goto err;
1086 }
1087
1088 pubkey = key->pubkey;
1089
1090 privkey = ossl_ecx_key_allocate_privkey(key);
1091 if (privkey == NULL) {
1092 ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1093 goto err;
1094 }
1095
1096 if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN) <= 0)
1097 goto err;
1098
1099 hashctx = EVP_MD_CTX_new();
1100 if (hashctx == NULL)
1101 goto err;
1102
1103 md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1104 if (md == NULL)
1105 goto err;
1106
1107 rv = EVP_DigestInit_ex(hashctx, md, NULL);
1108 EVP_MD_free(md);
1109 if (rv != 1)
1110 goto err;
1111
1112 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1113 goto err;
1114 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1115 goto err;
1116
1117 buff[0] &= -4;
1118 buff[55] |= 0x80;
1119 buff[56] = 0;
1120
1121 if (s390x_ed448_mul(x_dst, pubkey,
1122 generator_x, generator_y, buff) != 1)
1123 goto err;
1124
1125 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1126
1127 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1128 EVP_MD_CTX_free(hashctx);
1129 return 1;
1130 err:
1131 ossl_ecx_key_free(key);
1132 EVP_MD_CTX_free(hashctx);
1133 return 0;
1134 }
1135
1136 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1137 size_t *keylen)
1138 {
1139 const unsigned char *privkey, *pubkey;
1140
1141 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1142 return 0;
1143
1144 if (key != NULL)
1145 return s390x_x25519_mul(key, pubkey, privkey);
1146
1147 *keylen = X25519_KEYLEN;
1148 return 1;
1149 }
1150
1151 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1152 size_t *keylen)
1153 {
1154 const unsigned char *privkey, *pubkey;
1155
1156 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1157 return 0;
1158
1159 if (key != NULL)
1160 return s390x_x448_mul(key, pubkey, privkey);
1161
1162 *keylen = X448_KEYLEN;
1163 return 1;
1164 }
1165
1166 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1167 unsigned char *sig, size_t *siglen,
1168 const unsigned char *tbs,
1169 size_t tbslen)
1170 {
1171 union {
1172 struct {
1173 unsigned char sig[64];
1174 unsigned char priv[32];
1175 } ed25519;
1176 unsigned long long buff[512];
1177 } param;
1178 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1179 int rc;
1180
1181 if (sig == NULL) {
1182 *siglen = ED25519_SIGSIZE;
1183 return 1;
1184 }
1185
1186 if (*siglen < ED25519_SIGSIZE) {
1187 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1188 return 0;
1189 }
1190
1191 memset(&param, 0, sizeof(param));
1192 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1193
1194 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1195 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1196 if (rc != 0)
1197 return 0;
1198
1199 s390x_flip_endian32(sig, param.ed25519.sig);
1200 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1201
1202 *siglen = ED25519_SIGSIZE;
1203 return 1;
1204 }
1205
1206 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1207 unsigned char *sig, size_t *siglen,
1208 const unsigned char *tbs,
1209 size_t tbslen)
1210 {
1211 union {
1212 struct {
1213 unsigned char sig[128];
1214 unsigned char priv[64];
1215 } ed448;
1216 unsigned long long buff[512];
1217 } param;
1218 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1219 int rc;
1220
1221 if (sig == NULL) {
1222 *siglen = ED448_SIGSIZE;
1223 return 1;
1224 }
1225
1226 if (*siglen < ED448_SIGSIZE) {
1227 ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1228 return 0;
1229 }
1230
1231 memset(&param, 0, sizeof(param));
1232 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1233
1234 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1235 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1236 if (rc != 0)
1237 return 0;
1238
1239 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1240 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1241 memcpy(sig, param.ed448.sig, 57);
1242 memcpy(sig + 57, param.ed448.sig + 64, 57);
1243
1244 *siglen = ED448_SIGSIZE;
1245 return 1;
1246 }
1247
1248 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1249 const unsigned char *sig,
1250 size_t siglen,
1251 const unsigned char *tbs,
1252 size_t tbslen)
1253 {
1254 union {
1255 struct {
1256 unsigned char sig[64];
1257 unsigned char pub[32];
1258 } ed25519;
1259 unsigned long long buff[512];
1260 } param;
1261 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1262
1263 if (siglen != ED25519_SIGSIZE)
1264 return 0;
1265
1266 memset(&param, 0, sizeof(param));
1267 s390x_flip_endian32(param.ed25519.sig, sig);
1268 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1269 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1270
1271 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1272 &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1273 }
1274
1275 static int s390x_pkey_ecd_digestverify448(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[128];
1284 unsigned char pub[64];
1285 } ed448;
1286 unsigned long long buff[512];
1287 } param;
1288 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1289
1290 if (siglen != ED448_SIGSIZE)
1291 return 0;
1292
1293 memset(&param, 0, sizeof(param));
1294 memcpy(param.ed448.sig, sig, 57);
1295 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1296 memcpy(param.ed448.sig + 64, sig + 57, 57);
1297 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1298 memcpy(param.ed448.pub, edkey->pubkey, 57);
1299 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1300
1301 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1302 &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1303 }
1304
1305 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1306 EVP_PKEY_X25519,
1307 0, 0, 0, 0, 0, 0, 0,
1308 s390x_pkey_ecx_keygen25519,
1309 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1310 s390x_pkey_ecx_derive25519,
1311 pkey_ecx_ctrl,
1312 0
1313 };
1314
1315 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1316 EVP_PKEY_X448,
1317 0, 0, 0, 0, 0, 0, 0,
1318 s390x_pkey_ecx_keygen448,
1319 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1320 s390x_pkey_ecx_derive448,
1321 pkey_ecx_ctrl,
1322 0
1323 };
1324 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1325 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1326 0, 0, 0, 0, 0, 0,
1327 s390x_pkey_ecd_keygen25519,
1328 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1329 pkey_ecd_ctrl,
1330 0,
1331 s390x_pkey_ecd_digestsign25519,
1332 s390x_pkey_ecd_digestverify25519
1333 };
1334
1335 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1336 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1337 0, 0, 0, 0, 0, 0,
1338 s390x_pkey_ecd_keygen448,
1339 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1340 pkey_ecd_ctrl,
1341 0,
1342 s390x_pkey_ecd_digestsign448,
1343 s390x_pkey_ecd_digestverify448
1344 };
1345 #endif
1346
1347 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1348 {
1349 #ifdef S390X_EC_ASM
1350 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1351 return &ecx25519_s390x_pkey_meth;
1352 #endif
1353 return &ecx25519_pkey_meth;
1354 }
1355
1356 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1357 {
1358 #ifdef S390X_EC_ASM
1359 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1360 return &ecx448_s390x_pkey_meth;
1361 #endif
1362 return &ecx448_pkey_meth;
1363 }
1364
1365 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1366 {
1367 #ifdef S390X_EC_ASM
1368 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1369 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1370 && OPENSSL_s390xcap_P.kdsa[0]
1371 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1372 return &ed25519_s390x_pkey_meth;
1373 #endif
1374 return &ed25519_pkey_meth;
1375 }
1376
1377 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1378 {
1379 #ifdef S390X_EC_ASM
1380 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1381 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1382 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1383 return &ed448_s390x_pkey_meth;
1384 #endif
1385 return &ed448_pkey_meth;
1386 }