2 * Copyright 2020 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
11 #include <openssl/core_numbers.h>
12 #include <openssl/core_names.h>
13 #include <openssl/params.h>
14 #include <openssl/err.h>
15 #include <openssl/evp.h>
16 #include <openssl/rand.h>
17 #include "internal/param_build_set.h"
18 #include "openssl/param_build.h"
19 #include "crypto/ecx.h"
20 #include "prov/implementations.h"
21 #include "prov/providercommon.h"
22 #include "prov/provider_ctx.h"
24 # include "s390x_arch.h"
25 # include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
28 static OSSL_OP_keymgmt_new_fn x25519_new_key;
29 static OSSL_OP_keymgmt_new_fn x448_new_key;
30 static OSSL_OP_keymgmt_new_fn ed25519_new_key;
31 static OSSL_OP_keymgmt_new_fn ed448_new_key;
32 static OSSL_OP_keymgmt_gen_init_fn x25519_gen_init;
33 static OSSL_OP_keymgmt_gen_init_fn x448_gen_init;
34 static OSSL_OP_keymgmt_gen_init_fn ed25519_gen_init;
35 static OSSL_OP_keymgmt_gen_init_fn ed448_gen_init;
36 static OSSL_OP_keymgmt_gen_fn x25519_gen;
37 static OSSL_OP_keymgmt_gen_fn x448_gen;
38 static OSSL_OP_keymgmt_gen_fn ed25519_gen;
39 static OSSL_OP_keymgmt_gen_fn ed448_gen;
40 static OSSL_OP_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
41 static OSSL_OP_keymgmt_get_params_fn x25519_get_params;
42 static OSSL_OP_keymgmt_get_params_fn x448_get_params;
43 static OSSL_OP_keymgmt_get_params_fn ed25519_get_params;
44 static OSSL_OP_keymgmt_get_params_fn ed448_get_params;
45 static OSSL_OP_keymgmt_gettable_params_fn x25519_gettable_params;
46 static OSSL_OP_keymgmt_gettable_params_fn x448_gettable_params;
47 static OSSL_OP_keymgmt_gettable_params_fn ed25519_gettable_params;
48 static OSSL_OP_keymgmt_gettable_params_fn ed448_gettable_params;
49 static OSSL_OP_keymgmt_has_fn ecx_has;
50 static OSSL_OP_keymgmt_import_fn ecx_import;
51 static OSSL_OP_keymgmt_import_types_fn ecx_imexport_types;
52 static OSSL_OP_keymgmt_export_fn ecx_export;
53 static OSSL_OP_keymgmt_export_types_fn ecx_imexport_types;
55 #define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
63 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
64 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
65 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
66 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
69 static void *x25519_new_key(void *provctx)
71 return ecx_key_new(ECX_KEY_TYPE_X25519, 0);
74 static void *x448_new_key(void *provctx)
76 return ecx_key_new(ECX_KEY_TYPE_X448, 0);
79 static void *ed25519_new_key(void *provctx)
81 return ecx_key_new(ECX_KEY_TYPE_ED25519, 0);
84 static void *ed448_new_key(void *provctx)
86 return ecx_key_new(ECX_KEY_TYPE_ED448, 0);
89 static int ecx_has(void *keydata, int selection)
91 ECX_KEY *key = keydata;
95 if ((selection & ECX_POSSIBLE_SELECTIONS) != 0)
98 if ((selection & OSSL_KEYMGMT_SELECT_PUBLIC_KEY) != 0)
99 ok = ok && key->haspubkey;
101 if ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0)
102 ok = ok && key->privkey != NULL;
107 static int ecx_import(void *keydata, int selection, const OSSL_PARAM params[])
109 ECX_KEY *key = keydata;
111 int include_private = 0;
116 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
119 include_private = ((selection & OSSL_KEYMGMT_SELECT_PRIVATE_KEY) != 0);
120 ok = ok && ecx_key_fromdata(key, params, include_private);
125 static int key_to_params(ECX_KEY *key, OSSL_PARAM_BLD *tmpl,
131 if (!ossl_param_build_set_octet_string(tmpl, params,
132 OSSL_PKEY_PARAM_PUB_KEY,
133 key->pubkey, key->keylen))
136 if (key->privkey != NULL
137 && !ossl_param_build_set_octet_string(tmpl, params,
138 OSSL_PKEY_PARAM_PRIV_KEY,
139 key->privkey, key->keylen))
145 static int ecx_export(void *keydata, int selection, OSSL_CALLBACK *param_cb,
148 ECX_KEY *key = keydata;
149 OSSL_PARAM_BLD *tmpl;
150 OSSL_PARAM *params = NULL;
156 tmpl = OSSL_PARAM_BLD_new();
160 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
161 && !key_to_params(key, tmpl, NULL))
164 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0
165 && !key_to_params(key, tmpl, NULL))
168 params = OSSL_PARAM_BLD_to_param(tmpl);
172 ret = param_cb(params, cbarg);
173 OSSL_PARAM_BLD_free_params(params);
175 OSSL_PARAM_BLD_free(tmpl);
179 #define ECX_KEY_TYPES() \
180 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PUB_KEY, NULL, 0), \
181 OSSL_PARAM_octet_string(OSSL_PKEY_PARAM_PRIV_KEY, NULL, 0)
183 static const OSSL_PARAM ecx_key_types[] = {
187 static const OSSL_PARAM *ecx_imexport_types(int selection)
189 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) != 0)
190 return ecx_key_types;
194 static int ecx_get_params(void *key, OSSL_PARAM params[], int bits, int secbits,
200 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_BITS)) != NULL
201 && !OSSL_PARAM_set_int(p, bits))
203 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_SECURITY_BITS)) != NULL
204 && !OSSL_PARAM_set_int(p, secbits))
206 if ((p = OSSL_PARAM_locate(params, OSSL_PKEY_PARAM_MAX_SIZE)) != NULL
207 && !OSSL_PARAM_set_int(p, size))
209 return key_to_params(ecx, NULL, params);
212 static int ed_get_params(void *key, OSSL_PARAM params[])
216 if ((p = OSSL_PARAM_locate(params,
217 OSSL_PKEY_PARAM_MANDATORY_DIGEST)) != NULL
218 && !OSSL_PARAM_set_utf8_string(p, ""))
223 static int x25519_get_params(void *key, OSSL_PARAM params[])
225 return ecx_get_params(key, params, X25519_BITS, X25519_SECURITY_BITS,
229 static int x448_get_params(void *key, OSSL_PARAM params[])
231 return ecx_get_params(key, params, X448_BITS, X448_SECURITY_BITS,
235 static int ed25519_get_params(void *key, OSSL_PARAM params[])
237 return ecx_get_params(key, params, ED25519_BITS, ED25519_SECURITY_BITS,
239 && ed_get_params(key, params);
242 static int ed448_get_params(void *key, OSSL_PARAM params[])
244 return ecx_get_params(key, params, ED448_BITS, ED448_SECURITY_BITS,
246 && ed_get_params(key, params);
249 static const OSSL_PARAM ecx_params[] = {
250 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
251 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
252 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
253 OSSL_PARAM_utf8_string(OSSL_PKEY_PARAM_MANDATORY_DIGEST, NULL, 0),
258 static const OSSL_PARAM ed_params[] = {
259 OSSL_PARAM_int(OSSL_PKEY_PARAM_BITS, NULL),
260 OSSL_PARAM_int(OSSL_PKEY_PARAM_SECURITY_BITS, NULL),
261 OSSL_PARAM_int(OSSL_PKEY_PARAM_MAX_SIZE, NULL),
266 static const OSSL_PARAM *x25519_gettable_params(void)
271 static const OSSL_PARAM *x448_gettable_params(void)
276 static const OSSL_PARAM *ed25519_gettable_params(void)
281 static const OSSL_PARAM *ed448_gettable_params(void)
286 static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type)
288 OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
289 struct ecx_gen_ctx *gctx = NULL;
291 if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
294 if ((gctx = OPENSSL_malloc(sizeof(*gctx))) != NULL) {
295 gctx->libctx = libctx;
301 static void *x25519_gen_init(void *provctx, int selection)
303 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X25519);
306 static void *x448_gen_init(void *provctx, int selection)
308 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X448);
311 static void *ed25519_gen_init(void *provctx, int selection)
313 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED25519);
316 static void *ed448_gen_init(void *provctx, int selection)
318 return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448);
321 static void *ecx_gen(struct ecx_gen_ctx *gctx)
324 unsigned char *privkey;
328 if ((key = ecx_key_new(gctx->type, 0)) == NULL) {
329 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
332 if ((privkey = ecx_key_allocate_privkey(key)) == NULL) {
333 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
336 if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0)
338 switch (gctx->type) {
339 case ECX_KEY_TYPE_X25519:
341 privkey[X25519_KEYLEN - 1] &= 127;
342 privkey[X25519_KEYLEN - 1] |= 64;
343 X25519_public_from_private(key->pubkey, privkey);
345 case ECX_KEY_TYPE_X448:
347 privkey[X448_KEYLEN - 1] |= 128;
348 X448_public_from_private(key->pubkey, privkey);
350 case ECX_KEY_TYPE_ED25519:
351 if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey))
354 case ECX_KEY_TYPE_ED448:
355 if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey))
365 static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
367 struct ecx_gen_ctx *gctx = genctx;
370 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
371 return s390x_ecx_keygen25519(gctx);
373 return ecx_gen(gctx);
376 static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
378 struct ecx_gen_ctx *gctx = genctx;
381 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
382 return s390x_ecx_keygen448(gctx);
384 return ecx_gen(gctx);
387 static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
389 struct ecx_gen_ctx *gctx = genctx;
391 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
392 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
393 && OPENSSL_s390xcap_P.kdsa[0]
394 & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
395 return s390x_ecd_keygen25519(gctx);
397 return ecx_gen(gctx);
400 static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
402 struct ecx_gen_ctx *gctx = genctx;
405 if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
406 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
407 && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
408 return s390x_ecd_keygen448(gctx);
410 return ecx_gen(gctx);
413 static void ecx_gen_cleanup(void *genctx)
415 struct ecx_gen_ctx *gctx = genctx;
420 #define MAKE_KEYMGMT_FUNCTIONS(alg) \
421 const OSSL_DISPATCH alg##_keymgmt_functions[] = { \
422 { OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
423 { OSSL_FUNC_KEYMGMT_FREE, (void (*)(void))ecx_key_free }, \
424 { OSSL_FUNC_KEYMGMT_GET_PARAMS, (void (*) (void))alg##_get_params }, \
425 { OSSL_FUNC_KEYMGMT_GETTABLE_PARAMS, (void (*) (void))alg##_gettable_params }, \
426 { OSSL_FUNC_KEYMGMT_HAS, (void (*)(void))ecx_has }, \
427 { OSSL_FUNC_KEYMGMT_IMPORT, (void (*)(void))ecx_import }, \
428 { OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
429 { OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
430 { OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types }, \
431 { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
432 { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
433 { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
437 MAKE_KEYMGMT_FUNCTIONS(x25519)
438 MAKE_KEYMGMT_FUNCTIONS(x448)
439 MAKE_KEYMGMT_FUNCTIONS(ed25519)
440 MAKE_KEYMGMT_FUNCTIONS(ed448)
443 # include "s390x_arch.h"
445 static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
447 static const unsigned char generator[] = {
448 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
449 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
452 ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X25519, 1);
453 unsigned char *privkey = NULL, *pubkey;
456 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
460 pubkey = key->pubkey;
462 privkey = ecx_key_allocate_privkey(key);
463 if (privkey == NULL) {
464 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
468 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN) <= 0)
475 if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
483 static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
485 static const unsigned char generator[] = {
486 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
487 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
488 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
489 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
492 ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X448, 1);
493 unsigned char *privkey = NULL, *pubkey;
496 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
500 pubkey = key->pubkey;
502 privkey = ecx_key_allocate_privkey(key);
503 if (privkey == NULL) {
504 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
508 if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN) <= 0)
514 if (s390x_x448_mul(pubkey, generator, privkey) != 1)
522 static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
524 static const unsigned char generator_x[] = {
525 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
526 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
527 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
529 static const unsigned char generator_y[] = {
530 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
531 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
532 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
534 unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
535 ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED25519, 1);
536 unsigned char *privkey = NULL, *pubkey;
542 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
546 pubkey = key->pubkey;
548 privkey = ecx_key_allocate_privkey(key);
549 if (privkey == NULL) {
550 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
554 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN) <= 0)
557 sha = EVP_MD_fetch(gctx->libctx, "SHA512", NULL);
560 j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
569 if (s390x_ed25519_mul(x_dst, pubkey,
570 generator_x, generator_y, buff) != 1)
573 pubkey[31] |= ((x_dst[0] & 0x01) << 7);
580 static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
582 static const unsigned char generator_x[] = {
583 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
584 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
585 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
586 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
587 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
589 static const unsigned char generator_y[] = {
590 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
591 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
592 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
593 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
594 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
596 unsigned char x_dst[57], buff[114];
597 ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED448, 1);
598 unsigned char *privkey = NULL, *pubkey;
599 EVP_MD_CTX *hashctx = NULL;
600 EVP_MD *shake = NULL;
603 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
607 pubkey = key->pubkey;
609 privkey = ecx_key_allocate_privkey(key);
610 if (privkey == NULL) {
611 ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
615 shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", NULL);
618 if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN) <= 0)
621 hashctx = EVP_MD_CTX_new();
624 if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
626 if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
628 if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
635 if (s390x_ed448_mul(x_dst, pubkey,
636 generator_x, generator_y, buff) != 1)
639 pubkey[56] |= ((x_dst[0] & 0x01) << 7);
640 EVP_MD_CTX_free(hashctx);
645 EVP_MD_CTX_free(hashctx);