VirtualBox

source: vbox/trunk/src/libs/openssl-3.0.1/providers/implementations/keymgmt/ecx_kmgmt.c@ 94320

Last change on this file since 94320 was 94320, checked in by vboxsync, 3 years ago

libs/openssl-3.0.1: Export to OSE and fix copyright headers in Makefiles, bugref:10128

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette