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