]> git.ipfire.org Git - thirdparty/openssl.git/blob - providers/implementations/keymgmt/ecx_kmgmt.c
Update copyright year
[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_load_fn ecx_load;
45 static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
46 static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
47 static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
48 static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
49 static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
50 static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
51 static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
52 static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
53 static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
54 static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
55 static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
56 static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
57 static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
58 static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
59 static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
60 static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
61 static OSSL_FUNC_keymgmt_has_fn ecx_has;
62 static OSSL_FUNC_keymgmt_match_fn ecx_match;
63 static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
64 static OSSL_FUNC_keymgmt_validate_fn x448_validate;
65 static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
66 static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
67 static OSSL_FUNC_keymgmt_import_fn ecx_import;
68 static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
69 static OSSL_FUNC_keymgmt_export_fn ecx_export;
70 static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
71
72 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
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 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 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 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 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 && 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 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY);
377 if (p != NULL) {
378 void *buf = ecxkey->pubkey;
379
380 if (p->data_size != ecxkey->keylen
381 || !OSSL_PARAM_get_octet_string(p, &buf, sizeof(ecxkey->pubkey),
382 NULL))
383 return 0;
384 OPENSSL_clear_free(ecxkey->privkey, ecxkey->keylen);
385 ecxkey->privkey = NULL;
386 ecxkey->haspubkey = 1;
387 }
388 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_PROPERTIES);
389 if (p != NULL) {
390 if (p->data_type != OSSL_PARAM_UTF8_STRING
391 || !set_property_query(ecxkey, p->data))
392 return 0;
393 }
394
395 return 1;
396 }
397
398 static int x25519_set_params(void *key, const OSSL_PARAM params[])
399 {
400 return ecx_set_params(key, params);
401 }
402
403 static int x448_set_params(void *key, const OSSL_PARAM params[])
404 {
405 return ecx_set_params(key, params);
406 }
407
408 static int ed25519_set_params(void *key, const OSSL_PARAM params[])
409 {
410 return 1;
411 }
412
413 static int ed448_set_params(void *key, const OSSL_PARAM params[])
414 {
415 return 1;
416 }
417
418 static const OSSL_PARAM ecx_settable_params[] = {
419 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY, NULL, 0),
420 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES, NULL, 0),
421 OSSL_PARAM_END
422 };
423
424 static const OSSL_PARAM ed_settable_params[] = {
425 OSSL_PARAM_END
426 };
427
428 static const OSSL_PARAM *x25519_settable_params(void *provctx)
429 {
430 return ecx_settable_params;
431 }
432
433 static const OSSL_PARAM *x448_settable_params(void *provctx)
434 {
435 return ecx_settable_params;
436 }
437
438 static const OSSL_PARAM *ed25519_settable_params(void *provctx)
439 {
440 return ed_settable_params;
441 }
442
443 static const OSSL_PARAM *ed448_settable_params(void *provctx)
444 {
445 return ed_settable_params;
446 }
447
448 static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type)
449 {
450 OSSL_LIB_CTX *libctx = PROV_LIBCTX_OF(provctx);
451 struct ecx_gen_ctx *gctx = NULL;
452
453 if (!ossl_prov_is_running())
454 return NULL;
455
456 if ((gctx = OPENSSL_zalloc(sizeof(*gctx))) != NULL) {
457 gctx->libctx = libctx;
458 gctx->type = type;
459 gctx->selection = selection;
460 }
461 return gctx;
462 }
463
464 static void *x25519_gen_init(void *provctx, int selection)
465 {
466 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X25519);
467 }
468
469 static void *x448_gen_init(void *provctx, int selection)
470 {
471 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X448);
472 }
473
474 static void *ed25519_gen_init(void *provctx, int selection)
475 {
476 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED25519);
477 }
478
479 static void *ed448_gen_init(void *provctx, int selection)
480 {
481 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448);
482 }
483
484 static int ecx_gen_set_params(void *genctx, const OSSL_PARAM params[])
485 {
486 struct ecx_gen_ctx *gctx = genctx;
487 const OSSL_PARAM *p;
488
489 if (gctx == NULL)
490 return 0;
491
492 p = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME);
493 if (p != NULL) {
494 const char *groupname = NULL;
495
496 /*
497 * We optionally allow setting a group name - but each algorithm only
498 * support one such name, so all we do is verify that it is the one we
499 * expected.
500 */
501 switch (gctx->type) {
502 case ECX_KEY_TYPE_X25519:
503 groupname = "x25519";
504 break;
505 case ECX_KEY_TYPE_X448:
506 groupname = "x448";
507 break;
508 default:
509 /* We only support this for key exchange at the moment */
510 break;
511 }
512 if (p->data_type != OSSL_PARAM_UTF8_STRING
513 || groupname == NULL
514 || strcasecmp(p->data, groupname) != 0) {
515 ERR_raise(ERR_LIB_PROV, ERR_R_PASSED_INVALID_ARGUMENT);
516 return 0;
517 }
518 }
519 p = OSSL_PARAM_locate_const(params, OSSL_KDF_PARAM_PROPERTIES);
520 if (p != NULL) {
521 if (p->data_type != OSSL_PARAM_UTF8_STRING)
522 return 0;
523 OPENSSL_free(gctx->propq);
524 gctx->propq = OPENSSL_strdup(p->data);
525 if (gctx->propq == NULL)
526 return 0;
527 }
528
529 return 1;
530 }
531
532 static const OSSL_PARAM *ecx_gen_settable_params(void *provctx)
533 {
534 static OSSL_PARAM settable[] = {
535 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME, NULL, 0),
536 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES, NULL, 0),
537 OSSL_PARAM_END
538 };
539 return settable;
540 }
541
542 static void *ecx_gen(struct ecx_gen_ctx *gctx)
543 {
544 ECX_KEY *key;
545 unsigned char *privkey;
546
547 if (gctx == NULL)
548 return NULL;
549 if ((key = ecx_key_new(gctx->libctx, gctx->type, 0, gctx->propq)) == NULL) {
550 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
551 return NULL;
552 }
553
554 /* If we're doing parameter generation then we just return a blank key */
555 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
556 return key;
557
558 if ((privkey = ecx_key_allocate_privkey(key)) == NULL) {
559 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
560 goto err;
561 }
562 if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0)
563 goto err;
564 switch (gctx->type) {
565 case ECX_KEY_TYPE_X25519:
566 privkey[0] &= 248;
567 privkey[X25519_KEYLEN - 1] &= 127;
568 privkey[X25519_KEYLEN - 1] |= 64;
569 X25519_public_from_private(key->pubkey, privkey);
570 break;
571 case ECX_KEY_TYPE_X448:
572 privkey[0] &= 252;
573 privkey[X448_KEYLEN - 1] |= 128;
574 X448_public_from_private(key->pubkey, privkey);
575 break;
576 case ECX_KEY_TYPE_ED25519:
577 if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey,
578 gctx->propq))
579 goto err;
580 break;
581 case ECX_KEY_TYPE_ED448:
582 if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey,
583 gctx->propq))
584 goto err;
585 break;
586 }
587 key->haspubkey = 1;
588 return key;
589 err:
590 ecx_key_free(key);
591 return NULL;
592 }
593
594 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
595 {
596 struct ecx_gen_ctx *gctx = genctx;
597
598 if (!ossl_prov_is_running())
599 return 0;
600
601 #ifdef S390X_EC_ASM
602 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
603 return s390x_ecx_keygen25519(gctx);
604 #endif
605 return ecx_gen(gctx);
606 }
607
608 static void *x448_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_X448))
617 return s390x_ecx_keygen448(gctx);
618 #endif
619 return ecx_gen(gctx);
620 }
621
622 static void *ed25519_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_ED25519)
631 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
632 && OPENSSL_s390xcap_P.kdsa[0]
633 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
634 return s390x_ecd_keygen25519(gctx);
635 #endif
636 return ecx_gen(gctx);
637 }
638
639 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
640 {
641 struct ecx_gen_ctx *gctx = genctx;
642
643 if (!ossl_prov_is_running())
644 return 0;
645
646 #ifdef S390X_EC_ASM
647 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
648 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
649 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
650 return s390x_ecd_keygen448(gctx);
651 #endif
652 return ecx_gen(gctx);
653 }
654
655 static void ecx_gen_cleanup(void *genctx)
656 {
657 struct ecx_gen_ctx *gctx = genctx;
658
659 OPENSSL_free(gctx->propq);
660 OPENSSL_free(gctx);
661 }
662
663 void *ecx_load(const void *reference, size_t reference_sz)
664 {
665 ECX_KEY *key = NULL;
666
667 if (ossl_prov_is_running() && reference_sz == sizeof(key)) {
668 /* The contents of the reference is the address to our object */
669 key = *(ECX_KEY **)reference;
670 /* We grabbed, so we detach it */
671 *(ECX_KEY **)reference = NULL;
672 return key;
673 }
674 return NULL;
675 }
676
677 static int ecx_key_pairwise_check(const ECX_KEY *ecx, int type)
678 {
679 uint8_t pub[64];
680
681 switch (type) {
682 case ECX_KEY_TYPE_X25519:
683 X25519_public_from_private(pub, ecx->privkey);
684 break;
685 case ECX_KEY_TYPE_X448:
686 X448_public_from_private(pub, ecx->privkey);
687 break;
688 case ECX_KEY_TYPE_ED25519:
689 if (!ED25519_public_from_private(ecx->libctx, pub, ecx->privkey,
690 ecx->propq))
691 return 0;
692 break;
693 case ECX_KEY_TYPE_ED448:
694 if (!ED448_public_from_private(ecx->libctx, pub, ecx->privkey,
695 ecx->propq))
696 return 0;
697 break;
698 default:
699 return 0;
700 }
701 return CRYPTO_memcmp(ecx->pubkey, pub, ecx->keylen) == 0;
702 }
703
704 static int ecx_validate(const void *keydata, int selection, int type, size_t keylen)
705 {
706 const ECX_KEY *ecx = keydata;
707 int ok = 0;
708
709 if (!ossl_prov_is_running())
710 return 0;
711
712 assert(keylen == ecx->keylen);
713
714 if ((selection & ECX_POSSIBLE_SELECTIONS) != 0)
715 ok = 1;
716
717 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
718 ok = ok && ecx->haspubkey;
719
720 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
721 ok = ok && ecx->privkey != NULL;
722
723 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == OSSL_KEYMGMT_SELECT_KEYPAIR)
724 ok = ok && ecx_key_pairwise_check(ecx, type);
725
726 return ok;
727 }
728
729 static int x25519_validate(const void *keydata, int selection, int checktype)
730 {
731 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X25519, X25519_KEYLEN);
732 }
733
734 static int x448_validate(const void *keydata, int selection, int checktype)
735 {
736 return ecx_validate(keydata, selection, ECX_KEY_TYPE_X448, X448_KEYLEN);
737 }
738
739 static int ed25519_validate(const void *keydata, int selection, int checktype)
740 {
741 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED25519, ED25519_KEYLEN);
742 }
743
744 static int ed448_validate(const void *keydata, int selection, int checktype)
745 {
746 return ecx_validate(keydata, selection, ECX_KEY_TYPE_ED448, ED448_KEYLEN);
747 }
748
749 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
750 const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
751 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
752 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, \
753 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
754 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
755 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
756 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
757 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
758 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
759 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
760 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
761 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
762 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
763 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
764 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
765 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
766 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
767 (void (*)(void))ecx_gen_settable_params }, \
768 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
769 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
770 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
771 { 0, NULL } \
772 };
773
774 MAKE_KEYMGMT_FUNCTIONS(x25519)
775 MAKE_KEYMGMT_FUNCTIONS(x448)
776 MAKE_KEYMGMT_FUNCTIONS(ed25519)
777 MAKE_KEYMGMT_FUNCTIONS(ed448)
778
779 #ifdef S390X_EC_ASM
780 # include "s390x_arch.h"
781
782 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
783 {
784 static const unsigned char generator[] = {
785 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
786 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
787 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
788 };
789 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X25519, 1, gctx->propq);
790 unsigned char *privkey = NULL, *pubkey;
791
792 if (key == NULL) {
793 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
794 goto err;
795 }
796
797 /* If we're doing parameter generation then we just return a blank key */
798 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
799 return key;
800
801 pubkey = key->pubkey;
802
803 privkey = ecx_key_allocate_privkey(key);
804 if (privkey == NULL) {
805 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
806 goto err;
807 }
808
809 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN) <= 0)
810 goto err;
811
812 privkey[0] &= 248;
813 privkey[31] &= 127;
814 privkey[31] |= 64;
815
816 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
817 goto err;
818 key->haspubkey = 1;
819 return key;
820 err:
821 ecx_key_free(key);
822 return NULL;
823 }
824
825 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
826 {
827 static const unsigned char generator[] = {
828 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
829 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
830 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
831 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
833 };
834 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_X448, 1, gctx->propq);
835 unsigned char *privkey = NULL, *pubkey;
836
837 if (key == NULL) {
838 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
839 goto err;
840 }
841
842 /* If we're doing parameter generation then we just return a blank key */
843 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
844 return key;
845
846 pubkey = key->pubkey;
847
848 privkey = ecx_key_allocate_privkey(key);
849 if (privkey == NULL) {
850 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
851 goto err;
852 }
853
854 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN) <= 0)
855 goto err;
856
857 privkey[0] &= 252;
858 privkey[55] |= 128;
859
860 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
861 goto err;
862 key->haspubkey = 1;
863 return key;
864 err:
865 ecx_key_free(key);
866 return NULL;
867 }
868
869 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
870 {
871 static const unsigned char generator_x[] = {
872 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
873 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
874 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
875 };
876 static const unsigned char generator_y[] = {
877 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
878 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
879 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
880 };
881 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
882 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED25519, 1, gctx->propq);
883 unsigned char *privkey = NULL, *pubkey;
884 unsigned int sz;
885 EVP_MD *sha = NULL;
886 int j;
887
888 if (key == NULL) {
889 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
890 goto err;
891 }
892
893 /* If we're doing parameter generation then we just return a blank key */
894 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
895 return key;
896
897 pubkey = key->pubkey;
898
899 privkey = ecx_key_allocate_privkey(key);
900 if (privkey == NULL) {
901 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
902 goto err;
903 }
904
905 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN) <= 0)
906 goto err;
907
908 sha = EVP_MD_fetch(gctx->libctx, "SHA512", gctx->propq);
909 if (sha == NULL)
910 goto err;
911 j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
912 EVP_MD_free(sha);
913 if (!j)
914 goto err;
915
916 buff[0] &= 248;
917 buff[31] &= 63;
918 buff[31] |= 64;
919
920 if (s390x_ed25519_mul(x_dst, pubkey,
921 generator_x, generator_y, buff) != 1)
922 goto err;
923
924 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
925 key->haspubkey = 1;
926 return key;
927 err:
928 ecx_key_free(key);
929 return NULL;
930 }
931
932 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
933 {
934 static const unsigned char generator_x[] = {
935 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
936 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
937 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
938 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
939 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
940 };
941 static const unsigned char generator_y[] = {
942 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
943 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
944 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
945 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
946 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
947 };
948 unsigned char x_dst[57], buff[114];
949 ECX_KEY *key = ecx_key_new(gctx->libctx, ECX_KEY_TYPE_ED448, 1, gctx->propq);
950 unsigned char *privkey = NULL, *pubkey;
951 EVP_MD_CTX *hashctx = NULL;
952 EVP_MD *shake = NULL;
953
954 if (key == NULL) {
955 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
956 goto err;
957 }
958
959 /* If we're doing parameter generation then we just return a blank key */
960 if ((gctx->selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
961 return key;
962
963 pubkey = key->pubkey;
964
965 privkey = ecx_key_allocate_privkey(key);
966 if (privkey == NULL) {
967 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
968 goto err;
969 }
970
971 shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", gctx->propq);
972 if (shake == NULL)
973 goto err;
974 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN) <= 0)
975 goto err;
976
977 hashctx = EVP_MD_CTX_new();
978 if (hashctx == NULL)
979 goto err;
980 if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
981 goto err;
982 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
983 goto err;
984 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
985 goto err;
986
987 buff[0] &= -4;
988 buff[55] |= 0x80;
989 buff[56] = 0;
990
991 if (s390x_ed448_mul(x_dst, pubkey,
992 generator_x, generator_y, buff) != 1)
993 goto err;
994
995 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
996 EVP_MD_CTX_free(hashctx);
997 EVP_MD_free(shake);
998 key->haspubkey = 1;
999 return key;
1000 err:
1001 ecx_key_free(key);
1002 EVP_MD_CTX_free(hashctx);
1003 EVP_MD_free(shake);
1004 return NULL;
1005 }
1006 #endif