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