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