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