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