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