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