VirtualBox

source: vbox/trunk/src/libs/openssl-3.3.2/crypto/ec/ecx_meth.c

Last change on this file was 108206, checked in by vboxsync, 3 months ago

openssl-3.3.2: Exported all files to OSE and removed .scm-settings ​bugref:10757

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette