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