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