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