add zero strenght arguments to BN and RAND RNG calls
[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                               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_sign25519(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
565                               const void *asn,
566                               X509_ALGOR *alg1, X509_ALGOR *alg2,
567                               ASN1_BIT_STRING *str)
568 {
569     /* Set algorithms identifiers */
570     X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
571     if (alg2)
572         X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED25519), V_ASN1_UNDEF, NULL);
573     /* Algorithm identifiers set: carry on as normal */
574     return 3;
575 }
576
577 static int ecd_sig_info_set25519(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
578                                  const ASN1_STRING *sig)
579 {
580     X509_SIG_INFO_set(siginf, NID_undef, NID_ED25519, X25519_SECURITY_BITS,
581                       X509_SIG_INFO_TLS);
582     return 1;
583 }
584
585 static int ecd_item_sign448(EVP_MD_CTX *ctx, const ASN1_ITEM *it,
586                             const void *asn,
587                             X509_ALGOR *alg1, X509_ALGOR *alg2,
588                             ASN1_BIT_STRING *str)
589 {
590     /* Set algorithm identifier */
591     X509_ALGOR_set0(alg1, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
592     if (alg2 != NULL)
593         X509_ALGOR_set0(alg2, OBJ_nid2obj(NID_ED448), V_ASN1_UNDEF, NULL);
594     /* Algorithm identifier set: carry on as normal */
595     return 3;
596 }
597
598 static int ecd_sig_info_set448(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
599                                const ASN1_STRING *sig)
600 {
601     X509_SIG_INFO_set(siginf, NID_undef, NID_ED448, X448_SECURITY_BITS,
602                       X509_SIG_INFO_TLS);
603     return 1;
604 }
605
606 static int ed25519_import_from(const OSSL_PARAM params[], void *vpctx)
607 {
608     return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED25519);
609 }
610
611 const EVP_PKEY_ASN1_METHOD ossl_ed25519_asn1_meth = {
612     EVP_PKEY_ED25519,
613     EVP_PKEY_ED25519,
614     0,
615     "ED25519",
616     "OpenSSL ED25519 algorithm",
617
618     ecx_pub_decode,
619     ecx_pub_encode,
620     ecx_pub_cmp,
621     ecx_pub_print,
622
623     NULL,
624     ecx_priv_encode,
625     ecx_priv_print,
626
627     ecd_size25519,
628     ecx_bits,
629     ecx_security_bits,
630
631     0, 0, 0, 0,
632     ecx_cmp_parameters,
633     0, 0,
634
635     ecx_free,
636     ecd_ctrl,
637     NULL,
638     NULL,
639     ecd_item_verify,
640     ecd_item_sign25519,
641     ecd_sig_info_set25519,
642
643     NULL,
644     NULL,
645     NULL,
646
647     ecx_set_priv_key,
648     ecx_set_pub_key,
649     ecx_get_priv_key,
650     ecx_get_pub_key,
651     ecx_pkey_dirty_cnt,
652     ecx_pkey_export_to,
653     ed25519_import_from,
654     ecx_pkey_copy,
655
656     ecx_priv_decode_ex
657 };
658
659 static int ed448_import_from(const OSSL_PARAM params[], void *vpctx)
660 {
661     return ecx_generic_import_from(params, vpctx, EVP_PKEY_ED448);
662 }
663
664 const EVP_PKEY_ASN1_METHOD ossl_ed448_asn1_meth = {
665     EVP_PKEY_ED448,
666     EVP_PKEY_ED448,
667     0,
668     "ED448",
669     "OpenSSL ED448 algorithm",
670
671     ecx_pub_decode,
672     ecx_pub_encode,
673     ecx_pub_cmp,
674     ecx_pub_print,
675
676     NULL,
677     ecx_priv_encode,
678     ecx_priv_print,
679
680     ecd_size448,
681     ecx_bits,
682     ecx_security_bits,
683
684     0, 0, 0, 0,
685     ecx_cmp_parameters,
686     0, 0,
687
688     ecx_free,
689     ecd_ctrl,
690     NULL,
691     NULL,
692     ecd_item_verify,
693     ecd_item_sign448,
694     ecd_sig_info_set448,
695
696     NULL,
697     NULL,
698     NULL,
699
700     ecx_set_priv_key,
701     ecx_set_pub_key,
702     ecx_get_priv_key,
703     ecx_get_pub_key,
704     ecx_pkey_dirty_cnt,
705     ecx_pkey_export_to,
706     ed448_import_from,
707     ecx_pkey_copy,
708
709     ecx_priv_decode_ex
710 };
711
712 static int pkey_ecx_keygen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
713 {
714     ECX_KEY *ecx = ossl_ecx_key_op(NULL, NULL, 0, ctx->pmeth->pkey_id,
715                                    KEY_OP_PUBLIC, NULL, NULL);
716
717     if (ecx != NULL) {
718         EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, ecx);
719         return 1;
720     }
721     return 0;
722 }
723
724 static int validate_ecx_derive(EVP_PKEY_CTX *ctx, unsigned char *key,
725                                           size_t *keylen,
726                                           const unsigned char **privkey,
727                                           const unsigned char **pubkey)
728 {
729     const ECX_KEY *ecxkey, *peerkey;
730
731     if (ctx->pkey == NULL || ctx->peerkey == NULL) {
732         ERR_raise(ERR_LIB_EC, EC_R_KEYS_NOT_SET);
733         return 0;
734     }
735     ecxkey = ctx->pkey->pkey.ecx;
736     peerkey = EVP_PKEY_get0(ctx->peerkey);
737     if (ecxkey == NULL || ecxkey->privkey == NULL) {
738         ERR_raise(ERR_LIB_EC, EC_R_INVALID_PRIVATE_KEY);
739         return 0;
740     }
741     if (peerkey == NULL) {
742         ERR_raise(ERR_LIB_EC, EC_R_INVALID_PEER_KEY);
743         return 0;
744     }
745     *privkey = ecxkey->privkey;
746     *pubkey = peerkey->pubkey;
747
748     return 1;
749 }
750
751 static int pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
752                                 size_t *keylen)
753 {
754     const unsigned char *privkey, *pubkey;
755
756     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
757             || (key != NULL
758                 && ossl_x25519(key, privkey, pubkey) == 0))
759         return 0;
760     *keylen = X25519_KEYLEN;
761     return 1;
762 }
763
764 static int pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
765                               size_t *keylen)
766 {
767     const unsigned char *privkey, *pubkey;
768
769     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey)
770             || (key != NULL
771                 && ossl_x448(key, privkey, pubkey) == 0))
772         return 0;
773     *keylen = X448_KEYLEN;
774     return 1;
775 }
776
777 static int pkey_ecx_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
778 {
779     /* Only need to handle peer key for derivation */
780     if (type == EVP_PKEY_CTRL_PEER_KEY)
781         return 1;
782     return -2;
783 }
784
785 static const EVP_PKEY_METHOD ecx25519_pkey_meth = {
786     EVP_PKEY_X25519,
787     0, 0, 0, 0, 0, 0, 0,
788     pkey_ecx_keygen,
789     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
790     pkey_ecx_derive25519,
791     pkey_ecx_ctrl,
792     0
793 };
794
795 static const EVP_PKEY_METHOD ecx448_pkey_meth = {
796     EVP_PKEY_X448,
797     0, 0, 0, 0, 0, 0, 0,
798     pkey_ecx_keygen,
799     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
800     pkey_ecx_derive448,
801     pkey_ecx_ctrl,
802     0
803 };
804
805 static int pkey_ecd_digestsign25519(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 = ED25519_SIGSIZE;
813         return 1;
814     }
815     if (*siglen < ED25519_SIGSIZE) {
816         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
817         return 0;
818     }
819
820     if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
821                           NULL) == 0)
822         return 0;
823     *siglen = ED25519_SIGSIZE;
824     return 1;
825 }
826
827 static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, 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 (sig == NULL) {
834         *siglen = ED448_SIGSIZE;
835         return 1;
836     }
837     if (*siglen < ED448_SIGSIZE) {
838         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
839         return 0;
840     }
841
842     if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
843                         edkey->privkey, NULL, 0, edkey->propq) == 0)
844         return 0;
845     *siglen = ED448_SIGSIZE;
846     return 1;
847 }
848
849 static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
850                                       size_t siglen, const unsigned char *tbs,
851                                       size_t tbslen)
852 {
853     const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
854
855     if (siglen != ED25519_SIGSIZE)
856         return 0;
857
858     return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
859                                edkey->libctx, edkey->propq);
860 }
861
862 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
863                                     size_t siglen, const unsigned char *tbs,
864                                     size_t tbslen)
865 {
866     const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
867
868     if (siglen != ED448_SIGSIZE)
869         return 0;
870
871     return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
872                              NULL, 0, edkey->propq);
873 }
874
875 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
876 {
877     switch (type) {
878     case EVP_PKEY_CTRL_MD:
879         /* Only NULL allowed as digest */
880         if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
881             return 1;
882         ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
883         return 0;
884
885     case EVP_PKEY_CTRL_DIGESTINIT:
886         return 1;
887     }
888     return -2;
889 }
890
891 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
892     EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
893     0, 0, 0, 0, 0, 0,
894     pkey_ecx_keygen,
895     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
896     pkey_ecd_ctrl,
897     0,
898     pkey_ecd_digestsign25519,
899     pkey_ecd_digestverify25519
900 };
901
902 static const EVP_PKEY_METHOD ed448_pkey_meth = {
903     EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
904     0, 0, 0, 0, 0, 0,
905     pkey_ecx_keygen,
906     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
907     pkey_ecd_ctrl,
908     0,
909     pkey_ecd_digestsign448,
910     pkey_ecd_digestverify448
911 };
912
913 #ifdef S390X_EC_ASM
914 # include "s390x_arch.h"
915
916 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
917 {
918     static const unsigned char generator[] = {
919         0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
920         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
921         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
922     };
923     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
924                                     ctx->propquery);
925     unsigned char *privkey = NULL, *pubkey;
926
927     if (key == NULL) {
928         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
929         goto err;
930     }
931
932     pubkey = key->pubkey;
933
934     privkey = ossl_ecx_key_allocate_privkey(key);
935     if (privkey == NULL) {
936         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
937         goto err;
938     }
939
940     if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
941         goto err;
942
943     privkey[0] &= 248;
944     privkey[31] &= 127;
945     privkey[31] |= 64;
946
947     if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
948         goto err;
949
950     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
951     return 1;
952  err:
953     ossl_ecx_key_free(key);
954     return 0;
955 }
956
957 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
958 {
959     static const unsigned char generator[] = {
960         0x05, 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, 0x00, 0x00, 0x00, 0x00,
963         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
964         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
965     };
966     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
967                                     ctx->propquery);
968     unsigned char *privkey = NULL, *pubkey;
969
970     if (key == NULL) {
971         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
972         goto err;
973     }
974
975     pubkey = key->pubkey;
976
977     privkey = ossl_ecx_key_allocate_privkey(key);
978     if (privkey == NULL) {
979         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
980         goto err;
981     }
982
983     if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
984         goto err;
985
986     privkey[0] &= 252;
987     privkey[55] |= 128;
988
989     if (s390x_x448_mul(pubkey, generator, privkey) != 1)
990         goto err;
991
992     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
993     return 1;
994  err:
995     ossl_ecx_key_free(key);
996     return 0;
997 }
998
999 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1000 {
1001     static const unsigned char generator_x[] = {
1002         0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1003         0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1004         0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1005     };
1006     static const unsigned char generator_y[] = {
1007         0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1008         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1009         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1010     };
1011     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1012     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1013                                     ctx->propquery);
1014     unsigned char *privkey = NULL, *pubkey;
1015     unsigned int sz;
1016     EVP_MD *md = NULL;
1017     int rv;
1018
1019     if (key == NULL) {
1020         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1021         goto err;
1022     }
1023
1024     pubkey = key->pubkey;
1025
1026     privkey = ossl_ecx_key_allocate_privkey(key);
1027     if (privkey == NULL) {
1028         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1029         goto err;
1030     }
1031
1032     if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1033         goto err;
1034
1035     md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1036     if (md == NULL)
1037         goto err;
1038
1039     rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1040     EVP_MD_free(md);
1041     if (!rv)
1042         goto err;
1043
1044     buff[0] &= 248;
1045     buff[31] &= 63;
1046     buff[31] |= 64;
1047
1048     if (s390x_ed25519_mul(x_dst, pubkey,
1049                           generator_x, generator_y, buff) != 1)
1050         goto err;
1051
1052     pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1053
1054     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1055     return 1;
1056  err:
1057     ossl_ecx_key_free(key);
1058     return 0;
1059 }
1060
1061 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1062 {
1063     static const unsigned char generator_x[] = {
1064         0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1065         0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1066         0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1067         0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1068         0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1069     };
1070     static const unsigned char generator_y[] = {
1071         0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1072         0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1073         0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1074         0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1075         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1076     };
1077     unsigned char x_dst[57], buff[114];
1078     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1079                                     ctx->propquery);
1080     unsigned char *privkey = NULL, *pubkey;
1081     EVP_MD_CTX *hashctx = NULL;
1082     EVP_MD *md = NULL;
1083     int rv;
1084
1085     if (key == NULL) {
1086         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1087         goto err;
1088     }
1089
1090     pubkey = key->pubkey;
1091
1092     privkey = ossl_ecx_key_allocate_privkey(key);
1093     if (privkey == NULL) {
1094         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1095         goto err;
1096     }
1097
1098     if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1099         goto err;
1100
1101     hashctx = EVP_MD_CTX_new();
1102     if (hashctx == NULL)
1103         goto err;
1104
1105     md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1106     if (md == NULL)
1107         goto err;
1108
1109     rv = EVP_DigestInit_ex(hashctx, md, NULL);
1110     EVP_MD_free(md);
1111     if (rv != 1)
1112         goto err;
1113
1114     if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1115         goto err;
1116     if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1117         goto err;
1118
1119     buff[0] &= -4;
1120     buff[55] |= 0x80;
1121     buff[56] = 0;
1122
1123     if (s390x_ed448_mul(x_dst, pubkey,
1124                         generator_x, generator_y, buff) != 1)
1125         goto err;
1126
1127     pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1128
1129     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1130     EVP_MD_CTX_free(hashctx);
1131     return 1;
1132  err:
1133     ossl_ecx_key_free(key);
1134     EVP_MD_CTX_free(hashctx);
1135     return 0;
1136 }
1137
1138 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1139                                       size_t *keylen)
1140 {
1141     const unsigned char *privkey, *pubkey;
1142
1143     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1144         return 0;
1145
1146     if (key != NULL)
1147         return s390x_x25519_mul(key, pubkey, privkey);
1148
1149     *keylen = X25519_KEYLEN;
1150     return 1;
1151 }
1152
1153 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1154                                       size_t *keylen)
1155 {
1156     const unsigned char *privkey, *pubkey;
1157
1158     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1159         return 0;
1160
1161     if (key != NULL)
1162         return s390x_x448_mul(key, pubkey, privkey);
1163
1164     *keylen = X448_KEYLEN;
1165     return 1;
1166 }
1167
1168 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1169                                           unsigned char *sig, size_t *siglen,
1170                                           const unsigned char *tbs,
1171                                           size_t tbslen)
1172 {
1173     union {
1174         struct {
1175             unsigned char sig[64];
1176             unsigned char priv[32];
1177         } ed25519;
1178         unsigned long long buff[512];
1179     } param;
1180     const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1181     int rc;
1182
1183     if (sig == NULL) {
1184         *siglen = ED25519_SIGSIZE;
1185         return 1;
1186     }
1187
1188     if (*siglen < ED25519_SIGSIZE) {
1189         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1190         return 0;
1191     }
1192
1193     memset(&param, 0, sizeof(param));
1194     memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1195
1196     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1197     OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1198     if (rc != 0)
1199         return 0;
1200
1201     s390x_flip_endian32(sig, param.ed25519.sig);
1202     s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1203
1204     *siglen = ED25519_SIGSIZE;
1205     return 1;
1206 }
1207
1208 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1209                                         unsigned char *sig, size_t *siglen,
1210                                         const unsigned char *tbs,
1211                                         size_t tbslen)
1212 {
1213     union {
1214         struct {
1215             unsigned char sig[128];
1216             unsigned char priv[64];
1217         } ed448;
1218         unsigned long long buff[512];
1219     } param;
1220     const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1221     int rc;
1222
1223     if (sig == NULL) {
1224         *siglen = ED448_SIGSIZE;
1225         return 1;
1226     }
1227
1228     if (*siglen < ED448_SIGSIZE) {
1229         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1230         return 0;
1231     }
1232
1233     memset(&param, 0, sizeof(param));
1234     memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1235
1236     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1237     OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1238     if (rc != 0)
1239         return 0;
1240
1241     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1242     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1243     memcpy(sig, param.ed448.sig, 57);
1244     memcpy(sig + 57, param.ed448.sig + 64, 57);
1245
1246     *siglen = ED448_SIGSIZE;
1247     return 1;
1248 }
1249
1250 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1251                                             const unsigned char *sig,
1252                                             size_t siglen,
1253                                             const unsigned char *tbs,
1254                                             size_t tbslen)
1255 {
1256     union {
1257         struct {
1258             unsigned char sig[64];
1259             unsigned char pub[32];
1260         } ed25519;
1261         unsigned long long buff[512];
1262     } param;
1263     const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1264
1265     if (siglen != ED25519_SIGSIZE)
1266         return 0;
1267
1268     memset(&param, 0, sizeof(param));
1269     s390x_flip_endian32(param.ed25519.sig, sig);
1270     s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1271     s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1272
1273     return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1274                       &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1275 }
1276
1277 static int s390x_pkey_ecd_digestverify448(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[128];
1286             unsigned char pub[64];
1287         } ed448;
1288         unsigned long long buff[512];
1289     } param;
1290     const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1291
1292     if (siglen != ED448_SIGSIZE)
1293         return 0;
1294
1295     memset(&param, 0, sizeof(param));
1296     memcpy(param.ed448.sig, sig, 57);
1297     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1298     memcpy(param.ed448.sig + 64, sig + 57, 57);
1299     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1300     memcpy(param.ed448.pub, edkey->pubkey, 57);
1301     s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1302
1303     return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1304                       &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1305 }
1306
1307 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1308     EVP_PKEY_X25519,
1309     0, 0, 0, 0, 0, 0, 0,
1310     s390x_pkey_ecx_keygen25519,
1311     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1312     s390x_pkey_ecx_derive25519,
1313     pkey_ecx_ctrl,
1314     0
1315 };
1316
1317 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1318     EVP_PKEY_X448,
1319     0, 0, 0, 0, 0, 0, 0,
1320     s390x_pkey_ecx_keygen448,
1321     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1322     s390x_pkey_ecx_derive448,
1323     pkey_ecx_ctrl,
1324     0
1325 };
1326 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1327     EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1328     0, 0, 0, 0, 0, 0,
1329     s390x_pkey_ecd_keygen25519,
1330     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1331     pkey_ecd_ctrl,
1332     0,
1333     s390x_pkey_ecd_digestsign25519,
1334     s390x_pkey_ecd_digestverify25519
1335 };
1336
1337 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1338     EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1339     0, 0, 0, 0, 0, 0,
1340     s390x_pkey_ecd_keygen448,
1341     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1342     pkey_ecd_ctrl,
1343     0,
1344     s390x_pkey_ecd_digestsign448,
1345     s390x_pkey_ecd_digestverify448
1346 };
1347 #endif
1348
1349 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1350 {
1351 #ifdef S390X_EC_ASM
1352     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1353         return &ecx25519_s390x_pkey_meth;
1354 #endif
1355     return &ecx25519_pkey_meth;
1356 }
1357
1358 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1359 {
1360 #ifdef S390X_EC_ASM
1361     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1362         return &ecx448_s390x_pkey_meth;
1363 #endif
1364     return &ecx448_pkey_meth;
1365 }
1366
1367 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1368 {
1369 #ifdef S390X_EC_ASM
1370     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1371         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1372         && OPENSSL_s390xcap_P.kdsa[0]
1373             & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1374         return &ed25519_s390x_pkey_meth;
1375 #endif
1376     return &ed25519_pkey_meth;
1377 }
1378
1379 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1380 {
1381 #ifdef S390X_EC_ASM
1382     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1383         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1384         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1385         return &ed448_s390x_pkey_meth;
1386 #endif
1387     return &ed448_pkey_meth;
1388 }