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