]> git.ipfire.org Git - thirdparty/openssl.git/blob - providers/implementations/keymgmt/ecx_kmgmt.c
Implement PCT for EDDSA
[thirdparty/openssl.git] / providers / implementations / keymgmt / ecx_kmgmt.c
1 /*
2 * Copyright 2020-2024 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 #include <openssl/core_dispatch.h>
13 #include <openssl/core_names.h>
14 #include <openssl/params.h>
15 #include <openssl/err.h>
16 #include <openssl/proverr.h>
17 #include <openssl/evp.h>
18 #include <openssl/rand.h>
19 #include <openssl/self_test.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 #include "prov/ecx.h"
27 #ifdef S390X_EC_ASM
28 # include "s390x_arch.h"
29 # include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
30 #endif
31
32 static OSSL_FUNC_keymgmt_new_fn x25519_new_key;
33 static OSSL_FUNC_keymgmt_new_fn x448_new_key;
34 static OSSL_FUNC_keymgmt_new_fn ed25519_new_key;
35 static OSSL_FUNC_keymgmt_new_fn ed448_new_key;
36 static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init;
37 static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init;
38 static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init;
39 static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init;
40 static OSSL_FUNC_keymgmt_gen_fn x25519_gen;
41 static OSSL_FUNC_keymgmt_gen_fn x448_gen;
42 static OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
43 static OSSL_FUNC_keymgmt_gen_fn ed448_gen;
44 static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
45 static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params;
46 static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params;
47 static OSSL_FUNC_keymgmt_load_fn ecx_load;
48 static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
49 static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
50 static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
51 static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
52 static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
53 static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
54 static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
55 static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
56 static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
57 static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
58 static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
59 static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
60 static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
61 static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
62 static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
63 static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
64 static OSSL_FUNC_keymgmt_has_fn ecx_has;
65 static OSSL_FUNC_keymgmt_match_fn ecx_match;
66 static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
67 static OSSL_FUNC_keymgmt_validate_fn x448_validate;
68 static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
69 static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
70 static OSSL_FUNC_keymgmt_import_fn ecx_import;
71 static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
72 static OSSL_FUNC_keymgmt_export_fn ecx_export;
73 static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
74 static OSSL_FUNC_keymgmt_dup_fn ecx_dup;
75
76 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
77
78 struct ecx_gen_ctx {
79 OSSL_LIB_CTX *libctx;
80 char *propq;
81 ECX_KEY_TYPE type;
82 int selection;
83 unsigned char *dhkem_ikm;
84 size_t dhkem_ikmlen;
85 };
86
87 #ifdef S390X_EC_ASM
88 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
89 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
90 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
91 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
92 #endif
93
94 static void *x25519_new_key(void *provctx)
95 {
96 if (!ossl_prov_is_running())
97 return 0;
98 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
99 NULL);
100 }
101
102 static void *x448_new_key(void *provctx)
103 {
104 if (!ossl_prov_is_running())
105 return 0;
106 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0,
107 NULL);
108 }
109
110 static void *ed25519_new_key(void *provctx)
111 {
112 if (!ossl_prov_is_running())
113 return 0;
114 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0,
115 NULL);
116 }
117
118 static void *ed448_new_key(void *provctx)
119 {
120 if (!ossl_prov_is_running())
121 return 0;
122 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0,
123 NULL);
124 }
125
126 static int ecx_has(const void *keydata, int selection)
127 {
128 const ECX_KEY *key = keydata;
129 int ok = 0;
130
131 if (ossl_prov_is_running() && key != NULL) {
132 /*
133 * ECX keys always have all the parameters they need (i.e. none).
134 * Therefore we always return with 1, if asked about parameters.
135 */
136 ok = 1;
137
138 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
139 ok = ok && key->haspubkey;
140
141 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
142 ok = ok && key->privkey != NULL;
143 }
144 return ok;
145 }
146
147 static int ecx_match(const void *keydata1, const void *keydata2, int selection)
148 {
149 const ECX_KEY *key1 = keydata1;
150 const ECX_KEY *key2 = keydata2;
151 int ok = 1;
152
153 if (!ossl_prov_is_running())
154 return 0;
155
156 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
157 ok = ok && key1->type == key2->type;
158 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
159 int key_checked = 0;
160
161 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
162 const unsigned char *pa = key1->haspubkey ? key1->pubkey : NULL;
163 const unsigned char *pb = key2->haspubkey ? key2->pubkey : NULL;
164 size_t pal = key1->keylen;
165 size_t pbl = key2->keylen;
166
167 if (pa != NULL && pb != NULL) {
168 ok = ok
169 && key1->type == key2->type
170 && pal == pbl
171 && CRYPTO_memcmp(pa, pb, pal) == 0;
172 key_checked = 1;
173 }
174 }
175 if (!key_checked
176 && (selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
177 const unsigned char *pa = key1->privkey;
178 const unsigned char *pb = key2->privkey;
179 size_t pal = key1->keylen;
180 size_t pbl = key2->keylen;
181
182 if (pa != NULL && pb != NULL) {
183 ok = ok
184 && key1->type == key2->type
185 && pal == pbl
186 && CRYPTO_memcmp(pa, pb, pal) == 0;
187 key_checked = 1;
188 }
189 }
190 ok = ok && key_checked;
191 }
192 return ok;
193 }
194
195 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
196 {
197 ECX_KEY *key = keydata;
198 int ok = 1;
199 int include_private;
200
201 if (!ossl_prov_is_running() || key == NULL)
202 return 0;
203
204 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
205 return 0;
206
207 include_private = selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY ? 1 : 0;
208 ok = ok && ossl_ecx_key_fromdata(key, params, include_private);
209
210 return ok;
211 }
212
213 static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
214 OSSL_PARAM params[], int include_private)
215 {
216 if (key == NULL)
217 return 0;
218
219 if (!ossl_param_build_set_octet_string(tmpl, params,
220 OSSL_PKEY_PARAM_PUB_KEY,
221 key->pubkey, key->keylen))
222 return 0;
223
224 if (include_private
225 && key->privkey != NULL
226 && !ossl_param_build_set_octet_string(tmpl, params,
227 OSSL_PKEY_PARAM_PRIV_KEY,
228 key->privkey, key->keylen))
229 return 0;
230
231 return 1;
232 }
233
234 static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
235 void *cbarg)
236 {
237 ECX_KEY *key = keydata;
238 OSSL_PARAM_BLD *tmpl;
239 OSSL_PARAM *params = NULL;
240 int ret = 0;
241
242 if (!ossl_prov_is_running() || key == NULL)
243 return 0;
244
245 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
246 return 0;
247
248 tmpl = OSSL_PARAM_BLD_new();
249 if (tmpl == NULL)
250 return 0;
251
252 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0) {
253 int include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
254
255 if (!key_to_params(key, tmpl, NULL, include_private))
256 goto err;
257 }
258
259 params = OSSL_PARAM_BLD_to_param(tmpl);
260 if (params == NULL)
261 goto err;
262
263 ret = param_cb(params, cbarg);
264 OSSL_PARAM_free(params);
265 err:
266 OSSL_PARAM_BLD_free(tmpl);
267 return ret;
268 }
269
270 #define ECX_KEY_TYPES() \
271 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \
272 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
273
274 static const OSSL_PARAM ecx_key_types[] = {
275 ECX_KEY_TYPES(),
276 OSSL_PARAM_END
277 };
278 static const OSSL_PARAM *ecx_imexport_types(int selection)
279 {
280 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
281 return ecx_key_types;
282 return NULL;
283 }
284
285 static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
286 int size)
287 {
288 ECX_KEY *ecx = key;
289 OSSL_PARAM *p;
290
291 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
292 && !OSSL_PARAM_set_int(p, bits))
293 return 0;
294 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
295 && !OSSL_PARAM_set_int(p, secbits))
296 return 0;
297 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
298 && !OSSL_PARAM_set_int(p, size))
299 return 0;
300 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
301 && (ecx->type == ECX_KEY_TYPE_X25519
302 || ecx->type == ECX_KEY_TYPE_X448)) {
303 if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
304 return 0;
305 }
306
307 return key_to_params(ecx, NULL, params, 1);
308 }
309
310 static int ed_get_params(void *key, OSSL_PARAM params[])
311 {
312 OSSL_PARAM *p;
313
314 if ((p = OSSL_PARAM_locate(params,
315 OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
316 && !OSSL_PARAM_set_utf8_string(p, ""))
317 return 0;
318 return 1;
319 }
320
321 static int x25519_get_params(void *key, OSSL_PARAM params[])
322 {
323 return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
324 X25519_KEYLEN);
325 }
326
327 static int x448_get_params(void *key, OSSL_PARAM params[])
328 {
329 return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
330 X448_KEYLEN);
331 }
332
333 static int ed25519_get_params(void *key, OSSL_PARAM params[])
334 {
335 return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
336 ED25519_SIGSIZE)
337 && ed_get_params(key, params);
338 }
339
340 static int ed448_get_params(void *key, OSSL_PARAM params[])
341 {
342 return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
343 ED448_SIGSIZE)
344 && ed_get_params(key, params);
345 }
346
347 static const OSSL_PARAM ecx_gettable_params[] = {
348 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
349 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
350 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
351 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
352 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
353 ECX_KEY_TYPES(),
354 OSSL_PARAM_END
355 };
356
357 static const OSSL_PARAM ed_gettable_params[] = {
358 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
359 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
360 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
361 ECX_KEY_TYPES(),
362 OSSL_PARAM_END
363 };
364
365 static const OSSL_PARAM *x25519_gettable_params(void *provctx)
366 {
367 return ecx_gettable_params;
368 }
369
370 static const OSSL_PARAM *x448_gettable_params(void *provctx)
371 {
372 return ecx_gettable_params;
373 }
374
375 static const OSSL_PARAM *ed25519_gettable_params(void *provctx)
376 {
377 return ed_gettable_params;
378 }
379
380 static const OSSL_PARAM *ed448_gettable_params(void *provctx)
381 {
382 return ed_gettable_params;
383 }
384
385 static int set_property_query(ECX_KEY *ecxkey, const char *propq)
386 {
387 OPENSSL_free(ecxkey->propq);
388 ecxkey->propq = NULL;
389 if (propq != NULL) {
390 ecxkey->propq = OPENSSL_strdup(propq);
391 if (ecxkey->propq == NULL)
392 return 0;
393 }
394 return 1;
395 }
396
397 static int ecx_set_params(void *key, const OSSL_PARAM params[])
398 {
399 ECX_KEY *ecxkey = key;
400 const OSSL_PARAM *p;
401
402 if (params == NULL)
403 return 1;
404
405 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
406 if (p != NULL) {
407 void *buf = ecxkey->pubkey;
408
409 if (p->data_size != ecxkey->keylen
410 || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
411 NULL))
412 return 0;
413 OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
414 ecxkey->privkey = NULL;
415 ecxkey->haspubkey = 1;
416 }
417 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
418 if (p != NULL) {
419 if (p->data_type != OSSL_PARAM_UTF8_STRING
420 || !set_property_query(ecxkey, p->data))
421 return 0;
422 }
423
424 return 1;
425 }
426
427 static int x25519_set_params(void *key, const OSSL_PARAM params[])
428 {
429 return ecx_set_params(key, params);
430 }
431
432 static int x448_set_params(void *key, const OSSL_PARAM params[])
433 {
434 return ecx_set_params(key, params);
435 }
436
437 static int ed25519_set_params(void *key, const OSSL_PARAM params[])
438 {
439 return 1;
440 }
441
442 static int ed448_set_params(void *key, const OSSL_PARAM params[])
443 {
444 return 1;
445 }
446
447 static const OSSL_PARAM ecx_settable_params[] = {
448 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
449 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
450 OSSL_PARAM_END
451 };
452
453 static const OSSL_PARAM ed_settable_params[] = {
454 OSSL_PARAM_END
455 };
456
457 static const OSSL_PARAM *x25519_settable_params(void *provctx)
458 {
459 return ecx_settable_params;
460 }
461
462 static const OSSL_PARAM *x448_settable_params(void *provctx)
463 {
464 return ecx_settable_params;
465 }
466
467 static const OSSL_PARAM *ed25519_settable_params(void *provctx)
468 {
469 return ed_settable_params;
470 }
471
472 static const OSSL_PARAM *ed448_settable_params(void *provctx)
473 {
474 return ed_settable_params;
475 }
476
477 static void *ecx_gen_init(void *provctx, int selection,
478 const OSSL_PARAM params[], ECX_KEY_TYPE type)
479 {
480 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
481 struct ecx_gen_ctx *gctx = NULL;
482
483 if (!ossl_prov_is_running())
484 return NULL;
485
486 if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
487 gctx->libctx = libctx;
488 gctx->type = type;
489 gctx->selection = selection;
490 }
491 if (!ecx_gen_set_params(gctx, params)) {
492 OPENSSL_free(gctx);
493 gctx = NULL;
494 }
495 return gctx;
496 }
497
498 static void *x25519_gen_init(void *provctx, int selection,
499 const OSSL_PARAM params[])
500 {
501 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
502 }
503
504 static void *x448_gen_init(void *provctx, int selection,
505 const OSSL_PARAM params[])
506 {
507 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
508 }
509
510 static void *ed25519_gen_init(void *provctx, int selection,
511 const OSSL_PARAM params[])
512 {
513 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519);
514 }
515
516 static void *ed448_gen_init(void *provctx, int selection,
517 const OSSL_PARAM params[])
518 {
519 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448);
520 }
521
522 static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
523 {
524 struct ecx_gen_ctx *gctx = genctx;
525 const OSSL_PARAM *p;
526
527 if (gctx == NULL)
528 return 0;
529
530 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
531 if (p != NULL) {
532 const char *groupname = NULL;
533
534 /*
535 * We optionally allow setting a group name - but each algorithm only
536 * support one such name, so all we do is verify that it is the one we
537 * expected.
538 */
539 switch (gctx->type) {
540 case ECX_KEY_TYPE_X25519:
541 groupname = "x25519";
542 break;
543 case ECX_KEY_TYPE_X448:
544 groupname = "x448";
545 break;
546 default:
547 /* We only support this for key exchange at the moment */
548 break;
549 }
550 if (p->data_type != OSSL_PARAM_UTF8_STRING
551 || groupname == NULL
552 || OPENSSL_strcasecmp(p->data, groupname) != 0) {
553 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
554 return 0;
555 }
556 }
557 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
558 if (p != NULL) {
559 if (p->data_type != OSSL_PARAM_UTF8_STRING)
560 return 0;
561 OPENSSL_free(gctx->propq);
562 gctx->propq = OPENSSL_strdup(p->data);
563 if (gctx->propq == NULL)
564 return 0;
565 }
566 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DHKEM_IKM);
567 if (p != NULL) {
568 if (p->data_size != 0 && p->data != NULL) {
569 OPENSSL_free(gctx->dhkem_ikm);
570 gctx->dhkem_ikm = NULL;
571 if (!OSSL_PARAM_get_octet_string(p, (void **)&gctx->dhkem_ikm, 0,
572 &gctx->dhkem_ikmlen))
573 return 0;
574 }
575 }
576
577 return 1;
578 }
579
580 static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
581 ossl_unused void *provctx)
582 {
583 static OSSL_PARAM settable[] = {
584 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
585 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
586 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM, NULL, 0),
587 OSSL_PARAM_END
588 };
589 return settable;
590 }
591
592 #ifdef FIPS_MODULE
593 /*
594 * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1
595 * Perform a pairwise test for EDDSA by signing and verifying signature.
596 *
597 * The parameter `self_test` is used to indicate whether to create OSSL_SELF_TEST
598 * instance.
599 */
600 static int ecd_fips140_pairwise_test(const ECX_KEY *ecx, int type, int self_test)
601 {
602 int ret = 0;
603 OSSL_SELF_TEST *st = NULL;
604 OSSL_CALLBACK *cb = NULL;
605 void *cbarg = NULL;
606
607 unsigned char msg[16] = {0};
608 size_t msg_len = sizeof(msg);
609 unsigned char sig[ED448_SIGSIZE] = {0};
610
611 int is_ed25519 = (type == ECX_KEY_TYPE_ED25519) ? 1 : 0;
612 int operation_result = 0;
613
614 /*
615 * The functions `OSSL_SELF_TEST_*` will return directly if parameter `st`
616 * is NULL.
617 */
618 if (self_test) {
619 OSSL_SELF_TEST_get_callback(ecx->libctx, &cb, &cbarg);
620
621 st = OSSL_SELF_TEST_new(cb, cbarg);
622 if (st == NULL)
623 return 0;
624 }
625
626 OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
627 OSSL_SELF_TEST_DESC_PCT_EDDSA);
628
629 if (is_ed25519)
630 operation_result = ossl_ed25519_sign(sig, msg, msg_len, ecx->pubkey,
631 ecx->privkey, 0, 0, 0, NULL, 0,
632 ecx->libctx, ecx->propq);
633 else
634 operation_result = ossl_ed448_sign(ecx->libctx, sig, msg, msg_len,
635 ecx->pubkey, ecx->privkey, NULL, 0,
636 0, ecx->propq);
637 if (operation_result != 1)
638 goto err;
639
640 OSSL_SELF_TEST_oncorrupt_byte(st, sig);
641
642 if (is_ed25519)
643 operation_result = ossl_ed25519_verify(msg, msg_len, sig, ecx->pubkey,
644 0, 0, 0, NULL, 0, ecx->libctx,
645 ecx->propq);
646 else
647 operation_result = ossl_ed448_verify(ecx->libctx, msg, msg_len, sig,
648 ecx->pubkey, NULL, 0, 0, ecx->propq);
649 if (operation_result != 1)
650 goto err;
651
652 ret = 1;
653 err:
654 OSSL_SELF_TEST_onend(st, ret);
655 OSSL_SELF_TEST_free(st);
656 return ret;
657 }
658 #endif
659
660 static void *ecx_gen(struct ecx_gen_ctx *gctx)
661 {
662 ECX_KEY *key;
663 unsigned char *privkey;
664
665 if (gctx == NULL)
666 return NULL;
667 if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
668 gctx->propq)) == NULL) {
669 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
670 return NULL;
671 }
672
673 /* If we're doing parameter generation then we just return a blank key */
674 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
675 return key;
676
677 if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
678 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
679 goto err;
680 }
681 #ifndef FIPS_MODULE
682 if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
683 if (gctx->type == ECX_KEY_TYPE_ED25519
684 || gctx->type == ECX_KEY_TYPE_ED448)
685 goto err;
686 if (!ossl_ecx_dhkem_derive_private(key, privkey,
687 gctx->dhkem_ikm, gctx->dhkem_ikmlen))
688 goto err;
689 } else
690 #endif
691 {
692 if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
693 goto err;
694 }
695
696 switch (gctx->type) {
697 case ECX_KEY_TYPE_X25519:
698 privkey[0] &= 248;
699 privkey[X25519_KEYLEN - 1] &= 127;
700 privkey[X25519_KEYLEN - 1] |= 64;
701 ossl_x25519_public_from_private(key->pubkey, privkey);
702 break;
703 case ECX_KEY_TYPE_X448:
704 privkey[0] &= 252;
705 privkey[X448_KEYLEN - 1] |= 128;
706 ossl_x448_public_from_private(key->pubkey, privkey);
707 break;
708 case ECX_KEY_TYPE_ED25519:
709 if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey,
710 gctx->propq))
711 goto err;
712 break;
713 case ECX_KEY_TYPE_ED448:
714 if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey,
715 gctx->propq))
716 goto err;
717 break;
718 }
719 key->haspubkey = 1;
720 return key;
721 err:
722 ossl_ecx_key_free(key);
723 return NULL;
724 }
725
726 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
727 {
728 struct ecx_gen_ctx *gctx = genctx;
729
730 if (!ossl_prov_is_running())
731 return 0;
732
733 #ifdef S390X_EC_ASM
734 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
735 return s390x_ecx_keygen25519(gctx);
736 #endif
737 return ecx_gen(gctx);
738 }
739
740 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
741 {
742 struct ecx_gen_ctx *gctx = genctx;
743
744 if (!ossl_prov_is_running())
745 return 0;
746
747 #ifdef S390X_EC_ASM
748 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
749 return s390x_ecx_keygen448(gctx);
750 #endif
751 return ecx_gen(gctx);
752 }
753
754 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
755 {
756 ECX_KEY *key = NULL;
757 struct ecx_gen_ctx *gctx = genctx;
758
759 if (!ossl_prov_is_running())
760 return 0;
761
762 #ifdef S390X_EC_ASM
763 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
764 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
765 && OPENSSL_s390xcap_P.kdsa[0]
766 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)) {
767 key = s390x_ecd_keygen25519(gctx);
768 } else
769 #endif
770 {
771 key = ecx_gen(gctx);
772 }
773
774 #ifdef FIPS_MODULE
775 /* Exit if keygen failed OR we are doing parameter generation (blank key) */
776 if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
777 return key;
778 if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED25519, 1) != 1) {
779 ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
780 ossl_ecx_key_free(key);
781 return NULL;
782 }
783 #endif
784
785 return key;
786 }
787
788 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
789 {
790 ECX_KEY *key = NULL;
791 struct ecx_gen_ctx *gctx = genctx;
792
793 if (!ossl_prov_is_running())
794 return 0;
795
796 #ifdef S390X_EC_ASM
797 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
798 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
799 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) {
800 key = s390x_ecd_keygen448(gctx);
801 } else
802 #endif
803 {
804 key = ecx_gen(gctx);
805 }
806
807 #ifdef FIPS_MODULE
808 /* Exit if keygen failed OR we are doing parameter generation (blank key) */
809 if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
810 return key;
811 if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED448, 1) != 1) {
812 ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
813 ossl_ecx_key_free(key);
814 return NULL;
815 }
816 #endif
817
818 return key;
819 }
820
821 static void ecx_gen_cleanup(void *genctx)
822 {
823 struct ecx_gen_ctx *gctx = genctx;
824
825 OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
826 OPENSSL_free(gctx->propq);
827 OPENSSL_free(gctx);
828 }
829
830 void *ecx_load(const void *reference, size_t reference_sz)
831 {
832 ECX_KEY *key = NULL;
833
834 if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
835 /* The contents of the reference is the address to our object */
836 key = *(ECX_KEY **)reference;
837 /* We grabbed, so we detach it */
838 *(ECX_KEY **)reference = NULL;
839 return key;
840 }
841 return NULL;
842 }
843
844 static void *ecx_dup(const void *keydata_from, int selection)
845 {
846 if (ossl_prov_is_running())
847 return ossl_ecx_key_dup(keydata_from, selection);
848 return NULL;
849 }
850
851 static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
852 {
853 uint8_t pub[64];
854
855 switch (type) {
856 case ECX_KEY_TYPE_X25519:
857 ossl_x25519_public_from_private(pub, ecx->privkey);
858 break;
859 case ECX_KEY_TYPE_X448:
860 ossl_x448_public_from_private(pub, ecx->privkey);
861 break;
862 default:
863 return 0;
864 }
865 return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
866 }
867
868 #ifdef FIPS_MODULE
869 static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
870 {
871 return ecd_fips140_pairwise_test(ecx, type, 0);
872 }
873 #else
874 static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
875 {
876 uint8_t pub[64];
877
878 switch (type) {
879 case ECX_KEY_TYPE_ED25519:
880 if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
881 ecx->propq))
882 return 0;
883 break;
884 case ECX_KEY_TYPE_ED448:
885 if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
886 ecx->propq))
887 return 0;
888 break;
889 default:
890 return 0;
891 }
892 return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
893 }
894 #endif
895
896 static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
897 {
898 const ECX_KEY *ecx = keydata;
899 int ok = keylen == ecx->keylen;
900
901 if (!ossl_prov_is_running())
902 return 0;
903
904 if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
905 return 1; /* nothing to validate */
906
907 if (!ok) {
908 ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
909 return 0;
910 }
911
912 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
913 ok = ok && ecx->haspubkey;
914
915 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
916 ok = ok && ecx->privkey != NULL;
917
918 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
919 return ok;
920
921 if (type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448)
922 ok = ok && ecd_key_pairwise_check(ecx, type);
923 else
924 ok = ok && ecx_key_pairwise_check(ecx, type);
925
926 return ok;
927 }
928
929 static int x25519_validate(const void *keydata, int selection, int checktype)
930 {
931 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
932 }
933
934 static int x448_validate(const void *keydata, int selection, int checktype)
935 {
936 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
937 }
938
939 static int ed25519_validate(const void *keydata, int selection, int checktype)
940 {
941 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
942 }
943
944 static int ed448_validate(const void *keydata, int selection, int checktype)
945 {
946 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
947 }
948
949 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
950 const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
951 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
952 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
953 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
954 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
955 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
956 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
957 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
958 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
959 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
960 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
961 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
962 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
963 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
964 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
965 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
966 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
967 (void (*)(void))ecx_gen_settable_params }, \
968 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
969 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
970 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
971 { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
972 OSSL_DISPATCH_END \
973 };
974
975 MAKE_KEYMGMT_FUNCTIONS(x25519)
976 MAKE_KEYMGMT_FUNCTIONS(x448)
977 MAKE_KEYMGMT_FUNCTIONS(ed25519)
978 MAKE_KEYMGMT_FUNCTIONS(ed448)
979
980 #ifdef S390X_EC_ASM
981 # include "s390x_arch.h"
982
983 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
984 {
985 static const unsigned char generator[] = {
986 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
987 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
988 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
989 };
990 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
991 gctx->propq);
992 unsigned char *privkey = NULL, *pubkey;
993
994 if (key == NULL) {
995 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
996 goto err;
997 }
998
999 /* If we're doing parameter generation then we just return a blank key */
1000 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1001 return key;
1002
1003 pubkey = key->pubkey;
1004
1005 privkey = ossl_ecx_key_allocate_privkey(key);
1006 if (privkey == NULL) {
1007 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1008 goto err;
1009 }
1010
1011 #ifndef FIPS_MODULE
1012 if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1013 if (gctx->type != ECX_KEY_TYPE_X25519)
1014 goto err;
1015 if (!ossl_ecx_dhkem_derive_private(key, privkey,
1016 gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1017 goto err;
1018 } else
1019 #endif
1020 {
1021 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
1022 goto err;
1023 }
1024
1025 privkey[0] &= 248;
1026 privkey[31] &= 127;
1027 privkey[31] |= 64;
1028
1029 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
1030 goto err;
1031 key->haspubkey = 1;
1032 return key;
1033 err:
1034 ossl_ecx_key_free(key);
1035 return NULL;
1036 }
1037
1038 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
1039 {
1040 static const unsigned char generator[] = {
1041 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1042 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1043 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1044 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1045 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1046 };
1047 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
1048 gctx->propq);
1049 unsigned char *privkey = NULL, *pubkey;
1050
1051 if (key == NULL) {
1052 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1053 goto err;
1054 }
1055
1056 /* If we're doing parameter generation then we just return a blank key */
1057 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1058 return key;
1059
1060 pubkey = key->pubkey;
1061
1062 privkey = ossl_ecx_key_allocate_privkey(key);
1063 if (privkey == NULL) {
1064 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1065 goto err;
1066 }
1067
1068 #ifndef FIPS_MODULE
1069 if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1070 if (gctx->type != ECX_KEY_TYPE_X448)
1071 goto err;
1072 if (!ossl_ecx_dhkem_derive_private(key, privkey,
1073 gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1074 goto err;
1075 } else
1076 #endif
1077 {
1078 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1079 goto err;
1080 }
1081
1082 privkey[0] &= 252;
1083 privkey[55] |= 128;
1084
1085 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1086 goto err;
1087 key->haspubkey = 1;
1088 return key;
1089 err:
1090 ossl_ecx_key_free(key);
1091 return NULL;
1092 }
1093
1094 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
1095 {
1096 static const unsigned char generator_x[] = {
1097 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1098 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1099 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1100 };
1101 static const unsigned char generator_y[] = {
1102 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1103 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1104 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1105 };
1106 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1107 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1108 gctx->propq);
1109 unsigned char *privkey = NULL, *pubkey;
1110 unsigned int sz;
1111 EVP_MD *sha = NULL;
1112 int j;
1113
1114 if (key == NULL) {
1115 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1116 goto err;
1117 }
1118
1119 /* If we're doing parameter generation then we just return a blank key */
1120 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1121 return key;
1122
1123 pubkey = key->pubkey;
1124
1125 privkey = ossl_ecx_key_allocate_privkey(key);
1126 if (privkey == NULL) {
1127 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1128 goto err;
1129 }
1130
1131 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1132 goto err;
1133
1134 sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
1135 if (sha == NULL)
1136 goto err;
1137 j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
1138 EVP_MD_free(sha);
1139 if (!j)
1140 goto err;
1141
1142 buff[0] &= 248;
1143 buff[31] &= 63;
1144 buff[31] |= 64;
1145
1146 if (s390x_ed25519_mul(x_dst, pubkey,
1147 generator_x, generator_y, buff) != 1)
1148 goto err;
1149
1150 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1151 key->haspubkey = 1;
1152 return key;
1153 err:
1154 ossl_ecx_key_free(key);
1155 return NULL;
1156 }
1157
1158 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
1159 {
1160 static const unsigned char generator_x[] = {
1161 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1162 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1163 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1164 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1165 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1166 };
1167 static const unsigned char generator_y[] = {
1168 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1169 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1170 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1171 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1172 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1173 };
1174 unsigned char x_dst[57], buff[114];
1175 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
1176 gctx->propq);
1177 unsigned char *privkey = NULL, *pubkey;
1178 EVP_MD_CTX *hashctx = NULL;
1179 EVP_MD *shake = NULL;
1180
1181 if (key == NULL) {
1182 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1183 goto err;
1184 }
1185
1186 /* If we're doing parameter generation then we just return a blank key */
1187 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1188 return key;
1189
1190 pubkey = key->pubkey;
1191
1192 privkey = ossl_ecx_key_allocate_privkey(key);
1193 if (privkey == NULL) {
1194 ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1195 goto err;
1196 }
1197
1198 shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1199 if (shake == NULL)
1200 goto err;
1201 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1202 goto err;
1203
1204 hashctx = EVP_MD_CTX_new();
1205 if (hashctx == NULL)
1206 goto err;
1207 if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1208 goto err;
1209 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1210 goto err;
1211 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1212 goto err;
1213
1214 buff[0] &= -4;
1215 buff[55] |= 0x80;
1216 buff[56] = 0;
1217
1218 if (s390x_ed448_mul(x_dst, pubkey,
1219 generator_x, generator_y, buff) != 1)
1220 goto err;
1221
1222 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1223 EVP_MD_CTX_free(hashctx);
1224 EVP_MD_free(shake);
1225 key->haspubkey = 1;
1226 return key;
1227 err:
1228 ossl_ecx_key_free(key);
1229 EVP_MD_CTX_free(hashctx);
1230 EVP_MD_free(shake);
1231 return NULL;
1232 }
1233 #endif