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