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