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