1b077aed3SPierre Pronchery /*
2*6f1af0d7SPierre Pronchery * Copyright 2020-2023 The OpenSSL Project Authors. All Rights Reserved.
3b077aed3SPierre Pronchery *
4b077aed3SPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5b077aed3SPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6b077aed3SPierre Pronchery * in the file LICENSE in the source distribution or at
7b077aed3SPierre Pronchery * https://www.openssl.org/source/license.html
8b077aed3SPierre Pronchery */
9b077aed3SPierre Pronchery
10b077aed3SPierre Pronchery #include <assert.h>
11b077aed3SPierre Pronchery #include <string.h>
12b077aed3SPierre Pronchery #include <openssl/core_dispatch.h>
13b077aed3SPierre Pronchery #include <openssl/core_names.h>
14b077aed3SPierre Pronchery #include <openssl/params.h>
15b077aed3SPierre Pronchery #include <openssl/err.h>
16b077aed3SPierre Pronchery #include <openssl/proverr.h>
17b077aed3SPierre Pronchery #include <openssl/evp.h>
18b077aed3SPierre Pronchery #include <openssl/rand.h>
19b077aed3SPierre Pronchery #include "internal/param_build_set.h"
20b077aed3SPierre Pronchery #include <openssl/param_build.h>
21b077aed3SPierre Pronchery #include "crypto/ecx.h"
22b077aed3SPierre Pronchery #include "prov/implementations.h"
23b077aed3SPierre Pronchery #include "prov/providercommon.h"
24b077aed3SPierre Pronchery #include "prov/provider_ctx.h"
25b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
26b077aed3SPierre Pronchery # include "s390x_arch.h"
27b077aed3SPierre Pronchery # include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
28b077aed3SPierre Pronchery #endif
29b077aed3SPierre Pronchery
30b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_new_fn x25519_new_key;
31b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_new_fn x448_new_key;
32b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_new_fn ed25519_new_key;
33b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_new_fn ed448_new_key;
34b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init;
35b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init;
36b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init;
37b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init;
38b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_fn x25519_gen;
39b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_fn x448_gen;
40b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
41b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_fn ed448_gen;
42b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
43b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params;
44b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params;
45b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_load_fn ecx_load;
46b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
47b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
48b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
49b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
50b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
51b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
52b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
53b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
54b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
55b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
56b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
57b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
58b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
59b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
60b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
61b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
62b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_has_fn ecx_has;
63b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_match_fn ecx_match;
64b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
65b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_validate_fn x448_validate;
66b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
67b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
68b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_import_fn ecx_import;
69b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
70b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_export_fn ecx_export;
71b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
72b077aed3SPierre Pronchery static OSSL_FUNC_keymgmt_dup_fn ecx_dup;
73b077aed3SPierre Pronchery
74b077aed3SPierre Pronchery #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
75b077aed3SPierre Pronchery
76b077aed3SPierre Pronchery struct ecx_gen_ctx {
77b077aed3SPierre Pronchery OSSL_LIB_CTX *libctx;
78b077aed3SPierre Pronchery char *propq;
79b077aed3SPierre Pronchery ECX_KEY_TYPE type;
80b077aed3SPierre Pronchery int selection;
81b077aed3SPierre Pronchery };
82b077aed3SPierre Pronchery
83b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
84b077aed3SPierre Pronchery static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
85b077aed3SPierre Pronchery static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
86b077aed3SPierre Pronchery static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
87b077aed3SPierre Pronchery static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
88b077aed3SPierre Pronchery #endif
89b077aed3SPierre Pronchery
x25519_new_key(void * provctx)90b077aed3SPierre Pronchery static void *x25519_new_key(void *provctx)
91b077aed3SPierre Pronchery {
92b077aed3SPierre Pronchery if (!ossl_prov_is_running())
93b077aed3SPierre Pronchery return 0;
94b077aed3SPierre Pronchery return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
95b077aed3SPierre Pronchery NULL);
96b077aed3SPierre Pronchery }
97b077aed3SPierre Pronchery
x448_new_key(void * provctx)98b077aed3SPierre Pronchery static void *x448_new_key(void *provctx)
99b077aed3SPierre Pronchery {
100b077aed3SPierre Pronchery if (!ossl_prov_is_running())
101b077aed3SPierre Pronchery return 0;
102b077aed3SPierre Pronchery return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0,
103b077aed3SPierre Pronchery NULL);
104b077aed3SPierre Pronchery }
105b077aed3SPierre Pronchery
ed25519_new_key(void * provctx)106b077aed3SPierre Pronchery static void *ed25519_new_key(void *provctx)
107b077aed3SPierre Pronchery {
108b077aed3SPierre Pronchery if (!ossl_prov_is_running())
109b077aed3SPierre Pronchery return 0;
110b077aed3SPierre Pronchery return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0,
111b077aed3SPierre Pronchery NULL);
112b077aed3SPierre Pronchery }
113b077aed3SPierre Pronchery
ed448_new_key(void * provctx)114b077aed3SPierre Pronchery static void *ed448_new_key(void *provctx)
115b077aed3SPierre Pronchery {
116b077aed3SPierre Pronchery if (!ossl_prov_is_running())
117b077aed3SPierre Pronchery return 0;
118b077aed3SPierre Pronchery return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0,
119b077aed3SPierre Pronchery NULL);
120b077aed3SPierre Pronchery }
121b077aed3SPierre Pronchery
ecx_has(const void * keydata,int selection)122b077aed3SPierre Pronchery static int ecx_has(const void *keydata, int selection)
123b077aed3SPierre Pronchery {
124b077aed3SPierre Pronchery const ECX_KEY *key = keydata;
125b077aed3SPierre Pronchery int ok = 0;
126b077aed3SPierre Pronchery
127b077aed3SPierre Pronchery if (ossl_prov_is_running() && key != NULL) {
128b077aed3SPierre Pronchery /*
129b077aed3SPierre Pronchery * ECX keys always have all the parameters they need (i.e. none).
130b077aed3SPierre Pronchery * Therefore we always return with 1, if asked about parameters.
131b077aed3SPierre Pronchery */
132b077aed3SPierre Pronchery ok = 1;
133b077aed3SPierre Pronchery
134b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
135b077aed3SPierre Pronchery ok = ok && key->haspubkey;
136b077aed3SPierre Pronchery
137b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
138b077aed3SPierre Pronchery ok = ok && key->privkey != NULL;
139b077aed3SPierre Pronchery }
140b077aed3SPierre Pronchery return ok;
141b077aed3SPierre Pronchery }
142b077aed3SPierre Pronchery
ecx_match(const void * keydata1,const void * keydata2,int selection)143b077aed3SPierre Pronchery static int ecx_match(const void *keydata1, const void *keydata2, int selection)
144b077aed3SPierre Pronchery {
145b077aed3SPierre Pronchery const ECX_KEY *key1 = keydata1;
146b077aed3SPierre Pronchery const ECX_KEY *key2 = keydata2;
147b077aed3SPierre Pronchery int ok = 1;
148b077aed3SPierre Pronchery
149b077aed3SPierre Pronchery if (!ossl_prov_is_running())
150b077aed3SPierre Pronchery return 0;
151b077aed3SPierre Pronchery
152b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
153b077aed3SPierre Pronchery ok = ok && key1->type == key2->type;
154b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
155b077aed3SPierre Pronchery int key_checked = 0;
156b077aed3SPierre Pronchery
157b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
158b077aed3SPierre Pronchery const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
159b077aed3SPierre Pronchery const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
160b077aed3SPierre Pronchery size_t pal = key1->keylen;
161b077aed3SPierre Pronchery size_t pbl = key2->keylen;
162b077aed3SPierre Pronchery
163b077aed3SPierre Pronchery if (pa != NULL && pb != NULL) {
164b077aed3SPierre Pronchery ok = ok
165b077aed3SPierre Pronchery && key1->type == key2->type
166b077aed3SPierre Pronchery && pal == pbl
167b077aed3SPierre Pronchery && CRYPTO_memcmp(pa, pb, pal) == 0;
168b077aed3SPierre Pronchery key_checked = 1;
169b077aed3SPierre Pronchery }
170b077aed3SPierre Pronchery }
171b077aed3SPierre Pronchery if (!key_checked
172b077aed3SPierre Pronchery && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
173b077aed3SPierre Pronchery const unsigned char *pa = key1->privkey;
174b077aed3SPierre Pronchery const unsigned char *pb = key2->privkey;
175b077aed3SPierre Pronchery size_t pal = key1->keylen;
176b077aed3SPierre Pronchery size_t pbl = key2->keylen;
177b077aed3SPierre Pronchery
178b077aed3SPierre Pronchery if (pa != NULL && pb != NULL) {
179b077aed3SPierre Pronchery ok = ok
180b077aed3SPierre Pronchery && key1->type == key2->type
181b077aed3SPierre Pronchery && pal == pbl
182b077aed3SPierre Pronchery && CRYPTO_memcmp(pa, pb, pal) == 0;
183b077aed3SPierre Pronchery key_checked = 1;
184b077aed3SPierre Pronchery }
185b077aed3SPierre Pronchery }
186b077aed3SPierre Pronchery ok = ok && key_checked;
187b077aed3SPierre Pronchery }
188b077aed3SPierre Pronchery return ok;
189b077aed3SPierre Pronchery }
190b077aed3SPierre Pronchery
ecx_import(void * keydata,int selection,const OSSL_PARAM params[])191b077aed3SPierre Pronchery static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
192b077aed3SPierre Pronchery {
193b077aed3SPierre Pronchery ECX_KEY *key = keydata;
194b077aed3SPierre Pronchery int ok = 1;
195b077aed3SPierre Pronchery int include_private;
196b077aed3SPierre Pronchery
197b077aed3SPierre Pronchery if (!ossl_prov_is_running() || key == NULL)
198b077aed3SPierre Pronchery return 0;
199b077aed3SPierre Pronchery
200b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
201b077aed3SPierre Pronchery return 0;
202b077aed3SPierre Pronchery
203b077aed3SPierre Pronchery include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
204b077aed3SPierre Pronchery ok = ok && ossl_ecx_key_fromdata(key, params, include_private);
205b077aed3SPierre Pronchery
206b077aed3SPierre Pronchery return ok;
207b077aed3SPierre Pronchery }
208b077aed3SPierre Pronchery
key_to_params(ECX_KEY * key,OSSL_PARAM_BLD * tmpl,OSSL_PARAM params[],int include_private)209b077aed3SPierre Pronchery static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
210b077aed3SPierre Pronchery OSSL_PARAM params[], int include_private)
211b077aed3SPierre Pronchery {
212b077aed3SPierre Pronchery if (key == NULL)
213b077aed3SPierre Pronchery return 0;
214b077aed3SPierre Pronchery
215b077aed3SPierre Pronchery if (!ossl_param_build_set_octet_string(tmpl, params,
216b077aed3SPierre Pronchery OSSL_PKEY_PARAM_PUB_KEY,
217b077aed3SPierre Pronchery key->pubkey, key->keylen))
218b077aed3SPierre Pronchery return 0;
219b077aed3SPierre Pronchery
220b077aed3SPierre Pronchery if (include_private
221b077aed3SPierre Pronchery && key->privkey != NULL
222b077aed3SPierre Pronchery && !ossl_param_build_set_octet_string(tmpl, params,
223b077aed3SPierre Pronchery OSSL_PKEY_PARAM_PRIV_KEY,
224b077aed3SPierre Pronchery key->privkey, key->keylen))
225b077aed3SPierre Pronchery return 0;
226b077aed3SPierre Pronchery
227b077aed3SPierre Pronchery return 1;
228b077aed3SPierre Pronchery }
229b077aed3SPierre Pronchery
ecx_export(void * keydata,int selection,OSSL_CALLBACK * param_cb,void * cbarg)230b077aed3SPierre Pronchery static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
231b077aed3SPierre Pronchery void *cbarg)
232b077aed3SPierre Pronchery {
233b077aed3SPierre Pronchery ECX_KEY *key = keydata;
234b077aed3SPierre Pronchery OSSL_PARAM_BLD *tmpl;
235b077aed3SPierre Pronchery OSSL_PARAM *params = NULL;
236b077aed3SPierre Pronchery int ret = 0;
237b077aed3SPierre Pronchery
238b077aed3SPierre Pronchery if (!ossl_prov_is_running() || key == NULL)
239b077aed3SPierre Pronchery return 0;
240b077aed3SPierre Pronchery
241*6f1af0d7SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
242*6f1af0d7SPierre Pronchery return 0;
243*6f1af0d7SPierre Pronchery
244b077aed3SPierre Pronchery tmpl = OSSL_PARAM_BLD_new();
245b077aed3SPierre Pronchery if (tmpl == NULL)
246b077aed3SPierre Pronchery return 0;
247b077aed3SPierre Pronchery
248b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
249b077aed3SPierre Pronchery int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
250b077aed3SPierre Pronchery
251b077aed3SPierre Pronchery if (!key_to_params(key, tmpl, NULL, include_private))
252b077aed3SPierre Pronchery goto err;
253b077aed3SPierre Pronchery }
254b077aed3SPierre Pronchery
255b077aed3SPierre Pronchery params = OSSL_PARAM_BLD_to_param(tmpl);
256b077aed3SPierre Pronchery if (params == NULL)
257b077aed3SPierre Pronchery goto err;
258b077aed3SPierre Pronchery
259b077aed3SPierre Pronchery ret = param_cb(params, cbarg);
260b077aed3SPierre Pronchery OSSL_PARAM_free(params);
261b077aed3SPierre Pronchery err:
262b077aed3SPierre Pronchery OSSL_PARAM_BLD_free(tmpl);
263b077aed3SPierre Pronchery return ret;
264b077aed3SPierre Pronchery }
265b077aed3SPierre Pronchery
266b077aed3SPierre Pronchery #define ECX_KEY_TYPES() \
267b077aed3SPierre Pronchery OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \
268b077aed3SPierre Pronchery OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
269b077aed3SPierre Pronchery
270b077aed3SPierre Pronchery static const OSSL_PARAM ecx_key_types[] = {
271b077aed3SPierre Pronchery ECX_KEY_TYPES(),
272b077aed3SPierre Pronchery OSSL_PARAM_END
273b077aed3SPierre Pronchery };
ecx_imexport_types(int selection)274b077aed3SPierre Pronchery static const OSSL_PARAM *ecx_imexport_types(int selection)
275b077aed3SPierre Pronchery {
276b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
277b077aed3SPierre Pronchery return ecx_key_types;
278b077aed3SPierre Pronchery return NULL;
279b077aed3SPierre Pronchery }
280b077aed3SPierre Pronchery
ecx_get_params(void * key,OSSL_PARAM params[],int bits,int secbits,int size)281b077aed3SPierre Pronchery static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
282b077aed3SPierre Pronchery int size)
283b077aed3SPierre Pronchery {
284b077aed3SPierre Pronchery ECX_KEY *ecx = key;
285b077aed3SPierre Pronchery OSSL_PARAM *p;
286b077aed3SPierre Pronchery
287b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
288b077aed3SPierre Pronchery && !OSSL_PARAM_set_int(p, bits))
289b077aed3SPierre Pronchery return 0;
290b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
291b077aed3SPierre Pronchery && !OSSL_PARAM_set_int(p, secbits))
292b077aed3SPierre Pronchery return 0;
293b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
294b077aed3SPierre Pronchery && !OSSL_PARAM_set_int(p, size))
295b077aed3SPierre Pronchery return 0;
296b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
297b077aed3SPierre Pronchery && (ecx->type == ECX_KEY_TYPE_X25519
298b077aed3SPierre Pronchery || ecx->type == ECX_KEY_TYPE_X448)) {
299b077aed3SPierre Pronchery if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
300b077aed3SPierre Pronchery return 0;
301b077aed3SPierre Pronchery }
302b077aed3SPierre Pronchery
303b077aed3SPierre Pronchery return key_to_params(ecx, NULL, params, 1);
304b077aed3SPierre Pronchery }
305b077aed3SPierre Pronchery
ed_get_params(void * key,OSSL_PARAM params[])306b077aed3SPierre Pronchery static int ed_get_params(void *key, OSSL_PARAM params[])
307b077aed3SPierre Pronchery {
308b077aed3SPierre Pronchery OSSL_PARAM *p;
309b077aed3SPierre Pronchery
310b077aed3SPierre Pronchery if ((p = OSSL_PARAM_locate(params,
311b077aed3SPierre Pronchery OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
312b077aed3SPierre Pronchery && !OSSL_PARAM_set_utf8_string(p, ""))
313b077aed3SPierre Pronchery return 0;
314b077aed3SPierre Pronchery return 1;
315b077aed3SPierre Pronchery }
316b077aed3SPierre Pronchery
x25519_get_params(void * key,OSSL_PARAM params[])317b077aed3SPierre Pronchery static int x25519_get_params(void *key, OSSL_PARAM params[])
318b077aed3SPierre Pronchery {
319b077aed3SPierre Pronchery return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
320b077aed3SPierre Pronchery X25519_KEYLEN);
321b077aed3SPierre Pronchery }
322b077aed3SPierre Pronchery
x448_get_params(void * key,OSSL_PARAM params[])323b077aed3SPierre Pronchery static int x448_get_params(void *key, OSSL_PARAM params[])
324b077aed3SPierre Pronchery {
325b077aed3SPierre Pronchery return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
326b077aed3SPierre Pronchery X448_KEYLEN);
327b077aed3SPierre Pronchery }
328b077aed3SPierre Pronchery
ed25519_get_params(void * key,OSSL_PARAM params[])329b077aed3SPierre Pronchery static int ed25519_get_params(void *key, OSSL_PARAM params[])
330b077aed3SPierre Pronchery {
331b077aed3SPierre Pronchery return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
332b077aed3SPierre Pronchery ED25519_SIGSIZE)
333b077aed3SPierre Pronchery && ed_get_params(key, params);
334b077aed3SPierre Pronchery }
335b077aed3SPierre Pronchery
ed448_get_params(void * key,OSSL_PARAM params[])336b077aed3SPierre Pronchery static int ed448_get_params(void *key, OSSL_PARAM params[])
337b077aed3SPierre Pronchery {
338b077aed3SPierre Pronchery return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
339b077aed3SPierre Pronchery ED448_SIGSIZE)
340b077aed3SPierre Pronchery && ed_get_params(key, params);
341b077aed3SPierre Pronchery }
342b077aed3SPierre Pronchery
343b077aed3SPierre Pronchery static const OSSL_PARAM ecx_gettable_params[] = {
344b077aed3SPierre Pronchery OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
345b077aed3SPierre Pronchery OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
346b077aed3SPierre Pronchery OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
347b077aed3SPierre Pronchery OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
348b077aed3SPierre Pronchery OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
349b077aed3SPierre Pronchery ECX_KEY_TYPES(),
350b077aed3SPierre Pronchery OSSL_PARAM_END
351b077aed3SPierre Pronchery };
352b077aed3SPierre Pronchery
353b077aed3SPierre Pronchery static const OSSL_PARAM ed_gettable_params[] = {
354b077aed3SPierre Pronchery OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
355b077aed3SPierre Pronchery OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
356b077aed3SPierre Pronchery OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
357b077aed3SPierre Pronchery ECX_KEY_TYPES(),
358b077aed3SPierre Pronchery OSSL_PARAM_END
359b077aed3SPierre Pronchery };
360b077aed3SPierre Pronchery
x25519_gettable_params(void * provctx)361b077aed3SPierre Pronchery static const OSSL_PARAM *x25519_gettable_params(void *provctx)
362b077aed3SPierre Pronchery {
363b077aed3SPierre Pronchery return ecx_gettable_params;
364b077aed3SPierre Pronchery }
365b077aed3SPierre Pronchery
x448_gettable_params(void * provctx)366b077aed3SPierre Pronchery static const OSSL_PARAM *x448_gettable_params(void *provctx)
367b077aed3SPierre Pronchery {
368b077aed3SPierre Pronchery return ecx_gettable_params;
369b077aed3SPierre Pronchery }
370b077aed3SPierre Pronchery
ed25519_gettable_params(void * provctx)371b077aed3SPierre Pronchery static const OSSL_PARAM *ed25519_gettable_params(void *provctx)
372b077aed3SPierre Pronchery {
373b077aed3SPierre Pronchery return ed_gettable_params;
374b077aed3SPierre Pronchery }
375b077aed3SPierre Pronchery
ed448_gettable_params(void * provctx)376b077aed3SPierre Pronchery static const OSSL_PARAM *ed448_gettable_params(void *provctx)
377b077aed3SPierre Pronchery {
378b077aed3SPierre Pronchery return ed_gettable_params;
379b077aed3SPierre Pronchery }
380b077aed3SPierre Pronchery
set_property_query(ECX_KEY * ecxkey,const char * propq)381b077aed3SPierre Pronchery static int set_property_query(ECX_KEY *ecxkey, const char *propq)
382b077aed3SPierre Pronchery {
383b077aed3SPierre Pronchery OPENSSL_free(ecxkey->propq);
384b077aed3SPierre Pronchery ecxkey->propq = NULL;
385b077aed3SPierre Pronchery if (propq != NULL) {
386b077aed3SPierre Pronchery ecxkey->propq = OPENSSL_strdup(propq);
387b077aed3SPierre Pronchery if (ecxkey->propq == NULL) {
388b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
389b077aed3SPierre Pronchery return 0;
390b077aed3SPierre Pronchery }
391b077aed3SPierre Pronchery }
392b077aed3SPierre Pronchery return 1;
393b077aed3SPierre Pronchery }
394b077aed3SPierre Pronchery
ecx_set_params(void * key,const OSSL_PARAM params[])395b077aed3SPierre Pronchery static int ecx_set_params(void *key, const OSSL_PARAM params[])
396b077aed3SPierre Pronchery {
397b077aed3SPierre Pronchery ECX_KEY *ecxkey = key;
398b077aed3SPierre Pronchery const OSSL_PARAM *p;
399b077aed3SPierre Pronchery
400b077aed3SPierre Pronchery if (params == NULL)
401b077aed3SPierre Pronchery return 1;
402b077aed3SPierre Pronchery
403b077aed3SPierre Pronchery p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
404b077aed3SPierre Pronchery if (p != NULL) {
405b077aed3SPierre Pronchery void *buf = ecxkey->pubkey;
406b077aed3SPierre Pronchery
407b077aed3SPierre Pronchery if (p->data_size != ecxkey->keylen
408b077aed3SPierre Pronchery || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
409b077aed3SPierre Pronchery NULL))
410b077aed3SPierre Pronchery return 0;
411b077aed3SPierre Pronchery OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
412b077aed3SPierre Pronchery ecxkey->privkey = NULL;
413b077aed3SPierre Pronchery ecxkey->haspubkey = 1;
414b077aed3SPierre Pronchery }
415b077aed3SPierre Pronchery p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
416b077aed3SPierre Pronchery if (p != NULL) {
417b077aed3SPierre Pronchery if (p->data_type != OSSL_PARAM_UTF8_STRING
418b077aed3SPierre Pronchery || !set_property_query(ecxkey, p->data))
419b077aed3SPierre Pronchery return 0;
420b077aed3SPierre Pronchery }
421b077aed3SPierre Pronchery
422b077aed3SPierre Pronchery return 1;
423b077aed3SPierre Pronchery }
424b077aed3SPierre Pronchery
x25519_set_params(void * key,const OSSL_PARAM params[])425b077aed3SPierre Pronchery static int x25519_set_params(void *key, const OSSL_PARAM params[])
426b077aed3SPierre Pronchery {
427b077aed3SPierre Pronchery return ecx_set_params(key, params);
428b077aed3SPierre Pronchery }
429b077aed3SPierre Pronchery
x448_set_params(void * key,const OSSL_PARAM params[])430b077aed3SPierre Pronchery static int x448_set_params(void *key, const OSSL_PARAM params[])
431b077aed3SPierre Pronchery {
432b077aed3SPierre Pronchery return ecx_set_params(key, params);
433b077aed3SPierre Pronchery }
434b077aed3SPierre Pronchery
ed25519_set_params(void * key,const OSSL_PARAM params[])435b077aed3SPierre Pronchery static int ed25519_set_params(void *key, const OSSL_PARAM params[])
436b077aed3SPierre Pronchery {
437b077aed3SPierre Pronchery return 1;
438b077aed3SPierre Pronchery }
439b077aed3SPierre Pronchery
ed448_set_params(void * key,const OSSL_PARAM params[])440b077aed3SPierre Pronchery static int ed448_set_params(void *key, const OSSL_PARAM params[])
441b077aed3SPierre Pronchery {
442b077aed3SPierre Pronchery return 1;
443b077aed3SPierre Pronchery }
444b077aed3SPierre Pronchery
445b077aed3SPierre Pronchery static const OSSL_PARAM ecx_settable_params[] = {
446b077aed3SPierre Pronchery OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
447b077aed3SPierre Pronchery OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
448b077aed3SPierre Pronchery OSSL_PARAM_END
449b077aed3SPierre Pronchery };
450b077aed3SPierre Pronchery
451b077aed3SPierre Pronchery static const OSSL_PARAM ed_settable_params[] = {
452b077aed3SPierre Pronchery OSSL_PARAM_END
453b077aed3SPierre Pronchery };
454b077aed3SPierre Pronchery
x25519_settable_params(void * provctx)455b077aed3SPierre Pronchery static const OSSL_PARAM *x25519_settable_params(void *provctx)
456b077aed3SPierre Pronchery {
457b077aed3SPierre Pronchery return ecx_settable_params;
458b077aed3SPierre Pronchery }
459b077aed3SPierre Pronchery
x448_settable_params(void * provctx)460b077aed3SPierre Pronchery static const OSSL_PARAM *x448_settable_params(void *provctx)
461b077aed3SPierre Pronchery {
462b077aed3SPierre Pronchery return ecx_settable_params;
463b077aed3SPierre Pronchery }
464b077aed3SPierre Pronchery
ed25519_settable_params(void * provctx)465b077aed3SPierre Pronchery static const OSSL_PARAM *ed25519_settable_params(void *provctx)
466b077aed3SPierre Pronchery {
467b077aed3SPierre Pronchery return ed_settable_params;
468b077aed3SPierre Pronchery }
469b077aed3SPierre Pronchery
ed448_settable_params(void * provctx)470b077aed3SPierre Pronchery static const OSSL_PARAM *ed448_settable_params(void *provctx)
471b077aed3SPierre Pronchery {
472b077aed3SPierre Pronchery return ed_settable_params;
473b077aed3SPierre Pronchery }
474b077aed3SPierre Pronchery
ecx_gen_init(void * provctx,int selection,const OSSL_PARAM params[],ECX_KEY_TYPE type)475b077aed3SPierre Pronchery static void *ecx_gen_init(void *provctx, int selection,
476b077aed3SPierre Pronchery const OSSL_PARAM params[], ECX_KEY_TYPE type)
477b077aed3SPierre Pronchery {
478b077aed3SPierre Pronchery OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
479b077aed3SPierre Pronchery struct ecx_gen_ctx *gctx = NULL;
480b077aed3SPierre Pronchery
481b077aed3SPierre Pronchery if (!ossl_prov_is_running())
482b077aed3SPierre Pronchery return NULL;
483b077aed3SPierre Pronchery
484b077aed3SPierre Pronchery if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
485b077aed3SPierre Pronchery gctx->libctx = libctx;
486b077aed3SPierre Pronchery gctx->type = type;
487b077aed3SPierre Pronchery gctx->selection = selection;
488b077aed3SPierre Pronchery }
489b077aed3SPierre Pronchery if (!ecx_gen_set_params(gctx, params)) {
490b077aed3SPierre Pronchery OPENSSL_free(gctx);
491b077aed3SPierre Pronchery gctx = NULL;
492b077aed3SPierre Pronchery }
493b077aed3SPierre Pronchery return gctx;
494b077aed3SPierre Pronchery }
495b077aed3SPierre Pronchery
x25519_gen_init(void * provctx,int selection,const OSSL_PARAM params[])496b077aed3SPierre Pronchery static void *x25519_gen_init(void *provctx, int selection,
497b077aed3SPierre Pronchery const OSSL_PARAM params[])
498b077aed3SPierre Pronchery {
499b077aed3SPierre Pronchery return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
500b077aed3SPierre Pronchery }
501b077aed3SPierre Pronchery
x448_gen_init(void * provctx,int selection,const OSSL_PARAM params[])502b077aed3SPierre Pronchery static void *x448_gen_init(void *provctx, int selection,
503b077aed3SPierre Pronchery const OSSL_PARAM params[])
504b077aed3SPierre Pronchery {
505b077aed3SPierre Pronchery return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
506b077aed3SPierre Pronchery }
507b077aed3SPierre Pronchery
ed25519_gen_init(void * provctx,int selection,const OSSL_PARAM params[])508b077aed3SPierre Pronchery static void *ed25519_gen_init(void *provctx, int selection,
509b077aed3SPierre Pronchery const OSSL_PARAM params[])
510b077aed3SPierre Pronchery {
511b077aed3SPierre Pronchery return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519);
512b077aed3SPierre Pronchery }
513b077aed3SPierre Pronchery
ed448_gen_init(void * provctx,int selection,const OSSL_PARAM params[])514b077aed3SPierre Pronchery static void *ed448_gen_init(void *provctx, int selection,
515b077aed3SPierre Pronchery const OSSL_PARAM params[])
516b077aed3SPierre Pronchery {
517b077aed3SPierre Pronchery return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448);
518b077aed3SPierre Pronchery }
519b077aed3SPierre Pronchery
ecx_gen_set_params(void * genctx,const OSSL_PARAM params[])520b077aed3SPierre Pronchery static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
521b077aed3SPierre Pronchery {
522b077aed3SPierre Pronchery struct ecx_gen_ctx *gctx = genctx;
523b077aed3SPierre Pronchery const OSSL_PARAM *p;
524b077aed3SPierre Pronchery
525b077aed3SPierre Pronchery if (gctx == NULL)
526b077aed3SPierre Pronchery return 0;
527b077aed3SPierre Pronchery
528b077aed3SPierre Pronchery p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
529b077aed3SPierre Pronchery if (p != NULL) {
530b077aed3SPierre Pronchery const char *groupname = NULL;
531b077aed3SPierre Pronchery
532b077aed3SPierre Pronchery /*
533b077aed3SPierre Pronchery * We optionally allow setting a group name - but each algorithm only
534b077aed3SPierre Pronchery * support one such name, so all we do is verify that it is the one we
535b077aed3SPierre Pronchery * expected.
536b077aed3SPierre Pronchery */
537b077aed3SPierre Pronchery switch (gctx->type) {
538b077aed3SPierre Pronchery case ECX_KEY_TYPE_X25519:
539b077aed3SPierre Pronchery groupname = "x25519";
540b077aed3SPierre Pronchery break;
541b077aed3SPierre Pronchery case ECX_KEY_TYPE_X448:
542b077aed3SPierre Pronchery groupname = "x448";
543b077aed3SPierre Pronchery break;
544b077aed3SPierre Pronchery default:
545b077aed3SPierre Pronchery /* We only support this for key exchange at the moment */
546b077aed3SPierre Pronchery break;
547b077aed3SPierre Pronchery }
548b077aed3SPierre Pronchery if (p->data_type != OSSL_PARAM_UTF8_STRING
549b077aed3SPierre Pronchery || groupname == NULL
550b077aed3SPierre Pronchery || OPENSSL_strcasecmp(p->data, groupname) != 0) {
551b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
552b077aed3SPierre Pronchery return 0;
553b077aed3SPierre Pronchery }
554b077aed3SPierre Pronchery }
555b077aed3SPierre Pronchery p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
556b077aed3SPierre Pronchery if (p != NULL) {
557b077aed3SPierre Pronchery if (p->data_type != OSSL_PARAM_UTF8_STRING)
558b077aed3SPierre Pronchery return 0;
559b077aed3SPierre Pronchery OPENSSL_free(gctx->propq);
560b077aed3SPierre Pronchery gctx->propq = OPENSSL_strdup(p->data);
561b077aed3SPierre Pronchery if (gctx->propq == NULL)
562b077aed3SPierre Pronchery return 0;
563b077aed3SPierre Pronchery }
564b077aed3SPierre Pronchery
565b077aed3SPierre Pronchery return 1;
566b077aed3SPierre Pronchery }
567b077aed3SPierre Pronchery
ecx_gen_settable_params(ossl_unused void * genctx,ossl_unused void * provctx)568b077aed3SPierre Pronchery static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
569b077aed3SPierre Pronchery ossl_unused void *provctx)
570b077aed3SPierre Pronchery {
571b077aed3SPierre Pronchery static OSSL_PARAM settable[] = {
572b077aed3SPierre Pronchery OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
573b077aed3SPierre Pronchery OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
574b077aed3SPierre Pronchery OSSL_PARAM_END
575b077aed3SPierre Pronchery };
576b077aed3SPierre Pronchery return settable;
577b077aed3SPierre Pronchery }
578b077aed3SPierre Pronchery
ecx_gen(struct ecx_gen_ctx * gctx)579b077aed3SPierre Pronchery static void *ecx_gen(struct ecx_gen_ctx *gctx)
580b077aed3SPierre Pronchery {
581b077aed3SPierre Pronchery ECX_KEY *key;
582b077aed3SPierre Pronchery unsigned char *privkey;
583b077aed3SPierre Pronchery
584b077aed3SPierre Pronchery if (gctx == NULL)
585b077aed3SPierre Pronchery return NULL;
586b077aed3SPierre Pronchery if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
587b077aed3SPierre Pronchery gctx->propq)) == NULL) {
588b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
589b077aed3SPierre Pronchery return NULL;
590b077aed3SPierre Pronchery }
591b077aed3SPierre Pronchery
592b077aed3SPierre Pronchery /* If we're doing parameter generation then we just return a blank key */
593b077aed3SPierre Pronchery if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
594b077aed3SPierre Pronchery return key;
595b077aed3SPierre Pronchery
596b077aed3SPierre Pronchery if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
597b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
598b077aed3SPierre Pronchery goto err;
599b077aed3SPierre Pronchery }
600b077aed3SPierre Pronchery if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
601b077aed3SPierre Pronchery goto err;
602b077aed3SPierre Pronchery switch (gctx->type) {
603b077aed3SPierre Pronchery case ECX_KEY_TYPE_X25519:
604b077aed3SPierre Pronchery privkey[0] &= 248;
605b077aed3SPierre Pronchery privkey[X25519_KEYLEN - 1] &= 127;
606b077aed3SPierre Pronchery privkey[X25519_KEYLEN - 1] |= 64;
607b077aed3SPierre Pronchery ossl_x25519_public_from_private(key->pubkey, privkey);
608b077aed3SPierre Pronchery break;
609b077aed3SPierre Pronchery case ECX_KEY_TYPE_X448:
610b077aed3SPierre Pronchery privkey[0] &= 252;
611b077aed3SPierre Pronchery privkey[X448_KEYLEN - 1] |= 128;
612b077aed3SPierre Pronchery ossl_x448_public_from_private(key->pubkey, privkey);
613b077aed3SPierre Pronchery break;
614b077aed3SPierre Pronchery case ECX_KEY_TYPE_ED25519:
615b077aed3SPierre Pronchery if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey,
616b077aed3SPierre Pronchery gctx->propq))
617b077aed3SPierre Pronchery goto err;
618b077aed3SPierre Pronchery break;
619b077aed3SPierre Pronchery case ECX_KEY_TYPE_ED448:
620b077aed3SPierre Pronchery if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey,
621b077aed3SPierre Pronchery gctx->propq))
622b077aed3SPierre Pronchery goto err;
623b077aed3SPierre Pronchery break;
624b077aed3SPierre Pronchery }
625b077aed3SPierre Pronchery key->haspubkey = 1;
626b077aed3SPierre Pronchery return key;
627b077aed3SPierre Pronchery err:
628b077aed3SPierre Pronchery ossl_ecx_key_free(key);
629b077aed3SPierre Pronchery return NULL;
630b077aed3SPierre Pronchery }
631b077aed3SPierre Pronchery
x25519_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)632b077aed3SPierre Pronchery static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
633b077aed3SPierre Pronchery {
634b077aed3SPierre Pronchery struct ecx_gen_ctx *gctx = genctx;
635b077aed3SPierre Pronchery
636b077aed3SPierre Pronchery if (!ossl_prov_is_running())
637b077aed3SPierre Pronchery return 0;
638b077aed3SPierre Pronchery
639b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
640b077aed3SPierre Pronchery if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
641b077aed3SPierre Pronchery return s390x_ecx_keygen25519(gctx);
642b077aed3SPierre Pronchery #endif
643b077aed3SPierre Pronchery return ecx_gen(gctx);
644b077aed3SPierre Pronchery }
645b077aed3SPierre Pronchery
x448_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)646b077aed3SPierre Pronchery static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
647b077aed3SPierre Pronchery {
648b077aed3SPierre Pronchery struct ecx_gen_ctx *gctx = genctx;
649b077aed3SPierre Pronchery
650b077aed3SPierre Pronchery if (!ossl_prov_is_running())
651b077aed3SPierre Pronchery return 0;
652b077aed3SPierre Pronchery
653b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
654b077aed3SPierre Pronchery if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
655b077aed3SPierre Pronchery return s390x_ecx_keygen448(gctx);
656b077aed3SPierre Pronchery #endif
657b077aed3SPierre Pronchery return ecx_gen(gctx);
658b077aed3SPierre Pronchery }
659b077aed3SPierre Pronchery
ed25519_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)660b077aed3SPierre Pronchery static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
661b077aed3SPierre Pronchery {
662b077aed3SPierre Pronchery struct ecx_gen_ctx *gctx = genctx;
663b077aed3SPierre Pronchery
664b077aed3SPierre Pronchery if (!ossl_prov_is_running())
665b077aed3SPierre Pronchery return 0;
666b077aed3SPierre Pronchery
667b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
668b077aed3SPierre Pronchery if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
669b077aed3SPierre Pronchery && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
670b077aed3SPierre Pronchery && OPENSSL_s390xcap_P.kdsa[0]
671b077aed3SPierre Pronchery & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
672b077aed3SPierre Pronchery return s390x_ecd_keygen25519(gctx);
673b077aed3SPierre Pronchery #endif
674b077aed3SPierre Pronchery return ecx_gen(gctx);
675b077aed3SPierre Pronchery }
676b077aed3SPierre Pronchery
ed448_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)677b077aed3SPierre Pronchery static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
678b077aed3SPierre Pronchery {
679b077aed3SPierre Pronchery struct ecx_gen_ctx *gctx = genctx;
680b077aed3SPierre Pronchery
681b077aed3SPierre Pronchery if (!ossl_prov_is_running())
682b077aed3SPierre Pronchery return 0;
683b077aed3SPierre Pronchery
684b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
685b077aed3SPierre Pronchery if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
686b077aed3SPierre Pronchery && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
687b077aed3SPierre Pronchery && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
688b077aed3SPierre Pronchery return s390x_ecd_keygen448(gctx);
689b077aed3SPierre Pronchery #endif
690b077aed3SPierre Pronchery return ecx_gen(gctx);
691b077aed3SPierre Pronchery }
692b077aed3SPierre Pronchery
ecx_gen_cleanup(void * genctx)693b077aed3SPierre Pronchery static void ecx_gen_cleanup(void *genctx)
694b077aed3SPierre Pronchery {
695b077aed3SPierre Pronchery struct ecx_gen_ctx *gctx = genctx;
696b077aed3SPierre Pronchery
697b077aed3SPierre Pronchery OPENSSL_free(gctx->propq);
698b077aed3SPierre Pronchery OPENSSL_free(gctx);
699b077aed3SPierre Pronchery }
700b077aed3SPierre Pronchery
ecx_load(const void * reference,size_t reference_sz)701b077aed3SPierre Pronchery void *ecx_load(const void *reference, size_t reference_sz)
702b077aed3SPierre Pronchery {
703b077aed3SPierre Pronchery ECX_KEY *key = NULL;
704b077aed3SPierre Pronchery
705b077aed3SPierre Pronchery if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
706b077aed3SPierre Pronchery /* The contents of the reference is the address to our object */
707b077aed3SPierre Pronchery key = *(ECX_KEY **)reference;
708b077aed3SPierre Pronchery /* We grabbed, so we detach it */
709b077aed3SPierre Pronchery *(ECX_KEY **)reference = NULL;
710b077aed3SPierre Pronchery return key;
711b077aed3SPierre Pronchery }
712b077aed3SPierre Pronchery return NULL;
713b077aed3SPierre Pronchery }
714b077aed3SPierre Pronchery
ecx_dup(const void * keydata_from,int selection)715b077aed3SPierre Pronchery static void *ecx_dup(const void *keydata_from, int selection)
716b077aed3SPierre Pronchery {
717b077aed3SPierre Pronchery if (ossl_prov_is_running())
718b077aed3SPierre Pronchery return ossl_ecx_key_dup(keydata_from, selection);
719b077aed3SPierre Pronchery return NULL;
720b077aed3SPierre Pronchery }
721b077aed3SPierre Pronchery
ecx_key_pairwise_check(const ECX_KEY * ecx,int type)722b077aed3SPierre Pronchery static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
723b077aed3SPierre Pronchery {
724b077aed3SPierre Pronchery uint8_t pub[64];
725b077aed3SPierre Pronchery
726b077aed3SPierre Pronchery switch (type) {
727b077aed3SPierre Pronchery case ECX_KEY_TYPE_X25519:
728b077aed3SPierre Pronchery ossl_x25519_public_from_private(pub, ecx->privkey);
729b077aed3SPierre Pronchery break;
730b077aed3SPierre Pronchery case ECX_KEY_TYPE_X448:
731b077aed3SPierre Pronchery ossl_x448_public_from_private(pub, ecx->privkey);
732b077aed3SPierre Pronchery break;
733b077aed3SPierre Pronchery case ECX_KEY_TYPE_ED25519:
734b077aed3SPierre Pronchery if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
735b077aed3SPierre Pronchery ecx->propq))
736b077aed3SPierre Pronchery return 0;
737b077aed3SPierre Pronchery break;
738b077aed3SPierre Pronchery case ECX_KEY_TYPE_ED448:
739b077aed3SPierre Pronchery if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
740b077aed3SPierre Pronchery ecx->propq))
741b077aed3SPierre Pronchery return 0;
742b077aed3SPierre Pronchery break;
743b077aed3SPierre Pronchery default:
744b077aed3SPierre Pronchery return 0;
745b077aed3SPierre Pronchery }
746b077aed3SPierre Pronchery return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
747b077aed3SPierre Pronchery }
748b077aed3SPierre Pronchery
ecx_validate(const void * keydata,int selection,int type,size_t keylen)749b077aed3SPierre Pronchery static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
750b077aed3SPierre Pronchery {
751b077aed3SPierre Pronchery const ECX_KEY *ecx = keydata;
752b077aed3SPierre Pronchery int ok = keylen == ecx->keylen;
753b077aed3SPierre Pronchery
754b077aed3SPierre Pronchery if (!ossl_prov_is_running())
755b077aed3SPierre Pronchery return 0;
756b077aed3SPierre Pronchery
757b077aed3SPierre Pronchery if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
758b077aed3SPierre Pronchery return 1; /* nothing to validate */
759b077aed3SPierre Pronchery
760b077aed3SPierre Pronchery if (!ok) {
761b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
762b077aed3SPierre Pronchery return 0;
763b077aed3SPierre Pronchery }
764b077aed3SPierre Pronchery
765b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
766b077aed3SPierre Pronchery ok = ok && ecx->haspubkey;
767b077aed3SPierre Pronchery
768b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
769b077aed3SPierre Pronchery ok = ok && ecx->privkey != NULL;
770b077aed3SPierre Pronchery
771b077aed3SPierre Pronchery if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
772b077aed3SPierre Pronchery ok = ok && ecx_key_pairwise_check(ecx, type);
773b077aed3SPierre Pronchery
774b077aed3SPierre Pronchery return ok;
775b077aed3SPierre Pronchery }
776b077aed3SPierre Pronchery
x25519_validate(const void * keydata,int selection,int checktype)777b077aed3SPierre Pronchery static int x25519_validate(const void *keydata, int selection, int checktype)
778b077aed3SPierre Pronchery {
779b077aed3SPierre Pronchery return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
780b077aed3SPierre Pronchery }
781b077aed3SPierre Pronchery
x448_validate(const void * keydata,int selection,int checktype)782b077aed3SPierre Pronchery static int x448_validate(const void *keydata, int selection, int checktype)
783b077aed3SPierre Pronchery {
784b077aed3SPierre Pronchery return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
785b077aed3SPierre Pronchery }
786b077aed3SPierre Pronchery
ed25519_validate(const void * keydata,int selection,int checktype)787b077aed3SPierre Pronchery static int ed25519_validate(const void *keydata, int selection, int checktype)
788b077aed3SPierre Pronchery {
789b077aed3SPierre Pronchery return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
790b077aed3SPierre Pronchery }
791b077aed3SPierre Pronchery
ed448_validate(const void * keydata,int selection,int checktype)792b077aed3SPierre Pronchery static int ed448_validate(const void *keydata, int selection, int checktype)
793b077aed3SPierre Pronchery {
794b077aed3SPierre Pronchery return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
795b077aed3SPierre Pronchery }
796b077aed3SPierre Pronchery
797b077aed3SPierre Pronchery #define MAKE_KEYMGMT_FUNCTIONS(alg) \
798b077aed3SPierre Pronchery const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
799b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
800b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
801b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
802b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
803b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
804b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
805b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
806b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
807b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
808b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
809b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
810b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
811b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
812b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
813b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
814b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
815b077aed3SPierre Pronchery (void (*)(void))ecx_gen_settable_params }, \
816b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
817b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
818b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
819b077aed3SPierre Pronchery { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
820b077aed3SPierre Pronchery { 0, NULL } \
821b077aed3SPierre Pronchery };
822b077aed3SPierre Pronchery
823b077aed3SPierre Pronchery MAKE_KEYMGMT_FUNCTIONS(x25519)
MAKE_KEYMGMT_FUNCTIONS(x448)824b077aed3SPierre Pronchery MAKE_KEYMGMT_FUNCTIONS(x448)
825b077aed3SPierre Pronchery MAKE_KEYMGMT_FUNCTIONS(ed25519)
826b077aed3SPierre Pronchery MAKE_KEYMGMT_FUNCTIONS(ed448)
827b077aed3SPierre Pronchery
828b077aed3SPierre Pronchery #ifdef S390X_EC_ASM
829b077aed3SPierre Pronchery # include "s390x_arch.h"
830b077aed3SPierre Pronchery
831b077aed3SPierre Pronchery static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
832b077aed3SPierre Pronchery {
833b077aed3SPierre Pronchery static const unsigned char generator[] = {
834b077aed3SPierre Pronchery 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
835b077aed3SPierre Pronchery 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
836b077aed3SPierre Pronchery 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
837b077aed3SPierre Pronchery };
838b077aed3SPierre Pronchery ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
839b077aed3SPierre Pronchery gctx->propq);
840b077aed3SPierre Pronchery unsigned char *privkey = NULL, *pubkey;
841b077aed3SPierre Pronchery
842b077aed3SPierre Pronchery if (key == NULL) {
843b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
844b077aed3SPierre Pronchery goto err;
845b077aed3SPierre Pronchery }
846b077aed3SPierre Pronchery
847b077aed3SPierre Pronchery /* If we're doing parameter generation then we just return a blank key */
848b077aed3SPierre Pronchery if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
849b077aed3SPierre Pronchery return key;
850b077aed3SPierre Pronchery
851b077aed3SPierre Pronchery pubkey = key->pubkey;
852b077aed3SPierre Pronchery
853b077aed3SPierre Pronchery privkey = ossl_ecx_key_allocate_privkey(key);
854b077aed3SPierre Pronchery if (privkey == NULL) {
855b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
856b077aed3SPierre Pronchery goto err;
857b077aed3SPierre Pronchery }
858b077aed3SPierre Pronchery
859b077aed3SPierre Pronchery if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
860b077aed3SPierre Pronchery goto err;
861b077aed3SPierre Pronchery
862b077aed3SPierre Pronchery privkey[0] &= 248;
863b077aed3SPierre Pronchery privkey[31] &= 127;
864b077aed3SPierre Pronchery privkey[31] |= 64;
865b077aed3SPierre Pronchery
866b077aed3SPierre Pronchery if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
867b077aed3SPierre Pronchery goto err;
868b077aed3SPierre Pronchery key->haspubkey = 1;
869b077aed3SPierre Pronchery return key;
870b077aed3SPierre Pronchery err:
871b077aed3SPierre Pronchery ossl_ecx_key_free(key);
872b077aed3SPierre Pronchery return NULL;
873b077aed3SPierre Pronchery }
874b077aed3SPierre Pronchery
s390x_ecx_keygen448(struct ecx_gen_ctx * gctx)875b077aed3SPierre Pronchery static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
876b077aed3SPierre Pronchery {
877b077aed3SPierre Pronchery static const unsigned char generator[] = {
878b077aed3SPierre Pronchery 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
879b077aed3SPierre Pronchery 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
880b077aed3SPierre Pronchery 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
881b077aed3SPierre Pronchery 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
882b077aed3SPierre Pronchery 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
883b077aed3SPierre Pronchery };
884b077aed3SPierre Pronchery ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
885b077aed3SPierre Pronchery gctx->propq);
886b077aed3SPierre Pronchery unsigned char *privkey = NULL, *pubkey;
887b077aed3SPierre Pronchery
888b077aed3SPierre Pronchery if (key == NULL) {
889b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
890b077aed3SPierre Pronchery goto err;
891b077aed3SPierre Pronchery }
892b077aed3SPierre Pronchery
893b077aed3SPierre Pronchery /* If we're doing parameter generation then we just return a blank key */
894b077aed3SPierre Pronchery if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
895b077aed3SPierre Pronchery return key;
896b077aed3SPierre Pronchery
897b077aed3SPierre Pronchery pubkey = key->pubkey;
898b077aed3SPierre Pronchery
899b077aed3SPierre Pronchery privkey = ossl_ecx_key_allocate_privkey(key);
900b077aed3SPierre Pronchery if (privkey == NULL) {
901b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
902b077aed3SPierre Pronchery goto err;
903b077aed3SPierre Pronchery }
904b077aed3SPierre Pronchery
905b077aed3SPierre Pronchery if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
906b077aed3SPierre Pronchery goto err;
907b077aed3SPierre Pronchery
908b077aed3SPierre Pronchery privkey[0] &= 252;
909b077aed3SPierre Pronchery privkey[55] |= 128;
910b077aed3SPierre Pronchery
911b077aed3SPierre Pronchery if (s390x_x448_mul(pubkey, generator, privkey) != 1)
912b077aed3SPierre Pronchery goto err;
913b077aed3SPierre Pronchery key->haspubkey = 1;
914b077aed3SPierre Pronchery return key;
915b077aed3SPierre Pronchery err:
916b077aed3SPierre Pronchery ossl_ecx_key_free(key);
917b077aed3SPierre Pronchery return NULL;
918b077aed3SPierre Pronchery }
919b077aed3SPierre Pronchery
s390x_ecd_keygen25519(struct ecx_gen_ctx * gctx)920b077aed3SPierre Pronchery static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
921b077aed3SPierre Pronchery {
922b077aed3SPierre Pronchery static const unsigned char generator_x[] = {
923b077aed3SPierre Pronchery 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
924b077aed3SPierre Pronchery 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
925b077aed3SPierre Pronchery 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
926b077aed3SPierre Pronchery };
927b077aed3SPierre Pronchery static const unsigned char generator_y[] = {
928b077aed3SPierre Pronchery 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
929b077aed3SPierre Pronchery 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
930b077aed3SPierre Pronchery 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
931b077aed3SPierre Pronchery };
932b077aed3SPierre Pronchery unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
933b077aed3SPierre Pronchery ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
934b077aed3SPierre Pronchery gctx->propq);
935b077aed3SPierre Pronchery unsigned char *privkey = NULL, *pubkey;
936b077aed3SPierre Pronchery unsigned int sz;
937b077aed3SPierre Pronchery EVP_MD *sha = NULL;
938b077aed3SPierre Pronchery int j;
939b077aed3SPierre Pronchery
940b077aed3SPierre Pronchery if (key == NULL) {
941b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
942b077aed3SPierre Pronchery goto err;
943b077aed3SPierre Pronchery }
944b077aed3SPierre Pronchery
945b077aed3SPierre Pronchery /* If we're doing parameter generation then we just return a blank key */
946b077aed3SPierre Pronchery if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
947b077aed3SPierre Pronchery return key;
948b077aed3SPierre Pronchery
949b077aed3SPierre Pronchery pubkey = key->pubkey;
950b077aed3SPierre Pronchery
951b077aed3SPierre Pronchery privkey = ossl_ecx_key_allocate_privkey(key);
952b077aed3SPierre Pronchery if (privkey == NULL) {
953b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
954b077aed3SPierre Pronchery goto err;
955b077aed3SPierre Pronchery }
956b077aed3SPierre Pronchery
957b077aed3SPierre Pronchery if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
958b077aed3SPierre Pronchery goto err;
959b077aed3SPierre Pronchery
960b077aed3SPierre Pronchery sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
961b077aed3SPierre Pronchery if (sha == NULL)
962b077aed3SPierre Pronchery goto err;
963b077aed3SPierre Pronchery j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
964b077aed3SPierre Pronchery EVP_MD_free(sha);
965b077aed3SPierre Pronchery if (!j)
966b077aed3SPierre Pronchery goto err;
967b077aed3SPierre Pronchery
968b077aed3SPierre Pronchery buff[0] &= 248;
969b077aed3SPierre Pronchery buff[31] &= 63;
970b077aed3SPierre Pronchery buff[31] |= 64;
971b077aed3SPierre Pronchery
972b077aed3SPierre Pronchery if (s390x_ed25519_mul(x_dst, pubkey,
973b077aed3SPierre Pronchery generator_x, generator_y, buff) != 1)
974b077aed3SPierre Pronchery goto err;
975b077aed3SPierre Pronchery
976b077aed3SPierre Pronchery pubkey[31] |= ((x_dst[0] & 0x01) << 7);
977b077aed3SPierre Pronchery key->haspubkey = 1;
978b077aed3SPierre Pronchery return key;
979b077aed3SPierre Pronchery err:
980b077aed3SPierre Pronchery ossl_ecx_key_free(key);
981b077aed3SPierre Pronchery return NULL;
982b077aed3SPierre Pronchery }
983b077aed3SPierre Pronchery
s390x_ecd_keygen448(struct ecx_gen_ctx * gctx)984b077aed3SPierre Pronchery static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
985b077aed3SPierre Pronchery {
986b077aed3SPierre Pronchery static const unsigned char generator_x[] = {
987b077aed3SPierre Pronchery 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
988b077aed3SPierre Pronchery 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
989b077aed3SPierre Pronchery 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
990b077aed3SPierre Pronchery 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
991b077aed3SPierre Pronchery 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
992b077aed3SPierre Pronchery };
993b077aed3SPierre Pronchery static const unsigned char generator_y[] = {
994b077aed3SPierre Pronchery 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
995b077aed3SPierre Pronchery 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
996b077aed3SPierre Pronchery 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
997b077aed3SPierre Pronchery 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
998b077aed3SPierre Pronchery 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
999b077aed3SPierre Pronchery };
1000b077aed3SPierre Pronchery unsigned char x_dst[57], buff[114];
1001b077aed3SPierre Pronchery ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
1002b077aed3SPierre Pronchery gctx->propq);
1003b077aed3SPierre Pronchery unsigned char *privkey = NULL, *pubkey;
1004b077aed3SPierre Pronchery EVP_MD_CTX *hashctx = NULL;
1005b077aed3SPierre Pronchery EVP_MD *shake = NULL;
1006b077aed3SPierre Pronchery
1007b077aed3SPierre Pronchery if (key == NULL) {
1008b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
1009b077aed3SPierre Pronchery goto err;
1010b077aed3SPierre Pronchery }
1011b077aed3SPierre Pronchery
1012b077aed3SPierre Pronchery /* If we're doing parameter generation then we just return a blank key */
1013b077aed3SPierre Pronchery if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1014b077aed3SPierre Pronchery return key;
1015b077aed3SPierre Pronchery
1016b077aed3SPierre Pronchery pubkey = key->pubkey;
1017b077aed3SPierre Pronchery
1018b077aed3SPierre Pronchery privkey = ossl_ecx_key_allocate_privkey(key);
1019b077aed3SPierre Pronchery if (privkey == NULL) {
1020b077aed3SPierre Pronchery ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
1021b077aed3SPierre Pronchery goto err;
1022b077aed3SPierre Pronchery }
1023b077aed3SPierre Pronchery
1024b077aed3SPierre Pronchery shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1025b077aed3SPierre Pronchery if (shake == NULL)
1026b077aed3SPierre Pronchery goto err;
1027b077aed3SPierre Pronchery if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1028b077aed3SPierre Pronchery goto err;
1029b077aed3SPierre Pronchery
1030b077aed3SPierre Pronchery hashctx = EVP_MD_CTX_new();
1031b077aed3SPierre Pronchery if (hashctx == NULL)
1032b077aed3SPierre Pronchery goto err;
1033b077aed3SPierre Pronchery if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1034b077aed3SPierre Pronchery goto err;
1035b077aed3SPierre Pronchery if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1036b077aed3SPierre Pronchery goto err;
1037b077aed3SPierre Pronchery if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1038b077aed3SPierre Pronchery goto err;
1039b077aed3SPierre Pronchery
1040b077aed3SPierre Pronchery buff[0] &= -4;
1041b077aed3SPierre Pronchery buff[55] |= 0x80;
1042b077aed3SPierre Pronchery buff[56] = 0;
1043b077aed3SPierre Pronchery
1044b077aed3SPierre Pronchery if (s390x_ed448_mul(x_dst, pubkey,
1045b077aed3SPierre Pronchery generator_x, generator_y, buff) != 1)
1046b077aed3SPierre Pronchery goto err;
1047b077aed3SPierre Pronchery
1048b077aed3SPierre Pronchery pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1049b077aed3SPierre Pronchery EVP_MD_CTX_free(hashctx);
1050b077aed3SPierre Pronchery EVP_MD_free(shake);
1051b077aed3SPierre Pronchery key->haspubkey = 1;
1052b077aed3SPierre Pronchery return key;
1053b077aed3SPierre Pronchery err:
1054b077aed3SPierre Pronchery ossl_ecx_key_free(key);
1055b077aed3SPierre Pronchery EVP_MD_CTX_free(hashctx);
1056b077aed3SPierre Pronchery EVP_MD_free(shake);
1057b077aed3SPierre Pronchery return NULL;
1058b077aed3SPierre Pronchery }
1059b077aed3SPierre Pronchery #endif
1060