The branch master has been updated
via 4350a6bd427f52d38f32b19f1c4b38a3afe62941 (commit)
via 19985ac42cab57bf55acb626aebfdc1194771b76 (commit)
via b5bcc053024ce5adeb714d0a48dce71188cbd13c (commit)
via d8171446a274ab57e7d55d8d9f6ca8a0a7144d13 (commit)
via c1e48c5171affd99111fd08e7a0a7e1a76121138 (commit)
via 43cd37014ef4433ae8e82ba64bddc42cf0bd618a (commit)
via 1ee1e551148d963b566a69c2e6e9a583646112fc (commit)
from 8a5cb59601fa9892e22e26337917cf513d57c473 (commit)
- Log -----------------------------------------------------------------
commit 4350a6bd427f52d38f32b19f1c4b38a3afe62941
Author: Pauli <[email protected]>
Date: Thu Apr 16 10:17:07 2020 +1000
doc: note that the FIPS provider contains some non-approved algorithms.
Also note how to select them.
Reviewed-by: Matt Caswell <[email protected]>
(Merged from https://github.com/openssl/openssl/pull/11371)
commit 19985ac42cab57bf55acb626aebfdc1194771b76
Author: Pauli <[email protected]>
Date: Thu Apr 16 07:55:17 2020 +1000
news: note the addition of ECX and SHAKE256 to the FIPS provider as
non-approved algorithms
Reviewed-by: Matt Caswell <[email protected]>
(Merged from https://github.com/openssl/openssl/pull/11371)
commit b5bcc053024ce5adeb714d0a48dce71188cbd13c
Author: Pauli <[email protected]>
Date: Wed Apr 15 12:32:01 2020 +1000
pkey: free key manager on error path
Reviewed-by: Matt Caswell <[email protected]>
(Merged from https://github.com/openssl/openssl/pull/11371)
commit d8171446a274ab57e7d55d8d9f6ca8a0a7144d13
Author: Pauli <[email protected]>
Date: Wed Apr 15 10:06:20 2020 +1000
ecx: check for errors creating public keys from private ones.
Reviewed-by: Matt Caswell <[email protected]>
(Merged from https://github.com/openssl/openssl/pull/11371)
commit c1e48c5171affd99111fd08e7a0a7e1a76121138
Author: Pauli <[email protected]>
Date: Thu Apr 2 14:37:26 2020 +1000
s390: ECX key generation fixes.
Reviewed-by: Matt Caswell <[email protected]>
(Merged from https://github.com/openssl/openssl/pull/11371)
commit 43cd37014ef4433ae8e82ba64bddc42cf0bd618a
Author: Pauli <[email protected]>
Date: Wed Mar 18 09:25:33 2020 +1000
ecx: add key generation support.
Specifically for x25519, x448, ed25519 and ed448.
Reviewed-by: Matt Caswell <[email protected]>
(Merged from https://github.com/openssl/openssl/pull/11371)
commit 1ee1e551148d963b566a69c2e6e9a583646112fc
Author: Pauli <[email protected]>
Date: Fri Mar 20 12:58:37 2020 +1000
Add ECX to FIPS provider as non-FIPS algorithms
Reviewed-by: Matt Caswell <[email protected]>
(Merged from https://github.com/openssl/openssl/pull/11371)
-----------------------------------------------------------------------
Summary of changes:
NEWS.md | 3 +
crypto/ec/build.info | 5 +-
crypto/ec/curve25519.c | 17 +-
crypto/ec/curve448/curve448_local.h | 3 -
crypto/ec/ec_err.c | 4 +-
crypto/ec/ec_local.h | 2 -
crypto/ec/ecx_meth.c | 209 +-------------
crypto/ec/ecx_s390x.c | 217 +++++++++++++++
crypto/err/openssl.txt | 3 +-
crypto/evp/pmeth_lib.c | 1 +
crypto/s390x_arch.h | 17 ++
doc/man7/provider.pod | 5 +-
include/crypto/ecx.h | 12 +-
include/openssl/ecerr.h | 3 +-
providers/fips/fipsprov.c | 10 +
providers/implementations/keymgmt/build.info | 12 +
providers/implementations/keymgmt/ecx_kmgmt.c | 379 +++++++++++++++++++++++++-
17 files changed, 678 insertions(+), 224 deletions(-)
create mode 100644 crypto/ec/ecx_s390x.c
diff --git a/NEWS.md b/NEWS.md
index 9f29a59323..9f18f416f8 100644
--- a/NEWS.md
+++ b/NEWS.md
@@ -21,6 +21,9 @@ OpenSSL 3.0
### Major changes between OpenSSL 1.1.1 and OpenSSL 3.0 [under development] ###
+ * The X25519, X448, Ed25519, Ed448 and SHAKE256 algorithms are included in
+ the FIPS provider. None have the "fips=yes" property set and, as such,
+ will not be accidentially used.
* The algorithm specific public key command line applications have
been deprecated. These include dhparam, gendsa and others. The pkey
alternatives should be used intead: pkey, pkeyparam and genpkey.
diff --git a/crypto/ec/build.info b/crypto/ec/build.info
index a802beaa68..8e4a6a9f4b 100644
--- a/crypto/ec/build.info
+++ b/crypto/ec/build.info
@@ -18,7 +18,7 @@ IF[{- !$disabled{asm} -}]
$ECASM_mips32=
$ECASM_mips64=
- $ECASM_s390x=ecp_s390x_nistp.c
+ $ECASM_s390x=ecp_s390x_nistp.c ecx_s390x.c
$ECDEF_s390x=S390X_EC_ASM
$ECASM_armv4=ecp_nistz256.c ecp_nistz256-armv4.S
@@ -44,7 +44,7 @@ IF[{- !$disabled{asm} -}]
ENDIF
$COMMON=ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
- ec_curve.c ec_check.c ec_print.c ec_key.c ec_asn1.c \
+ ec_curve.c ec_check.c ec_print.c ec_key.c ecx_key.c ec_asn1.c \
ec2_smpl.c \
ecp_oct.c ec2_oct.c ec_oct.c ec_kmeth.c ecdh_ossl.c \
ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c \
@@ -76,6 +76,7 @@ GENERATE[ecp_nistz256-sparcv9.S]=asm/ecp_nistz256-sparcv9.pl
INCLUDE[ecp_nistz256-sparcv9.o]=..
INCLUDE[ecp_s390x_nistp.o]=..
+INCLUDE[ecx_s390x.o]=..
INCLUDE[ecx_meth.o]=..
GENERATE[ecp_nistz256-armv4.S]=asm/ecp_nistz256-armv4.pl
diff --git a/crypto/ec/curve25519.c b/crypto/ec/curve25519.c
index 8db6cdb16d..b8e998a0f4 100644
--- a/crypto/ec/curve25519.c
+++ b/crypto/ec/curve25519.c
@@ -5577,13 +5577,23 @@ err:
return res;
}
-void ED25519_public_from_private(uint8_t out_public_key[32],
- const uint8_t private_key[32])
+int ED25519_public_from_private(OPENSSL_CTX *ctx, uint8_t out_public_key[32],
+ const uint8_t private_key[32])
{
uint8_t az[SHA512_DIGEST_LENGTH];
ge_p3 A;
+ int r;
+ EVP_MD *sha512 = NULL;
- SHA512(private_key, 32, az);
+ sha512 = EVP_MD_fetch(ctx, SN_sha512, NULL);
+ if (sha512 == NULL)
+ return 0;
+ r = EVP_Digest(private_key, 32, az, NULL, sha512, NULL);
+ EVP_MD_free(sha512);
+ if (!r) {
+ OPENSSL_cleanse(az, sizeof(az));
+ return 0;
+ }
az[0] &= 248;
az[31] &= 63;
@@ -5593,6 +5603,7 @@ void ED25519_public_from_private(uint8_t
out_public_key[32],
ge_p3_tobytes(out_public_key, &A);
OPENSSL_cleanse(az, sizeof(az));
+ return 1;
}
int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
diff --git a/crypto/ec/curve448/curve448_local.h
b/crypto/ec/curve448/curve448_local.h
index b70a1b5406..5b3b71ff62 100644
--- a/crypto/ec/curve448/curve448_local.h
+++ b/crypto/ec/curve448/curve448_local.h
@@ -18,7 +18,4 @@ int ED448ph_verify(OPENSSL_CTX *ctx, const uint8_t hash[64],
const uint8_t signature[114], const uint8_t public_key[57],
const uint8_t *context, size_t context_len);
-int ED448_public_from_private(OPENSSL_CTX *ctx, uint8_t out_public_key[57],
- const uint8_t private_key[57]);
-
#endif /* OSSL_CRYPTO_EC_CURVE448_LOCAL_H */
diff --git a/crypto/ec/ec_err.c b/crypto/ec/ec_err.c
index 66d9c4b16e..d775ced93a 100644
--- a/crypto/ec/ec_err.c
+++ b/crypto/ec/ec_err.c
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -34,6 +34,8 @@ static const ERR_STRING_DATA EC_str_reasons[] = {
"discriminant is zero"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_EC_GROUP_NEW_BY_NAME_FAILURE),
"ec group new by name failure"},
+ {ERR_PACK(ERR_LIB_EC, 0, EC_R_FAILED_MAKING_PUBLIC_KEY),
+ "failed making public key"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_FIELD_TOO_LARGE), "field too large"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_GF2M_NOT_SUPPORTED), "gf2m not supported"},
{ERR_PACK(ERR_LIB_EC, 0, EC_R_GROUP2PKPARAMETERS_FAILURE),
diff --git a/crypto/ec/ec_local.h b/crypto/ec/ec_local.h
index b5963a7e5f..d10de2fc98 100644
--- a/crypto/ec/ec_local.h
+++ b/crypto/ec/ec_local.h
@@ -679,8 +679,6 @@ ECDSA_SIG *ecdsa_simple_sign_sig(const unsigned char *dgst,
int dgst_len,
int ecdsa_simple_verify_sig(const unsigned char *dgst, int dgst_len,
const ECDSA_SIG *sig, EC_KEY *eckey);
-void ED25519_public_from_private(uint8_t out_public_key[32],
- const uint8_t private_key[32]);
/*-
* This functions computes a single point multiplication over the EC group,
diff --git a/crypto/ec/ecx_meth.c b/crypto/ec/ecx_meth.c
index 62a73f9b08..ba037ffb8b 100644
--- a/crypto/ec/ecx_meth.c
+++ b/crypto/ec/ecx_meth.c
@@ -93,13 +93,19 @@ static int ecx_key_op(EVP_PKEY *pkey, int id, const
X509_ALGOR *palg,
X25519_public_from_private(pubkey, privkey);
break;
case EVP_PKEY_ED25519:
- ED25519_public_from_private(pubkey, privkey);
+ if (!ED25519_public_from_private(libctx, pubkey, privkey)) {
+ ECerr(EC_F_ECX_KEY_OP, EC_R_FAILED_MAKING_PUBLIC_KEY);
+ return 0;
+ }
break;
case EVP_PKEY_X448:
X448_public_from_private(pubkey, privkey);
break;
case EVP_PKEY_ED448:
- ED448_public_from_private(libctx, pubkey, privkey);
+ if (!ED448_public_from_private(libctx, pubkey, privkey)) {
+ ECerr(EC_F_ECX_KEY_OP, EC_R_FAILED_MAKING_PUBLIC_KEY);
+ return 0;
+ }
break;
}
}
@@ -948,205 +954,6 @@ static const EVP_PKEY_METHOD ed448_pkey_meth = {
#ifdef S390X_EC_ASM
# include "s390x_arch.h"
-# include "internal/constant_time.h"
-
-static void s390x_x25519_mod_p(unsigned char u[32])
-{
- unsigned char u_red[32];
- unsigned int c = 0;
- int i;
-
- memcpy(u_red, u, sizeof(u_red));
-
- c += (unsigned int)u_red[31] + 19;
- u_red[31] = (unsigned char)c;
- c >>= 8;
-
- for (i = 30; i >= 0; i--) {
- c += (unsigned int)u_red[i];
- u_red[i] = (unsigned char)c;
- c >>= 8;
- }
-
- c = (u_red[0] & 0x80) >> 7;
- u_red[0] &= 0x7f;
- constant_time_cond_swap_buff(0 - (unsigned char)c,
- u, u_red, sizeof(u_red));
-}
-
-static void s390x_x448_mod_p(unsigned char u[56])
-{
- unsigned char u_red[56];
- unsigned int c = 0;
- int i;
-
- memcpy(u_red, u, sizeof(u_red));
-
- c += (unsigned int)u_red[55] + 1;
- u_red[55] = (unsigned char)c;
- c >>= 8;
-
- for (i = 54; i >= 28; i--) {
- c += (unsigned int)u_red[i];
- u_red[i] = (unsigned char)c;
- c >>= 8;
- }
-
- c += (unsigned int)u_red[27] + 1;
- u_red[27] = (unsigned char)c;
- c >>= 8;
-
- for (i = 26; i >= 0; i--) {
- c += (unsigned int)u_red[i];
- u_red[i] = (unsigned char)c;
- c >>= 8;
- }
-
- constant_time_cond_swap_buff(0 - (unsigned char)c,
- u, u_red, sizeof(u_red));
-}
-
-int s390x_x25519_mul(unsigned char u_dst[32],
- const unsigned char u_src[32],
- const unsigned char d_src[32])
-{
- union {
- struct {
- unsigned char u_dst[32];
- unsigned char u_src[32];
- unsigned char d_src[32];
- } x25519;
- unsigned long long buff[512];
- } param;
- int rc;
-
- memset(¶m, 0, sizeof(param));
-
- s390x_flip_endian32(param.x25519.u_src, u_src);
- param.x25519.u_src[0] &= 0x7f;
- s390x_x25519_mod_p(param.x25519.u_src);
-
- s390x_flip_endian32(param.x25519.d_src, d_src);
- param.x25519.d_src[31] &= 248;
- param.x25519.d_src[0] &= 127;
- param.x25519.d_src[0] |= 64;
-
- rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X25519, ¶m.x25519) ? 0 : 1;
- if (rc == 1)
- s390x_flip_endian32(u_dst, param.x25519.u_dst);
-
- OPENSSL_cleanse(param.x25519.d_src, sizeof(param.x25519.d_src));
- return rc;
-}
-
-int s390x_x448_mul(unsigned char u_dst[56],
- const unsigned char u_src[56],
- const unsigned char d_src[56])
-{
- union {
- struct {
- unsigned char u_dst[64];
- unsigned char u_src[64];
- unsigned char d_src[64];
- } x448;
- unsigned long long buff[512];
- } param;
- int rc;
-
- memset(¶m, 0, sizeof(param));
-
- memcpy(param.x448.u_src, u_src, 56);
- memcpy(param.x448.d_src, d_src, 56);
-
- s390x_flip_endian64(param.x448.u_src, param.x448.u_src);
- s390x_x448_mod_p(param.x448.u_src + 8);
-
- s390x_flip_endian64(param.x448.d_src, param.x448.d_src);
- param.x448.d_src[63] &= 252;
- param.x448.d_src[8] |= 128;
-
- rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X448, ¶m.x448) ? 0 : 1;
- if (rc == 1) {
- s390x_flip_endian64(param.x448.u_dst, param.x448.u_dst);
- memcpy(u_dst, param.x448.u_dst, 56);
- }
-
- OPENSSL_cleanse(param.x448.d_src, sizeof(param.x448.d_src));
- return rc;
-}
-
-static int s390x_ed25519_mul(unsigned char x_dst[32],
- unsigned char y_dst[32],
- const unsigned char x_src[32],
- const unsigned char y_src[32],
- const unsigned char d_src[32])
-{
- union {
- struct {
- unsigned char x_dst[32];
- unsigned char y_dst[32];
- unsigned char x_src[32];
- unsigned char y_src[32];
- unsigned char d_src[32];
- } ed25519;
- unsigned long long buff[512];
- } param;
- int rc;
-
- memset(¶m, 0, sizeof(param));
-
- s390x_flip_endian32(param.ed25519.x_src, x_src);
- s390x_flip_endian32(param.ed25519.y_src, y_src);
- s390x_flip_endian32(param.ed25519.d_src, d_src);
-
- rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED25519, ¶m.ed25519) ? 0 : 1;
- if (rc == 1) {
- s390x_flip_endian32(x_dst, param.ed25519.x_dst);
- s390x_flip_endian32(y_dst, param.ed25519.y_dst);
- }
-
- OPENSSL_cleanse(param.ed25519.d_src, sizeof(param.ed25519.d_src));
- return rc;
-}
-
-static int s390x_ed448_mul(unsigned char x_dst[57],
- unsigned char y_dst[57],
- const unsigned char x_src[57],
- const unsigned char y_src[57],
- const unsigned char d_src[57])
-{
- union {
- struct {
- unsigned char x_dst[64];
- unsigned char y_dst[64];
- unsigned char x_src[64];
- unsigned char y_src[64];
- unsigned char d_src[64];
- } ed448;
- unsigned long long buff[512];
- } param;
- int rc;
-
- memset(¶m, 0, sizeof(param));
-
- memcpy(param.ed448.x_src, x_src, 57);
- memcpy(param.ed448.y_src, y_src, 57);
- memcpy(param.ed448.d_src, d_src, 57);
- s390x_flip_endian64(param.ed448.x_src, param.ed448.x_src);
- s390x_flip_endian64(param.ed448.y_src, param.ed448.y_src);
- s390x_flip_endian64(param.ed448.d_src, param.ed448.d_src);
-
- rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED448, ¶m.ed448) ? 0 : 1;
- if (rc == 1) {
- s390x_flip_endian64(param.ed448.x_dst, param.ed448.x_dst);
- s390x_flip_endian64(param.ed448.y_dst, param.ed448.y_dst);
- memcpy(x_dst, param.ed448.x_dst, 57);
- memcpy(y_dst, param.ed448.y_dst, 57);
- }
-
- OPENSSL_cleanse(param.ed448.d_src, sizeof(param.ed448.d_src));
- return rc;
-}
static int s390x_pkey_ecx_keygen25519(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
{
diff --git a/crypto/ec/ecx_s390x.c b/crypto/ec/ecx_s390x.c
new file mode 100644
index 0000000000..1e6f65011b
--- /dev/null
+++ b/crypto/ec/ecx_s390x.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/ec.h>
+#include <openssl/rand.h>
+#include "crypto/ecx.h"
+#include "ec_local.h"
+#include "curve448/curve448_local.h"
+#include "ecx_backend.h"
+#include "s390x_arch.h"
+#include "internal/constant_time.h"
+
+static void s390x_x25519_mod_p(unsigned char u[32])
+{
+ unsigned char u_red[32];
+ unsigned int c = 0;
+ int i;
+
+ memcpy(u_red, u, sizeof(u_red));
+
+ c += (unsigned int)u_red[31] + 19;
+ u_red[31] = (unsigned char)c;
+ c >>= 8;
+
+ for (i = 30; i >= 0; i--) {
+ c += (unsigned int)u_red[i];
+ u_red[i] = (unsigned char)c;
+ c >>= 8;
+ }
+
+ c = (u_red[0] & 0x80) >> 7;
+ u_red[0] &= 0x7f;
+ constant_time_cond_swap_buff(0 - (unsigned char)c,
+ u, u_red, sizeof(u_red));
+}
+
+static void s390x_x448_mod_p(unsigned char u[56])
+{
+ unsigned char u_red[56];
+ unsigned int c = 0;
+ int i;
+
+ memcpy(u_red, u, sizeof(u_red));
+
+ c += (unsigned int)u_red[55] + 1;
+ u_red[55] = (unsigned char)c;
+ c >>= 8;
+
+ for (i = 54; i >= 28; i--) {
+ c += (unsigned int)u_red[i];
+ u_red[i] = (unsigned char)c;
+ c >>= 8;
+ }
+
+ c += (unsigned int)u_red[27] + 1;
+ u_red[27] = (unsigned char)c;
+ c >>= 8;
+
+ for (i = 26; i >= 0; i--) {
+ c += (unsigned int)u_red[i];
+ u_red[i] = (unsigned char)c;
+ c >>= 8;
+ }
+
+ constant_time_cond_swap_buff(0 - (unsigned char)c,
+ u, u_red, sizeof(u_red));
+}
+
+int s390x_x25519_mul(unsigned char u_dst[32],
+ const unsigned char u_src[32],
+ const unsigned char d_src[32])
+{
+ union {
+ struct {
+ unsigned char u_dst[32];
+ unsigned char u_src[32];
+ unsigned char d_src[32];
+ } x25519;
+ unsigned long long buff[512];
+ } param;
+ int rc;
+
+ memset(¶m, 0, sizeof(param));
+
+ s390x_flip_endian32(param.x25519.u_src, u_src);
+ param.x25519.u_src[0] &= 0x7f;
+ s390x_x25519_mod_p(param.x25519.u_src);
+
+ s390x_flip_endian32(param.x25519.d_src, d_src);
+ param.x25519.d_src[31] &= 248;
+ param.x25519.d_src[0] &= 127;
+ param.x25519.d_src[0] |= 64;
+
+ rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X25519, ¶m.x25519) ? 0 : 1;
+ if (rc == 1)
+ s390x_flip_endian32(u_dst, param.x25519.u_dst);
+
+ OPENSSL_cleanse(param.x25519.d_src, sizeof(param.x25519.d_src));
+ return rc;
+}
+
+int s390x_x448_mul(unsigned char u_dst[56],
+ const unsigned char u_src[56],
+ const unsigned char d_src[56])
+{
+ union {
+ struct {
+ unsigned char u_dst[64];
+ unsigned char u_src[64];
+ unsigned char d_src[64];
+ } x448;
+ unsigned long long buff[512];
+ } param;
+ int rc;
+
+ memset(¶m, 0, sizeof(param));
+
+ memcpy(param.x448.u_src, u_src, 56);
+ memcpy(param.x448.d_src, d_src, 56);
+
+ s390x_flip_endian64(param.x448.u_src, param.x448.u_src);
+ s390x_x448_mod_p(param.x448.u_src + 8);
+
+ s390x_flip_endian64(param.x448.d_src, param.x448.d_src);
+ param.x448.d_src[63] &= 252;
+ param.x448.d_src[8] |= 128;
+
+ rc = s390x_pcc(S390X_SCALAR_MULTIPLY_X448, ¶m.x448) ? 0 : 1;
+ if (rc == 1) {
+ s390x_flip_endian64(param.x448.u_dst, param.x448.u_dst);
+ memcpy(u_dst, param.x448.u_dst, 56);
+ }
+
+ OPENSSL_cleanse(param.x448.d_src, sizeof(param.x448.d_src));
+ return rc;
+}
+
+int s390x_ed25519_mul(unsigned char x_dst[32],
+ unsigned char y_dst[32],
+ const unsigned char x_src[32],
+ const unsigned char y_src[32],
+ const unsigned char d_src[32])
+{
+ union {
+ struct {
+ unsigned char x_dst[32];
+ unsigned char y_dst[32];
+ unsigned char x_src[32];
+ unsigned char y_src[32];
+ unsigned char d_src[32];
+ } ed25519;
+ unsigned long long buff[512];
+ } param;
+ int rc;
+
+ memset(¶m, 0, sizeof(param));
+
+ s390x_flip_endian32(param.ed25519.x_src, x_src);
+ s390x_flip_endian32(param.ed25519.y_src, y_src);
+ s390x_flip_endian32(param.ed25519.d_src, d_src);
+
+ rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED25519, ¶m.ed25519) ? 0 : 1;
+ if (rc == 1) {
+ s390x_flip_endian32(x_dst, param.ed25519.x_dst);
+ s390x_flip_endian32(y_dst, param.ed25519.y_dst);
+ }
+
+ OPENSSL_cleanse(param.ed25519.d_src, sizeof(param.ed25519.d_src));
+ return rc;
+}
+
+int s390x_ed448_mul(unsigned char x_dst[57],
+ unsigned char y_dst[57],
+ const unsigned char x_src[57],
+ const unsigned char y_src[57],
+ const unsigned char d_src[57])
+{
+ union {
+ struct {
+ unsigned char x_dst[64];
+ unsigned char y_dst[64];
+ unsigned char x_src[64];
+ unsigned char y_src[64];
+ unsigned char d_src[64];
+ } ed448;
+ unsigned long long buff[512];
+ } param;
+ int rc;
+
+ memset(¶m, 0, sizeof(param));
+
+ memcpy(param.ed448.x_src, x_src, 57);
+ memcpy(param.ed448.y_src, y_src, 57);
+ memcpy(param.ed448.d_src, d_src, 57);
+ s390x_flip_endian64(param.ed448.x_src, param.ed448.x_src);
+ s390x_flip_endian64(param.ed448.y_src, param.ed448.y_src);
+ s390x_flip_endian64(param.ed448.d_src, param.ed448.d_src);
+
+ rc = s390x_pcc(S390X_SCALAR_MULTIPLY_ED448, ¶m.ed448) ? 0 : 1;
+ if (rc == 1) {
+ s390x_flip_endian64(param.ed448.x_dst, param.ed448.x_dst);
+ s390x_flip_endian64(param.ed448.y_dst, param.ed448.y_dst);
+ memcpy(x_dst, param.ed448.x_dst, 57);
+ memcpy(y_dst, param.ed448.y_dst, 57);
+ }
+
+ OPENSSL_cleanse(param.ed448.d_src, sizeof(param.ed448.d_src));
+ return rc;
+}
diff --git a/crypto/err/openssl.txt b/crypto/err/openssl.txt
index 12826beb0b..793473684c 100644
--- a/crypto/err/openssl.txt
+++ b/crypto/err/openssl.txt
@@ -2402,6 +2402,7 @@ EC_R_D2I_ECPKPARAMETERS_FAILURE:117:d2i ecpkparameters
failure
EC_R_DECODE_ERROR:142:decode error
EC_R_DISCRIMINANT_IS_ZERO:118:discriminant is zero
EC_R_EC_GROUP_NEW_BY_NAME_FAILURE:119:ec group new by name failure
+EC_R_FAILED_MAKING_PUBLIC_KEY:166:failed making public key
EC_R_FIELD_TOO_LARGE:143:field too large
EC_R_GF2M_NOT_SUPPORTED:147:gf2m not supported
EC_R_GROUP2PKPARAMETERS_FAILURE:120:group2pkparameters failure
@@ -3013,6 +3014,7 @@ SM2_R_INVALID_ENCODING:104:invalid encoding
SM2_R_INVALID_FIELD:105:invalid field
SM2_R_NO_PARAMETERS_SET:109:no parameters set
SM2_R_USER_ID_TOO_LARGE:106:user id too large
+SSL_R_ALGORITHM_FETCH_FAILED:295:algorithm fetch failed
SSL_R_APPLICATION_DATA_AFTER_CLOSE_NOTIFY:291:\
application data after close notify
SSL_R_APP_DATA_IN_HANDSHAKE:100:app data in handshake
@@ -3119,7 +3121,6 @@ SSL_R_EXTENSION_NOT_RECEIVED:279:extension not received
SSL_R_EXTRA_DATA_IN_MESSAGE:153:extra data in message
SSL_R_EXT_LENGTH_MISMATCH:163:ext length mismatch
SSL_R_FAILED_TO_INIT_ASYNC:405:failed to init async
-SSL_R_ALGORITHM_FETCH_FAILED:295:algorithm fetch failed
SSL_R_FRAGMENTED_CLIENT_HELLO:401:fragmented client hello
SSL_R_GOT_A_FIN_BEFORE_A_CCS:154:got a fin before a ccs
SSL_R_HTTPS_PROXY_REQUEST:155:https proxy request
diff --git a/crypto/evp/pmeth_lib.c b/crypto/evp/pmeth_lib.c
index b6617492da..e816265bc7 100644
--- a/crypto/evp/pmeth_lib.c
+++ b/crypto/evp/pmeth_lib.c
@@ -236,6 +236,7 @@ static EVP_PKEY_CTX *int_ctx_new(OPENSSL_CTX *libctx,
ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
+ EVP_KEYMGMT_free(keymgmt);
#if !defined(OPENSSL_NO_ENGINE) && !defined(FIPS_MODE)
ENGINE_finish(e);
#endif
diff --git a/crypto/s390x_arch.h b/crypto/s390x_arch.h
index 0123de9477..c20fc342f6 100644
--- a/crypto/s390x_arch.h
+++ b/crypto/s390x_arch.h
@@ -33,6 +33,23 @@ int s390x_kdsa(unsigned int fc, void *param, const unsigned
char *in,
void s390x_flip_endian32(unsigned char dst[32], const unsigned char src[32]);
void s390x_flip_endian64(unsigned char dst[64], const unsigned char src[64]);
+int s390x_x25519_mul(unsigned char u_dst[32],
+ const unsigned char u_src[32],
+ const unsigned char d_src[32]);
+int s390x_x448_mul(unsigned char u_dst[56],
+ const unsigned char u_src[56],
+ const unsigned char d_src[56]);
+int s390x_ed25519_mul(unsigned char x_dst[32],
+ unsigned char y_dst[32],
+ const unsigned char x_src[32],
+ const unsigned char y_src[32],
+ const unsigned char d_src[32]);
+int s390x_ed448_mul(unsigned char x_dst[57],
+ unsigned char y_dst[57],
+ const unsigned char x_src[57],
+ const unsigned char y_src[57],
+ const unsigned char d_src[57]);
+
/*
* The field elements of OPENSSL_s390xcap_P are the 64-bit words returned by
* the STFLE instruction followed by the 64-bit word pairs returned by
diff --git a/doc/man7/provider.pod b/doc/man7/provider.pod
index de8e2499d9..fcb9fa1122 100644
--- a/doc/man7/provider.pod
+++ b/doc/man7/provider.pod
@@ -274,9 +274,10 @@ be loaded explicitly, either in code or through OpenSSL
configuration
(see L<config(5)>).
Should it be needed (if other providers are loaded and offer
implementations of the same algorithms), the property "provider=fips" can
-be used as a search criterion for these implementations. All algorithm
+be used as a search criterion for these implementations. All approved algorithm
implementations in the FIPS provider can also be selected with the property
-"fips=yes".
+"fips=yes". The FIPS provider also contains a number of non-approved algorithm
+implementations and these can be selected with the property "fips=no".
=head2 Legacy provider
diff --git a/include/crypto/ecx.h b/include/crypto/ecx.h
index 0c6655ca79..5ee6b8ce7e 100644
--- a/include/crypto/ecx.h
+++ b/include/crypto/ecx.h
@@ -72,6 +72,7 @@ struct ecx_key_st {
typedef struct ecx_key_st ECX_KEY;
+size_t ecx_key_length(ECX_KEY_TYPE type);
ECX_KEY *ecx_key_new(ECX_KEY_TYPE type, int haspubkey);
unsigned char *ecx_key_allocate_privkey(ECX_KEY *key);
void ecx_key_free(ECX_KEY *key);
@@ -82,6 +83,8 @@ int X25519(uint8_t out_shared_key[32], const uint8_t
private_key[32],
void X25519_public_from_private(uint8_t out_public_value[32],
const uint8_t private_key[32]);
+int ED25519_public_from_private(OPENSSL_CTX *ctx, uint8_t out_public_key[32],
+ const uint8_t private_key[32]);
int ED25519_sign(uint8_t *out_sig, const uint8_t *message, size_t message_len,
const uint8_t public_key[32], const uint8_t private_key[32],
OPENSSL_CTX *libctx, const char *propq);
@@ -89,6 +92,8 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[64], const uint8_t public_key[32],
OPENSSL_CTX *libctx, const char *propq);
+int ED448_public_from_private(OPENSSL_CTX *ctx, uint8_t out_public_key[57],
+ const uint8_t private_key[57]);
int ED448_sign(OPENSSL_CTX *ctx, uint8_t *out_sig, const uint8_t *message,
size_t message_len, const uint8_t public_key[57],
const uint8_t private_key[57], const uint8_t *context,
@@ -103,13 +108,6 @@ int X448(uint8_t out_shared_key[56], const uint8_t
private_key[56],
void X448_public_from_private(uint8_t out_public_value[56],
const uint8_t private_key[56]);
-int s390x_x25519_mul(unsigned char u_dst[32],
- const unsigned char u_src[32],
- const unsigned char d_src[32]);
-int s390x_x448_mul(unsigned char u_dst[56],
- const unsigned char u_src[56],
- const unsigned char d_src[56]);
-
/* Backend support */
int ecx_key_fromdata(ECX_KEY *ecx, const OSSL_PARAM params[],
int include_private);
diff --git a/include/openssl/ecerr.h b/include/openssl/ecerr.h
index 41d592b085..cf845fbb1a 100644
--- a/include/openssl/ecerr.h
+++ b/include/openssl/ecerr.h
@@ -1,6 +1,6 @@
/*
* Generated by util/mkerr.pl DO NOT EDIT
- * Copyright 1995-2019 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 1995-2020 The OpenSSL Project Authors. All Rights Reserved.
*
* Licensed under the Apache License 2.0 (the "License"). You may not use
* this file except in compliance with the License. You can obtain a copy
@@ -237,6 +237,7 @@ int ERR_load_EC_strings(void);
# define EC_R_DECODE_ERROR 142
# define EC_R_DISCRIMINANT_IS_ZERO 118
# define EC_R_EC_GROUP_NEW_BY_NAME_FAILURE 119
+# define EC_R_FAILED_MAKING_PUBLIC_KEY 166
# define EC_R_FIELD_TOO_LARGE 143
# define EC_R_GF2M_NOT_SUPPORTED 147
# define EC_R_GROUP2PKPARAMETERS_FAILURE 120
diff --git a/providers/fips/fipsprov.c b/providers/fips/fipsprov.c
index c107d690b7..4fe14c2ba3 100644
--- a/providers/fips/fipsprov.c
+++ b/providers/fips/fipsprov.c
@@ -374,6 +374,8 @@ static const OSSL_ALGORITHM fips_digests[] = {
{ "KECCAK-KMAC-128:KECCAK-KMAC128", "provider=fips,fips=yes",
keccak_kmac_128_functions },
{ "KECCAK-KMAC-256:KECCAK-KMAC256", "provider=fips,fips=yes",
keccak_kmac_256_functions },
+ /* Non-FIPS algorithm to support oneshot_hash in the Ed448 code */
+ { "SHAKE-256:SHAKE256", "provider=fips,fips=no", shake_256_functions },
{ NULL, NULL, NULL }
};
@@ -447,6 +449,8 @@ static const OSSL_ALGORITHM fips_keyexch[] = {
#endif
#ifndef OPENSSL_NO_EC
{ "ECDH", "provider=fips,fips=yes", ecdh_keyexch_functions },
+ { "X25519", "provider=fips,fips=no", x25519_keyexch_functions },
+ { "X448", "provider=fips,fips=no", x448_keyexch_functions },
#endif
{ NULL, NULL, NULL }
};
@@ -457,6 +461,8 @@ static const OSSL_ALGORITHM fips_signature[] = {
#endif
{ "RSA:rsaEncryption", "provider=fips,fips=yes", rsa_signature_functions },
#ifndef OPENSSL_NO_EC
+ { "ED25519", "provider=fips,fips=no", ed25519_signature_functions },
+ { "ED448", "provider=fips,fips=no", ed448_signature_functions },
{ "ECDSA", "provider=fips,fips=yes", ecdsa_signature_functions },
#endif
{ NULL, NULL, NULL }
@@ -477,6 +483,10 @@ static const OSSL_ALGORITHM fips_keymgmt[] = {
{ "RSA:rsaEncryption", "provider=fips,fips=yes", rsa_keymgmt_functions },
#ifndef OPENSSL_NO_EC
{ "EC:id-ecPublicKey", "provider=fips,fips=yes", ec_keymgmt_functions },
+ { "X25519", "provider=fips,fips=no", x25519_keymgmt_functions },
+ { "X448", "provider=fips,fips=no", x448_keymgmt_functions },
+ { "ED25519", "provider=fips,fips=no", ed25519_keymgmt_functions },
+ { "ED448", "provider=fips,fips=no", ed448_keymgmt_functions },
#endif
{ NULL, NULL, NULL }
};
diff --git a/providers/implementations/keymgmt/build.info
b/providers/implementations/keymgmt/build.info
index 92cac52e11..73597c7cea 100644
--- a/providers/implementations/keymgmt/build.info
+++ b/providers/implementations/keymgmt/build.info
@@ -15,8 +15,20 @@ ENDIF
IF[{- !$disabled{ec} -}]
SOURCE[$EC_GOAL]=ec_kmgmt.c
ENDIF
+
+IF[{- !$disabled{asm} -}]
+ $ECDEF_s390x=S390X_EC_ASM
+
+ # Now that we have defined all the arch specific variables, use the
+ # appropriate one, and define the appropriate macros
+ IF[$ECASM_{- $target{asm_arch} -}]
+ $ECDEF=$ECDEF_{- $target{asm_arch} -}
+ ENDIF
+ENDIF
+
IF[{- !$disabled{ec} -}]
SOURCE[$ECX_GOAL]=ecx_kmgmt.c
+ DEFINE[$ECX_GOAL]=$ECDEF
ENDIF
SOURCE[../../libfips.a]=rsa_kmgmt.c
diff --git a/providers/implementations/keymgmt/ecx_kmgmt.c
b/providers/implementations/keymgmt/ecx_kmgmt.c
index ca53a93f5e..c9105f777d 100644
--- a/providers/implementations/keymgmt/ecx_kmgmt.c
+++ b/providers/implementations/keymgmt/ecx_kmgmt.c
@@ -10,15 +10,34 @@
#include <assert.h>
#include <openssl/core_numbers.h>
#include <openssl/core_names.h>
+#include <openssl/params.h>
+#include <openssl/err.h>
+#include <openssl/evp.h>
+#include <openssl/rand.h>
+#include "internal/param_build_set.h"
+#include "openssl/param_build.h"
#include "crypto/ecx.h"
#include "prov/implementations.h"
#include "prov/providercommon.h"
-#include "internal/param_build_set.h"
+#include "prov/provider_ctx.h"
+#ifdef S390X_EC_ASM
+# include "s390x_arch.h"
+# include <openssl/sha.h> /* For SHA512_DIGEST_LENGTH */
+#endif
static OSSL_OP_keymgmt_new_fn x25519_new_key;
static OSSL_OP_keymgmt_new_fn x448_new_key;
static OSSL_OP_keymgmt_new_fn ed25519_new_key;
static OSSL_OP_keymgmt_new_fn ed448_new_key;
+static OSSL_OP_keymgmt_gen_init_fn x25519_gen_init;
+static OSSL_OP_keymgmt_gen_init_fn x448_gen_init;
+static OSSL_OP_keymgmt_gen_init_fn ed25519_gen_init;
+static OSSL_OP_keymgmt_gen_init_fn ed448_gen_init;
+static OSSL_OP_keymgmt_gen_fn x25519_gen;
+static OSSL_OP_keymgmt_gen_fn x448_gen;
+static OSSL_OP_keymgmt_gen_fn ed25519_gen;
+static OSSL_OP_keymgmt_gen_fn ed448_gen;
+static OSSL_OP_keymgmt_gen_cleanup_fn ecx_gen_cleanup;
static OSSL_OP_keymgmt_get_params_fn x25519_get_params;
static OSSL_OP_keymgmt_get_params_fn x448_get_params;
static OSSL_OP_keymgmt_get_params_fn ed25519_get_params;
@@ -32,6 +51,18 @@ static OSSL_OP_keymgmt_export_types_fn ecx_imexport_types;
#define ECX_POSSIBLE_SELECTIONS (OSSL_KEYMGMT_SELECT_KEYPAIR)
+struct ecx_gen_ctx {
+ OPENSSL_CTX *libctx;
+ ECX_KEY_TYPE type;
+};
+
+#ifdef S390X_EC_ASM
+static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx);
+static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx);
+static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx);
+static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx);
+#endif
+
static void *x25519_new_key(void *provctx)
{
return ecx_key_new(ECX_KEY_TYPE_X25519, 0);
@@ -213,6 +244,140 @@ static const OSSL_PARAM *ecx_gettable_params(void)
return ecx_params;
}
+static void *ecx_gen_init(void *provctx, int selection, ECX_KEY_TYPE type)
+{
+ OPENSSL_CTX *libctx = PROV_LIBRARY_CONTEXT_OF(provctx);
+ struct ecx_gen_ctx *gctx = NULL;
+
+ if ((selection & OSSL_KEYMGMT_SELECT_KEYPAIR) == 0)
+ return NULL;
+
+ if ((gctx = OPENSSL_malloc(sizeof(*gctx))) != NULL) {
+ gctx->libctx = libctx;
+ gctx->type = type;
+ }
+ return gctx;
+}
+
+static void *x25519_gen_init(void *provctx, int selection)
+{
+ return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X25519);
+}
+
+static void *x448_gen_init(void *provctx, int selection)
+{
+ return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_X448);
+}
+
+static void *ed25519_gen_init(void *provctx, int selection)
+{
+ return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED25519);
+}
+
+static void *ed448_gen_init(void *provctx, int selection)
+{
+ return ecx_gen_init(provctx, selection, ECX_KEY_TYPE_ED448);
+}
+
+static void *ecx_gen(struct ecx_gen_ctx *gctx)
+{
+ ECX_KEY *key;
+ unsigned char *privkey;
+
+ if (gctx == NULL)
+ return NULL;
+ if ((key = ecx_key_new(gctx->type, 0)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ return NULL;
+ }
+ if ((privkey = ecx_key_allocate_privkey(key)) == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ if (RAND_priv_bytes_ex(gctx->libctx, privkey, key->keylen) <= 0)
+ goto err;
+ switch (gctx->type) {
+ case ECX_KEY_TYPE_X25519:
+ privkey[0] &= 248;
+ privkey[X25519_KEYLEN - 1] &= 127;
+ privkey[X25519_KEYLEN - 1] |= 64;
+ X25519_public_from_private(key->pubkey, privkey);
+ break;
+ case ECX_KEY_TYPE_X448:
+ privkey[0] &= 252;
+ privkey[X448_KEYLEN - 1] |= 128;
+ X448_public_from_private(key->pubkey, privkey);
+ break;
+ case ECX_KEY_TYPE_ED25519:
+ if (!ED25519_public_from_private(gctx->libctx, key->pubkey, privkey))
+ goto err;
+ break;
+ case ECX_KEY_TYPE_ED448:
+ if (!ED448_public_from_private(gctx->libctx, key->pubkey, privkey))
+ goto err;
+ break;
+ }
+ return key;
+err:
+ ecx_key_free(key);
+ return NULL;
+}
+
+static void *x25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct ecx_gen_ctx *gctx = genctx;
+
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519))
+ return s390x_ecx_keygen25519(gctx);
+#endif
+ return ecx_gen(gctx);
+}
+
+static void *x448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct ecx_gen_ctx *gctx = genctx;
+
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448))
+ return s390x_ecx_keygen448(gctx);
+#endif
+ return ecx_gen(gctx);
+}
+
+static void *ed25519_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct ecx_gen_ctx *gctx = genctx;
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
+ && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
+ && OPENSSL_s390xcap_P.kdsa[0]
+ & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519))
+ return s390x_ecd_keygen25519(gctx);
+#endif
+ return ecx_gen(gctx);
+}
+
+static void *ed448_gen(void *genctx, OSSL_CALLBACK *osslcb, void *cbarg)
+{
+ struct ecx_gen_ctx *gctx = genctx;
+
+#ifdef S390X_EC_ASM
+ if (OPENSSL_s390xcap_P.pcc[1] & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
+ && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_SIGN_ED448)
+ && OPENSSL_s390xcap_P.kdsa[0] & S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448))
+ return s390x_ecd_keygen448(gctx);
+#endif
+ return ecx_gen(gctx);
+}
+
+static void ecx_gen_cleanup(void *genctx)
+{
+ struct ecx_gen_ctx *gctx = genctx;
+
+ OPENSSL_free(gctx);
+}
+
#define MAKE_KEYMGMT_FUNCTIONS(alg) \
const OSSL_DISPATCH alg##_keymgmt_functions[] = { \
{ OSSL_FUNC_KEYMGMT_NEW, (void (*)(void))alg##_new_key }, \
@@ -224,6 +389,9 @@ static const OSSL_PARAM *ecx_gettable_params(void)
{ OSSL_FUNC_KEYMGMT_IMPORT_TYPES, (void (*)(void))ecx_imexport_types
}, \
{ OSSL_FUNC_KEYMGMT_EXPORT, (void (*)(void))ecx_export }, \
{ OSSL_FUNC_KEYMGMT_EXPORT_TYPES, (void (*)(void))ecx_imexport_types
}, \
+ { OSSL_FUNC_KEYMGMT_GEN_INIT, (void (*)(void))alg##_gen_init }, \
+ { OSSL_FUNC_KEYMGMT_GEN, (void (*)(void))alg##_gen }, \
+ { OSSL_FUNC_KEYMGMT_GEN_CLEANUP, (void (*)(void))ecx_gen_cleanup }, \
{ 0, NULL } \
};
@@ -231,3 +399,212 @@ MAKE_KEYMGMT_FUNCTIONS(x25519)
MAKE_KEYMGMT_FUNCTIONS(x448)
MAKE_KEYMGMT_FUNCTIONS(ed25519)
MAKE_KEYMGMT_FUNCTIONS(ed448)
+
+#ifdef S390X_EC_ASM
+# include "s390x_arch.h"
+
+static void *s390x_ecx_keygen25519(struct ecx_gen_ctx *gctx)
+{
+ static const unsigned char generator[] = {
+ 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X25519, 1);
+ unsigned char *privkey = NULL, *pubkey;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pubkey = key->pubkey;
+
+ privkey = ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_priv_bytes_ex(gctx->libctx, privkey, X25519_KEYLEN) <= 0)
+ goto err;
+
+ privkey[0] &= 248;
+ privkey[31] &= 127;
+ privkey[31] |= 64;
+
+ if (s390x_x25519_mul(pubkey, generator, privkey) != 1)
+ goto err;
+ return key;
+ err:
+ ecx_key_free(key);
+ return NULL;
+}
+
+static void *s390x_ecx_keygen448(struct ecx_gen_ctx *gctx)
+{
+ static const unsigned char generator[] = {
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ };
+ ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_X448, 1);
+ unsigned char *privkey = NULL, *pubkey;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pubkey = key->pubkey;
+
+ privkey = ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_priv_bytes_ex(gctx->libctx, privkey, X448_KEYLEN) <= 0)
+ goto err;
+
+ privkey[0] &= 252;
+ privkey[55] |= 128;
+
+ if (s390x_x448_mul(pubkey, generator, privkey) != 1)
+ goto err;
+ return key;
+ err:
+ ecx_key_free(key);
+ return NULL;
+}
+
+static void *s390x_ecd_keygen25519(struct ecx_gen_ctx *gctx)
+{
+ static const unsigned char generator_x[] = {
+ 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, 0xb2, 0xa7, 0x25, 0x95,
+ 0x60, 0xc7, 0x2c, 0x69, 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0,
+ 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21
+ };
+ static const unsigned char generator_y[] = {
+ 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
+ };
+ unsigned char x_dst[32], buff[SHA512_DIGEST_LENGTH];
+ ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED25519, 1);
+ unsigned char *privkey = NULL, *pubkey;
+ unsigned int sz;
+ EVP_MD *sha = NULL;
+ int j;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pubkey = key->pubkey;
+
+ privkey = ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED25519_KEYLEN) <= 0)
+ goto err;
+
+ sha = EVP_MD_fetch(gctx->libctx, "SHA512", NULL);
+ if (sha == NULL)
+ goto err;
+ j = EVP_Digest(privkey, 32, buff, &sz, sha, NULL);
+ EVP_MD_free(sha);
+ if (!j)
+ goto err;
+
+ buff[0] &= 248;
+ buff[31] &= 63;
+ buff[31] |= 64;
+
+ if (s390x_ed25519_mul(x_dst, pubkey,
+ generator_x, generator_y, buff) != 1)
+ goto err;
+
+ pubkey[31] |= ((x_dst[0] & 0x01) << 7);
+ return key;
+ err:
+ ecx_key_free(key);
+ return NULL;
+}
+
+static void *s390x_ecd_keygen448(struct ecx_gen_ctx *gctx)
+{
+ static const unsigned char generator_x[] = {
+ 0x5e, 0xc0, 0x0c, 0xc7, 0x2b, 0xa8, 0x26, 0x26, 0x8e, 0x93, 0x00, 0x8b,
+ 0xe1, 0x80, 0x3b, 0x43, 0x11, 0x65, 0xb6, 0x2a, 0xf7, 0x1a, 0xae, 0x12,
+ 0x64, 0xa4, 0xd3, 0xa3, 0x24, 0xe3, 0x6d, 0xea, 0x67, 0x17, 0x0f, 0x47,
+ 0x70, 0x65, 0x14, 0x9e, 0xda, 0x36, 0xbf, 0x22, 0xa6, 0x15, 0x1d, 0x22,
+ 0xed, 0x0d, 0xed, 0x6b, 0xc6, 0x70, 0x19, 0x4f, 0x00
+ };
+ static const unsigned char generator_y[] = {
+ 0x14, 0xfa, 0x30, 0xf2, 0x5b, 0x79, 0x08, 0x98, 0xad, 0xc8, 0xd7, 0x4e,
+ 0x2c, 0x13, 0xbd, 0xfd, 0xc4, 0x39, 0x7c, 0xe6, 0x1c, 0xff, 0xd3, 0x3a,
+ 0xd7, 0xc2, 0xa0, 0x05, 0x1e, 0x9c, 0x78, 0x87, 0x40, 0x98, 0xa3, 0x6c,
+ 0x73, 0x73, 0xea, 0x4b, 0x62, 0xc7, 0xc9, 0x56, 0x37, 0x20, 0x76, 0x88,
+ 0x24, 0xbc, 0xb6, 0x6e, 0x71, 0x46, 0x3f, 0x69, 0x00
+ };
+ unsigned char x_dst[57], buff[114];
+ ECX_KEY *key = ecx_key_new(ECX_KEY_TYPE_ED448, 1);
+ unsigned char *privkey = NULL, *pubkey;
+ EVP_MD_CTX *hashctx = NULL;
+ EVP_MD *shake = NULL;
+
+ if (key == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ pubkey = key->pubkey;
+
+ privkey = ecx_key_allocate_privkey(key);
+ if (privkey == NULL) {
+ ERR_raise(ERR_LIB_PROV, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+
+ shake = EVP_MD_fetch(gctx->libctx, "SHAKE256", NULL);
+ if (shake == NULL)
+ goto err;
+ if (RAND_priv_bytes_ex(gctx->libctx, privkey, ED448_KEYLEN) <= 0)
+ goto err;
+
+ hashctx = EVP_MD_CTX_new();
+ if (hashctx == NULL)
+ goto err;
+ if (EVP_DigestInit_ex(hashctx, shake, NULL) != 1)
+ goto err;
+ if (EVP_DigestUpdate(hashctx, privkey, 57) != 1)
+ goto err;
+ if (EVP_DigestFinalXOF(hashctx, buff, sizeof(buff)) != 1)
+ goto err;
+
+ buff[0] &= -4;
+ buff[55] |= 0x80;
+ buff[56] = 0;
+
+ if (s390x_ed448_mul(x_dst, pubkey,
+ generator_x, generator_y, buff) != 1)
+ goto err;
+
+ pubkey[56] |= ((x_dst[0] & 0x01) << 7);
+ EVP_MD_CTX_free(hashctx);
+ EVP_MD_free(shake);
+ return key;
+ err:
+ ecx_key_free(key);
+ EVP_MD_CTX_free(hashctx);
+ EVP_MD_free(shake);
+ return NULL;
+}
+#endif