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