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 "crypto/asn1.h"
16#include "crypto/evp.h"
17#include "ec_local.h"
18#include "curve448/curve448_local.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
39typedef 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 */
46static 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
129static 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
154static 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
166static 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
177static 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
202static 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
234static int ecx_size(const EVP_PKEY *pkey)
235{
236 return KEYLEN(pkey);
237}
238
239static 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
250static 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
259static 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 */
267static int ecx_cmp_parameters(const EVP_PKEY *a, const EVP_PKEY *b)
268{
269 return 1;
270}
271
272static 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
309static 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
315static 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
321static 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
345static 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
359static 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
366static 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
372static 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
393static 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
413const 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
456const 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
499static int ecd_size25519(const EVP_PKEY *pkey)
500{
501 return ED25519_SIGSIZE;
502}
503
504static int ecd_size448(const EVP_PKEY *pkey)
505{
506 return ED448_SIGSIZE;
507}
508
509static 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
531static 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
543static 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
551static 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
563static 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
572const 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
614const 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
656static 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
661static 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
688static 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
701static 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
714static 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
722static 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
732static 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
742static 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
763static 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
789static 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
801static 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
817static 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
833static 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
844static 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# include "internal/constant_time.h"
858
859static void s390x_x25519_mod_p(unsigned char u[32])
860{
861 unsigned char u_red[32];
862 unsigned int c = 0;
863 int i;
864
865 memcpy(u_red, u, sizeof(u_red));
866
867 c += (unsigned int)u_red[31] + 19;
868 u_red[31] = (unsigned char)c;
869 c >>= 8;
870
871 for (i = 30; i >= 0; i--) {
872 c += (unsigned int)u_red[i];
873 u_red[i] = (unsigned char)c;
874 c >>= 8;
875 }
876
877 c = (u_red[0] & 0x80) >> 7;
878 u_red[0] &= 0x7f;
879 constant_time_cond_swap_buff(0 - (unsigned char)c,
880 u, u_red, sizeof(u_red));
881}
882
883static void s390x_x448_mod_p(unsigned char u[56])
884{
885 unsigned char u_red[56];
886 unsigned int c = 0;
887 int i;
888
889 memcpy(u_red, u, sizeof(u_red));
890
891 c += (unsigned int)u_red[55] + 1;
892 u_red[55] = (unsigned char)c;
893 c >>= 8;
894
895 for (i = 54; i >= 28; i--) {
896 c += (unsigned int)u_red[i];
897 u_red[i] = (unsigned char)c;
898 c >>= 8;
899 }
900
901 c += (unsigned int)u_red[27] + 1;
902 u_red[27] = (unsigned char)c;
903 c >>= 8;
904
905 for (i = 26; i >= 0; i--) {
906 c += (unsigned int)u_red[i];
907 u_red[i] = (unsigned char)c;
908 c >>= 8;
909 }
910
911 constant_time_cond_swap_buff(0 - (unsigned char)c,
912 u, u_red, sizeof(u_red));
913}
914
915static int s390x_x25519_mul(unsigned char u_dst[32],
916 const unsigned char u_src[32],
917 const unsigned char d_src[32])
918{
919 union {
920 struct {
921 unsigned char u_dst[32];
922 unsigned char u_src[32];
923 unsigned char d_src[32];
924 } x25519;
925 unsigned long long buff[512];
926 } param;
927 int rc;
928
929 memset(&param, 0, sizeof(param));
930
931 s390x_flip_endian32(param.x25519.u_src, u_src);
932 param.x25519.u_src[0] &= 0x7f;
933 s390x_x25519_mod_p(param.x25519.u_src);
934
935 s390x_flip_endian32(param.x25519.d_src, d_src);
936 param.x25519.d_src[31] &= 248;
937 param.x25519.d_src[0] &= 127;
938 param.x25519.d_src[0] |= 64;
939
940 rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X25519, &param.x25519) ? 0 : 1;
941 if (rc == 1)
942 s390x_flip_endian32(u_dst, param.x25519.u_dst);
943
944 OPENSSL_cleanse(param.x25519.d_src, sizeof(param.x25519.d_src));
945 return rc;
946}
947
948static int s390x_x448_mul(unsigned char u_dst[56],
949 const unsigned char u_src[56],
950 const unsigned char d_src[56])
951{
952 union {
953 struct {
954 unsigned char u_dst[64];
955 unsigned char u_src[64];
956 unsigned char d_src[64];
957 } x448;
958 unsigned long long buff[512];
959 } param;
960 int rc;
961
962 memset(&param, 0, sizeof(param));
963
964 memcpy(param.x448.u_src, u_src, 56);
965 memcpy(param.x448.d_src, d_src, 56);
966
967 s390x_flip_endian64(param.x448.u_src, param.x448.u_src);
968 s390x_x448_mod_p(param.x448.u_src + 8);
969
970 s390x_flip_endian64(param.x448.d_src, param.x448.d_src);
971 param.x448.d_src[63] &= 252;
972 param.x448.d_src[8] |= 128;
973
974 rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X448, &param.x448) ? 0 : 1;
975 if (rc == 1) {
976 s390x_flip_endian64(param.x448.u_dst, param.x448.u_dst);
977 memcpy(u_dst, param.x448.u_dst, 56);
978 }
979
980 OPENSSL_cleanse(param.x448.d_src, sizeof(param.x448.d_src));
981 return rc;
982}
983
984static int s390x_ed25519_mul(unsigned char x_dst[32],
985 unsigned char y_dst[32],
986 const unsigned char x_src[32],
987 const unsigned char y_src[32],
988 const unsigned char d_src[32])
989{
990 union {
991 struct {
992 unsigned char x_dst[32];
993 unsigned char y_dst[32];
994 unsigned char x_src[32];
995 unsigned char y_src[32];
996 unsigned char d_src[32];
997 } ed25519;
998 unsigned long long buff[512];
999 } param;
1000 int rc;
1001
1002 memset(&param, 0, sizeof(param));
1003
1004 s390x_flip_endian32(param.ed25519.x_src, x_src);
1005 s390x_flip_endian32(param.ed25519.y_src, y_src);
1006 s390x_flip_endian32(param.ed25519.d_src, d_src);
1007
1008 rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED25519, &param.ed25519) ? 0 : 1;
1009 if (rc == 1) {
1010 s390x_flip_endian32(x_dst, param.ed25519.x_dst);
1011 s390x_flip_endian32(y_dst, param.ed25519.y_dst);
1012 }
1013
1014 OPENSSL_cleanse(param.ed25519.d_src, sizeof(param.ed25519.d_src));
1015 return rc;
1016}
1017
1018static int s390x_ed448_mul(unsigned char x_dst[57],
1019 unsigned char y_dst[57],
1020 const unsigned char x_src[57],
1021 const unsigned char y_src[57],
1022 const unsigned char d_src[57])
1023{
1024 union {
1025 struct {
1026 unsigned char x_dst[64];
1027 unsigned char y_dst[64];
1028 unsigned char x_src[64];
1029 unsigned char y_src[64];
1030 unsigned char d_src[64];
1031 } ed448;
1032 unsigned long long buff[512];
1033 } param;
1034 int rc;
1035
1036 memset(&param, 0, sizeof(param));
1037
1038 memcpy(param.ed448.x_src, x_src, 57);
1039 memcpy(param.ed448.y_src, y_src, 57);
1040 memcpy(param.ed448.d_src, d_src, 57);
1041 s390x_flip_endian64(param.ed448.x_src, param.ed448.x_src);
1042 s390x_flip_endian64(param.ed448.y_src, param.ed448.y_src);
1043 s390x_flip_endian64(param.ed448.d_src, param.ed448.d_src);
1044
1045 rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED448, &param.ed448) ? 0 : 1;
1046 if (rc == 1) {
1047 s390x_flip_endian64(param.ed448.x_dst, param.ed448.x_dst);
1048 s390x_flip_endian64(param.ed448.y_dst, param.ed448.y_dst);
1049 memcpy(x_dst, param.ed448.x_dst, 57);
1050 memcpy(y_dst, param.ed448.y_dst, 57);
1051 }
1052
1053 OPENSSL_cleanse(param.ed448.d_src, sizeof(param.ed448.d_src));
1054 return rc;
1055}
1056
1057static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1058{
1059 static const unsigned char generator[] = {
1060 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1061 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1062 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1063 };
1064 ECX_KEY *key;
1065 unsigned char *privkey = NULL, *pubkey;
1066
1067 key = OPENSSL_zalloc(sizeof(*key));
1068 if (key == NULL) {
1069 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN25519, ERR_R_MALLOC_FAILURE);
1070 goto err;
1071 }
1072
1073 pubkey = key->pubkey;
1074
1075 privkey = key->privkey = OPENSSL_secure_malloc(X25519_KEYLEN);
1076 if (privkey == NULL) {
1077 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN25519, ERR_R_MALLOC_FAILURE);
1078 goto err;
1079 }
1080
1081 if (RAND_priv_bytes(privkey, X25519_KEYLEN) <= 0)
1082 goto err;
1083
1084 privkey[0] &= 248;
1085 privkey[31] &= 127;
1086 privkey[31] |= 64;
1087
1088 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
1089 goto err;
1090
1091 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1092 return 1;
1093 err:
1094 OPENSSL_secure_clear_free(privkey, X25519_KEYLEN);
1095 key->privkey = NULL;
1096 OPENSSL_free(key);
1097 return 0;
1098}
1099
1100static int s390x_pkey_ecx_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1101{
1102 static const unsigned char generator[] = {
1103 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1104 0x00, 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
1108 };
1109 ECX_KEY *key;
1110 unsigned char *privkey = NULL, *pubkey;
1111
1112 key = OPENSSL_zalloc(sizeof(*key));
1113 if (key == NULL) {
1114 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN448, ERR_R_MALLOC_FAILURE);
1115 goto err;
1116 }
1117
1118 pubkey = key->pubkey;
1119
1120 privkey = key->privkey = OPENSSL_secure_malloc(X448_KEYLEN);
1121 if (privkey == NULL) {
1122 ECerr(EC_F_S390X_PKEY_ECX_KEYGEN448, ERR_R_MALLOC_FAILURE);
1123 goto err;
1124 }
1125
1126 if (RAND_priv_bytes(privkey, X448_KEYLEN) <= 0)
1127 goto err;
1128
1129 privkey[0] &= 252;
1130 privkey[55] |= 128;
1131
1132 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1133 goto err;
1134
1135 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1136 return 1;
1137 err:
1138 OPENSSL_secure_clear_free(privkey, X448_KEYLEN);
1139 key->privkey = NULL;
1140 OPENSSL_free(key);
1141 return 0;
1142}
1143
1144static int s390x_pkey_ecd_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1145{
1146 static const unsigned char generator_x[] = {
1147 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1148 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1149 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1150 };
1151 static const unsigned char generator_y[] = {
1152 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1153 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1154 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1155 };
1156 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1157 ECX_KEY *key;
1158 unsigned char *privkey = NULL, *pubkey;
1159
1160 key = OPENSSL_zalloc(sizeof(*key));
1161 if (key == NULL) {
1162 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN25519, ERR_R_MALLOC_FAILURE);
1163 goto err;
1164 }
1165
1166 pubkey = key->pubkey;
1167
1168 privkey = key->privkey = OPENSSL_secure_malloc(ED25519_KEYLEN);
1169 if (privkey == NULL) {
1170 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN25519, ERR_R_MALLOC_FAILURE);
1171 goto err;
1172 }
1173
1174 if (RAND_priv_bytes(privkey, ED25519_KEYLEN) <= 0)
1175 goto err;
1176
1177 SHA512(privkey, 32, buff);
1178 buff[0] &= 248;
1179 buff[31] &= 63;
1180 buff[31] |= 64;
1181
1182 if (s390x_ed25519_mul(x_dst, pubkey,
1183 generator_x, generator_y, buff) != 1)
1184 goto err;
1185
1186 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1187
1188 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1189 return 1;
1190 err:
1191 OPENSSL_secure_clear_free(privkey, ED25519_KEYLEN);
1192 key->privkey = NULL;
1193 OPENSSL_free(key);
1194 return 0;
1195}
1196
1197static int s390x_pkey_ecd_keygen448(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
1198{
1199 static const unsigned char generator_x[] = {
1200 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1201 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1202 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1203 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1204 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1205 };
1206 static const unsigned char generator_y[] = {
1207 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1208 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1209 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1210 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1211 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1212 };
1213 unsigned char x_dst[57], buff[114];
1214 ECX_KEY *key;
1215 unsigned char *privkey = NULL, *pubkey;
1216 EVP_MD_CTX *hashctx = NULL;
1217
1218 key = OPENSSL_zalloc(sizeof(*key));
1219 if (key == NULL) {
1220 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN448, ERR_R_MALLOC_FAILURE);
1221 goto err;
1222 }
1223
1224 pubkey = key->pubkey;
1225
1226 privkey = key->privkey = OPENSSL_secure_malloc(ED448_KEYLEN);
1227 if (privkey == NULL) {
1228 ECerr(EC_F_S390X_PKEY_ECD_KEYGEN448, ERR_R_MALLOC_FAILURE);
1229 goto err;
1230 }
1231
1232 if (RAND_priv_bytes(privkey, ED448_KEYLEN) <= 0)
1233 goto err;
1234
1235 hashctx = EVP_MD_CTX_new();
1236 if (hashctx == NULL)
1237 goto err;
1238 if (EVP_DigestInit_ex(hashctx, EVP_shake256(), NULL) != 1)
1239 goto err;
1240 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1241 goto err;
1242 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1243 goto err;
1244
1245 buff[0] &= -4;
1246 buff[55] |= 0x80;
1247 buff[56] = 0;
1248
1249 if (s390x_ed448_mul(x_dst, pubkey,
1250 generator_x, generator_y, buff) != 1)
1251 goto err;
1252
1253 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1254
1255 EVP_PKEY_assign(pkey, ctx->pmeth->pkey_id, key);
1256 EVP_MD_CTX_free(hashctx);
1257 return 1;
1258 err:
1259 OPENSSL_secure_clear_free(privkey, ED448_KEYLEN);
1260 key->privkey = NULL;
1261 OPENSSL_free(key);
1262 EVP_MD_CTX_free(hashctx);
1263 return 0;
1264}
1265
1266static int s390x_pkey_ecx_derive25519(EVP_PKEY_CTX *ctx, unsigned char *key,
1267 size_t *keylen)
1268{
1269 const unsigned char *privkey, *pubkey;
1270
1271 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1272 return 0;
1273
1274 if (key != NULL)
1275 return s390x_x25519_mul(key, pubkey, privkey);
1276
1277 *keylen = X25519_KEYLEN;
1278 return 1;
1279}
1280
1281static int s390x_pkey_ecx_derive448(EVP_PKEY_CTX *ctx, unsigned char *key,
1282 size_t *keylen)
1283{
1284 const unsigned char *privkey, *pubkey;
1285
1286 if (!validate_ecx_derive(ctx, key, keylen, &privkey, &pubkey))
1287 return 0;
1288
1289 if (key != NULL)
1290 return s390x_x448_mul(key, pubkey, privkey);
1291
1292 *keylen = X448_KEYLEN;
1293 return 1;
1294}
1295
1296static int s390x_pkey_ecd_digestsign25519(EVP_MD_CTX *ctx,
1297 unsigned char *sig, size_t *siglen,
1298 const unsigned char *tbs,
1299 size_t tbslen)
1300{
1301 union {
1302 struct {
1303 unsigned char sig[64];
1304 unsigned char priv[32];
1305 } ed25519;
1306 unsigned long long buff[512];
1307 } param;
1308 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1309 int rc;
1310
1311 if (sig == NULL) {
1312 *siglen = ED25519_SIGSIZE;
1313 return 1;
1314 }
1315
1316 if (*siglen < ED25519_SIGSIZE) {
1317 ECerr(EC_F_S390X_PKEY_ECD_DIGESTSIGN25519, EC_R_BUFFER_TOO_SMALL);
1318 return 0;
1319 }
1320
1321 memset(&param, 0, sizeof(param));
1322 memcpy(param.ed25519.priv, edkey->privkey, sizeof(param.ed25519.priv));
1323
1324 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED25519, &param.ed25519, tbs, tbslen);
1325 OPENSSL_cleanse(param.ed25519.priv, sizeof(param.ed25519.priv));
1326 if (rc != 0)
1327 return 0;
1328
1329 s390x_flip_endian32(sig, param.ed25519.sig);
1330 s390x_flip_endian32(sig + 32, param.ed25519.sig + 32);
1331
1332 *siglen = ED25519_SIGSIZE;
1333 return 1;
1334}
1335
1336static int s390x_pkey_ecd_digestsign448(EVP_MD_CTX *ctx,
1337 unsigned char *sig, size_t *siglen,
1338 const unsigned char *tbs,
1339 size_t tbslen)
1340{
1341 union {
1342 struct {
1343 unsigned char sig[128];
1344 unsigned char priv[64];
1345 } ed448;
1346 unsigned long long buff[512];
1347 } param;
1348 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1349 int rc;
1350
1351 if (sig == NULL) {
1352 *siglen = ED448_SIGSIZE;
1353 return 1;
1354 }
1355
1356 if (*siglen < ED448_SIGSIZE) {
1357 ECerr(EC_F_S390X_PKEY_ECD_DIGESTSIGN448, EC_R_BUFFER_TOO_SMALL);
1358 return 0;
1359 }
1360
1361 memset(&param, 0, sizeof(param));
1362 memcpy(param.ed448.priv + 64 - 57, edkey->privkey, 57);
1363
1364 rc = s390x_kdsa(S390X_EDDSA_SIGN_ED448, &param.ed448, tbs, tbslen);
1365 OPENSSL_cleanse(param.ed448.priv, sizeof(param.ed448.priv));
1366 if (rc != 0)
1367 return 0;
1368
1369 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1370 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1371 memcpy(sig, param.ed448.sig, 57);
1372 memcpy(sig + 57, param.ed448.sig + 64, 57);
1373
1374 *siglen = ED448_SIGSIZE;
1375 return 1;
1376}
1377
1378static int s390x_pkey_ecd_digestverify25519(EVP_MD_CTX *ctx,
1379 const unsigned char *sig,
1380 size_t siglen,
1381 const unsigned char *tbs,
1382 size_t tbslen)
1383{
1384 union {
1385 struct {
1386 unsigned char sig[64];
1387 unsigned char pub[32];
1388 } ed25519;
1389 unsigned long long buff[512];
1390 } param;
1391 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1392
1393 if (siglen != ED25519_SIGSIZE)
1394 return 0;
1395
1396 memset(&param, 0, sizeof(param));
1397 s390x_flip_endian32(param.ed25519.sig, sig);
1398 s390x_flip_endian32(param.ed25519.sig + 32, sig + 32);
1399 s390x_flip_endian32(param.ed25519.pub, edkey->pubkey);
1400
1401 return s390x_kdsa(S390X_EDDSA_VERIFY_ED25519,
1402 &param.ed25519, tbs, tbslen) == 0 ? 1 : 0;
1403}
1404
1405static int s390x_pkey_ecd_digestverify448(EVP_MD_CTX *ctx,
1406 const unsigned char *sig,
1407 size_t siglen,
1408 const unsigned char *tbs,
1409 size_t tbslen)
1410{
1411 union {
1412 struct {
1413 unsigned char sig[128];
1414 unsigned char pub[64];
1415 } ed448;
1416 unsigned long long buff[512];
1417 } param;
1418 const ECX_KEY *edkey = EVP_MD_CTX_pkey_ctx(ctx)->pkey->pkey.ecx;
1419
1420 if (siglen != ED448_SIGSIZE)
1421 return 0;
1422
1423 memset(&param, 0, sizeof(param));
1424 memcpy(param.ed448.sig, sig, 57);
1425 s390x_flip_endian64(param.ed448.sig, param.ed448.sig);
1426 memcpy(param.ed448.sig + 64, sig + 57, 57);
1427 s390x_flip_endian64(param.ed448.sig + 64, param.ed448.sig + 64);
1428 memcpy(param.ed448.pub, edkey->pubkey, 57);
1429 s390x_flip_endian64(param.ed448.pub, param.ed448.pub);
1430
1431 return s390x_kdsa(S390X_EDDSA_VERIFY_ED448,
1432 &param.ed448, tbs, tbslen) == 0 ? 1 : 0;
1433}
1434
1435static const EVP_PKEY_METHOD ecx25519_s390x_pkey_meth = {
1436 EVP_PKEY_X25519,
1437 0, 0, 0, 0, 0, 0, 0,
1438 s390x_pkey_ecx_keygen25519,
1439 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1440 s390x_pkey_ecx_derive25519,
1441 pkey_ecx_ctrl,
1442 0
1443};
1444
1445static const EVP_PKEY_METHOD ecx448_s390x_pkey_meth = {
1446 EVP_PKEY_X448,
1447 0, 0, 0, 0, 0, 0, 0,
1448 s390x_pkey_ecx_keygen448,
1449 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1450 s390x_pkey_ecx_derive448,
1451 pkey_ecx_ctrl,
1452 0
1453};
1454static const EVP_PKEY_METHOD ed25519_s390x_pkey_meth = {
1455 EVP_PKEY_ED25519, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1456 0, 0, 0, 0, 0, 0,
1457 s390x_pkey_ecd_keygen25519,
1458 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1459 pkey_ecd_ctrl,
1460 0,
1461 s390x_pkey_ecd_digestsign25519,
1462 s390x_pkey_ecd_digestverify25519
1463};
1464
1465static const EVP_PKEY_METHOD ed448_s390x_pkey_meth = {
1466 EVP_PKEY_ED448, EVP_PKEY_FLAG_SIGCTX_CUSTOM,
1467 0, 0, 0, 0, 0, 0,
1468 s390x_pkey_ecd_keygen448,
1469 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1470 pkey_ecd_ctrl,
1471 0,
1472 s390x_pkey_ecd_digestsign448,
1473 s390x_pkey_ecd_digestverify448
1474};
1475#endif
1476
1477const EVP_PKEY_METHOD *ecx25519_pkey_method(void)
1478{
1479#ifdef S390X_EC_ASM
1480 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
1481 return &ecx25519_s390x_pkey_meth;
1482#endif
1483 return &ecx25519_pkey_meth;
1484}
1485
1486const EVP_PKEY_METHOD *ecx448_pkey_method(void)
1487{
1488#ifdef S390X_EC_ASM
1489 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
1490 return &ecx448_s390x_pkey_meth;
1491#endif
1492 return &ecx448_pkey_meth;
1493}
1494
1495const EVP_PKEY_METHOD *ed25519_pkey_method(void)
1496{
1497#ifdef S390X_EC_ASM
1498 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
1499 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
1500 && OPENSSL_s390xcap_P.kdsa[0]
1501 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
1502 return &ed25519_s390x_pkey_meth;
1503#endif
1504 return &ed25519_pkey_meth;
1505}
1506
1507const EVP_PKEY_METHOD *ed448_pkey_method(void)
1508{
1509#ifdef S390X_EC_ASM
1510 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
1511 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
1512 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
1513 return &ed448_s390x_pkey_meth;
1514#endif
1515 return &ed448_pkey_meth;
1516}
1517