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