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