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