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