2 * Copyright 2020-2022 The OpenSSL Project Authors. All Rights Reserved.
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
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"
27 # include "s390x_arch.h"
28 # include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
31 static OSSL_FUNC_keymgmt_new_fn x25519_new_key
;
32 static OSSL_FUNC_keymgmt_new_fn x448_new_key
;
33 static OSSL_FUNC_keymgmt_new_fn ed25519_new_key
;
34 static OSSL_FUNC_keymgmt_new_fn ed448_new_key
;
35 static OSSL_FUNC_keymgmt_gen_init_fn x25519_gen_init
;
36 static OSSL_FUNC_keymgmt_gen_init_fn x448_gen_init
;
37 static OSSL_FUNC_keymgmt_gen_init_fn ed25519_gen_init
;
38 static OSSL_FUNC_keymgmt_gen_init_fn ed448_gen_init
;
39 static OSSL_FUNC_keymgmt_gen_fn x25519_gen
;
40 static OSSL_FUNC_keymgmt_gen_fn x448_gen
;
41 static OSSL_FUNC_keymgmt_gen_fn ed25519_gen
;
42 static OSSL_FUNC_keymgmt_gen_fn ed448_gen
;
43 static OSSL_FUNC_keymgmt_gen_cleanup_fn ecx_gen_cleanup
;
44 static OSSL_FUNC_keymgmt_gen_set_params_fn ecx_gen_set_params
;
45 static OSSL_FUNC_keymgmt_gen_settable_params_fn ecx_gen_settable_params
;
46 static OSSL_FUNC_keymgmt_load_fn ecx_load
;
47 static OSSL_FUNC_keymgmt_get_params_fn x25519_get_params
;
48 static OSSL_FUNC_keymgmt_get_params_fn x448_get_params
;
49 static OSSL_FUNC_keymgmt_get_params_fn ed25519_get_params
;
50 static OSSL_FUNC_keymgmt_get_params_fn ed448_get_params
;
51 static OSSL_FUNC_keymgmt_gettable_params_fn x25519_gettable_params
;
52 static OSSL_FUNC_keymgmt_gettable_params_fn x448_gettable_params
;
53 static OSSL_FUNC_keymgmt_gettable_params_fn ed25519_gettable_params
;
54 static OSSL_FUNC_keymgmt_gettable_params_fn ed448_gettable_params
;
55 static OSSL_FUNC_keymgmt_set_params_fn x25519_set_params
;
56 static OSSL_FUNC_keymgmt_set_params_fn x448_set_params
;
57 static OSSL_FUNC_keymgmt_set_params_fn ed25519_set_params
;
58 static OSSL_FUNC_keymgmt_set_params_fn ed448_set_params
;
59 static OSSL_FUNC_keymgmt_settable_params_fn x25519_settable_params
;
60 static OSSL_FUNC_keymgmt_settable_params_fn x448_settable_params
;
61 static OSSL_FUNC_keymgmt_settable_params_fn ed25519_settable_params
;
62 static OSSL_FUNC_keymgmt_settable_params_fn ed448_settable_params
;
63 static OSSL_FUNC_keymgmt_has_fn ecx_has
;
64 static OSSL_FUNC_keymgmt_match_fn ecx_match
;
65 static OSSL_FUNC_keymgmt_validate_fn x25519_validate
;
66 static OSSL_FUNC_keymgmt_validate_fn x448_validate
;
67 static OSSL_FUNC_keymgmt_validate_fn ed25519_validate
;
68 static OSSL_FUNC_keymgmt_validate_fn ed448_validate
;
69 static OSSL_FUNC_keymgmt_import_fn ecx_import
;
70 static OSSL_FUNC_keymgmt_import_types_fn ecx_imexport_types
;
71 static OSSL_FUNC_keymgmt_export_fn ecx_export
;
72 static OSSL_FUNC_keymgmt_export_types_fn ecx_imexport_types
;
73 static OSSL_FUNC_keymgmt_dup_fn ecx_dup
;
75 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
82 unsigned char *dhkem_ikm
;
87 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx
*gctx
);
88 static void *s390x_ecx_keygen448(struct ecx_gen_ctx
*gctx
);
89 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx
*gctx
);
90 static void *s390x_ecd_keygen448(struct ecx_gen_ctx
*gctx
);
93 static void *x25519_new_key(void *provctx
)
95 if (!ossl_prov_is_running())
97 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx
), ECX_KEY_TYPE_X25519
, 0,
101 static void *x448_new_key(void *provctx
)
103 if (!ossl_prov_is_running())
105 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx
), ECX_KEY_TYPE_X448
, 0,
109 static void *ed25519_new_key(void *provctx
)
111 if (!ossl_prov_is_running())
113 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx
), ECX_KEY_TYPE_ED25519
, 0,
117 static void *ed448_new_key(void *provctx
)
119 if (!ossl_prov_is_running())
121 return ossl_ecx_key_new(PROV_LIBCTX_OF(provctx
), ECX_KEY_TYPE_ED448
, 0,
125 static int ecx_has(const void *keydata
, int selection
)
127 const ECX_KEY
*key
= keydata
;
130 if (ossl_prov_is_running() && key
!= NULL
) {
132 * ECX keys always have all the parameters they need (i.e. none).
133 * Therefore we always return with 1, if asked about parameters.
137 if ((selection
& OSSL_KEYMGMT_SELECT_PUBLIC_KEY
) != 0)
138 ok
= ok
&& key
->haspubkey
;
140 if ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) != 0)
141 ok
= ok
&& key
->privkey
!= NULL
;
146 static int ecx_match(const void *keydata1
, const void *keydata2
, int selection
)
148 const ECX_KEY
*key1
= keydata1
;
149 const ECX_KEY
*key2
= keydata2
;
152 if (!ossl_prov_is_running())
155 if ((selection
& OSSL_KEYMGMT_SELECT_DOMAIN_PARAMETERS
) != 0)
156 ok
= ok
&& key1
->type
== key2
->type
;
157 if ((selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) != 0) {
160 if ((selection
& OSSL_KEYMGMT_SELECT_PUBLIC_KEY
) != 0) {
161 const unsigned char *pa
= key1
->haspubkey
? key1
->pubkey
: NULL
;
162 const unsigned char *pb
= key2
->haspubkey
? key2
->pubkey
: NULL
;
163 size_t pal
= key1
->keylen
;
164 size_t pbl
= key2
->keylen
;
166 if (pa
!= NULL
&& pb
!= NULL
) {
168 && key1
->type
== key2
->type
170 && CRYPTO_memcmp(pa
, pb
, pal
) == 0;
175 && (selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) != 0) {
176 const unsigned char *pa
= key1
->privkey
;
177 const unsigned char *pb
= key2
->privkey
;
178 size_t pal
= key1
->keylen
;
179 size_t pbl
= key2
->keylen
;
181 if (pa
!= NULL
&& pb
!= NULL
) {
183 && key1
->type
== key2
->type
185 && CRYPTO_memcmp(pa
, pb
, pal
) == 0;
189 ok
= ok
&& key_checked
;
194 static int ecx_import(void *keydata
, int selection
, const OSSL_PARAM params
[])
196 ECX_KEY
*key
= keydata
;
200 if (!ossl_prov_is_running() || key
== NULL
)
203 if ((selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) == 0)
206 include_private
= selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
? 1 : 0;
207 ok
= ok
&& ossl_ecx_key_fromdata(key
, params
, include_private
);
212 static int key_to_params(ECX_KEY
*key
, OSSL_PARAM_BLD
*tmpl
,
213 OSSL_PARAM params
[], int include_private
)
218 if (!ossl_param_build_set_octet_string(tmpl
, params
,
219 OSSL_PKEY_PARAM_PUB_KEY
,
220 key
->pubkey
, key
->keylen
))
224 && key
->privkey
!= NULL
225 && !ossl_param_build_set_octet_string(tmpl
, params
,
226 OSSL_PKEY_PARAM_PRIV_KEY
,
227 key
->privkey
, key
->keylen
))
233 static int ecx_export(void *keydata
, int selection
, OSSL_CALLBACK
*param_cb
,
236 ECX_KEY
*key
= keydata
;
237 OSSL_PARAM_BLD
*tmpl
;
238 OSSL_PARAM
*params
= NULL
;
241 if (!ossl_prov_is_running() || key
== NULL
)
244 tmpl
= OSSL_PARAM_BLD_new();
248 if ((selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) != 0) {
249 int include_private
= ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) != 0);
251 if (!key_to_params(key
, tmpl
, NULL
, include_private
))
255 params
= OSSL_PARAM_BLD_to_param(tmpl
);
259 ret
= param_cb(params
, cbarg
);
260 OSSL_PARAM_free(params
);
262 OSSL_PARAM_BLD_free(tmpl
);
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)
270 static const OSSL_PARAM ecx_key_types
[] = {
274 static const OSSL_PARAM
*ecx_imexport_types(int selection
)
276 if ((selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) != 0)
277 return ecx_key_types
;
281 static int ecx_get_params(void *key
, OSSL_PARAM params
[], int bits
, int secbits
,
287 if ((p
= OSSL_PARAM_locate(params
, OSSL_PKEY_PARAM_BITS
)) != NULL
288 && !OSSL_PARAM_set_int(p
, bits
))
290 if ((p
= OSSL_PARAM_locate(params
, OSSL_PKEY_PARAM_SECURITY_BITS
)) != NULL
291 && !OSSL_PARAM_set_int(p
, secbits
))
293 if ((p
= OSSL_PARAM_locate(params
, OSSL_PKEY_PARAM_MAX_SIZE
)) != NULL
294 && !OSSL_PARAM_set_int(p
, size
))
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
))
303 return key_to_params(ecx
, NULL
, params
, 1);
306 static int ed_get_params(void *key
, OSSL_PARAM params
[])
310 if ((p
= OSSL_PARAM_locate(params
,
311 OSSL_PKEY_PARAM_MANDATORY_DIGEST
)) != NULL
312 && !OSSL_PARAM_set_utf8_string(p
, ""))
317 static int x25519_get_params(void *key
, OSSL_PARAM params
[])
319 return ecx_get_params(key
, params
, X25519_BITS
, X25519_SECURITY_BITS
,
323 static int x448_get_params(void *key
, OSSL_PARAM params
[])
325 return ecx_get_params(key
, params
, X448_BITS
, X448_SECURITY_BITS
,
329 static int ed25519_get_params(void *key
, OSSL_PARAM params
[])
331 return ecx_get_params(key
, params
, ED25519_BITS
, ED25519_SECURITY_BITS
,
333 && ed_get_params(key
, params
);
336 static int ed448_get_params(void *key
, OSSL_PARAM params
[])
338 return ecx_get_params(key
, params
, ED448_BITS
, ED448_SECURITY_BITS
,
340 && ed_get_params(key
, params
);
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),
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
),
361 static const OSSL_PARAM
*x25519_gettable_params(void *provctx
)
363 return ecx_gettable_params
;
366 static const OSSL_PARAM
*x448_gettable_params(void *provctx
)
368 return ecx_gettable_params
;
371 static const OSSL_PARAM
*ed25519_gettable_params(void *provctx
)
373 return ed_gettable_params
;
376 static const OSSL_PARAM
*ed448_gettable_params(void *provctx
)
378 return ed_gettable_params
;
381 static int set_property_query(ECX_KEY
*ecxkey
, const char *propq
)
383 OPENSSL_free(ecxkey
->propq
);
384 ecxkey
->propq
= NULL
;
386 ecxkey
->propq
= OPENSSL_strdup(propq
);
387 if (ecxkey
->propq
== NULL
)
393 static int ecx_set_params(void *key
, const OSSL_PARAM params
[])
395 ECX_KEY
*ecxkey
= key
;
401 p
= OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY
);
403 void *buf
= ecxkey
->pubkey
;
405 if (p
->data_size
!= ecxkey
->keylen
406 || !OSSL_PARAM_get_octet_string(p
, &buf
, sizeof(ecxkey
->pubkey
),
409 OPENSSL_clear_free(ecxkey
->privkey
, ecxkey
->keylen
);
410 ecxkey
->privkey
= NULL
;
411 ecxkey
->haspubkey
= 1;
413 p
= OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_PROPERTIES
);
415 if (p
->data_type
!= OSSL_PARAM_UTF8_STRING
416 || !set_property_query(ecxkey
, p
->data
))
423 static int x25519_set_params(void *key
, const OSSL_PARAM params
[])
425 return ecx_set_params(key
, params
);
428 static int x448_set_params(void *key
, const OSSL_PARAM params
[])
430 return ecx_set_params(key
, params
);
433 static int ed25519_set_params(void *key
, const OSSL_PARAM params
[])
438 static int ed448_set_params(void *key
, const OSSL_PARAM params
[])
443 static const OSSL_PARAM ecx_settable_params
[] = {
444 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_ENCODED_PUBLIC_KEY
, NULL
, 0),
445 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_PROPERTIES
, NULL
, 0),
449 static const OSSL_PARAM ed_settable_params
[] = {
453 static const OSSL_PARAM
*x25519_settable_params(void *provctx
)
455 return ecx_settable_params
;
458 static const OSSL_PARAM
*x448_settable_params(void *provctx
)
460 return ecx_settable_params
;
463 static const OSSL_PARAM
*ed25519_settable_params(void *provctx
)
465 return ed_settable_params
;
468 static const OSSL_PARAM
*ed448_settable_params(void *provctx
)
470 return ed_settable_params
;
473 static void *ecx_gen_init(void *provctx
, int selection
,
474 const OSSL_PARAM params
[], ECX_KEY_TYPE type
)
476 OSSL_LIB_CTX
*libctx
= PROV_LIBCTX_OF(provctx
);
477 struct ecx_gen_ctx
*gctx
= NULL
;
479 if (!ossl_prov_is_running())
482 if ((gctx
= OPENSSL_zalloc(sizeof(*gctx
))) != NULL
) {
483 gctx
->libctx
= libctx
;
485 gctx
->selection
= selection
;
487 if (!ecx_gen_set_params(gctx
, params
)) {
494 static void *x25519_gen_init(void *provctx
, int selection
,
495 const OSSL_PARAM params
[])
497 return ecx_gen_init(provctx
, selection
, params
, ECX_KEY_TYPE_X25519
);
500 static void *x448_gen_init(void *provctx
, int selection
,
501 const OSSL_PARAM params
[])
503 return ecx_gen_init(provctx
, selection
, params
, ECX_KEY_TYPE_X448
);
506 static void *ed25519_gen_init(void *provctx
, int selection
,
507 const OSSL_PARAM params
[])
509 return ecx_gen_init(provctx
, selection
, params
, ECX_KEY_TYPE_ED25519
);
512 static void *ed448_gen_init(void *provctx
, int selection
,
513 const OSSL_PARAM params
[])
515 return ecx_gen_init(provctx
, selection
, params
, ECX_KEY_TYPE_ED448
);
518 static int ecx_gen_set_params(void *genctx
, const OSSL_PARAM params
[])
520 struct ecx_gen_ctx
*gctx
= genctx
;
526 p
= OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_GROUP_NAME
);
528 const char *groupname
= NULL
;
531 * We optionally allow setting a group name - but each algorithm only
532 * support one such name, so all we do is verify that it is the one we
535 switch (gctx
->type
) {
536 case ECX_KEY_TYPE_X25519
:
537 groupname
= "x25519";
539 case ECX_KEY_TYPE_X448
:
543 /* We only support this for key exchange at the moment */
546 if (p
->data_type
!= OSSL_PARAM_UTF8_STRING
548 || OPENSSL_strcasecmp(p
->data
, groupname
) != 0) {
549 ERR_raise(ERR_LIB_PROV
, ERR_R_PASSED_INVALID_ARGUMENT
);
553 p
= OSSL_PARAM_locate_const(params
, OSSL_KDF_PARAM_PROPERTIES
);
555 if (p
->data_type
!= OSSL_PARAM_UTF8_STRING
)
557 OPENSSL_free(gctx
->propq
);
558 gctx
->propq
= OPENSSL_strdup(p
->data
);
559 if (gctx
->propq
== NULL
)
562 p
= OSSL_PARAM_locate_const(params
, OSSL_PKEY_PARAM_DHKEM_IKM
);
564 if (p
->data_size
!= 0 && p
->data
!= NULL
) {
565 OPENSSL_free(gctx
->dhkem_ikm
);
566 gctx
->dhkem_ikm
= NULL
;
567 if (!OSSL_PARAM_get_octet_string(p
, (void **)&gctx
->dhkem_ikm
, 0,
568 &gctx
->dhkem_ikmlen
))
576 static const OSSL_PARAM
*ecx_gen_settable_params(ossl_unused
void *genctx
,
577 ossl_unused
void *provctx
)
579 static OSSL_PARAM settable
[] = {
580 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_GROUP_NAME
, NULL
, 0),
581 OSSL_PARAM_utf8_string(OSSL_KDF_PARAM_PROPERTIES
, NULL
, 0),
582 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_DHKEM_IKM
, NULL
, 0),
588 static void *ecx_gen(struct ecx_gen_ctx
*gctx
)
591 unsigned char *privkey
;
595 if ((key
= ossl_ecx_key_new(gctx
->libctx
, gctx
->type
, 0,
596 gctx
->propq
)) == NULL
) {
597 ERR_raise(ERR_LIB_PROV
, ERR_R_EC_LIB
);
601 /* If we're doing parameter generation then we just return a blank key */
602 if ((gctx
->selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) == 0)
605 if ((privkey
= ossl_ecx_key_allocate_privkey(key
)) == NULL
) {
606 ERR_raise(ERR_LIB_PROV
, ERR_R_EC_LIB
);
610 if (gctx
->dhkem_ikm
!= NULL
&& gctx
->dhkem_ikmlen
!= 0) {
611 if (gctx
->type
== ECX_KEY_TYPE_ED25519
612 || gctx
->type
== ECX_KEY_TYPE_ED448
)
614 if (!ossl_ecx_dhkem_derive_private(key
, privkey
,
615 gctx
->dhkem_ikm
, gctx
->dhkem_ikmlen
))
620 if (RAND_priv_bytes_ex(gctx
->libctx
, privkey
, key
->keylen
, 0) <= 0)
624 switch (gctx
->type
) {
625 case ECX_KEY_TYPE_X25519
:
627 privkey
[X25519_KEYLEN
- 1] &= 127;
628 privkey
[X25519_KEYLEN
- 1] |= 64;
629 ossl_x25519_public_from_private(key
->pubkey
, privkey
);
631 case ECX_KEY_TYPE_X448
:
633 privkey
[X448_KEYLEN
- 1] |= 128;
634 ossl_x448_public_from_private(key
->pubkey
, privkey
);
636 case ECX_KEY_TYPE_ED25519
:
637 if (!ossl_ed25519_public_from_private(gctx
->libctx
, key
->pubkey
, privkey
,
641 case ECX_KEY_TYPE_ED448
:
642 if (!ossl_ed448_public_from_private(gctx
->libctx
, key
->pubkey
, privkey
,
650 ossl_ecx_key_free(key
);
654 static void *x25519_gen(void *genctx
, OSSL_CALLBACK
*osslcb
, void *cbarg
)
656 struct ecx_gen_ctx
*gctx
= genctx
;
658 if (!ossl_prov_is_running())
662 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519
))
663 return s390x_ecx_keygen25519(gctx
);
665 return ecx_gen(gctx
);
668 static void *x448_gen(void *genctx
, OSSL_CALLBACK
*osslcb
, void *cbarg
)
670 struct ecx_gen_ctx
*gctx
= genctx
;
672 if (!ossl_prov_is_running())
676 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448
))
677 return s390x_ecx_keygen448(gctx
);
679 return ecx_gen(gctx
);
682 static void *ed25519_gen(void *genctx
, OSSL_CALLBACK
*osslcb
, void *cbarg
)
684 struct ecx_gen_ctx
*gctx
= genctx
;
686 if (!ossl_prov_is_running())
690 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519
)
691 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519
)
692 && OPENSSL_s390xcap_P
.kdsa
[0]
693 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519
))
694 return s390x_ecd_keygen25519(gctx
);
696 return ecx_gen(gctx
);
699 static void *ed448_gen(void *genctx
, OSSL_CALLBACK
*osslcb
, void *cbarg
)
701 struct ecx_gen_ctx
*gctx
= genctx
;
703 if (!ossl_prov_is_running())
707 if (OPENSSL_s390xcap_P
.pcc
[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448
)
708 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448
)
709 && OPENSSL_s390xcap_P
.kdsa
[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448
))
710 return s390x_ecd_keygen448(gctx
);
712 return ecx_gen(gctx
);
715 static void ecx_gen_cleanup(void *genctx
)
717 struct ecx_gen_ctx
*gctx
= genctx
;
719 OPENSSL_clear_free(gctx
->dhkem_ikm
, gctx
->dhkem_ikmlen
);
720 OPENSSL_free(gctx
->propq
);
724 void *ecx_load(const void *reference
, size_t reference_sz
)
728 if (ossl_prov_is_running() && reference_sz
== sizeof(key
)) {
729 /* The contents of the reference is the address to our object */
730 key
= *(ECX_KEY
**)reference
;
731 /* We grabbed, so we detach it */
732 *(ECX_KEY
**)reference
= NULL
;
738 static void *ecx_dup(const void *keydata_from
, int selection
)
740 if (ossl_prov_is_running())
741 return ossl_ecx_key_dup(keydata_from
, selection
);
745 static int ecx_key_pairwise_check(const ECX_KEY
*ecx
, int type
)
750 case ECX_KEY_TYPE_X25519
:
751 ossl_x25519_public_from_private(pub
, ecx
->privkey
);
753 case ECX_KEY_TYPE_X448
:
754 ossl_x448_public_from_private(pub
, ecx
->privkey
);
756 case ECX_KEY_TYPE_ED25519
:
757 if (!ossl_ed25519_public_from_private(ecx
->libctx
, pub
, ecx
->privkey
,
761 case ECX_KEY_TYPE_ED448
:
762 if (!ossl_ed448_public_from_private(ecx
->libctx
, pub
, ecx
->privkey
,
769 return CRYPTO_memcmp(ecx
->pubkey
, pub
, ecx
->keylen
) == 0;
772 static int ecx_validate(const void *keydata
, int selection
, int type
, size_t keylen
)
774 const ECX_KEY
*ecx
= keydata
;
775 int ok
= keylen
== ecx
->keylen
;
777 if (!ossl_prov_is_running())
780 if ((selection
& ECX_POSSIBLE_SELECTIONS
) == 0)
781 return 1; /* nothing to validate */
784 ERR_raise(ERR_LIB_PROV
, PROV_R_ALGORITHM_MISMATCH
);
788 if ((selection
& OSSL_KEYMGMT_SELECT_PUBLIC_KEY
) != 0)
789 ok
= ok
&& ecx
->haspubkey
;
791 if ((selection
& OSSL_KEYMGMT_SELECT_PRIVATE_KEY
) != 0)
792 ok
= ok
&& ecx
->privkey
!= NULL
;
794 if ((selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) == OSSL_KEYMGMT_SELECT_KEYPAIR
)
795 ok
= ok
&& ecx_key_pairwise_check(ecx
, type
);
800 static int x25519_validate(const void *keydata
, int selection
, int checktype
)
802 return ecx_validate(keydata
, selection
, ECX_KEY_TYPE_X25519
, X25519_KEYLEN
);
805 static int x448_validate(const void *keydata
, int selection
, int checktype
)
807 return ecx_validate(keydata
, selection
, ECX_KEY_TYPE_X448
, X448_KEYLEN
);
810 static int ed25519_validate(const void *keydata
, int selection
, int checktype
)
812 return ecx_validate(keydata
, selection
, ECX_KEY_TYPE_ED25519
, ED25519_KEYLEN
);
815 static int ed448_validate(const void *keydata
, int selection
, int checktype
)
817 return ecx_validate(keydata
, selection
, ECX_KEY_TYPE_ED448
, ED448_KEYLEN
);
820 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
821 const OSSL_DISPATCH ossl_##alg##_keymgmt_functions[] = { \
822 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
823 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ossl_ecx_key_free }, \
824 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
825 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
826 { OSSL_FUNC_KEYMGMT_SET_PARAMS, (void (*) (void))alg##_set_params }, \
827 { OSSL_FUNC_KEYMGMT_SETTABLE_PARAMS, (void (*) (void))alg##_settable_params }, \
828 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
829 { OSSL_FUNC_KEYMGMT_MATCH, (void (*)(void))ecx_match }, \
830 { OSSL_FUNC_KEYMGMT_VALIDATE, (void (*)(void))alg##_validate }, \
831 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
832 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
833 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
834 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
835 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
836 { OSSL_FUNC_KEYMGMT_GEN_SET_PARAMS, (void (*)(void))ecx_gen_set_params }, \
837 { OSSL_FUNC_KEYMGMT_GEN_SETTABLE_PARAMS, \
838 (void (*)(void))ecx_gen_settable_params }, \
839 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
840 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
841 { OSSL_FUNC_KEYMGMT_LOAD, (void (*)(void))ecx_load }, \
842 { OSSL_FUNC_KEYMGMT_DUP, (void (*)(void))ecx_dup }, \
846 MAKE_KEYMGMT_FUNCTIONS(x25519
)
847 MAKE_KEYMGMT_FUNCTIONS(x448
)
848 MAKE_KEYMGMT_FUNCTIONS(ed25519
)
849 MAKE_KEYMGMT_FUNCTIONS(ed448
)
852 # include "s390x_arch.h"
854 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx
*gctx
)
856 static const unsigned char generator
[] = {
857 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
858 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
859 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
861 ECX_KEY
*key
= ossl_ecx_key_new(gctx
->libctx
, ECX_KEY_TYPE_X25519
, 1,
863 unsigned char *privkey
= NULL
, *pubkey
;
866 ERR_raise(ERR_LIB_PROV
, ERR_R_EC_LIB
);
870 /* If we're doing parameter generation then we just return a blank key */
871 if ((gctx
->selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) == 0)
874 pubkey
= key
->pubkey
;
876 privkey
= ossl_ecx_key_allocate_privkey(key
);
877 if (privkey
== NULL
) {
878 ERR_raise(ERR_LIB_PROV
, ERR_R_EC_LIB
);
883 if (gctx
->dhkem_ikm
!= NULL
&& gctx
->dhkem_ikmlen
!= 0) {
884 if (gctx
->type
!= ECX_KEY_TYPE_X25519
)
886 if (!ossl_ecx_dhkem_derive_private(key
, privkey
,
887 gctx
->dhkem_ikm
, gctx
->dhkem_ikmlen
))
892 if (RAND_priv_bytes_ex(gctx
->libctx
, privkey
, X25519_KEYLEN
, 0) <= 0)
900 if (s390x_x25519_mul(pubkey
, generator
, privkey
) != 1)
905 ossl_ecx_key_free(key
);
909 static void *s390x_ecx_keygen448(struct ecx_gen_ctx
*gctx
)
911 static const unsigned char generator
[] = {
912 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
913 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
914 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
915 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
916 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
918 ECX_KEY
*key
= ossl_ecx_key_new(gctx
->libctx
, ECX_KEY_TYPE_X448
, 1,
920 unsigned char *privkey
= NULL
, *pubkey
;
923 ERR_raise(ERR_LIB_PROV
, ERR_R_EC_LIB
);
927 /* If we're doing parameter generation then we just return a blank key */
928 if ((gctx
->selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) == 0)
931 pubkey
= key
->pubkey
;
933 privkey
= ossl_ecx_key_allocate_privkey(key
);
934 if (privkey
== NULL
) {
935 ERR_raise(ERR_LIB_PROV
, ERR_R_EC_LIB
);
940 if (gctx
->dhkem_ikm
!= NULL
&& gctx
->dhkem_ikmlen
!= 0) {
941 if (gctx
->type
!= ECX_KEY_TYPE_X448
)
943 if (!ossl_ecx_dhkem_derive_private(key
, privkey
,
944 gctx
->dhkem_ikm
, gctx
->dhkem_ikmlen
))
949 if (RAND_priv_bytes_ex(gctx
->libctx
, privkey
, X448_KEYLEN
, 0) <= 0)
956 if (s390x_x448_mul(pubkey
, generator
, privkey
) != 1)
961 ossl_ecx_key_free(key
);
965 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx
*gctx
)
967 static const unsigned char generator_x
[] = {
968 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
969 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
970 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
972 static const unsigned char generator_y
[] = {
973 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
974 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
975 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
977 unsigned char x_dst
[32], buff
[SHA512_DIGEST_LENGTH
];
978 ECX_KEY
*key
= ossl_ecx_key_new(gctx
->libctx
, ECX_KEY_TYPE_ED25519
, 1,
980 unsigned char *privkey
= NULL
, *pubkey
;
986 ERR_raise(ERR_LIB_PROV
, ERR_R_EC_LIB
);
990 /* If we're doing parameter generation then we just return a blank key */
991 if ((gctx
->selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) == 0)
994 pubkey
= key
->pubkey
;
996 privkey
= ossl_ecx_key_allocate_privkey(key
);
997 if (privkey
== NULL
) {
998 ERR_raise(ERR_LIB_PROV
, ERR_R_EC_LIB
);
1002 if (RAND_priv_bytes_ex(gctx
->libctx
, privkey
, ED25519_KEYLEN
, 0) <= 0)
1005 sha
= EVP_MD_fetch(gctx
->libctx
, "SHA512", gctx
->propq
);
1008 j
= EVP_Digest(privkey
, 32, buff
, &sz
, sha
, NULL
);
1017 if (s390x_ed25519_mul(x_dst
, pubkey
,
1018 generator_x
, generator_y
, buff
) != 1)
1021 pubkey
[31] |= ((x_dst
[0] & 0x01) << 7);
1025 ossl_ecx_key_free(key
);
1029 static void *s390x_ecd_keygen448(struct ecx_gen_ctx
*gctx
)
1031 static const unsigned char generator_x
[] = {
1032 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
1033 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
1034 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
1035 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
1036 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
1038 static const unsigned char generator_y
[] = {
1039 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
1040 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
1041 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
1042 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
1043 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
1045 unsigned char x_dst
[57], buff
[114];
1046 ECX_KEY
*key
= ossl_ecx_key_new(gctx
->libctx
, ECX_KEY_TYPE_ED448
, 1,
1048 unsigned char *privkey
= NULL
, *pubkey
;
1049 EVP_MD_CTX
*hashctx
= NULL
;
1050 EVP_MD
*shake
= NULL
;
1053 ERR_raise(ERR_LIB_PROV
, ERR_R_EC_LIB
);
1057 /* If we're doing parameter generation then we just return a blank key */
1058 if ((gctx
->selection
& OSSL_KEYMGMT_SELECT_KEYPAIR
) == 0)
1061 pubkey
= key
->pubkey
;
1063 privkey
= ossl_ecx_key_allocate_privkey(key
);
1064 if (privkey
== NULL
) {
1065 ERR_raise(ERR_LIB_PROV
, ERR_R_EC_LIB
);
1069 shake
= EVP_MD_fetch(gctx
->libctx
, "SHAKE256", gctx
->propq
);
1072 if (RAND_priv_bytes_ex(gctx
->libctx
, privkey
, ED448_KEYLEN
, 0) <= 0)
1075 hashctx
= EVP_MD_CTX_new();
1076 if (hashctx
== NULL
)
1078 if (EVP_DigestInit_ex(hashctx
, shake
, NULL
) != 1)
1080 if (EVP_DigestUpdate(hashctx
, privkey
, 57) != 1)
1082 if (EVP_DigestFinalXOF(hashctx
, buff
, sizeof(buff
)) != 1)
1089 if (s390x_ed448_mul(x_dst
, pubkey
,
1090 generator_x
, generator_y
, buff
) != 1)
1093 pubkey
[56] |= ((x_dst
[0] & 0x01) << 7);
1094 EVP_MD_CTX_free(hashctx
);
1099 ossl_ecx_key_free(key
);
1100 EVP_MD_CTX_free(hashctx
);