Update copyright year
[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 (sig == NULL) {
813         *siglen = ED25519_SIGSIZE;
814         return 1;
815     }
816     if (*siglen < ED25519_SIGSIZE) {
817         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
818         return 0;
819     }
820
821     if (ossl_ed25519_sign(sig, tbs, tbslen, edkey->pubkey, edkey->privkey, NULL,
822                           NULL) == 0)
823         return 0;
824     *siglen = ED25519_SIGSIZE;
825     return 1;
826 }
827
828 static int pkey_ecd_digestsign448(EVP_MD_CTX *ctx, unsigned char *sig,
829                                   size_t *siglen, const unsigned char *tbs,
830                                   size_t tbslen)
831 {
832     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
833
834     if (sig == NULL) {
835         *siglen = ED448_SIGSIZE;
836         return 1;
837     }
838     if (*siglen < ED448_SIGSIZE) {
839         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
840         return 0;
841     }
842
843     if (ossl_ed448_sign(edkey->libctx, sig, tbs, tbslen, edkey->pubkey,
844                         edkey->privkey, NULL, 0, edkey->propq) == 0)
845         return 0;
846     *siglen = ED448_SIGSIZE;
847     return 1;
848 }
849
850 static int pkey_ecd_digestverify25519(EVP_MD_CTX *ctx, const unsigned char *sig,
851                                       size_t siglen, const unsigned char *tbs,
852                                       size_t tbslen)
853 {
854     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
855
856     if (siglen != ED25519_SIGSIZE)
857         return 0;
858
859     return ossl_ed25519_verify(tbs, tbslen, sig, edkey->pubkey,
860                                edkey->libctx, edkey->propq);
861 }
862
863 static int pkey_ecd_digestverify448(EVP_MD_CTX *ctx, const unsigned char *sig,
864                                     size_t siglen, const unsigned char *tbs,
865                                     size_t tbslen)
866 {
867     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
868
869     if (siglen != ED448_SIGSIZE)
870         return 0;
871
872     return ossl_ed448_verify(edkey->libctx, tbs, tbslen, sig, edkey->pubkey,
873                              NULL, 0, edkey->propq);
874 }
875
876 static int pkey_ecd_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
877 {
878     switch (type) {
879     case EVP_PKEY_CTRL_MD:
880         /* Only NULL allowed as digest */
881         if (p2 == NULL || (const EVP_MD *)p2 == EVP_md_null())
882             return 1;
883         ERR_raise(ERR_LIB_EC, EC_R_INVALID_DIGEST_TYPE);
884         return 0;
885
886     case EVP_PKEY_CTRL_DIGESTINIT:
887         return 1;
888     }
889     return -2;
890 }
891
892 static const EVP_PKEY_METHOD ed25519_pkey_meth = {
893     EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
894     0, 0, 0, 0, 0, 0,
895     pkey_ecx_keygen,
896     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
897     pkey_ecd_ctrl,
898     0,
899     pkey_ecd_digestsign25519,
900     pkey_ecd_digestverify25519
901 };
902
903 static const EVP_PKEY_METHOD ed448_pkey_meth = {
904     EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
905     0, 0, 0, 0, 0, 0,
906     pkey_ecx_keygen,
907     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
908     pkey_ecd_ctrl,
909     0,
910     pkey_ecd_digestsign448,
911     pkey_ecd_digestverify448
912 };
913
914 #ifdef S390X_EC_ASM
915 # include "s390x_arch.h"
916
917 static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
918 {
919     static const unsigned char generator[] = {
920         0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
921         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
922         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
923     };
924     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X25519, 1,
925                                     ctx->propquery);
926     unsigned char *privkey = NULL, *pubkey;
927
928     if (key == NULL) {
929         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
930         goto err;
931     }
932
933     pubkey = key->pubkey;
934
935     privkey = ossl_ecx_key_allocate_privkey(key);
936     if (privkey == NULL) {
937         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
938         goto err;
939     }
940
941     if (RAND_priv_bytes_ex(ctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
942         goto err;
943
944     privkey[0] &= 248;
945     privkey[31] &= 127;
946     privkey[31] |= 64;
947
948     if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
949         goto err;
950
951     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
952     return 1;
953  err:
954     ossl_ecx_key_free(key);
955     return 0;
956 }
957
958 static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
959 {
960     static const unsigned char generator[] = {
961         0x05, 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, 0x00, 0x00, 0x00, 0x00,
965         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
966     };
967     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_X448, 1,
968                                     ctx->propquery);
969     unsigned char *privkey = NULL, *pubkey;
970
971     if (key == NULL) {
972         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
973         goto err;
974     }
975
976     pubkey = key->pubkey;
977
978     privkey = ossl_ecx_key_allocate_privkey(key);
979     if (privkey == NULL) {
980         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
981         goto err;
982     }
983
984     if (RAND_priv_bytes_ex(ctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
985         goto err;
986
987     privkey[0] &= 252;
988     privkey[55] |= 128;
989
990     if (s390x_x448_mul(pubkey, generator, privkey) != 1)
991         goto err;
992
993     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
994     return 1;
995  err:
996     ossl_ecx_key_free(key);
997     return 0;
998 }
999
1000 static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1001 {
1002     static const unsigned char generator_x[] = {
1003         0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1004         0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1005         0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1006     };
1007     static const unsigned char generator_y[] = {
1008         0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1009         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1010         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1011     };
1012     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1013     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1014                                     ctx->propquery);
1015     unsigned char *privkey = NULL, *pubkey;
1016     unsigned int sz;
1017     EVP_MD *md = NULL;
1018     int rv;
1019
1020     if (key == NULL) {
1021         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1022         goto err;
1023     }
1024
1025     pubkey = key->pubkey;
1026
1027     privkey = ossl_ecx_key_allocate_privkey(key);
1028     if (privkey == NULL) {
1029         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1030         goto err;
1031     }
1032
1033     if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1034         goto err;
1035
1036     md = EVP_MD_fetch(ctx->libctx, "SHA512", ctx->propquery);
1037     if (md == NULL)
1038         goto err;
1039
1040     rv = EVP_Digest(privkey, 32, buff, &sz, md, NULL);
1041     EVP_MD_free(md);
1042     if (!rv)
1043         goto err;
1044
1045     buff[0] &= 248;
1046     buff[31] &= 63;
1047     buff[31] |= 64;
1048
1049     if (s390x_ed25519_mul(x_dst, pubkey,
1050                           generator_x, generator_y, buff) != 1)
1051         goto err;
1052
1053     pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1054
1055     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1056     return 1;
1057  err:
1058     ossl_ecx_key_free(key);
1059     return 0;
1060 }
1061
1062 static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1063 {
1064     static const unsigned char generator_x[] = {
1065         0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1066         0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1067         0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1068         0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1069         0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1070     };
1071     static const unsigned char generator_y[] = {
1072         0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1073         0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1074         0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1075         0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1076         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1077     };
1078     unsigned char x_dst[57], buff[114];
1079     ECX_KEY *key = ossl_ecx_key_new(ctx->libctx, ECX_KEY_TYPE_ED448, 1,
1080                                     ctx->propquery);
1081     unsigned char *privkey = NULL, *pubkey;
1082     EVP_MD_CTX *hashctx = NULL;
1083     EVP_MD *md = NULL;
1084     int rv;
1085
1086     if (key == NULL) {
1087         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1088         goto err;
1089     }
1090
1091     pubkey = key->pubkey;
1092
1093     privkey = ossl_ecx_key_allocate_privkey(key);
1094     if (privkey == NULL) {
1095         ERR_raise(ERR_LIB_EC, ERR_R_MALLOC_FAILURE);
1096         goto err;
1097     }
1098
1099     if (RAND_priv_bytes_ex(ctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1100         goto err;
1101
1102     hashctx = EVP_MD_CTX_new();
1103     if (hashctx == NULL)
1104         goto err;
1105
1106     md = EVP_MD_fetch(ctx->libctx, "SHAKE256", ctx->propquery);
1107     if (md == NULL)
1108         goto err;
1109
1110     rv = EVP_DigestInit_ex(hashctx, md, NULL);
1111     EVP_MD_free(md);
1112     if (rv != 1)
1113         goto err;
1114
1115     if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1116         goto err;
1117     if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1118         goto err;
1119
1120     buff[0] &= -4;
1121     buff[55] |= 0x80;
1122     buff[56] = 0;
1123
1124     if (s390x_ed448_mul(x_dst, pubkey,
1125                         generator_x, generator_y, buff) != 1)
1126         goto err;
1127
1128     pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1129
1130     EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1131     EVP_MD_CTX_free(hashctx);
1132     return 1;
1133  err:
1134     ossl_ecx_key_free(key);
1135     EVP_MD_CTX_free(hashctx);
1136     return 0;
1137 }
1138
1139 static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1140                                       size_t *keylen)
1141 {
1142     const unsigned char *privkey, *pubkey;
1143
1144     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1145         return 0;
1146
1147     if (key != NULL)
1148         return s390x_x25519_mul(key, pubkey, privkey);
1149
1150     *keylen = X25519_KEYLEN;
1151     return 1;
1152 }
1153
1154 static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1155                                       size_t *keylen)
1156 {
1157     const unsigned char *privkey, *pubkey;
1158
1159     if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1160         return 0;
1161
1162     if (key != NULL)
1163         return s390x_x448_mul(key, pubkey, privkey);
1164
1165     *keylen = X448_KEYLEN;
1166     return 1;
1167 }
1168
1169 static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1170                                           unsigned char *sig, size_t *siglen,
1171                                           const unsigned char *tbs,
1172                                           size_t tbslen)
1173 {
1174     union {
1175         struct {
1176             unsigned char sig[64];
1177             unsigned char priv[32];
1178         } ed25519;
1179         unsigned long long buff[512];
1180     } param;
1181     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1182     int rc;
1183
1184     if (sig == NULL) {
1185         *siglen = ED25519_SIGSIZE;
1186         return 1;
1187     }
1188
1189     if (*siglen < ED25519_SIGSIZE) {
1190         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1191         return 0;
1192     }
1193
1194     memset(&param, 0, sizeof(param));
1195     memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1196
1197     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1198     OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1199     if (rc != 0)
1200         return 0;
1201
1202     s390x_flip_endian32(sig, param.ed25519.sig);
1203     s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1204
1205     *siglen = ED25519_SIGSIZE;
1206     return 1;
1207 }
1208
1209 static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1210                                         unsigned char *sig, size_t *siglen,
1211                                         const unsigned char *tbs,
1212                                         size_t tbslen)
1213 {
1214     union {
1215         struct {
1216             unsigned char sig[128];
1217             unsigned char priv[64];
1218         } ed448;
1219         unsigned long long buff[512];
1220     } param;
1221     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1222     int rc;
1223
1224     if (sig == NULL) {
1225         *siglen = ED448_SIGSIZE;
1226         return 1;
1227     }
1228
1229     if (*siglen < ED448_SIGSIZE) {
1230         ERR_raise(ERR_LIB_EC, EC_R_BUFFER_TOO_SMALL);
1231         return 0;
1232     }
1233
1234     memset(&param, 0, sizeof(param));
1235     memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1236
1237     rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1238     OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1239     if (rc != 0)
1240         return 0;
1241
1242     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1243     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1244     memcpy(sig, param.ed448.sig, 57);
1245     memcpy(sig + 57, param.ed448.sig + 64, 57);
1246
1247     *siglen = ED448_SIGSIZE;
1248     return 1;
1249 }
1250
1251 static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1252                                             const unsigned char *sig,
1253                                             size_t siglen,
1254                                             const unsigned char *tbs,
1255                                             size_t tbslen)
1256 {
1257     union {
1258         struct {
1259             unsigned char sig[64];
1260             unsigned char pub[32];
1261         } ed25519;
1262         unsigned long long buff[512];
1263     } param;
1264     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1265
1266     if (siglen != ED25519_SIGSIZE)
1267         return 0;
1268
1269     memset(&param, 0, sizeof(param));
1270     s390x_flip_endian32(param.ed25519.sig, sig);
1271     s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1272     s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1273
1274     return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1275                       &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1276 }
1277
1278 static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1279                                           const unsigned char *sig,
1280                                           size_t siglen,
1281                                           const unsigned char *tbs,
1282                                           size_t tbslen)
1283 {
1284     union {
1285         struct {
1286             unsigned char sig[128];
1287             unsigned char pub[64];
1288         } ed448;
1289         unsigned long long buff[512];
1290     } param;
1291     const ECX_KEY *edkey = evp_pkey_get_legacy(EVP_MD_CTX_get_pkey_ctx(ctx)->pkey);
1292
1293     if (siglen != ED448_SIGSIZE)
1294         return 0;
1295
1296     memset(&param, 0, sizeof(param));
1297     memcpy(param.ed448.sig, sig, 57);
1298     s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1299     memcpy(param.ed448.sig + 64, sig + 57, 57);
1300     s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1301     memcpy(param.ed448.pub, edkey->pubkey, 57);
1302     s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1303
1304     return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1305                       &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1306 }
1307
1308 static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1309     EVP_PKEY_X25519,
1310     0, 0, 0, 0, 0, 0, 0,
1311     s390x_pkey_ecx_keygen25519,
1312     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1313     s390x_pkey_ecx_derive25519,
1314     pkey_ecx_ctrl,
1315     0
1316 };
1317
1318 static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1319     EVP_PKEY_X448,
1320     0, 0, 0, 0, 0, 0, 0,
1321     s390x_pkey_ecx_keygen448,
1322     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1323     s390x_pkey_ecx_derive448,
1324     pkey_ecx_ctrl,
1325     0
1326 };
1327 static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1328     EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1329     0, 0, 0, 0, 0, 0,
1330     s390x_pkey_ecd_keygen25519,
1331     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1332     pkey_ecd_ctrl,
1333     0,
1334     s390x_pkey_ecd_digestsign25519,
1335     s390x_pkey_ecd_digestverify25519
1336 };
1337
1338 static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1339     EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1340     0, 0, 0, 0, 0, 0,
1341     s390x_pkey_ecd_keygen448,
1342     0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1343     pkey_ecd_ctrl,
1344     0,
1345     s390x_pkey_ecd_digestsign448,
1346     s390x_pkey_ecd_digestverify448
1347 };
1348 #endif
1349
1350 const EVP_PKEY_METHOD *ossl_ecx25519_pkey_method(void)
1351 {
1352 #ifdef S390X_EC_ASM
1353     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1354         return &ecx25519_s390x_pkey_meth;
1355 #endif
1356     return &ecx25519_pkey_meth;
1357 }
1358
1359 const EVP_PKEY_METHOD *ossl_ecx448_pkey_method(void)
1360 {
1361 #ifdef S390X_EC_ASM
1362     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1363         return &ecx448_s390x_pkey_meth;
1364 #endif
1365     return &ecx448_pkey_meth;
1366 }
1367
1368 const EVP_PKEY_METHOD *ossl_ed25519_pkey_method(void)
1369 {
1370 #ifdef S390X_EC_ASM
1371     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1372         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1373         && OPENSSL_s390xcap_P.kdsa[0]
1374             & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1375         return &ed25519_s390x_pkey_meth;
1376 #endif
1377     return &ed25519_pkey_meth;
1378 }
1379
1380 const EVP_PKEY_METHOD *ossl_ed448_pkey_method(void)
1381 {
1382 #ifdef S390X_EC_ASM
1383     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1384         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1385         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1386         return &ed448_s390x_pkey_meth;
1387 #endif
1388     return &ed448_pkey_meth;
1389 }