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