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