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