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