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