xref: /freebsd/crypto/openssl/providers/implementations/keymgmt/ecx_kmgmt.c (revision e7be843b4a162e68651d3911f0357ed464915629)
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/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_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
363     ECX_KEY_TYPES(),
364     OSSL_FIPS_IND_GETTABLE_CTX_PARAM()
365     OSSL_PARAM_END
366 };
367 
368 static const OSSL_PARAM ed_gettable_params[] = {
369     OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
370     OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
371     OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
372     OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
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 NULL;
509         }
510 #endif
511     } else {
512         return NULL;
513     }
514     if (!ecx_gen_set_params(gctx, params)) {
515         ecx_gen_cleanup(gctx);
516         gctx = NULL;
517     }
518     return gctx;
519 }
520 
x25519_gen_init(void * provctx,int selection,const OSSL_PARAM params[])521 static void *x25519_gen_init(void *provctx, int selection,
522                              const OSSL_PARAM params[])
523 {
524     return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519, "X25519");
525 }
526 
x448_gen_init(void * provctx,int selection,const OSSL_PARAM params[])527 static void *x448_gen_init(void *provctx, int selection,
528                            const OSSL_PARAM params[])
529 {
530     return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448, "X448");
531 }
532 
ed25519_gen_init(void * provctx,int selection,const OSSL_PARAM params[])533 static void *ed25519_gen_init(void *provctx, int selection,
534                               const OSSL_PARAM params[])
535 {
536     return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519, NULL);
537 }
538 
ed448_gen_init(void * provctx,int selection,const OSSL_PARAM params[])539 static void *ed448_gen_init(void *provctx, int selection,
540                             const OSSL_PARAM params[])
541 {
542     return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448, NULL);
543 }
544 
ecx_gen_set_params(void * genctx,const OSSL_PARAM params[])545 static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
546 {
547     struct ecx_gen_ctx *gctx = genctx;
548     const OSSL_PARAM *p;
549 
550     if (gctx == NULL)
551         return 0;
552 
553     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
554     if (p != NULL) {
555         const char *groupname = NULL;
556 
557         /*
558          * We optionally allow setting a group name - but each algorithm only
559          * support one such name, so all we do is verify that it is the one we
560          * expected.
561          */
562         switch (gctx->type) {
563             case ECX_KEY_TYPE_X25519:
564                 groupname = "x25519";
565                 break;
566             case ECX_KEY_TYPE_X448:
567                 groupname = "x448";
568                 break;
569             default:
570                 /* We only support this for key exchange at the moment */
571                 break;
572         }
573         if (p->data_type != OSSL_PARAM_UTF8_STRING
574                 || groupname == NULL
575                 || OPENSSL_strcasecmp(p->data, groupname) != 0) {
576             ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
577             return 0;
578         }
579     }
580     p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
581     if (p != NULL) {
582         if (p->data_type != OSSL_PARAM_UTF8_STRING)
583             return 0;
584         OPENSSL_free(gctx->propq);
585         gctx->propq = OPENSSL_strdup(p->data);
586         if (gctx->propq == NULL)
587             return 0;
588     }
589     p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_DHKEM_IKM);
590     if (p != NULL) {
591         if (p->data_size != 0 && p->data != NULL) {
592             OPENSSL_free(gctx->dhkem_ikm);
593             gctx->dhkem_ikm = NULL;
594             if (!OSSL_PARAM_get_octet_string(p, (void **)&gctx->dhkem_ikm, 0,
595                                              &gctx->dhkem_ikmlen))
596                 return 0;
597         }
598     }
599 
600     return 1;
601 }
602 
ecx_gen_settable_params(ossl_unused void * genctx,ossl_unused void * provctx)603 static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
604                                                  ossl_unused void *provctx)
605 {
606     static OSSL_PARAM settable[] = {
607         OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
608         OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
609         OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM, NULL, 0),
610         OSSL_PARAM_END
611     };
612     return settable;
613 }
614 
615 #ifdef FIPS_MODULE
616 /*
617  * Refer: FIPS 140-3 IG 10.3.A Additional Comment 1
618  * Perform a pairwise test for EDDSA by signing and verifying signature.
619  *
620  * The parameter `self_test` is used to indicate whether to create OSSL_SELF_TEST
621  * instance.
622  */
ecd_fips140_pairwise_test(const ECX_KEY * ecx,int type,int self_test)623 static int ecd_fips140_pairwise_test(const ECX_KEY *ecx, int type, int self_test)
624 {
625     int ret = 0;
626     OSSL_SELF_TEST *st = NULL;
627     OSSL_CALLBACK *cb = NULL;
628     void *cbarg = NULL;
629 
630     unsigned char msg[16] = {0};
631     size_t msg_len = sizeof(msg);
632     unsigned char sig[ED448_SIGSIZE] = {0};
633 
634     int is_ed25519 = (type == ECX_KEY_TYPE_ED25519) ? 1 : 0;
635     int operation_result = 0;
636 
637     /*
638      * The functions `OSSL_SELF_TEST_*` will return directly if parameter `st`
639      * is NULL.
640      */
641     if (self_test)  {
642         OSSL_SELF_TEST_get_callback(ecx->libctx, &cb, &cbarg);
643 
644         st = OSSL_SELF_TEST_new(cb, cbarg);
645         if (st == NULL)
646             return 0;
647     }
648 
649     OSSL_SELF_TEST_onbegin(st, OSSL_SELF_TEST_TYPE_PCT,
650                            OSSL_SELF_TEST_DESC_PCT_EDDSA);
651 
652     if (is_ed25519)
653         operation_result = ossl_ed25519_sign(sig, msg, msg_len, ecx->pubkey,
654                                              ecx->privkey, 0, 0, 0, NULL, 0,
655                                              ecx->libctx, ecx->propq);
656     else
657         operation_result = ossl_ed448_sign(ecx->libctx, sig, msg, msg_len,
658                                            ecx->pubkey, ecx->privkey, NULL, 0,
659                                            0, ecx->propq);
660     if (operation_result != 1)
661         goto err;
662 
663     OSSL_SELF_TEST_oncorrupt_byte(st, sig);
664 
665     if (is_ed25519)
666         operation_result = ossl_ed25519_verify(msg, msg_len, sig, ecx->pubkey,
667                                                0, 0, 0, NULL, 0, ecx->libctx,
668                                                ecx->propq);
669     else
670         operation_result = ossl_ed448_verify(ecx->libctx, msg, msg_len, sig,
671                                              ecx->pubkey, NULL, 0, 0, ecx->propq);
672     if (operation_result != 1)
673         goto err;
674 
675     ret = 1;
676 err:
677     OSSL_SELF_TEST_onend(st, ret);
678     OSSL_SELF_TEST_free(st);
679     return ret;
680 }
681 #endif
682 
ecx_gen(struct ecx_gen_ctx * gctx)683 static void *ecx_gen(struct ecx_gen_ctx *gctx)
684 {
685     ECX_KEY *key;
686     unsigned char *privkey;
687 
688     if (gctx == NULL)
689         return NULL;
690     if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
691                                 gctx->propq)) == NULL) {
692         ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
693         return NULL;
694     }
695 
696     /* If we're doing parameter generation then we just return a blank key */
697     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
698         return key;
699 
700     if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
701         ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
702         goto err;
703     }
704 #ifndef FIPS_MODULE
705     if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
706         if (gctx->type == ECX_KEY_TYPE_ED25519
707                 || gctx->type == ECX_KEY_TYPE_ED448)
708             goto err;
709         if (!ossl_ecx_dhkem_derive_private(key, privkey,
710                                            gctx->dhkem_ikm, gctx->dhkem_ikmlen))
711             goto err;
712     } else
713 #endif
714     {
715         if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen, 0) <= 0)
716             goto err;
717     }
718 
719     switch (gctx->type) {
720     case ECX_KEY_TYPE_X25519:
721         privkey[0] &= 248;
722         privkey[X25519_KEYLEN - 1] &= 127;
723         privkey[X25519_KEYLEN - 1] |= 64;
724         ossl_x25519_public_from_private(key->pubkey, privkey);
725         break;
726     case ECX_KEY_TYPE_X448:
727         privkey[0] &= 252;
728         privkey[X448_KEYLEN - 1] |= 128;
729         ossl_x448_public_from_private(key->pubkey, privkey);
730         break;
731     case ECX_KEY_TYPE_ED25519:
732         if (!ossl_ed25519_public_from_private(gctx->libctx, key->pubkey, privkey,
733                                               gctx->propq))
734             goto err;
735         break;
736     case ECX_KEY_TYPE_ED448:
737         if (!ossl_ed448_public_from_private(gctx->libctx, key->pubkey, privkey,
738                                             gctx->propq))
739             goto err;
740         break;
741     }
742     key->haspubkey = 1;
743     return key;
744 err:
745     ossl_ecx_key_free(key);
746     return NULL;
747 }
748 
x25519_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)749 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
750 {
751     struct ecx_gen_ctx *gctx = genctx;
752 
753     if (!ossl_prov_is_running())
754         return 0;
755 
756 #ifdef S390X_EC_ASM
757     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
758         return s390x_ecx_keygen25519(gctx);
759 #endif
760     return ecx_gen(gctx);
761 }
762 
x448_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)763 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
764 {
765     struct ecx_gen_ctx *gctx = genctx;
766 
767     if (!ossl_prov_is_running())
768         return 0;
769 
770 #ifdef S390X_EC_ASM
771     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
772         return s390x_ecx_keygen448(gctx);
773 #endif
774     return ecx_gen(gctx);
775 }
776 
ed25519_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)777 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
778 {
779     ECX_KEY *key = NULL;
780     struct ecx_gen_ctx *gctx = genctx;
781 
782     if (!ossl_prov_is_running())
783         return 0;
784 
785 #ifdef S390X_EC_ASM
786     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
787         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
788         && OPENSSL_s390xcap_P.kdsa[0]
789             & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)) {
790         key = s390x_ecd_keygen25519(gctx);
791     } else
792 #endif
793     {
794         key = ecx_gen(gctx);
795     }
796 
797 #ifdef FIPS_MODULE
798     /* Exit if keygen failed OR we are doing parameter generation (blank key) */
799     if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
800         return key;
801     if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED25519, 1) != 1) {
802         ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
803         ossl_ecx_key_free(key);
804         return NULL;
805     }
806 #endif
807 
808     return key;
809 }
810 
ed448_gen(void * genctx,OSSL_CALLBACK * osslcb,void * cbarg)811 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
812 {
813     ECX_KEY *key = NULL;
814     struct ecx_gen_ctx *gctx = genctx;
815 
816     if (!ossl_prov_is_running())
817         return 0;
818 
819 #ifdef S390X_EC_ASM
820     if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
821         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
822         && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)) {
823         key = s390x_ecd_keygen448(gctx);
824     } else
825 #endif
826     {
827         key = ecx_gen(gctx);
828     }
829 
830 #ifdef FIPS_MODULE
831     /* Exit if keygen failed OR we are doing parameter generation (blank key) */
832     if (!key || ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0))
833         return key;
834     if (ecd_fips140_pairwise_test(key, ECX_KEY_TYPE_ED448, 1) != 1) {
835         ossl_set_error_state(OSSL_SELF_TEST_TYPE_PCT);
836         ossl_ecx_key_free(key);
837         return NULL;
838     }
839 #endif
840 
841     return key;
842 }
843 
ecx_gen_cleanup(void * genctx)844 static void ecx_gen_cleanup(void *genctx)
845 {
846     struct ecx_gen_ctx *gctx = genctx;
847 
848     if (gctx == NULL)
849         return;
850 
851     OPENSSL_clear_free(gctx->dhkem_ikm, gctx->dhkem_ikmlen);
852     OPENSSL_free(gctx->propq);
853     OPENSSL_free(gctx);
854 }
855 
ecx_load(const void * reference,size_t reference_sz)856 void *ecx_load(const void *reference, size_t reference_sz)
857 {
858     ECX_KEY *key = NULL;
859 
860     if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
861         /* The contents of the reference is the address to our object */
862         key = *(ECX_KEY **)reference;
863         /* We grabbed, so we detach it */
864         *(ECX_KEY **)reference = NULL;
865         return key;
866     }
867     return NULL;
868 }
869 
ecx_dup(const void * keydata_from,int selection)870 static void *ecx_dup(const void *keydata_from, int selection)
871 {
872     if (ossl_prov_is_running())
873         return ossl_ecx_key_dup(keydata_from, selection);
874     return NULL;
875 }
876 
ecx_key_pairwise_check(const ECX_KEY * ecx,int type)877 static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
878 {
879     uint8_t pub[64];
880 
881     switch (type) {
882     case ECX_KEY_TYPE_X25519:
883         ossl_x25519_public_from_private(pub, ecx->privkey);
884         break;
885     case ECX_KEY_TYPE_X448:
886         ossl_x448_public_from_private(pub, ecx->privkey);
887         break;
888     default:
889         return 0;
890     }
891     return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
892 }
893 
894 #ifdef FIPS_MODULE
895 /*
896  * FIPS ACVP testing requires the ability to check if the public key is valid
897  * This is not required normally since the ED signature verify does the test
898  * internally.
899  */
ecd_key_pub_check(const ECX_KEY * ecx,int type)900 static int ecd_key_pub_check(const ECX_KEY *ecx, int type)
901 {
902     switch (type) {
903     case ECX_KEY_TYPE_ED25519:
904         return ossl_ed25519_pubkey_verify(ecx->pubkey, ecx->keylen);
905     case ECX_KEY_TYPE_ED448:
906         return ossl_ed448_pubkey_verify(ecx->pubkey, ecx->keylen);
907     default:
908         return 1;
909     }
910 }
911 #endif
912 
913 #ifdef FIPS_MODULE
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     return ecd_fips140_pairwise_test(ecx, type, 0);
917 }
918 #else
ecd_key_pairwise_check(const ECX_KEY * ecx,int type)919 static int ecd_key_pairwise_check(const ECX_KEY *ecx, int type)
920 {
921     uint8_t pub[64];
922 
923     switch (type) {
924     case ECX_KEY_TYPE_ED25519:
925         if (!ossl_ed25519_public_from_private(ecx->libctx, pub, ecx->privkey,
926                                               ecx->propq))
927             return 0;
928         break;
929     case ECX_KEY_TYPE_ED448:
930         if (!ossl_ed448_public_from_private(ecx->libctx, pub, ecx->privkey,
931                                             ecx->propq))
932             return 0;
933         break;
934     default:
935         return 0;
936     }
937     return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
938 }
939 #endif
940 
ecx_validate(const void * keydata,int selection,int type,size_t keylen)941 static int ecx_validate(const void *keydata, int selection, int type,
942                         size_t keylen)
943 {
944     const ECX_KEY *ecx = keydata;
945     int ok = keylen == ecx->keylen;
946 
947     if (!ossl_prov_is_running())
948         return 0;
949 
950     if ((selection & ECX_POSSIBLE_SELECTIONS) == 0)
951         return 1; /* nothing to validate */
952 
953     if (!ok) {
954         ERR_raise(ERR_LIB_PROV, PROV_R_ALGORITHM_MISMATCH);
955         return 0;
956     }
957 
958     if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
959         ok = ok && ecx->haspubkey;
960 #ifdef FIPS_MODULE
961         ok = ok && ecd_key_pub_check(ecx, type);
962 #endif
963     }
964 
965     if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
966         ok = ok && ecx->privkey != NULL;
967 
968     if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != OSSL_KEYMGMT_SELECT_KEYPAIR)
969         return ok;
970 
971     if (type == ECX_KEY_TYPE_ED25519 || type == ECX_KEY_TYPE_ED448)
972         ok = ok && ecd_key_pairwise_check(ecx, type);
973     else
974         ok = ok && ecx_key_pairwise_check(ecx, type);
975 
976     return ok;
977 }
978 
x25519_validate(const void * keydata,int selection,int checktype)979 static int x25519_validate(const void *keydata, int selection, int checktype)
980 {
981     return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
982 }
983 
x448_validate(const void * keydata,int selection,int checktype)984 static int x448_validate(const void *keydata, int selection, int checktype)
985 {
986     return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
987 }
988 
ed25519_validate(const void * keydata,int selection,int checktype)989 static int ed25519_validate(const void *keydata, int selection, int checktype)
990 {
991     return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
992 }
993 
ed448_validate(const void * keydata,int selection,int checktype)994 static int ed448_validate(const void *keydata, int selection, int checktype)
995 {
996     return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
997 }
998 
999 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
1000     const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
1001         { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
1002         { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
1003         { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
1004         { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
1005         { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
1006         { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
1007         { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
1008         { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
1009         { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
1010         { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
1011         { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
1012         { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
1013         { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
1014         { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
1015         { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
1016         { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
1017           (void (*)(void))ecx_gen_settable_params }, \
1018         { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
1019         { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
1020         { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
1021         { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
1022         OSSL_DISPATCH_END \
1023     };
1024 
1025 MAKE_KEYMGMT_FUNCTIONS(x25519)
MAKE_KEYMGMT_FUNCTIONS(x448)1026 MAKE_KEYMGMT_FUNCTIONS(x448)
1027 MAKE_KEYMGMT_FUNCTIONS(ed25519)
1028 MAKE_KEYMGMT_FUNCTIONS(ed448)
1029 
1030 #ifdef S390X_EC_ASM
1031 # include "s390x_arch.h"
1032 
1033 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
1034 {
1035     static const unsigned char generator[] = {
1036         0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1037         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1038         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1039     };
1040     ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
1041                                     gctx->propq);
1042     unsigned char *privkey = NULL, *pubkey;
1043 
1044     if (key == NULL) {
1045         ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1046         goto err;
1047     }
1048 
1049     /* If we're doing parameter generation then we just return a blank key */
1050     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1051         return key;
1052 
1053     pubkey = key->pubkey;
1054 
1055     privkey = ossl_ecx_key_allocate_privkey(key);
1056     if (privkey == NULL) {
1057         ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1058         goto err;
1059     }
1060 
1061 #ifndef FIPS_MODULE
1062     if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1063         if (gctx->type != ECX_KEY_TYPE_X25519)
1064             goto err;
1065         if (!ossl_ecx_dhkem_derive_private(key, privkey,
1066                                            gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1067             goto err;
1068     } else
1069 #endif
1070     {
1071         if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN, 0) <= 0)
1072             goto err;
1073     }
1074 
1075     privkey[0] &= 248;
1076     privkey[31] &= 127;
1077     privkey[31] |= 64;
1078 
1079     if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
1080         goto err;
1081     key->haspubkey = 1;
1082     return key;
1083  err:
1084     ossl_ecx_key_free(key);
1085     return NULL;
1086 }
1087 
s390x_ecx_keygen448(struct ecx_gen_ctx * gctx)1088 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
1089 {
1090     static const unsigned char generator[] = {
1091         0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1092         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1093         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1094         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1095         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
1096     };
1097     ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
1098                                     gctx->propq);
1099     unsigned char *privkey = NULL, *pubkey;
1100 
1101     if (key == NULL) {
1102         ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1103         goto err;
1104     }
1105 
1106     /* If we're doing parameter generation then we just return a blank key */
1107     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1108         return key;
1109 
1110     pubkey = key->pubkey;
1111 
1112     privkey = ossl_ecx_key_allocate_privkey(key);
1113     if (privkey == NULL) {
1114         ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1115         goto err;
1116     }
1117 
1118 #ifndef FIPS_MODULE
1119     if (gctx->dhkem_ikm != NULL && gctx->dhkem_ikmlen != 0) {
1120         if (gctx->type != ECX_KEY_TYPE_X448)
1121             goto err;
1122         if (!ossl_ecx_dhkem_derive_private(key, privkey,
1123                                            gctx->dhkem_ikm, gctx->dhkem_ikmlen))
1124             goto err;
1125     } else
1126 #endif
1127     {
1128         if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN, 0) <= 0)
1129             goto err;
1130     }
1131 
1132     privkey[0] &= 252;
1133     privkey[55] |= 128;
1134 
1135     if (s390x_x448_mul(pubkey, generator, privkey) != 1)
1136         goto err;
1137     key->haspubkey = 1;
1138     return key;
1139  err:
1140     ossl_ecx_key_free(key);
1141     return NULL;
1142 }
1143 
s390x_ecd_keygen25519(struct ecx_gen_ctx * gctx)1144 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
1145 {
1146     static const unsigned char generator_x[] = {
1147         0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
1148         0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
1149         0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
1150     };
1151     static const unsigned char generator_y[] = {
1152         0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1153         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1154         0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
1155     };
1156     unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
1157     ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
1158                                     gctx->propq);
1159     unsigned char *privkey = NULL, *pubkey;
1160     unsigned int sz;
1161     EVP_MD *sha = NULL;
1162     int j;
1163 
1164     if (key == NULL) {
1165         ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1166         goto err;
1167     }
1168 
1169     /* If we're doing parameter generation then we just return a blank key */
1170     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1171         return key;
1172 
1173     pubkey = key->pubkey;
1174 
1175     privkey = ossl_ecx_key_allocate_privkey(key);
1176     if (privkey == NULL) {
1177         ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1178         goto err;
1179     }
1180 
1181     if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN, 0) <= 0)
1182         goto err;
1183 
1184     sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
1185     if (sha == NULL)
1186         goto err;
1187     j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
1188     EVP_MD_free(sha);
1189     if (!j)
1190         goto err;
1191 
1192     buff[0] &= 248;
1193     buff[31] &= 63;
1194     buff[31] |= 64;
1195 
1196     if (s390x_ed25519_mul(x_dst, pubkey,
1197                           generator_x, generator_y, buff) != 1)
1198         goto err;
1199 
1200     pubkey[31] |= ((x_dst[0] & 0x01) << 7);
1201     key->haspubkey = 1;
1202     return key;
1203  err:
1204     ossl_ecx_key_free(key);
1205     return NULL;
1206 }
1207 
s390x_ecd_keygen448(struct ecx_gen_ctx * gctx)1208 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
1209 {
1210     static const unsigned char generator_x[] = {
1211         0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1212         0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1213         0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1214         0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1215         0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1216     };
1217     static const unsigned char generator_y[] = {
1218         0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1219         0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1220         0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1221         0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1222         0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1223     };
1224     unsigned char x_dst[57], buff[114];
1225     ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
1226                                     gctx->propq);
1227     unsigned char *privkey = NULL, *pubkey;
1228     EVP_MD_CTX *hashctx = NULL;
1229     EVP_MD *shake = NULL;
1230 
1231     if (key == NULL) {
1232         ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1233         goto err;
1234     }
1235 
1236     /* If we're doing parameter generation then we just return a blank key */
1237     if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
1238         return key;
1239 
1240     pubkey = key->pubkey;
1241 
1242     privkey = ossl_ecx_key_allocate_privkey(key);
1243     if (privkey == NULL) {
1244         ERR_raise(ERR_LIB_PROV, ERR_R_EC_LIB);
1245         goto err;
1246     }
1247 
1248     shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
1249     if (shake == NULL)
1250         goto err;
1251     if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN, 0) <= 0)
1252         goto err;
1253 
1254     hashctx = EVP_MD_CTX_new();
1255     if (hashctx == NULL)
1256         goto err;
1257     if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1258         goto err;
1259     if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1260         goto err;
1261     if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1262         goto err;
1263 
1264     buff[0] &= -4;
1265     buff[55] |= 0x80;
1266     buff[56] = 0;
1267 
1268     if (s390x_ed448_mul(x_dst, pubkey,
1269                         generator_x, generator_y, buff) != 1)
1270         goto err;
1271 
1272     pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1273     EVP_MD_CTX_free(hashctx);
1274     EVP_MD_free(shake);
1275     key->haspubkey = 1;
1276     return key;
1277  err:
1278     ossl_ecx_key_free(key);
1279     EVP_MD_CTX_free(hashctx);
1280     EVP_MD_free(shake);
1281     return NULL;
1282 }
1283 #endif
1284