ae11fd4bc072f146845b42161efc5d1ad700944e
[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