Checking __STDC_VERSION__ rather than __STRICT_ANSI__
[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         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_get0_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_get0_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                               OSSL_FUNC_keymgmt_import_fn *importer,
350                               OSSL_LIB_CTX *libctx, 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 = importer(to_keydata, selection, params);
379
380  err:
381     OSSL_PARAM_BLD_free(tmpl);
382     OSSL_PARAM_free(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, *dupkey = NULL;
410     int ret;
411
412     if (ecx != NULL) {
413         dupkey = ossl_ecx_key_dup(ecx, OSSL_KEYMGMT_SELECT_ALL);
414         if (dupkey == NULL)
415             return 0;
416     }
417
418     ret = EVP_PKEY_assign(to, from->type, dupkey);
419     if (!ret)
420         ossl_ecx_key_free(dupkey);
421     return ret;
422 }
423
424 static int x25519_import_from(const OSSL_PARAM params[], void *vpctx)
425 {
426     return ecx_generic_import_from(params, vpctx, EVP_PKEY_X25519);
427 }
428
429 const EVP_PKEY_ASN1_METHOD ossl_ecx25519_asn1_meth = {
430     EVP_PKEY_X25519,
431     EVP_PKEY_X25519,
432     0,
433     "X25519",
434     "OpenSSL X25519 algorithm",
435
436     ecx_pub_decode,
437     ecx_pub_encode,
438     ecx_pub_cmp,
439     ecx_pub_print,
440
441     NULL,
442     ecx_priv_encode,
443     ecx_priv_print,
444
445     ecx_size,
446     ecx_bits,
447     ecx_security_bits,
448
449     0, 0, 0, 0,
450     ecx_cmp_parameters,
451     0, 0,
452
453     ecx_free,
454     ecx_ctrl,
455     NULL,
456     NULL,
457
458     NULL,
459     NULL,
460     NULL,
461
462     NULL,
463     NULL,
464     NULL,
465
466     ecx_set_priv_key,
467     ecx_set_pub_key,
468     ecx_get_priv_key,
469     ecx_get_pub_key,
470     ecx_pkey_dirty_cnt,
471     ecx_pkey_export_to,
472     x25519_import_from,
473     ecx_pkey_copy,
474
475     ecx_priv_decode_ex
476 };
477
478 static int x448_import_from(const OSSL_PARAM params[], void *vpctx)
479 {
480     return ecx_generic_import_from(params, vpctx, EVP_PKEY_X448);
481 }
482
483 const EVP_PKEY_ASN1_METHOD ossl_ecx448_asn1_meth = {
484     EVP_PKEY_X448,
485     EVP_PKEY_X448,
486     0,
487     "X448",
488     "OpenSSL X448 algorithm",
489
490     ecx_pub_decode,
491     ecx_pub_encode,
492     ecx_pub_cmp,
493     ecx_pub_print,
494
495     NULL,
496     ecx_priv_encode,
497     ecx_priv_print,
498
499     ecx_size,
500     ecx_bits,
501     ecx_security_bits,
502
503     0, 0, 0, 0,
504     ecx_cmp_parameters,
505     0, 0,
506
507     ecx_free,
508     ecx_ctrl,
509     NULL,
510     NULL,
511
512     NULL,
513     NULL,
514     NULL,
515
516     NULL,
517     NULL,
518     NULL,
519
520     ecx_set_priv_key,
521     ecx_set_pub_key,
522     ecx_get_priv_key,
523     ecx_get_pub_key,
524     ecx_pkey_dirty_cnt,
525     ecx_pkey_export_to,
526     x448_import_from,
527     ecx_pkey_copy,
528
529     ecx_priv_decode_ex
530 };
531
532 static int ecd_size25519(const EVP_PKEY *pkey)
533 {
534     return ED25519_SIGSIZE;
535 }
536
537 static int ecd_size448(const EVP_PKEY *pkey)
538 {
539     return ED448_SIGSIZE;
540 }
541
542 static int ecd_item_verify(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
543                            const void *asn, const X509_ALGOR *sigalg,
544                            const ASN1_BIT_STRING *str, EVP_PKEY *pkey)
545 {
546     const ASN1_OBJECT *obj;
547     int ptype;
548     int nid;
549
550     /* Sanity check: make sure it is ED25519/ED448 with absent parameters */
551     X509_ALGOR_get0(&obj, &ptype, NULL, sigalg);
552     nid = OBJ_obj2nid(obj);
553     if ((nid != NID_ED25519 && nid != NID_ED448) || ptype != V_ASN1_UNDEF) {
554         ERR_raise(ERR_LIB_EC, EC_R_INVALID_ENCODING);
555         return 0;
556     }
557
558     if (!EVP_DigestVerifyInit(ctx, NULL, NULL, NULL, pkey))
559         return 0;
560
561     return 2;
562 }
563
564 static int ecd_item_sign(X509_ALGOR *alg1, X509_ALGOR *alg2, int nid)
565 {
566     /* Note that X509_ALGOR_set0(..., ..., V_ASN1_UNDEF, ...) cannot fail */
567     /* Set algorithms identifiers */
568     (void)X509_ALGOR_set0(alg1, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
569     if (alg2 != NULL)
570         (void)X509_ALGOR_set0(alg2, OBJ_nid2obj(nid), V_ASN1_UNDEF, NULL);
571     /* Algorithm identifiers set: carry on as normal */
572     return 3;
573 }
574
575 static int ecd_item_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
576                               const void *asn,
577                               X509_ALGOR *alg1, X509_ALGOR *alg2,
578                               ASN1_BIT_STRING *str)
579 {
580     return ecd_item_sign(alg1, alg2, NID_ED25519);
581 }
582
583 static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
584                                  const ASN1_STRING *sig)
585 {
586     X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
587                       X509_SIG_INFO_TLS);
588     return 1;
589 }
590
591 static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
592                             const void *asn,
593                             X509_ALGOR *alg1, X509_ALGOR *alg2,
594                             ASN1_BIT_STRING *str)
595 {
596     return ecd_item_sign(alg1, alg2, NID_ED448);
597 }
598
599 static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
600                                const ASN1_STRING *sig)
601 {
602     X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
603                       X509_SIG_INFO_TLS);
604     return 1;
605 }
606
607 static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
608 {
609     return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
610 }
611
612 const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
613     EVP_PKEY_ED25519,
614     EVP_PKEY_ED25519,
615     0,
616     "ED25519",
617     "OpenSSL ED25519 algorithm",
618
619     ecx_pub_decode,
620     ecx_pub_encode,
621     ecx_pub_cmp,
622     ecx_pub_print,
623
624     NULL,
625     ecx_priv_encode,
626     ecx_priv_print,
627
628     ecd_size25519,
629     ecx_bits,
630     ecx_security_bits,
631
632     0, 0, 0, 0,
633     ecx_cmp_parameters,
634     0, 0,
635
636     ecx_free,
637     ecd_ctrl,
638     NULL,
639     NULL,
640     ecd_item_verify,
641     ecd_item_sign25519,
642     ecd_sig_info_set25519,
643
644     NULL,
645     NULL,
646     NULL,
647
648     ecx_set_priv_key,
649     ecx_set_pub_key,
650     ecx_get_priv_key,
651     ecx_get_pub_key,
652     ecx_pkey_dirty_cnt,
653     ecx_pkey_export_to,
654     ed25519_import_from,
655     ecx_pkey_copy,
656
657     ecx_priv_decode_ex
658 };
659
660 static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
661 {
662     return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
663 }
664
665 const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
666     EVP_PKEY_ED448,
667     EVP_PKEY_ED448,
668     0,
669     "ED448",
670     "OpenSSL ED448 algorithm",
671
672     ecx_pub_decode,
673     ecx_pub_encode,
674     ecx_pub_cmp,
675     ecx_pub_print,
676
677     NULL,
678     ecx_priv_encode,
679     ecx_priv_print,
680
681     ecd_size448,
682     ecx_bits,
683     ecx_security_bits,
684
685     0, 0, 0, 0,
686     ecx_cmp_parameters,
687     0, 0,
688
689     ecx_free,
690     ecd_ctrl,
691     NULL,
692     NULL,
693     ecd_item_verify,
694     ecd_item_sign448,
695     ecd_sig_info_set448,
696
697     NULL,
698     NULL,
699     NULL,
700
701     ecx_set_priv_key,
702     ecx_set_pub_key,
703     ecx_get_priv_key,
704     ecx_get_pub_key,
705     ecx_pkey_dirty_cnt,
706     ecx_pkey_export_to,
707     ed448_import_from,
708     ecx_pkey_copy,
709
710     ecx_priv_decode_ex
711 };
712
713 static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
714 {
715     ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
716                                    KEY_OP_PUBLIC, NULL, NULL);
717
718     if (ecx != NULL) {
719         EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
720         return 1;
721     }
722     return 0;
723 }
724
725 static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
726                                           size_t *keylen,
727                                           const unsigned char **privkey,
728                                           const unsigned char **pubkey)
729 {
730     const ECX_KEY *ecxkey, *peerkey;
731
732     if (ctx->pkey == NULL || ctx->peerkey == NULL) {
733         ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
734         return 0;
735     }
736     ecxkey = evp_pkey_get_legacy(ctx->pkey);
737     peerkey = evp_pkey_get_legacy(ctx->peerkey);
738     if (ecxkey == NULL || ecxkey->privkey == NULL) {
739         ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
740         return 0;
741     }
742     if (peerkey == NULL) {
743         ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
744         return 0;
745     }
746     *privkey = ecxkey->privkey;
747     *pubkey = peerkey->pubkey;
748
749     return 1;
750 }
751
752 static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
753                                 size_t *keylen)
754 {
755     const unsigned char *privkey, *pubkey;
756
757     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
758             || (key != NULL
759                 && ossl_x25519(key, privkey, pubkey) == 0))
760         return 0;
761     *keylen = X25519_KEYLEN;
762     return 1;
763 }
764
765 static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
766                               size_t *keylen)
767 {
768     const unsigned char *privkey, *pubkey;
769
770     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
771             || (key != NULL
772                 && ossl_x448(key, privkey, pubkey) == 0))
773         return 0;
774     *keylen = X448_KEYLEN;
775     return 1;
776 }
777
778 static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
779 {
780     /* Only need to handle peer key for derivation */
781     if (type == EVP_PKEY_CTRL_PEER_KEY)
782         return 1;
783     return -2;
784 }
785
786 static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
787     EVP_PKEY_X25519,
788     0, 0, 0, 0, 0, 0, 0,
789     pkey_ecx_keygen,
790     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
791     pkey_ecx_derive25519,
792     pkey_ecx_ctrl,
793     0
794 };
795
796 static const EVP_PKEY_METHOD ecx448_pkey_meth = {
797     EVP_PKEY_X448,
798     0, 0, 0, 0, 0, 0, 0,
799     pkey_ecx_keygen,
800     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
801     pkey_ecx_derive448,
802     pkey_ecx_ctrl,
803     0
804 };
805
806 static int pkey_ecd_digestsign25519(EVP_MD_CTX *ctx, unsigned char *sig,
807                                     size_t *siglen, const unsigned char *tbs,
808                                     size_t tbslen)
809 {
810     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
811
812     if (edkey == NULL) {
813         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
814         return 0;
815     }
816
817     if (sig == NULL) {
818         *siglen = ED25519_SIGSIZE;
819         return 1;
820     }
821     if (*siglen < ED25519_SIGSIZE) {
822         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
823         return 0;
824     }
825
826     if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
827                           NULL) == 0)
828         return 0;
829     *siglen = ED25519_SIGSIZE;
830     return 1;
831 }
832
833 static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
834                                   size_t *siglen, const unsigned char *tbs,
835                                   size_t tbslen)
836 {
837     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
838
839     if (edkey == NULL) {
840         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
841         return 0;
842     }
843
844     if (sig == NULL) {
845         *siglen = ED448_SIGSIZE;
846         return 1;
847     }
848     if (*siglen < ED448_SIGSIZE) {
849         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
850         return 0;
851     }
852
853     if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
854                         edkey->privkey, NULL, 0, edkey->propq) == 0)
855         return 0;
856     *siglen = ED448_SIGSIZE;
857     return 1;
858 }
859
860 static int pkey_ecd_digestverify25519(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_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
865
866     if (edkey == NULL) {
867         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
868         return 0;
869     }
870
871     if (siglen != ED25519_SIGSIZE)
872         return 0;
873
874     return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
875                                edkey->libctx, edkey->propq);
876 }
877
878 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
879                                     size_t siglen, const unsigned char *tbs,
880                                     size_t tbslen)
881 {
882     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
883
884     if (edkey == NULL) {
885         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
886         return 0;
887     }
888
889     if (siglen != ED448_SIGSIZE)
890         return 0;
891
892     return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
893                              NULL, 0, edkey->propq);
894 }
895
896 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
897 {
898     switch (type) {
899     case EVP_PKEY_CTRL_MD:
900         /* Only NULL allowed as digest */
901         if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
902             return 1;
903         ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
904         return 0;
905
906     case EVP_PKEY_CTRL_DIGESTINIT:
907         return 1;
908     }
909     return -2;
910 }
911
912 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
913     EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
914     0, 0, 0, 0, 0, 0,
915     pkey_ecx_keygen,
916     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
917     pkey_ecd_ctrl,
918     0,
919     pkey_ecd_digestsign25519,
920     pkey_ecd_digestverify25519
921 };
922
923 static const EVP_PKEY_METHOD ed448_pkey_meth = {
924     EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
925     0, 0, 0, 0, 0, 0,
926     pkey_ecx_keygen,
927     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
928     pkey_ecd_ctrl,
929     0,
930     pkey_ecd_digestsign448,
931     pkey_ecd_digestverify448
932 };
933
934 #ifdef S390X_EC_ASM
935 # include "s390x_arch.h"
936
937 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
938 {
939     static const unsigned char generator[] = {
940         0x09, 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_X25519, 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, X25519_KEYLEN, 0) <= 0)
962         goto err;
963
964     privkey[0] &= 248;
965     privkey[31] &= 127;
966     privkey[31] |= 64;
967
968     if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
969         goto err;
970
971     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
972     return 1;
973  err:
974     ossl_ecx_key_free(key);
975     return 0;
976 }
977
978 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
979 {
980     static const unsigned char generator[] = {
981         0x05, 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, 0x00, 0x00, 0x00, 0x00,
984         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
985         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
986     };
987     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
988                                     ctx->propquery);
989     unsigned char *privkey = NULL, *pubkey;
990
991     if (key == NULL) {
992         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
993         goto err;
994     }
995
996     pubkey = key->pubkey;
997
998     privkey = ossl_ecx_key_allocate_privkey(key);
999     if (privkey == NULL) {
1000         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1001         goto err;
1002     }
1003
1004     if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1005         goto err;
1006
1007     privkey[0] &= 252;
1008     privkey[55] |= 128;
1009
1010     if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1011         goto err;
1012
1013     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1014     return 1;
1015  err:
1016     ossl_ecx_key_free(key);
1017     return 0;
1018 }
1019
1020 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1021 {
1022     static const unsigned char generator_x[] = {
1023         0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1024         0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1025         0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1026     };
1027     static const unsigned char generator_y[] = {
1028         0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1029         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1030         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1031     };
1032     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1033     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1034                                     ctx->propquery);
1035     unsigned char *privkey = NULL, *pubkey;
1036     unsigned int sz;
1037     EVP_MD *md = NULL;
1038     int rv;
1039
1040     if (key == NULL) {
1041         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1042         goto err;
1043     }
1044
1045     pubkey = key->pubkey;
1046
1047     privkey = ossl_ecx_key_allocate_privkey(key);
1048     if (privkey == NULL) {
1049         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1050         goto err;
1051     }
1052
1053     if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1054         goto err;
1055
1056     md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1057     if (md == NULL)
1058         goto err;
1059
1060     rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1061     EVP_MD_free(md);
1062     if (!rv)
1063         goto err;
1064
1065     buff[0] &= 248;
1066     buff[31] &= 63;
1067     buff[31] |= 64;
1068
1069     if (s390x_ed25519_mul(x_dst, pubkey,
1070                           generator_x, generator_y, buff) != 1)
1071         goto err;
1072
1073     pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1074
1075     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1076     return 1;
1077  err:
1078     ossl_ecx_key_free(key);
1079     return 0;
1080 }
1081
1082 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1083 {
1084     static const unsigned char generator_x[] = {
1085         0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1086         0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1087         0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1088         0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1089         0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1090     };
1091     static const unsigned char generator_y[] = {
1092         0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1093         0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1094         0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1095         0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1096         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1097     };
1098     unsigned char x_dst[57], buff[114];
1099     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1100                                     ctx->propquery);
1101     unsigned char *privkey = NULL, *pubkey;
1102     EVP_MD_CTX *hashctx = NULL;
1103     EVP_MD *md = NULL;
1104     int rv;
1105
1106     if (key == NULL) {
1107         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1108         goto err;
1109     }
1110
1111     pubkey = key->pubkey;
1112
1113     privkey = ossl_ecx_key_allocate_privkey(key);
1114     if (privkey == NULL) {
1115         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1116         goto err;
1117     }
1118
1119     if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1120         goto err;
1121
1122     hashctx = EVP_MD_CTX_new();
1123     if (hashctx == NULL)
1124         goto err;
1125
1126     md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1127     if (md == NULL)
1128         goto err;
1129
1130     rv = EVP_DigestInit_ex(hashctx, md, NULL);
1131     EVP_MD_free(md);
1132     if (rv != 1)
1133         goto err;
1134
1135     if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1136         goto err;
1137     if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1138         goto err;
1139
1140     buff[0] &= -4;
1141     buff[55] |= 0x80;
1142     buff[56] = 0;
1143
1144     if (s390x_ed448_mul(x_dst, pubkey,
1145                         generator_x, generator_y, buff) != 1)
1146         goto err;
1147
1148     pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1149
1150     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1151     EVP_MD_CTX_free(hashctx);
1152     return 1;
1153  err:
1154     ossl_ecx_key_free(key);
1155     EVP_MD_CTX_free(hashctx);
1156     return 0;
1157 }
1158
1159 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1160                                       size_t *keylen)
1161 {
1162     const unsigned char *privkey, *pubkey;
1163
1164     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1165         || (key != NULL
1166             && s390x_x25519_mul(key, privkey, pubkey) == 0))
1167         return 0;
1168     *keylen = X25519_KEYLEN;
1169     return 1;
1170 }
1171
1172 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1173                                       size_t *keylen)
1174 {
1175     const unsigned char *privkey, *pubkey;
1176
1177     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
1178         || (key != NULL
1179             && s390x_x448_mul(key, pubkey, privkey) == 0))
1180         return 0;
1181     *keylen = X448_KEYLEN;
1182     return 1;
1183 }
1184
1185 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1186                                           unsigned char *sig, size_t *siglen,
1187                                           const unsigned char *tbs,
1188                                           size_t tbslen)
1189 {
1190     union {
1191         struct {
1192             unsigned char sig[64];
1193             unsigned char priv[32];
1194         } ed25519;
1195         unsigned long long buff[512];
1196     } param;
1197     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1198     int rc;
1199
1200     if (edkey == NULL) {
1201         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1202         return 0;
1203     }
1204
1205     if (sig == NULL) {
1206         *siglen = ED25519_SIGSIZE;
1207         return 1;
1208     }
1209
1210     if (*siglen < ED25519_SIGSIZE) {
1211         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1212         return 0;
1213     }
1214
1215     memset(&param, 0, sizeof(param));
1216     memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1217
1218     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1219     OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1220     if (rc != 0)
1221         return 0;
1222
1223     s390x_flip_endian32(sig, param.ed25519.sig);
1224     s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1225
1226     *siglen = ED25519_SIGSIZE;
1227     return 1;
1228 }
1229
1230 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1231                                         unsigned char *sig, size_t *siglen,
1232                                         const unsigned char *tbs,
1233                                         size_t tbslen)
1234 {
1235     union {
1236         struct {
1237             unsigned char sig[128];
1238             unsigned char priv[64];
1239         } ed448;
1240         unsigned long long buff[512];
1241     } param;
1242     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1243     int rc;
1244
1245     if (edkey == NULL) {
1246         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1247         return 0;
1248     }
1249
1250     if (sig == NULL) {
1251         *siglen = ED448_SIGSIZE;
1252         return 1;
1253     }
1254
1255     if (*siglen < ED448_SIGSIZE) {
1256         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1257         return 0;
1258     }
1259
1260     memset(&param, 0, sizeof(param));
1261     memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1262
1263     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1264     OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1265     if (rc != 0)
1266         return 0;
1267
1268     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1269     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1270     memcpy(sig, param.ed448.sig, 57);
1271     memcpy(sig + 57, param.ed448.sig + 64, 57);
1272
1273     *siglen = ED448_SIGSIZE;
1274     return 1;
1275 }
1276
1277 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1278                                             const unsigned char *sig,
1279                                             size_t siglen,
1280                                             const unsigned char *tbs,
1281                                             size_t tbslen)
1282 {
1283     union {
1284         struct {
1285             unsigned char sig[64];
1286             unsigned char pub[32];
1287         } ed25519;
1288         unsigned long long buff[512];
1289     } param;
1290     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1291
1292     if (edkey == NULL) {
1293         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1294         return 0;
1295     }
1296
1297     if (siglen != ED25519_SIGSIZE)
1298         return 0;
1299
1300     memset(&param, 0, sizeof(param));
1301     s390x_flip_endian32(param.ed25519.sig, sig);
1302     s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1303     s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1304
1305     return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1306                       &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1307 }
1308
1309 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1310                                           const unsigned char *sig,
1311                                           size_t siglen,
1312                                           const unsigned char *tbs,
1313                                           size_t tbslen)
1314 {
1315     union {
1316         struct {
1317             unsigned char sig[128];
1318             unsigned char pub[64];
1319         } ed448;
1320         unsigned long long buff[512];
1321     } param;
1322     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1323
1324     if (edkey == NULL) {
1325         ERR_raise(ERR_LIB_EC, EC_R_INVALID_KEY);
1326         return 0;
1327     }
1328
1329     if (siglen != ED448_SIGSIZE)
1330         return 0;
1331
1332     memset(&param, 0, sizeof(param));
1333     memcpy(param.ed448.sig, sig, 57);
1334     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1335     memcpy(param.ed448.sig + 64, sig + 57, 57);
1336     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1337     memcpy(param.ed448.pub, edkey->pubkey, 57);
1338     s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1339
1340     return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1341                       &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1342 }
1343
1344 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1345     EVP_PKEY_X25519,
1346     0, 0, 0, 0, 0, 0, 0,
1347     s390x_pkey_ecx_keygen25519,
1348     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1349     s390x_pkey_ecx_derive25519,
1350     pkey_ecx_ctrl,
1351     0
1352 };
1353
1354 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1355     EVP_PKEY_X448,
1356     0, 0, 0, 0, 0, 0, 0,
1357     s390x_pkey_ecx_keygen448,
1358     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1359     s390x_pkey_ecx_derive448,
1360     pkey_ecx_ctrl,
1361     0
1362 };
1363 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1364     EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1365     0, 0, 0, 0, 0, 0,
1366     s390x_pkey_ecd_keygen25519,
1367     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1368     pkey_ecd_ctrl,
1369     0,
1370     s390x_pkey_ecd_digestsign25519,
1371     s390x_pkey_ecd_digestverify25519
1372 };
1373
1374 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1375     EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1376     0, 0, 0, 0, 0, 0,
1377     s390x_pkey_ecd_keygen448,
1378     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1379     pkey_ecd_ctrl,
1380     0,
1381     s390x_pkey_ecd_digestsign448,
1382     s390x_pkey_ecd_digestverify448
1383 };
1384 #endif
1385
1386 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1387 {
1388 #ifdef S390X_EC_ASM
1389     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1390         return &ecx25519_s390x_pkey_meth;
1391 #endif
1392     return &ecx25519_pkey_meth;
1393 }
1394
1395 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1396 {
1397 #ifdef S390X_EC_ASM
1398     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1399         return &ecx448_s390x_pkey_meth;
1400 #endif
1401     return &ecx448_pkey_meth;
1402 }
1403
1404 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1405 {
1406 #ifdef S390X_EC_ASM
1407     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1408         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1409         && OPENSSL_s390xcap_P.kdsa[0]
1410             & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1411         return &ed25519_s390x_pkey_meth;
1412 #endif
1413     return &ed25519_pkey_meth;
1414 }
1415
1416 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1417 {
1418 #ifdef S390X_EC_ASM
1419     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1420         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1421         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1422         return &ed448_s390x_pkey_meth;
1423 #endif
1424     return &ed448_pkey_meth;
1425 }