]> git.ipfire.org Git - thirdparty/openssl.git/blob - providers/implementations/keymgmt/ecx_kmgmt.c
Ensure that ECX keys pass EVP_PKEY_param_check()
[thirdparty/openssl.git] / providers / implementations / keymgmt / ecx_kmgmt.c
1 /*
2 * Copyright 2020-2021 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 /* For strcasecmp on Windows */
13 #include "e_os.h"
14 #include <openssl/core_dispatch.h>
15 #include <openssl/core_names.h>
16 #include <openssl/params.h>
17 #include <openssl/err.h>
18 #include <openssl/evp.h>
19 #include <openssl/rand.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 #ifdef S390X_EC_ASM
27 # include "s390x_arch.h"
28 # include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
29 #endif
30
31 static OSSL_FUNC_keymgmt_new_fn x25519_new_key;
32 static OSSL_FUNC_keymgmt_new_fn x448_new_key;
33 static OSSL_FUNC_keymgmt_new_fn ed25519_new_key;
34 static OSSL_FUNC_keymgmt_new_fn ed448_new_key;
35 static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init;
36 static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init;
37 static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init;
38 static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init;
39 static OSSL_FUNC_keymgmt_gen_fn x25519_gen;
40 static OSSL_FUNC_keymgmt_gen_fn x448_gen;
41 static OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
42 static OSSL_FUNC_keymgmt_gen_fn ed448_gen;
43 static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
44 static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params;
45 static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params;
46 static OSSL_FUNC_keymgmt_load_fn ecx_load;
47 static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
48 static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
49 static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
50 static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
51 static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
52 static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
53 static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
54 static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
55 static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
56 static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
57 static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
58 static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
59 static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
60 static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
61 static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
62 static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
63 static OSSL_FUNC_keymgmt_has_fn ecx_has;
64 static OSSL_FUNC_keymgmt_match_fn ecx_match;
65 static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
66 static OSSL_FUNC_keymgmt_validate_fn x448_validate;
67 static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
68 static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
69 static OSSL_FUNC_keymgmt_import_fn ecx_import;
70 static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
71 static OSSL_FUNC_keymgmt_export_fn ecx_export;
72 static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
73
74 struct ecx_gen_ctx {
75 OSSL_LIB_CTX *libctx;
76 char *propq;
77 ECX_KEY_TYPE type;
78 int selection;
79 };
80
81 #ifdef S390X_EC_ASM
82 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
83 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
84 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
85 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
86 #endif
87
88 static void *x25519_new_key(void *provctx)
89 {
90 if (!ossl_prov_is_running())
91 return 0;
92 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X25519, 0,
93 NULL);
94 }
95
96 static void *x448_new_key(void *provctx)
97 {
98 if (!ossl_prov_is_running())
99 return 0;
100 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_X448, 0,
101 NULL);
102 }
103
104 static void *ed25519_new_key(void *provctx)
105 {
106 if (!ossl_prov_is_running())
107 return 0;
108 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED25519, 0,
109 NULL);
110 }
111
112 static void *ed448_new_key(void *provctx)
113 {
114 if (!ossl_prov_is_running())
115 return 0;
116 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx), ECX_KEY_TYPE_ED448, 0,
117 NULL);
118 }
119
120 static int ecx_has(const void *keydata, int selection)
121 {
122 const ECX_KEY *key = keydata;
123 int ok = 0;
124
125 if (ossl_prov_is_running() && key != NULL) {
126 /*
127 * ECX keys always have all the parameters they need (i.e. none).
128 * Therefore we always return with 1, if asked about parameters.
129 */
130 ok = 1;
131
132 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
133 ok = ok && key->haspubkey;
134
135 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
136 ok = ok && key->privkey != NULL;
137 }
138 return ok;
139 }
140
141 static int ecx_match(const void *keydata1, const void *keydata2, int selection)
142 {
143 const ECX_KEY *key1 = keydata1;
144 const ECX_KEY *key2 = keydata2;
145 int ok = 1;
146
147 if (!ossl_prov_is_running())
148 return 0;
149
150 if ((selection & OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS) != 0)
151 ok = ok && key1->type == key2->type;
152 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0) {
153 if ((key1->privkey == NULL && key2->privkey != NULL)
154 || (key1->privkey != NULL && key2->privkey == NULL)
155 || key1->type != key2->type)
156 ok = 0;
157 else
158 ok = ok && (key1->privkey == NULL /* implies key2->privkey == NULL */
159 || CRYPTO_memcmp(key1->privkey, key2->privkey,
160 key1->keylen) == 0);
161 }
162 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0) {
163 if (key1->haspubkey != key2->haspubkey
164 || key1->type != key2->type)
165 ok = 0;
166 else
167 ok = ok && (key1->haspubkey == 0 /* implies key2->haspubkey == 0 */
168 || CRYPTO_memcmp(key1->pubkey, key2->pubkey,
169 key1->keylen) == 0);
170 }
171 return ok;
172 }
173
174 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
175 {
176 ECX_KEY *key = keydata;
177 int ok = 1;
178 int include_private = 0;
179
180 if (!ossl_prov_is_running() || key == NULL)
181 return 0;
182
183 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
184 return 0;
185
186 include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
187 ok = ok && ossl_ecx_key_fromdata(key, params, include_private);
188
189 return ok;
190 }
191
192 static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
193 OSSL_PARAM params[])
194 {
195 if (key == NULL)
196 return 0;
197
198 if (!ossl_param_build_set_octet_string(tmpl, params,
199 OSSL_PKEY_PARAM_PUB_KEY,
200 key->pubkey, key->keylen))
201 return 0;
202
203 if (key->privkey != NULL
204 && !ossl_param_build_set_octet_string(tmpl, params,
205 OSSL_PKEY_PARAM_PRIV_KEY,
206 key->privkey, key->keylen))
207 return 0;
208
209 return 1;
210 }
211
212 static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
213 void *cbarg)
214 {
215 ECX_KEY *key = keydata;
216 OSSL_PARAM_BLD *tmpl;
217 OSSL_PARAM *params = NULL;
218 int ret = 0;
219
220 if (!ossl_prov_is_running() || key == NULL)
221 return 0;
222
223 tmpl = OSSL_PARAM_BLD_new();
224 if (tmpl == NULL)
225 return 0;
226
227 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
228 && !key_to_params(key, tmpl, NULL))
229 goto err;
230
231 params = OSSL_PARAM_BLD_to_param(tmpl);
232 if (params == NULL)
233 goto err;
234
235 ret = param_cb(params, cbarg);
236 OSSL_PARAM_BLD_free_params(params);
237 err:
238 OSSL_PARAM_BLD_free(tmpl);
239 return ret;
240 }
241
242 #define ECX_KEY_TYPES() \
243 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \
244 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
245
246 static const OSSL_PARAM ecx_key_types[] = {
247 ECX_KEY_TYPES(),
248 OSSL_PARAM_END
249 };
250 static const OSSL_PARAM *ecx_imexport_types(int selection)
251 {
252 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
253 return ecx_key_types;
254 return NULL;
255 }
256
257 static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
258 int size)
259 {
260 ECX_KEY *ecx = key;
261 OSSL_PARAM *p;
262
263 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
264 && !OSSL_PARAM_set_int(p, bits))
265 return 0;
266 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
267 && !OSSL_PARAM_set_int(p, secbits))
268 return 0;
269 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
270 && !OSSL_PARAM_set_int(p, size))
271 return 0;
272 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY)) != NULL
273 && (ecx->type == ECX_KEY_TYPE_X25519
274 || ecx->type == ECX_KEY_TYPE_X448)) {
275 if (!OSSL_PARAM_set_octet_string(p, ecx->pubkey, ecx->keylen))
276 return 0;
277 }
278
279 return key_to_params(ecx, NULL, params);
280 }
281
282 static int ed_get_params(void *key, OSSL_PARAM params[])
283 {
284 OSSL_PARAM *p;
285
286 if ((p = OSSL_PARAM_locate(params,
287 OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
288 && !OSSL_PARAM_set_utf8_string(p, ""))
289 return 0;
290 return 1;
291 }
292
293 static int x25519_get_params(void *key, OSSL_PARAM params[])
294 {
295 return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
296 X25519_KEYLEN);
297 }
298
299 static int x448_get_params(void *key, OSSL_PARAM params[])
300 {
301 return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
302 X448_KEYLEN);
303 }
304
305 static int ed25519_get_params(void *key, OSSL_PARAM params[])
306 {
307 return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
308 ED25519_KEYLEN)
309 && ed_get_params(key, params);
310 }
311
312 static int ed448_get_params(void *key, OSSL_PARAM params[])
313 {
314 return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
315 ED448_KEYLEN)
316 && ed_get_params(key, params);
317 }
318
319 static const OSSL_PARAM ecx_gettable_params[] = {
320 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
321 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
322 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
323 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
324 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
325 ECX_KEY_TYPES(),
326 OSSL_PARAM_END
327 };
328
329 static const OSSL_PARAM ed_gettable_params[] = {
330 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
331 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
332 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
333 ECX_KEY_TYPES(),
334 OSSL_PARAM_END
335 };
336
337 static const OSSL_PARAM *x25519_gettable_params(void *provctx)
338 {
339 return ecx_gettable_params;
340 }
341
342 static const OSSL_PARAM *x448_gettable_params(void *provctx)
343 {
344 return ecx_gettable_params;
345 }
346
347 static const OSSL_PARAM *ed25519_gettable_params(void *provctx)
348 {
349 return ed_gettable_params;
350 }
351
352 static const OSSL_PARAM *ed448_gettable_params(void *provctx)
353 {
354 return ed_gettable_params;
355 }
356
357 static int set_property_query(ECX_KEY *ecxkey, const char *propq)
358 {
359 OPENSSL_free(ecxkey->propq);
360 ecxkey->propq = NULL;
361 if (propq != NULL) {
362 ecxkey->propq = OPENSSL_strdup(propq);
363 if (ecxkey->propq == NULL) {
364 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
365 return 0;
366 }
367 }
368 return 1;
369 }
370
371 static int ecx_set_params(void *key, const OSSL_PARAM params[])
372 {
373 ECX_KEY *ecxkey = key;
374 const OSSL_PARAM *p;
375
376 if (params == NULL)
377 return 1;
378
379 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
380 if (p != NULL) {
381 void *buf = ecxkey->pubkey;
382
383 if (p->data_size != ecxkey->keylen
384 || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
385 NULL))
386 return 0;
387 OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
388 ecxkey->privkey = NULL;
389 ecxkey->haspubkey = 1;
390 }
391 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
392 if (p != NULL) {
393 if (p->data_type != OSSL_PARAM_UTF8_STRING
394 || !set_property_query(ecxkey, p->data))
395 return 0;
396 }
397
398 return 1;
399 }
400
401 static int x25519_set_params(void *key, const OSSL_PARAM params[])
402 {
403 return ecx_set_params(key, params);
404 }
405
406 static int x448_set_params(void *key, const OSSL_PARAM params[])
407 {
408 return ecx_set_params(key, params);
409 }
410
411 static int ed25519_set_params(void *key, const OSSL_PARAM params[])
412 {
413 return 1;
414 }
415
416 static int ed448_set_params(void *key, const OSSL_PARAM params[])
417 {
418 return 1;
419 }
420
421 static const OSSL_PARAM ecx_settable_params[] = {
422 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
423 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
424 OSSL_PARAM_END
425 };
426
427 static const OSSL_PARAM ed_settable_params[] = {
428 OSSL_PARAM_END
429 };
430
431 static const OSSL_PARAM *x25519_settable_params(void *provctx)
432 {
433 return ecx_settable_params;
434 }
435
436 static const OSSL_PARAM *x448_settable_params(void *provctx)
437 {
438 return ecx_settable_params;
439 }
440
441 static const OSSL_PARAM *ed25519_settable_params(void *provctx)
442 {
443 return ed_settable_params;
444 }
445
446 static const OSSL_PARAM *ed448_settable_params(void *provctx)
447 {
448 return ed_settable_params;
449 }
450
451 static void *ecx_gen_init(void *provctx, int selection,
452 const OSSL_PARAM params[], ECX_KEY_TYPE type)
453 {
454 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
455 struct ecx_gen_ctx *gctx = NULL;
456
457 if (!ossl_prov_is_running())
458 return NULL;
459
460 if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
461 gctx->libctx = libctx;
462 gctx->type = type;
463 gctx->selection = selection;
464 }
465 if (!ecx_gen_set_params(gctx, params)) {
466 OPENSSL_free(gctx);
467 gctx = NULL;
468 }
469 return gctx;
470 }
471
472 static void *x25519_gen_init(void *provctx, int selection,
473 const OSSL_PARAM params[])
474 {
475 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X25519);
476 }
477
478 static void *x448_gen_init(void *provctx, int selection,
479 const OSSL_PARAM params[])
480 {
481 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_X448);
482 }
483
484 static void *ed25519_gen_init(void *provctx, int selection,
485 const OSSL_PARAM params[])
486 {
487 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED25519);
488 }
489
490 static void *ed448_gen_init(void *provctx, int selection,
491 const OSSL_PARAM params[])
492 {
493 return ecx_gen_init(provctx, selection, params, ECX_KEY_TYPE_ED448);
494 }
495
496 static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
497 {
498 struct ecx_gen_ctx *gctx = genctx;
499 const OSSL_PARAM *p;
500
501 if (gctx == NULL)
502 return 0;
503
504 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
505 if (p != NULL) {
506 const char *groupname = NULL;
507
508 /*
509 * We optionally allow setting a group name - but each algorithm only
510 * support one such name, so all we do is verify that it is the one we
511 * expected.
512 */
513 switch (gctx->type) {
514 case ECX_KEY_TYPE_X25519:
515 groupname = "x25519";
516 break;
517 case ECX_KEY_TYPE_X448:
518 groupname = "x448";
519 break;
520 default:
521 /* We only support this for key exchange at the moment */
522 break;
523 }
524 if (p->data_type != OSSL_PARAM_UTF8_STRING
525 || groupname == NULL
526 || strcasecmp(p->data, groupname) != 0) {
527 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
528 return 0;
529 }
530 }
531 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
532 if (p != NULL) {
533 if (p->data_type != OSSL_PARAM_UTF8_STRING)
534 return 0;
535 OPENSSL_free(gctx->propq);
536 gctx->propq = OPENSSL_strdup(p->data);
537 if (gctx->propq == NULL)
538 return 0;
539 }
540
541 return 1;
542 }
543
544 static const OSSL_PARAM *ecx_gen_settable_params(ossl_unused void *genctx,
545 ossl_unused void *provctx)
546 {
547 static OSSL_PARAM settable[] = {
548 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
549 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
550 OSSL_PARAM_END
551 };
552 return settable;
553 }
554
555 static void *ecx_gen(struct ecx_gen_ctx *gctx)
556 {
557 ECX_KEY *key;
558 unsigned char *privkey;
559
560 if (gctx == NULL)
561 return NULL;
562 if ((key = ossl_ecx_key_new(gctx->libctx, gctx->type, 0,
563 gctx->propq)) == NULL) {
564 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
565 return NULL;
566 }
567
568 /* If we're doing parameter generation then we just return a blank key */
569 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
570 return key;
571
572 if ((privkey = ossl_ecx_key_allocate_privkey(key)) == NULL) {
573 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
574 goto err;
575 }
576 if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0)
577 goto err;
578 switch (gctx->type) {
579 case ECX_KEY_TYPE_X25519:
580 privkey[0] &= 248;
581 privkey[X25519_KEYLEN - 1] &= 127;
582 privkey[X25519_KEYLEN - 1] |= 64;
583 X25519_public_from_private(key->pubkey, privkey);
584 break;
585 case ECX_KEY_TYPE_X448:
586 privkey[0] &= 252;
587 privkey[X448_KEYLEN - 1] |= 128;
588 X448_public_from_private(key->pubkey, privkey);
589 break;
590 case ECX_KEY_TYPE_ED25519:
591 if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey,
592 gctx->propq))
593 goto err;
594 break;
595 case ECX_KEY_TYPE_ED448:
596 if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey,
597 gctx->propq))
598 goto err;
599 break;
600 }
601 key->haspubkey = 1;
602 return key;
603 err:
604 ossl_ecx_key_free(key);
605 return NULL;
606 }
607
608 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
609 {
610 struct ecx_gen_ctx *gctx = genctx;
611
612 if (!ossl_prov_is_running())
613 return 0;
614
615 #ifdef S390X_EC_ASM
616 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
617 return s390x_ecx_keygen25519(gctx);
618 #endif
619 return ecx_gen(gctx);
620 }
621
622 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
623 {
624 struct ecx_gen_ctx *gctx = genctx;
625
626 if (!ossl_prov_is_running())
627 return 0;
628
629 #ifdef S390X_EC_ASM
630 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
631 return s390x_ecx_keygen448(gctx);
632 #endif
633 return ecx_gen(gctx);
634 }
635
636 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
637 {
638 struct ecx_gen_ctx *gctx = genctx;
639
640 if (!ossl_prov_is_running())
641 return 0;
642
643 #ifdef S390X_EC_ASM
644 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
645 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
646 && OPENSSL_s390xcap_P.kdsa[0]
647 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
648 return s390x_ecd_keygen25519(gctx);
649 #endif
650 return ecx_gen(gctx);
651 }
652
653 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
654 {
655 struct ecx_gen_ctx *gctx = genctx;
656
657 if (!ossl_prov_is_running())
658 return 0;
659
660 #ifdef S390X_EC_ASM
661 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
662 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
663 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
664 return s390x_ecd_keygen448(gctx);
665 #endif
666 return ecx_gen(gctx);
667 }
668
669 static void ecx_gen_cleanup(void *genctx)
670 {
671 struct ecx_gen_ctx *gctx = genctx;
672
673 OPENSSL_free(gctx->propq);
674 OPENSSL_free(gctx);
675 }
676
677 void *ecx_load(const void *reference, size_t reference_sz)
678 {
679 ECX_KEY *key = NULL;
680
681 if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
682 /* The contents of the reference is the address to our object */
683 key = *(ECX_KEY **)reference;
684 /* We grabbed, so we detach it */
685 *(ECX_KEY **)reference = NULL;
686 return key;
687 }
688 return NULL;
689 }
690
691 static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
692 {
693 uint8_t pub[64];
694
695 switch (type) {
696 case ECX_KEY_TYPE_X25519:
697 X25519_public_from_private(pub, ecx->privkey);
698 break;
699 case ECX_KEY_TYPE_X448:
700 X448_public_from_private(pub, ecx->privkey);
701 break;
702 case ECX_KEY_TYPE_ED25519:
703 if (!ED25519_public_from_private(ecx->libctx, pub, ecx->privkey,
704 ecx->propq))
705 return 0;
706 break;
707 case ECX_KEY_TYPE_ED448:
708 if (!ED448_public_from_private(ecx->libctx, pub, ecx->privkey,
709 ecx->propq))
710 return 0;
711 break;
712 default:
713 return 0;
714 }
715 return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
716 }
717
718 static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
719 {
720 const ECX_KEY *ecx = keydata;
721 int ok = 0;
722
723 if (!ossl_prov_is_running())
724 return 0;
725
726 assert(keylen == ecx->keylen);
727
728 /*
729 * ECX keys have no parameters. But if EVP_PKEY_param_check() is called then
730 * we should return true.
731 */
732 if ((selection & (OSSL_KEYMGMT_SELECT_KEYPAIR
733 | OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
734 | OSSL_KEYMGMT_SELECT_OTHER_PARAMETERS)) != 0)
735 ok = 1;
736
737 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
738 ok = ok && ecx->haspubkey;
739
740 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
741 ok = ok && ecx->privkey != NULL;
742
743 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
744 ok = ok && ecx_key_pairwise_check(ecx, type);
745
746 return ok;
747 }
748
749 static int x25519_validate(const void *keydata, int selection, int checktype)
750 {
751 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
752 }
753
754 static int x448_validate(const void *keydata, int selection, int checktype)
755 {
756 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
757 }
758
759 static int ed25519_validate(const void *keydata, int selection, int checktype)
760 {
761 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
762 }
763
764 static int ed448_validate(const void *keydata, int selection, int checktype)
765 {
766 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
767 }
768
769 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
770 const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
771 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
772 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
773 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
774 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
775 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
776 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
777 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
778 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
779 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
780 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
781 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
782 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
783 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
784 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
785 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
786 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
787 (void (*)(void))ecx_gen_settable_params }, \
788 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
789 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
790 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
791 { 0, NULL } \
792 };
793
794 MAKE_KEYMGMT_FUNCTIONS(x25519)
795 MAKE_KEYMGMT_FUNCTIONS(x448)
796 MAKE_KEYMGMT_FUNCTIONS(ed25519)
797 MAKE_KEYMGMT_FUNCTIONS(ed448)
798
799 #ifdef S390X_EC_ASM
800 # include "s390x_arch.h"
801
802 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
803 {
804 static const unsigned char generator[] = {
805 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
806 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
807 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
808 };
809 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1,
810 gctx->propq);
811 unsigned char *privkey = NULL, *pubkey;
812
813 if (key == NULL) {
814 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
815 goto err;
816 }
817
818 /* If we're doing parameter generation then we just return a blank key */
819 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
820 return key;
821
822 pubkey = key->pubkey;
823
824 privkey = ossl_ecx_key_allocate_privkey(key);
825 if (privkey == NULL) {
826 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
827 goto err;
828 }
829
830 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN) <= 0)
831 goto err;
832
833 privkey[0] &= 248;
834 privkey[31] &= 127;
835 privkey[31] |= 64;
836
837 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
838 goto err;
839 key->haspubkey = 1;
840 return key;
841 err:
842 ossl_ecx_key_free(key);
843 return NULL;
844 }
845
846 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
847 {
848 static const unsigned char generator[] = {
849 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
851 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
852 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
853 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
854 };
855 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1,
856 gctx->propq);
857 unsigned char *privkey = NULL, *pubkey;
858
859 if (key == NULL) {
860 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
861 goto err;
862 }
863
864 /* If we're doing parameter generation then we just return a blank key */
865 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
866 return key;
867
868 pubkey = key->pubkey;
869
870 privkey = ossl_ecx_key_allocate_privkey(key);
871 if (privkey == NULL) {
872 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
873 goto err;
874 }
875
876 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN) <= 0)
877 goto err;
878
879 privkey[0] &= 252;
880 privkey[55] |= 128;
881
882 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
883 goto err;
884 key->haspubkey = 1;
885 return key;
886 err:
887 ossl_ecx_key_free(key);
888 return NULL;
889 }
890
891 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
892 {
893 static const unsigned char generator_x[] = {
894 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
895 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
896 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
897 };
898 static const unsigned char generator_y[] = {
899 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
900 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
901 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
902 };
903 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
904 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1,
905 gctx->propq);
906 unsigned char *privkey = NULL, *pubkey;
907 unsigned int sz;
908 EVP_MD *sha = NULL;
909 int j;
910
911 if (key == NULL) {
912 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
913 goto err;
914 }
915
916 /* If we're doing parameter generation then we just return a blank key */
917 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
918 return key;
919
920 pubkey = key->pubkey;
921
922 privkey = ossl_ecx_key_allocate_privkey(key);
923 if (privkey == NULL) {
924 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
925 goto err;
926 }
927
928 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN) <= 0)
929 goto err;
930
931 sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
932 if (sha == NULL)
933 goto err;
934 j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
935 EVP_MD_free(sha);
936 if (!j)
937 goto err;
938
939 buff[0] &= 248;
940 buff[31] &= 63;
941 buff[31] |= 64;
942
943 if (s390x_ed25519_mul(x_dst, pubkey,
944 generator_x, generator_y, buff) != 1)
945 goto err;
946
947 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
948 key->haspubkey = 1;
949 return key;
950 err:
951 ossl_ecx_key_free(key);
952 return NULL;
953 }
954
955 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
956 {
957 static const unsigned char generator_x[] = {
958 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
959 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
960 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
961 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
962 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
963 };
964 static const unsigned char generator_y[] = {
965 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
966 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
967 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
968 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
969 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
970 };
971 unsigned char x_dst[57], buff[114];
972 ECX_KEY *key = ossl_ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1,
973 gctx->propq);
974 unsigned char *privkey = NULL, *pubkey;
975 EVP_MD_CTX *hashctx = NULL;
976 EVP_MD *shake = NULL;
977
978 if (key == NULL) {
979 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
980 goto err;
981 }
982
983 /* If we're doing parameter generation then we just return a blank key */
984 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
985 return key;
986
987 pubkey = key->pubkey;
988
989 privkey = ossl_ecx_key_allocate_privkey(key);
990 if (privkey == NULL) {
991 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
992 goto err;
993 }
994
995 shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
996 if (shake == NULL)
997 goto err;
998 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN) <= 0)
999 goto err;
1000
1001 hashctx = EVP_MD_CTX_new();
1002 if (hashctx == NULL)
1003 goto err;
1004 if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
1005 goto err;
1006 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
1007 goto err;
1008 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
1009 goto err;
1010
1011 buff[0] &= -4;
1012 buff[55] |= 0x80;
1013 buff[56] = 0;
1014
1015 if (s390x_ed448_mul(x_dst, pubkey,
1016 generator_x, generator_y, buff) != 1)
1017 goto err;
1018
1019 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
1020 EVP_MD_CTX_free(hashctx);
1021 EVP_MD_free(shake);
1022 key->haspubkey = 1;
1023 return key;
1024 err:
1025 ossl_ecx_key_free(key);
1026 EVP_MD_CTX_free(hashctx);
1027 EVP_MD_free(shake);
1028 return NULL;
1029 }
1030 #endif