2 * Copyright 2020-2024 The OpenSSL Project Authors. All Rights Reserved.
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
12 #include <openssl/core_dispatch.h>
13 #include <openssl/core_names.h>
14 #include <openssl/params.h>
15 #include <openssl/err.h>
16 #include <openssl/proverr.h>
17 #include <openssl/evp.h>
18 #include <openssl/rand.h>
19 #include <openssl/self_test.h>
20 #include "internal/param_build_set.h"
21 #include <openssl/param_build.h>
22 #include "crypto/ecx.h"
23 #include "prov/implementations.h"
24 #include "prov/providercommon.h"
25 #include "prov/provider_ctx.h"
28 # include "s390x_arch.h"
29 # include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
32 static OSSL_FUNC_keymgmt_new_fn x25519_new_key;
33 static OSSL_FUNC_keymgmt_new_fn x448_new_key;
34 static OSSL_FUNC_keymgmt_new_fn ed25519_new_key;
35 static OSSL_FUNC_keymgmt_new_fn ed448_new_key;
36 static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init;
37 static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init;
38 static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init;
39 static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init;
40 static OSSL_FUNC_keymgmt_gen_fn x25519_gen;
41 static OSSL_FUNC_keymgmt_gen_fn x448_gen;
42 static OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
43 static OSSL_FUNC_keymgmt_gen_fn ed448_gen;
44 static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
45 static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params;
46 static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params;
47 static OSSL_FUNC_keymgmt_load_fn ecx_load;
48 static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
49 static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
50 static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
51 static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
52 static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
53 static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
54 static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
55 static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
56 static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
57 static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
58 static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
59 static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
60 static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
61 static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
62 static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
63 static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
64 static OSSL_FUNC_keymgmt_has_fn ecx_has;
65 static OSSL_FUNC_keymgmt_match_fn ecx_match;
66 static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
67 static OSSL_FUNC_keymgmt_validate_fn x448_validate;
68 static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
69 static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
70 static OSSL_FUNC_keymgmt_import_fn ecx_import;
71 static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
72 static OSSL_FUNC_keymgmt_export_fn ecx_export;
73 static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
74 static OSSL_FUNC_keymgmt_dup_fn ecx_dup;
76 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
83 unsigned char *dhkem_ikm;
88 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
89 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
90 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
91 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
94 static void *x25519_new_key(void *provctx)
96 if (!ossl_prov_is_running())
98 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
102 static void *x448_new_key(void *provctx)
104 if (!ossl_prov_is_running())
106 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0,
110 static void *ed25519_new_key(void *provctx)
112 if (!ossl_prov_is_running())
114 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0,
118 static void *ed448_new_key(void *provctx)
120 if (!ossl_prov_is_running())
122 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0,
126 static int ecx_has(const void *keydata, int selection)
128 const ECX_KEY *key = keydata;
131 if (ossl_prov_is_running() && key != NULL) {
133 * ECX keys always have all the parameters they need (i.e. none).
134 * Therefore we always return with 1, if asked about parameters.
138 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
139 ok = ok && key->haspubkey;
141 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
142 ok = ok && key->privkey != NULL;
147 static int ecx_match(const void *keydata1, const void *keydata2, int selection)
149 const ECX_KEY *key1 = keydata1;
150 const ECX_KEY *key2 = keydata2;
153 if (!ossl_prov_is_running())
156 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
157 ok = ok && key1->type == key2->type;
158 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
161 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
162 const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
163 const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
164 size_t pal = key1->keylen;
165 size_t pbl = key2->keylen;
167 if (pa != NULL && pb != NULL) {
169 && key1->type == key2->type
171 && CRYPTO_memcmp(pa, pb, pal) == 0;
176 && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
177 const unsigned char *pa = key1->privkey;
178 const unsigned char *pb = key2->privkey;
179 size_t pal = key1->keylen;
180 size_t pbl = key2->keylen;
182 if (pa != NULL && pb != NULL) {
184 && key1->type == key2->type
186 && CRYPTO_memcmp(pa, pb, pal) == 0;
190 ok = ok && key_checked;
195 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
197 ECX_KEY *key = keydata;
201 if (!ossl_prov_is_running() || key == NULL)
204 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
207 include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
208 ok = ok && ossl_ecx_key_fromdata(key, params, include_private);
213 static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
214 OSSL_PARAM params[], int include_private)
219 if (!ossl_param_build_set_octet_string(tmpl, params,
220 OSSL_PKEY_PARAM_PUB_KEY,
221 key->pubkey, key->keylen))
225 && key->privkey != NULL
226 && !ossl_param_build_set_octet_string(tmpl, params,
227 OSSL_PKEY_PARAM_PRIV_KEY,
228 key->privkey, key->keylen))
234 static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
237 ECX_KEY *key = keydata;
238 OSSL_PARAM_BLD *tmpl;
239 OSSL_PARAM *params = NULL;
242 if (!ossl_prov_is_running() || key == NULL)
245 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
248 tmpl = OSSL_PARAM_BLD_new();
252 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
253 int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
255 if (!key_to_params(key, tmpl, NULL, include_private))
259 params = OSSL_PARAM_BLD_to_param(tmpl);
263 ret = param_cb(params, cbarg);
264 OSSL_PARAM_free(params);
266 OSSL_PARAM_BLD_free(tmpl);
270 #define ECX_KEY_TYPES() \
271 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \
272 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
274 static const OSSL_PARAM ecx_key_types[] = {
278 static const OSSL_PARAM *ecx_imexport_types(int selection)
280 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
281 return ecx_key_types;
285 static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
291 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
292 && !OSSL_PARAM_set_int(p, bits))
294 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
295 && !OSSL_PARAM_set_int(p, secbits))
297 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
298 && !OSSL_PARAM_set_int(p, size))
300 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
301 && (ecx->type == ECX_KEY_TYPE_X25519
302 || ecx->type == ECX_KEY_TYPE_X448)) {
303 if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
307 return key_to_params(ecx, NULL, params, 1);
310 static int ed_get_params(void *key, OSSL_PARAM params[])
314 if ((p = OSSL_PARAM_locate(params,
315 OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
316 && !OSSL_PARAM_set_utf8_string(p, ""))
321 static int x25519_get_params(void *key, OSSL_PARAM params[])
323 return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
327 static int x448_get_params(void *key, OSSL_PARAM params[])
329 return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
333 static int ed25519_get_params(void *key, OSSL_PARAM params[])
335 return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
337 && ed_get_params(key, params);
340 static int ed448_get_params(void *key, OSSL_PARAM params[])
342 return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
344 && ed_get_params(key, params);
347 static const OSSL_PARAM ecx_gettable_params[] = {
348 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
349 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
350 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
351 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
352 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
357 static const OSSL_PARAM ed_gettable_params[] = {
358 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
359 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
360 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
365 static const OSSL_PARAM *x25519_gettable_params(void *provctx)
367 return ecx_gettable_params;
370 static const OSSL_PARAM *x448_gettable_params(void *provctx)
372 return ecx_gettable_params;
375 static const OSSL_PARAM *ed25519_gettable_params(void *provctx)
377 return ed_gettable_params;
380 static const OSSL_PARAM *ed448_gettable_params(void *provctx)
382 return ed_gettable_params;
385 static int set_property_query(ECX_KEY *ecxkey, const char *propq)
387 OPENSSL_free(ecxkey->propq);
388 ecxkey->propq = NULL;
390 ecxkey->propq = OPENSSL_strdup(propq);
391 if (ecxkey->propq == NULL)
397 static int ecx_set_params(void *key, const OSSL_PARAM params[])
399 ECX_KEY *ecxkey = key;
405 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
407 void *buf = ecxkey->pubkey;
409 if (p->data_size != ecxkey->keylen
410 || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
413 OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
414 ecxkey->privkey = NULL;
415 ecxkey->haspubkey = 1;
417 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
419 if (p->data_type != OSSL_PARAM_UTF8_STRING
420 || !set_property_query(ecxkey, p->data))
427 static int x25519_set_params(void *key, const OSSL_PARAM params[])
429 return ecx_set_params(key, params);
432 static int x448_set_params(void *key, const OSSL_PARAM params[])
434 return ecx_set_params(key, params);
437 static int ed25519_set_params(void *key, const OSSL_PARAM params[])
442 static int ed448_set_params(void *key, const OSSL_PARAM params[])
447 static const OSSL_PARAM ecx_settable_params[] = {
448 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
449 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
453 static const OSSL_PARAM ed_settable_params[] = {
457 static const OSSL_PARAM *x25519_settable_params(void *provctx)
459 return ecx_settable_params;
462 static const OSSL_PARAM *x448_settable_params(void *provctx)
464 return ecx_settable_params;
467 static const OSSL_PARAM *ed25519_settable_params(void *provctx)
469 return ed_settable_params;
472 static const OSSL_PARAM *ed448_settable_params(void *provctx)
474 return ed_settable_params;
477 static void *ecx_gen_init(void *provctx, int selection,
478 const OSSL_PARAM params[], ECX_KEY_TYPE type)
480 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
481 struct ecx_gen_ctx *gctx = NULL;
483 if (!ossl_prov_is_running())
486 if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
487 gctx->libctx = libctx;
489 gctx->selection = selection;
491 if (!ecx_gen_set_params(gctx, params)) {
498 static void *x25519_gen_init(void *provctx, int selection,
499 const OSSL_PARAM params[])
501 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
504 static void *x448_gen_init(void *provctx, int selection,
505 const OSSL_PARAM params[])
507 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
510 static void *ed25519_gen_init(void *provctx, int selection,
511 const OSSL_PARAM params[])
513 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519);
516 static void *ed448_gen_init(void *provctx, int selection,
517 const OSSL_PARAM params[])
519 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448);
522 static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
524 struct ecx_gen_ctx *gctx = genctx;
530 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
532 const char *groupname = NULL;
535 * We optionally allow setting a group name - but each algorithm only
536 * support one such name, so all we do is verify that it is the one we
539 switch (gctx->type) {
540 case ECX_KEY_TYPE_X25519:
541 groupname = "x25519";
543 case ECX_KEY_TYPE_X448:
547 /* We only support this for key exchange at the moment */
550 if (p->data_type != OSSL_PARAM_UTF8_STRING
552 || OPENSSL_strcasecmp(p->data, groupname) != 0) {
553 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
557 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
559 if (p->data_type != OSSL_PARAM_UTF8_STRING)
561 OPENSSL_free(gctx->propq);
562 gctx->propq = OPENSSL_strdup(p->data);
563 if (gctx->propq == NULL)
566 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DHKEM_IKM);
568 if (p->data_size != 0 && p->data != NULL) {
569 OPENSSL_free(gctx->dhkem_ikm);
570 gctx->dhkem_ikm = NULL;
571 if (!OSSL_PARAM_get_octet_string(p, (void **)&gctx->dhkem_ikm, 0,
572 &gctx->dhkem_ikmlen))
580 static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
581 ossl_unused void *provctx)
583 static OSSL_PARAM settable[] = {
584 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
585 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
586 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM, NULL, 0),
594 * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1
595 * Perform a pairwise test for EDDSA by signing and verifying signature.
597 * The parameter `self_test` is used to indicate whether to create OSSL_SELF_TEST
600 static int ecd_fips140_pairwise_test(const ECX_KEY *ecx, int type, int self_test)
603 OSSL_SELF_TEST *st = NULL;
604 OSSL_CALLBACK *cb = NULL;
607 unsigned char msg[16] = {0};
608 size_t msg_len = sizeof(msg);
609 unsigned char sig[ED448_SIGSIZE] = {0};
611 int is_ed25519 = (type == ECX_KEY_TYPE_ED25519) ? 1 : 0;
612 int operation_result = 0;
615 * The functions `OSSL_SELF_TEST_*` will return directly if parameter `st`
619 OSSL_SELF_TEST_get_callback(ecx->libctx, &cb, &cbarg);
621 st = OSSL_SELF_TEST_new(cb, cbarg);
626 OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
627 OSSL_SELF_TEST_DESC_PCT_EDDSA);
630 operation_result = ossl_ed25519_sign(sig, msg, msg_len, ecx->pubkey,
631 ecx->privkey, 0, 0, 0, NULL, 0,
632 ecx->libctx, ecx->propq);
634 operation_result = ossl_ed448_sign(ecx->libctx, sig, msg, msg_len,
635 ecx->pubkey, ecx->privkey, NULL, 0,
637 if (operation_result != 1)
640 OSSL_SELF_TEST_oncorrupt_byte(st, sig);
643 operation_result = ossl_ed25519_verify(msg, msg_len, sig, ecx->pubkey,
644 0, 0, 0, NULL, 0, ecx->libctx,
647 operation_result = ossl_ed448_verify(ecx->libctx, msg, msg_len, sig,
648 ecx->pubkey, NULL, 0, 0, ecx->propq);
649 if (operation_result != 1)
654 OSSL_SELF_TEST_onend(st, ret);
655 OSSL_SELF_TEST_free(st);
660 static void *ecx_gen(struct ecx_gen_ctx *gctx)
663 unsigned char *privkey;
667 if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
668 gctx->propq)) == NULL) {
669 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
673 /* If we're doing parameter generation then we just return a blank key */
674 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
677 if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
678 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
682 if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
683 if (gctx->type == ECX_KEY_TYPE_ED25519
684 || gctx->type == ECX_KEY_TYPE_ED448)
686 if (!ossl_ecx_dhkem_derive_private(key, privkey,
687 gctx->dhkem_ikm, gctx->dhkem_ikmlen))
692 if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
696 switch (gctx->type) {
697 case ECX_KEY_TYPE_X25519:
699 privkey[X25519_KEYLEN - 1] &= 127;
700 privkey[X25519_KEYLEN - 1] |= 64;
701 ossl_x25519_public_from_private(key->pubkey, privkey);
703 case ECX_KEY_TYPE_X448:
705 privkey[X448_KEYLEN - 1] |= 128;
706 ossl_x448_public_from_private(key->pubkey, privkey);
708 case ECX_KEY_TYPE_ED25519:
709 if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey,
713 case ECX_KEY_TYPE_ED448:
714 if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey,
722 ossl_ecx_key_free(key);
726 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
728 struct ecx_gen_ctx *gctx = genctx;
730 if (!ossl_prov_is_running())
734 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
735 return s390x_ecx_keygen25519(gctx);
737 return ecx_gen(gctx);
740 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
742 struct ecx_gen_ctx *gctx = genctx;
744 if (!ossl_prov_is_running())
748 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
749 return s390x_ecx_keygen448(gctx);
751 return ecx_gen(gctx);
754 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
757 struct ecx_gen_ctx *gctx = genctx;
759 if (!ossl_prov_is_running())
763 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
764 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
765 && OPENSSL_s390xcap_P.kdsa[0]
766 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)) {
767 key = s390x_ecd_keygen25519(gctx);
775 /* Exit if keygen failed OR we are doing parameter generation (blank key) */
776 if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
778 if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED25519, 1) != 1) {
779 ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
780 ossl_ecx_key_free(key);
788 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
791 struct ecx_gen_ctx *gctx = genctx;
793 if (!ossl_prov_is_running())
797 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
798 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
799 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) {
800 key = s390x_ecd_keygen448(gctx);
808 /* Exit if keygen failed OR we are doing parameter generation (blank key) */
809 if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
811 if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED448, 1) != 1) {
812 ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
813 ossl_ecx_key_free(key);
821 static void ecx_gen_cleanup(void *genctx)
823 struct ecx_gen_ctx *gctx = genctx;
825 OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
826 OPENSSL_free(gctx->propq);
830 void *ecx_load(const void *reference, size_t reference_sz)
834 if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
835 /* The contents of the reference is the address to our object */
836 key = *(ECX_KEY **)reference;
837 /* We grabbed, so we detach it */
838 *(ECX_KEY **)reference = NULL;
844 static void *ecx_dup(const void *keydata_from, int selection)
846 if (ossl_prov_is_running())
847 return ossl_ecx_key_dup(keydata_from, selection);
851 static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
856 case ECX_KEY_TYPE_X25519:
857 ossl_x25519_public_from_private(pub, ecx->privkey);
859 case ECX_KEY_TYPE_X448:
860 ossl_x448_public_from_private(pub, ecx->privkey);
865 return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
869 static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
871 return ecd_fips140_pairwise_test(ecx, type, 0);
874 static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
879 case ECX_KEY_TYPE_ED25519:
880 if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
884 case ECX_KEY_TYPE_ED448:
885 if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
892 return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
896 static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
898 const ECX_KEY *ecx = keydata;
899 int ok = keylen == ecx->keylen;
901 if (!ossl_prov_is_running())
904 if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
905 return 1; /* nothing to validate */
908 ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
912 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
913 ok = ok && ecx->haspubkey;
915 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
916 ok = ok && ecx->privkey != NULL;
918 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
921 if (type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448)
922 ok = ok && ecd_key_pairwise_check(ecx, type);
924 ok = ok && ecx_key_pairwise_check(ecx, type);
929 static int x25519_validate(const void *keydata, int selection, int checktype)
931 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
934 static int x448_validate(const void *keydata, int selection, int checktype)
936 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
939 static int ed25519_validate(const void *keydata, int selection, int checktype)
941 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
944 static int ed448_validate(const void *keydata, int selection, int checktype)
946 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
949 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
950 const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
951 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
952 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
953 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
954 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
955 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
956 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
957 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
958 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
959 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
960 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
961 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
962 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
963 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
964 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
965 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
966 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
967 (void (*)(void))ecx_gen_settable_params }, \
968 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
969 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
970 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
971 { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
975 MAKE_KEYMGMT_FUNCTIONS(x25519)
976 MAKE_KEYMGMT_FUNCTIONS(x448)
977 MAKE_KEYMGMT_FUNCTIONS(ed25519)
978 MAKE_KEYMGMT_FUNCTIONS(ed448)
981 # include "s390x_arch.h"
983 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
985 static const unsigned char generator[] = {
986 0x09, 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
990 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
992 unsigned char *privkey = NULL, *pubkey;
995 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
999 /* If we're doing parameter generation then we just return a blank key */
1000 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1003 pubkey = key->pubkey;
1005 privkey = ossl_ecx_key_allocate_privkey(key);
1006 if (privkey == NULL) {
1007 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1012 if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1013 if (gctx->type != ECX_KEY_TYPE_X25519)
1015 if (!ossl_ecx_dhkem_derive_private(key, privkey,
1016 gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1021 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
1029 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
1034 ossl_ecx_key_free(key);
1038 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
1040 static const unsigned char generator[] = {
1041 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1042 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1043 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1044 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1045 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1047 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
1049 unsigned char *privkey = NULL, *pubkey;
1052 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1056 /* If we're doing parameter generation then we just return a blank key */
1057 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1060 pubkey = key->pubkey;
1062 privkey = ossl_ecx_key_allocate_privkey(key);
1063 if (privkey == NULL) {
1064 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1069 if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1070 if (gctx->type != ECX_KEY_TYPE_X448)
1072 if (!ossl_ecx_dhkem_derive_private(key, privkey,
1073 gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1078 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1085 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1090 ossl_ecx_key_free(key);
1094 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
1096 static const unsigned char generator_x[] = {
1097 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1098 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1099 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1101 static const unsigned char generator_y[] = {
1102 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1103 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1104 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1106 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1107 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1109 unsigned char *privkey = NULL, *pubkey;
1115 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1119 /* If we're doing parameter generation then we just return a blank key */
1120 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1123 pubkey = key->pubkey;
1125 privkey = ossl_ecx_key_allocate_privkey(key);
1126 if (privkey == NULL) {
1127 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1131 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1134 sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
1137 j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
1146 if (s390x_ed25519_mul(x_dst, pubkey,
1147 generator_x, generator_y, buff) != 1)
1150 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1154 ossl_ecx_key_free(key);
1158 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
1160 static const unsigned char generator_x[] = {
1161 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1162 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1163 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1164 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1165 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1167 static const unsigned char generator_y[] = {
1168 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1169 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1170 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1171 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1172 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1174 unsigned char x_dst[57], buff[114];
1175 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
1177 unsigned char *privkey = NULL, *pubkey;
1178 EVP_MD_CTX *hashctx = NULL;
1179 EVP_MD *shake = NULL;
1182 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1186 /* If we're doing parameter generation then we just return a blank key */
1187 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1190 pubkey = key->pubkey;
1192 privkey = ossl_ecx_key_allocate_privkey(key);
1193 if (privkey == NULL) {
1194 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1198 shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1201 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1204 hashctx = EVP_MD_CTX_new();
1205 if (hashctx == NULL)
1207 if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1209 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1211 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1218 if (s390x_ed448_mul(x_dst, pubkey,
1219 generator_x, generator_y, buff) != 1)
1222 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1223 EVP_MD_CTX_free(hashctx);
1228 ossl_ecx_key_free(key);
1229 EVP_MD_CTX_free(hashctx);