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