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