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