]> git.ipfire.org Git - thirdparty/openssl.git/blame - providers/implementations/keymgmt/ecx_kmgmt.c
Update copyright year
[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;
7c664b1f 44static OSSL_FUNC_keymgmt_load_fn ecx_load;
363b1e5d
DMSP
45static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
46static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
47static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
48static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
49static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
50static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
51static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
52static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
53static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
54static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
55static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
56static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
57static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
58static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
59static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
60static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
61static OSSL_FUNC_keymgmt_has_fn ecx_has;
62static OSSL_FUNC_keymgmt_match_fn ecx_match;
f0591559
SL
63static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
64static OSSL_FUNC_keymgmt_validate_fn x448_validate;
65static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
66static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
363b1e5d
DMSP
67static OSSL_FUNC_keymgmt_import_fn ecx_import;
68static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
69static OSSL_FUNC_keymgmt_export_fn ecx_export;
70static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
90d3cb57 71
f552d900
SL
72#define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
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;
a829b735 92 return ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
8dbef010 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;
a829b735 100 return ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0,
8dbef010 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;
a829b735 108 return ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0,
8dbef010 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;
a829b735 116 return ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0,
8dbef010 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);
969024b4 187 ok = ok && 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
5ac8fb58 376 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
6a9bd929
MC
377 if (p != NULL) {
378 void *buf = ecxkey->pubkey;
379
380 if (p->data_size != ecxkey->keylen
381 || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
382 NULL))
383 return 0;
384 OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
385 ecxkey->privkey = NULL;
386 ecxkey->haspubkey = 1;
387 }
8dbef010
SL
388 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
389 if (p != NULL) {
390 if (p->data_type != OSSL_PARAM_UTF8_STRING
391 || !set_property_query(ecxkey, p->data))
392 return 0;
393 }
6a9bd929
MC
394
395 return 1;
396}
397
398static int x25519_set_params(void *key, const OSSL_PARAM params[])
399{
400 return ecx_set_params(key, params);
401}
402
403static int x448_set_params(void *key, const OSSL_PARAM params[])
404{
405 return ecx_set_params(key, params);
406}
407
408static int ed25519_set_params(void *key, const OSSL_PARAM params[])
409{
410 return 1;
411}
412
413static int ed448_set_params(void *key, const OSSL_PARAM params[])
414{
415 return 1;
416}
417
418static const OSSL_PARAM ecx_settable_params[] = {
5ac8fb58 419 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
8dbef010 420 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
6a9bd929
MC
421 OSSL_PARAM_END
422};
423
424static const OSSL_PARAM ed_settable_params[] = {
425 OSSL_PARAM_END
426};
427
af5e1e85 428static const OSSL_PARAM *x25519_settable_params(void *provctx)
6a9bd929
MC
429{
430 return ecx_settable_params;
431}
432
af5e1e85 433static const OSSL_PARAM *x448_settable_params(void *provctx)
6a9bd929
MC
434{
435 return ecx_settable_params;
436}
437
af5e1e85 438static const OSSL_PARAM *ed25519_settable_params(void *provctx)
6a9bd929
MC
439{
440 return ed_settable_params;
441}
442
af5e1e85 443static const OSSL_PARAM *ed448_settable_params(void *provctx)
6a9bd929
MC
444{
445 return ed_settable_params;
1a7328c8
RL
446}
447
43cd3701
P
448static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type)
449{
a829b735 450 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
43cd3701
P
451 struct ecx_gen_ctx *gctx = NULL;
452
422cbcee
P
453 if (!ossl_prov_is_running())
454 return NULL;
455
8dbef010 456 if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
43cd3701
P
457 gctx->libctx = libctx;
458 gctx->type = type;
381f3f3b 459 gctx->selection = selection;
43cd3701
P
460 }
461 return gctx;
462}
463
464static void *x25519_gen_init(void *provctx, int selection)
465{
466 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X25519);
467}
468
469static void *x448_gen_init(void *provctx, int selection)
470{
471 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X448);
472}
473
474static void *ed25519_gen_init(void *provctx, int selection)
475{
476 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED25519);
477}
478
479static void *ed448_gen_init(void *provctx, int selection)
480{
481 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448);
482}
483
381f3f3b
MC
484static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
485{
486 struct ecx_gen_ctx *gctx = genctx;
487 const OSSL_PARAM *p;
488
489 if (gctx == NULL)
490 return 0;
491
492 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
493 if (p != NULL) {
494 const char *groupname = NULL;
495
496 /*
497 * We optionally allow setting a group name - but each algorithm only
498 * support one such name, so all we do is verify that it is the one we
499 * expected.
500 */
501 switch (gctx->type) {
502 case ECX_KEY_TYPE_X25519:
503 groupname = "x25519";
504 break;
505 case ECX_KEY_TYPE_X448:
506 groupname = "x448";
507 break;
508 default:
509 /* We only support this for key exchange at the moment */
510 break;
511 }
512 if (p->data_type != OSSL_PARAM_UTF8_STRING
513 || groupname == NULL
514 || strcasecmp(p->data, groupname) != 0) {
515 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
516 return 0;
517 }
518 }
8dbef010
SL
519 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
520 if (p != NULL) {
521 if (p->data_type != OSSL_PARAM_UTF8_STRING)
522 return 0;
523 OPENSSL_free(gctx->propq);
524 gctx->propq = OPENSSL_strdup(p->data);
525 if (gctx->propq == NULL)
526 return 0;
527 }
381f3f3b
MC
528
529 return 1;
530}
531
532static const OSSL_PARAM *ecx_gen_settable_params(void *provctx)
533{
534 static OSSL_PARAM settable[] = {
535 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
8dbef010 536 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
381f3f3b
MC
537 OSSL_PARAM_END
538 };
539 return settable;
540}
541
43cd3701
P
542static void *ecx_gen(struct ecx_gen_ctx *gctx)
543{
544 ECX_KEY *key;
545 unsigned char *privkey;
546
c1e48c51
P
547 if (gctx == NULL)
548 return NULL;
8dbef010 549 if ((key = ecx_key_new(gctx->libctx, gctx->type, 0, gctx->propq)) == NULL) {
c1e48c51 550 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
43cd3701 551 return NULL;
c1e48c51 552 }
381f3f3b
MC
553
554 /* If we're doing parameter generation then we just return a blank key */
555 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
556 return key;
557
c1e48c51
P
558 if ((privkey = ecx_key_allocate_privkey(key)) == NULL) {
559 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
560 goto err;
561 }
562 if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0)
43cd3701
P
563 goto err;
564 switch (gctx->type) {
565 case ECX_KEY_TYPE_X25519:
566 privkey[0] &= 248;
567 privkey[X25519_KEYLEN - 1] &= 127;
568 privkey[X25519_KEYLEN - 1] |= 64;
569 X25519_public_from_private(key->pubkey, privkey);
570 break;
571 case ECX_KEY_TYPE_X448:
572 privkey[0] &= 252;
573 privkey[X448_KEYLEN - 1] |= 128;
574 X448_public_from_private(key->pubkey, privkey);
575 break;
576 case ECX_KEY_TYPE_ED25519:
8dbef010
SL
577 if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey,
578 gctx->propq))
43cd3701
P
579 goto err;
580 break;
581 case ECX_KEY_TYPE_ED448:
8dbef010
SL
582 if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey,
583 gctx->propq))
43cd3701
P
584 goto err;
585 break;
586 }
381f3f3b 587 key->haspubkey = 1;
43cd3701
P
588 return key;
589err:
590 ecx_key_free(key);
591 return NULL;
592}
593
594static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
595{
596 struct ecx_gen_ctx *gctx = genctx;
597
422cbcee
P
598 if (!ossl_prov_is_running())
599 return 0;
600
43cd3701
P
601#ifdef S390X_EC_ASM
602 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
603 return s390x_ecx_keygen25519(gctx);
604#endif
605 return ecx_gen(gctx);
606}
607
608static void *x448_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_X448))
617 return s390x_ecx_keygen448(gctx);
618#endif
619 return ecx_gen(gctx);
620}
621
622static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
623{
624 struct ecx_gen_ctx *gctx = genctx;
422cbcee
P
625
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_ED25519)
631 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
632 && OPENSSL_s390xcap_P.kdsa[0]
633 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
634 return s390x_ecd_keygen25519(gctx);
635#endif
636 return ecx_gen(gctx);
637}
638
639static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
640{
641 struct ecx_gen_ctx *gctx = genctx;
642
422cbcee
P
643 if (!ossl_prov_is_running())
644 return 0;
645
43cd3701
P
646#ifdef S390X_EC_ASM
647 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
648 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
649 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
650 return s390x_ecd_keygen448(gctx);
651#endif
652 return ecx_gen(gctx);
653}
654
655static void ecx_gen_cleanup(void *genctx)
656{
657 struct ecx_gen_ctx *gctx = genctx;
658
8dbef010 659 OPENSSL_free(gctx->propq);
43cd3701
P
660 OPENSSL_free(gctx);
661}
662
7c664b1f
RL
663void *ecx_load(const void *reference, size_t reference_sz)
664{
665 ECX_KEY *key = NULL;
666
422cbcee 667 if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
7c664b1f
RL
668 /* The contents of the reference is the address to our object */
669 key = *(ECX_KEY **)reference;
670 /* We grabbed, so we detach it */
671 *(ECX_KEY **)reference = NULL;
672 return key;
673 }
674 return NULL;
675}
676
f0591559
SL
677static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
678{
679 uint8_t pub[64];
680
681 switch (type) {
682 case ECX_KEY_TYPE_X25519:
683 X25519_public_from_private(pub, ecx->privkey);
684 break;
685 case ECX_KEY_TYPE_X448:
686 X448_public_from_private(pub, ecx->privkey);
687 break;
688 case ECX_KEY_TYPE_ED25519:
689 if (!ED25519_public_from_private(ecx->libctx, pub, ecx->privkey,
690 ecx->propq))
691 return 0;
692 break;
693 case ECX_KEY_TYPE_ED448:
694 if (!ED448_public_from_private(ecx->libctx, pub, ecx->privkey,
695 ecx->propq))
696 return 0;
697 break;
698 default:
699 return 0;
700 }
701 return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
702}
703
704static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
705{
706 const ECX_KEY *ecx = keydata;
707 int ok = 0;
708
709 if (!ossl_prov_is_running())
710 return 0;
711
712 assert(keylen == ecx->keylen);
713
714 if ((selection & ECX_POSSIBLE_SELECTIONS) != 0)
715 ok = 1;
716
717 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
718 ok = ok && ecx->haspubkey;
719
720 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
721 ok = ok && ecx->privkey != NULL;
722
723 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
724 ok = ok && ecx_key_pairwise_check(ecx, type);
725
726 return ok;
727}
728
899e2564 729static int x25519_validate(const void *keydata, int selection, int checktype)
f0591559
SL
730{
731 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
732}
733
899e2564 734static int x448_validate(const void *keydata, int selection, int checktype)
f0591559
SL
735{
736 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
737}
738
899e2564 739static int ed25519_validate(const void *keydata, int selection, int checktype)
f0591559
SL
740{
741 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
742}
743
899e2564 744static int ed448_validate(const void *keydata, int selection, int checktype)
f0591559
SL
745{
746 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
747}
748
af6d8dd3 749#define MAKE_KEYMGMT_FUNCTIONS(alg) \
1be63951 750 const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
af6d8dd3
MC
751 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
752 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, \
753 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
1a7328c8 754 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
6a9bd929
MC
755 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
756 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
af6d8dd3 757 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
262ff123 758 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
f0591559 759 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
af6d8dd3
MC
760 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
761 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
762 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
763 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
43cd3701 764 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
381f3f3b
MC
765 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
766 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
767 (void (*)(void))ecx_gen_settable_params }, \
43cd3701
P
768 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
769 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
7c664b1f 770 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
af6d8dd3
MC
771 { 0, NULL } \
772 };
773
774MAKE_KEYMGMT_FUNCTIONS(x25519)
775MAKE_KEYMGMT_FUNCTIONS(x448)
776MAKE_KEYMGMT_FUNCTIONS(ed25519)
777MAKE_KEYMGMT_FUNCTIONS(ed448)
43cd3701
P
778
779#ifdef S390X_EC_ASM
780# include "s390x_arch.h"
43cd3701
P
781
782static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
783{
784 static const unsigned char generator[] = {
785 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
788 };
8dbef010 789 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1, gctx->propq);
43cd3701
P
790 unsigned char *privkey = NULL, *pubkey;
791
792 if (key == NULL) {
c1e48c51 793 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
43cd3701
P
794 goto err;
795 }
796
381f3f3b
MC
797 /* If we're doing parameter generation then we just return a blank key */
798 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
799 return key;
800
43cd3701
P
801 pubkey = key->pubkey;
802
803 privkey = ecx_key_allocate_privkey(key);
804 if (privkey == NULL) {
c1e48c51 805 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
43cd3701
P
806 goto err;
807 }
808
c1e48c51 809 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN) <= 0)
43cd3701
P
810 goto err;
811
812 privkey[0] &= 248;
813 privkey[31] &= 127;
814 privkey[31] |= 64;
815
816 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
817 goto err;
381f3f3b 818 key->haspubkey = 1;
43cd3701
P
819 return key;
820 err:
821 ecx_key_free(key);
822 return NULL;
823}
824
825static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
826{
827 static const unsigned char generator[] = {
828 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
833 };
8dbef010 834 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1, gctx->propq);
43cd3701
P
835 unsigned char *privkey = NULL, *pubkey;
836
837 if (key == NULL) {
c1e48c51 838 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
43cd3701
P
839 goto err;
840 }
841
381f3f3b
MC
842 /* If we're doing parameter generation then we just return a blank key */
843 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
844 return key;
845
43cd3701
P
846 pubkey = key->pubkey;
847
848 privkey = ecx_key_allocate_privkey(key);
849 if (privkey == NULL) {
c1e48c51 850 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
43cd3701
P
851 goto err;
852 }
853
c1e48c51 854 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN) <= 0)
43cd3701
P
855 goto err;
856
857 privkey[0] &= 252;
858 privkey[55] |= 128;
859
860 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
861 goto err;
381f3f3b 862 key->haspubkey = 1;
43cd3701
P
863 return key;
864 err:
865 ecx_key_free(key);
866 return NULL;
867}
868
869static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
870{
871 static const unsigned char generator_x[] = {
872 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
873 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
874 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
875 };
876 static const unsigned char generator_y[] = {
877 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
878 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
879 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
880 };
881 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
8dbef010 882 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1, gctx->propq);
43cd3701
P
883 unsigned char *privkey = NULL, *pubkey;
884 unsigned int sz;
c1e48c51
P
885 EVP_MD *sha = NULL;
886 int j;
43cd3701
P
887
888 if (key == NULL) {
c1e48c51 889 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
43cd3701
P
890 goto err;
891 }
892
381f3f3b
MC
893 /* If we're doing parameter generation then we just return a blank key */
894 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
895 return key;
896
43cd3701
P
897 pubkey = key->pubkey;
898
899 privkey = ecx_key_allocate_privkey(key);
900 if (privkey == NULL) {
c1e48c51 901 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
43cd3701
P
902 goto err;
903 }
904
c1e48c51 905 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN) <= 0)
43cd3701
P
906 goto err;
907
8dbef010 908 sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
c1e48c51
P
909 if (sha == NULL)
910 goto err;
911 j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
912 EVP_MD_free(sha);
913 if (!j)
43cd3701
P
914 goto err;
915
916 buff[0] &= 248;
917 buff[31] &= 63;
918 buff[31] |= 64;
919
920 if (s390x_ed25519_mul(x_dst, pubkey,
921 generator_x, generator_y, buff) != 1)
922 goto err;
923
924 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
381f3f3b 925 key->haspubkey = 1;
43cd3701
P
926 return key;
927 err:
928 ecx_key_free(key);
929 return NULL;
930}
931
932static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
933{
934 static const unsigned char generator_x[] = {
935 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
936 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
937 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
938 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
939 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
940 };
941 static const unsigned char generator_y[] = {
942 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
943 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
944 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
945 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
946 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
947 };
948 unsigned char x_dst[57], buff[114];
8dbef010 949 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1, gctx->propq);
43cd3701
P
950 unsigned char *privkey = NULL, *pubkey;
951 EVP_MD_CTX *hashctx = NULL;
c1e48c51 952 EVP_MD *shake = NULL;
43cd3701
P
953
954 if (key == NULL) {
c1e48c51 955 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
43cd3701
P
956 goto err;
957 }
958
381f3f3b
MC
959 /* If we're doing parameter generation then we just return a blank key */
960 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
961 return key;
962
43cd3701
P
963 pubkey = key->pubkey;
964
965 privkey = ecx_key_allocate_privkey(key);
966 if (privkey == NULL) {
c1e48c51 967 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
43cd3701
P
968 goto err;
969 }
970
8dbef010 971 shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
c1e48c51
P
972 if (shake == NULL)
973 goto err;
974 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN) <= 0)
43cd3701
P
975 goto err;
976
977 hashctx = EVP_MD_CTX_new();
978 if (hashctx == NULL)
979 goto err;
c1e48c51 980 if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
43cd3701
P
981 goto err;
982 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
983 goto err;
984 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
985 goto err;
986
987 buff[0] &= -4;
988 buff[55] |= 0x80;
989 buff[56] = 0;
990
991 if (s390x_ed448_mul(x_dst, pubkey,
992 generator_x, generator_y, buff) != 1)
993 goto err;
994
995 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
43cd3701 996 EVP_MD_CTX_free(hashctx);
c1e48c51 997 EVP_MD_free(shake);
381f3f3b 998 key->haspubkey = 1;
43cd3701
P
999 return key;
1000 err:
1001 ecx_key_free(key);
1002 EVP_MD_CTX_free(hashctx);
c1e48c51 1003 EVP_MD_free(shake);
43cd3701
P
1004 return NULL;
1005}
1006#endif