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