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