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