VirtualBox

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

Last change on this file since 104078 was 104078, checked in by vboxsync, 11 months ago

openssl-3.1.5: Applied and adjusted our OpenSSL changes to 3.1.4. bugref:10638

File size: 32.2 KB
Line 
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
30static OSSL_FUNC_keymgmt_new_fn x25519_new_key;
31static OSSL_FUNC_keymgmt_new_fn x448_new_key;
32static OSSL_FUNC_keymgmt_new_fn ed25519_new_key;
33static OSSL_FUNC_keymgmt_new_fn ed448_new_key;
34static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init;
35static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init;
36static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init;
37static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init;
38static OSSL_FUNC_keymgmt_gen_fn x25519_gen;
39static OSSL_FUNC_keymgmt_gen_fn x448_gen;
40static OSSL_FUNC_keymgmt_gen_fn ed25519_gen;
41static OSSL_FUNC_keymgmt_gen_fn ed448_gen;
42static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
43static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params;
44static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params;
45static OSSL_FUNC_keymgmt_load_fn ecx_load;
46static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params;
47static OSSL_FUNC_keymgmt_get_params_fn x448_get_params;
48static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params;
49static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params;
50static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params;
51static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params;
52static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params;
53static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params;
54static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params;
55static OSSL_FUNC_keymgmt_set_params_fn x448_set_params;
56static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params;
57static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params;
58static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params;
59static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params;
60static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params;
61static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params;
62static OSSL_FUNC_keymgmt_has_fn ecx_has;
63static OSSL_FUNC_keymgmt_match_fn ecx_match;
64static OSSL_FUNC_keymgmt_validate_fn x25519_validate;
65static OSSL_FUNC_keymgmt_validate_fn x448_validate;
66static OSSL_FUNC_keymgmt_validate_fn ed25519_validate;
67static OSSL_FUNC_keymgmt_validate_fn ed448_validate;
68static OSSL_FUNC_keymgmt_import_fn ecx_import;
69static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types;
70static OSSL_FUNC_keymgmt_export_fn ecx_export;
71static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types;
72static OSSL_FUNC_keymgmt_dup_fn ecx_dup;
73
74#define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
75
76struct 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
84static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
85static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
86static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
87static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
88#endif
89
90static 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
98static 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
106static 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
114static 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
122static 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
143static 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
191static 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
209static 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
230static 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);
261err:
262 OSSL_PARAM_BLD_free(tmpl);
263 return ret;
264}
265
266#define ECX_KEY_TYPES() \
267OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \
268OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
269
270static const OSSL_PARAM ecx_key_types[] = {
271 ECX_KEY_TYPES(),
272 OSSL_PARAM_END
273};
274static 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
281static 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
306static 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
317static 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
323static 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
329static 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
336static 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
343static 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
353static 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
361static const OSSL_PARAM *x25519_gettable_params(void *provctx)
362{
363 return ecx_gettable_params;
364}
365
366static const OSSL_PARAM *x448_gettable_params(void *provctx)
367{
368 return ecx_gettable_params;
369}
370
371static const OSSL_PARAM *ed25519_gettable_params(void *provctx)
372{
373 return ed_gettable_params;
374}
375
376static const OSSL_PARAM *ed448_gettable_params(void *provctx)
377{
378 return ed_gettable_params;
379}
380
381static 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
395static 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
425static int x25519_set_params(void *key, const OSSL_PARAM params[])
426{
427 return ecx_set_params(key, params);
428}
429
430static int x448_set_params(void *key, const OSSL_PARAM params[])
431{
432 return ecx_set_params(key, params);
433}
434
435static int ed25519_set_params(void *key, const OSSL_PARAM params[])
436{
437 return 1;
438}
439
440static int ed448_set_params(void *key, const OSSL_PARAM params[])
441{
442 return 1;
443}
444
445static 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
451static const OSSL_PARAM ed_settable_params[] = {
452 OSSL_PARAM_END
453};
454
455static const OSSL_PARAM *x25519_settable_params(void *provctx)
456{
457 return ecx_settable_params;
458}
459
460static const OSSL_PARAM *x448_settable_params(void *provctx)
461{
462 return ecx_settable_params;
463}
464
465static const OSSL_PARAM *ed25519_settable_params(void *provctx)
466{
467 return ed_settable_params;
468}
469
470static const OSSL_PARAM *ed448_settable_params(void *provctx)
471{
472 return ed_settable_params;
473}
474
475static 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
496static 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
502static 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
508static 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
514static 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
520static 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
568static 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
579static 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;
627err:
628 ossl_ecx_key_free(key);
629 return NULL;
630}
631
632static 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
646static 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
660static 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
677static 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
693static 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
701void *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
715static 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
722static 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
749static 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
777static 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
782static 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
787static 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
792static 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
823MAKE_KEYMGMT_FUNCTIONS(x25519)
824MAKE_KEYMGMT_FUNCTIONS(x448)
825MAKE_KEYMGMT_FUNCTIONS(ed25519)
826MAKE_KEYMGMT_FUNCTIONS(ed448)
827
828#ifdef S390X_EC_ASM
829# include "s390x_arch.h"
830
831static 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
875static 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
920static 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
984static 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
Note: See TracBrowser for help on using the repository browser.

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