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