openssl-1_1/openssl-assembly-pack-accelerate-scalar-multiplication.patch

312 lines
14 KiB
Diff
Raw Normal View History

2020-01-24 12:52:58 +01:00
From 1461e66706f24da657d7322706d1165ae515533f Mon Sep 17 00:00:00 2001
From: Patrick Steuer <patrick.steuer@de.ibm.com>
Date: Tue, 9 Jul 2019 10:25:04 +0200
Subject: [PATCH 09204/10000] s390x assembly pack: accelerate scalar
multiplication
for NIST P-256, P-384 and P-521 using PCC instruction.
Signed-off-by: Patrick Steuer <patrick.steuer@de.ibm.com>
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Shane Lontis <shane.lontis@oracle.com>
(Merged from https://github.com/openssl/openssl/pull/9348)
---
crypto/ec/build.info | 3 +-
crypto/ec/ec_curve.c | 42 +++++---
Accepting request 786956 from home:vitezslav_cizek:branches:security:tls - Update to 1.1.1e * Properly detect EOF while reading in libssl. Previously if we hit an EOF while reading in libssl then we would report an error back to the application (SSL_ERROR_SYSCALL) but errno would be 0. We now add an error to the stack (which means we instead return SSL_ERROR_SSL) and therefore give a hint as to what went wrong. * Check that ed25519 and ed448 are allowed by the security level. Previously signature algorithms not using an MD were not being checked that they were allowed by the security level. * Fixed SSL_get_servername() behaviour. The behaviour of SSL_get_servername() was not quite right. The behaviour was not consistent between resumption and normal handshakes, and also not quite consistent with historical behaviour. The behaviour in various scenarios has been clarified and it has been updated to make it match historical behaviour as closely as possible. * Corrected the documentation of the return values from the EVP_DigestSign* set of functions. The documentation mentioned negative values for some errors, but this was never the case, so the mention of negative values was removed. * Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY. The presence of this system service is determined at run-time. * Added newline escaping functionality to a filename when using openssl dgst. This output format is to replicate the output format found in the '*sum' checksum programs. This aims to preserve backward compatibility. * Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just the first value. - Update bunch of patches as the internal crypto headers got reorganized - drop openssl-1_1-CVE-2019-1551.patch (upstream) - openssl dgst: default to SHA256 only when called without a digest, OBS-URL: https://build.opensuse.org/request/show/786956 OBS-URL: https://build.opensuse.org/package/show/security:tls/openssl-1_1?expand=0&rev=65
2020-03-20 18:43:35 +01:00
crypto/ec/ec_local.h | 5 +
2020-01-24 12:52:58 +01:00
crypto/ec/ecp_s390x_nistp.c | 197 ++++++++++++++++++++++++++++++++++++
4 files changed, 234 insertions(+), 13 deletions(-)
create mode 100644 crypto/ec/ecp_s390x_nistp.c
Index: openssl-1.1.1d/crypto/ec/ec_curve.c
===================================================================
--- openssl-1.1.1d.orig/crypto/ec/ec_curve.c
+++ openssl-1.1.1d/crypto/ec/ec_curve.c
@@ -2829,16 +2829,25 @@ static const ec_list_element curve_list[
{NID_secp256k1, &_EC_SECG_PRIME_256K1.h, 0,
"SECG curve over a 256 bit prime field"},
/* SECG secp256r1 is the same as X9.62 prime256v1 and hence omitted */
- {NID_secp384r1, &_EC_NIST_PRIME_384.h, 0,
+ {NID_secp384r1, &_EC_NIST_PRIME_384.h,
+# if defined(S390X_NISTP_ASM)
+ EC_GFp_s390x_nistp384_method,
+# else
+ 0,
+# endif
"NIST/SECG curve over a 384 bit prime field"},
-#ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
- {NID_secp521r1, &_EC_NIST_PRIME_521.h, EC_GFp_nistp521_method,
- "NIST/SECG curve over a 521 bit prime field"},
+
+ {NID_secp521r1, &_EC_NIST_PRIME_521.h,
+# if defined(S390X_NISTP_ASM)
+ EC_GFp_s390x_nistp521_method,
+# elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
+ EC_GFp_nistp521_method,
#else
- {NID_secp521r1, &_EC_NIST_PRIME_521.h, 0,
- "NIST/SECG curve over a 521 bit prime field"},
+ 0,
#endif
- /* X9.62 curves */
+ "NIST/SECG curve over a 521 bit prime field"},
+
+ /* X9.62 curves */
{NID_X9_62_prime192v1, &_EC_NIST_PRIME_192.h, 0,
"NIST/X9.62/SECG curve over a 192 bit prime field"},
{NID_X9_62_prime192v2, &_EC_X9_62_PRIME_192V2.h, 0,
@@ -2854,6 +2863,8 @@ static const ec_list_element curve_list[
{NID_X9_62_prime256v1, &_EC_X9_62_PRIME_256V1.h,
#if defined(ECP_NISTZ256_ASM)
EC_GFp_nistz256_method,
+# elif defined(S390X_NISTP_ASM)
+ EC_GFp_s390x_nistp256_method,
#elif !defined(OPENSSL_NO_EC_NISTP_64_GCC_128)
EC_GFp_nistp256_method,
#else
Accepting request 786956 from home:vitezslav_cizek:branches:security:tls - Update to 1.1.1e * Properly detect EOF while reading in libssl. Previously if we hit an EOF while reading in libssl then we would report an error back to the application (SSL_ERROR_SYSCALL) but errno would be 0. We now add an error to the stack (which means we instead return SSL_ERROR_SSL) and therefore give a hint as to what went wrong. * Check that ed25519 and ed448 are allowed by the security level. Previously signature algorithms not using an MD were not being checked that they were allowed by the security level. * Fixed SSL_get_servername() behaviour. The behaviour of SSL_get_servername() was not quite right. The behaviour was not consistent between resumption and normal handshakes, and also not quite consistent with historical behaviour. The behaviour in various scenarios has been clarified and it has been updated to make it match historical behaviour as closely as possible. * Corrected the documentation of the return values from the EVP_DigestSign* set of functions. The documentation mentioned negative values for some errors, but this was never the case, so the mention of negative values was removed. * Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY. The presence of this system service is determined at run-time. * Added newline escaping functionality to a filename when using openssl dgst. This output format is to replicate the output format found in the '*sum' checksum programs. This aims to preserve backward compatibility. * Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just the first value. - Update bunch of patches as the internal crypto headers got reorganized - drop openssl-1_1-CVE-2019-1551.patch (upstream) - openssl dgst: default to SHA256 only when called without a digest, OBS-URL: https://build.opensuse.org/request/show/786956 OBS-URL: https://build.opensuse.org/package/show/security:tls/openssl-1_1?expand=0&rev=65
2020-03-20 18:43:35 +01:00
Index: openssl-1.1.1d/crypto/ec/ec_local.h
2020-01-24 12:52:58 +01:00
===================================================================
Accepting request 786956 from home:vitezslav_cizek:branches:security:tls - Update to 1.1.1e * Properly detect EOF while reading in libssl. Previously if we hit an EOF while reading in libssl then we would report an error back to the application (SSL_ERROR_SYSCALL) but errno would be 0. We now add an error to the stack (which means we instead return SSL_ERROR_SSL) and therefore give a hint as to what went wrong. * Check that ed25519 and ed448 are allowed by the security level. Previously signature algorithms not using an MD were not being checked that they were allowed by the security level. * Fixed SSL_get_servername() behaviour. The behaviour of SSL_get_servername() was not quite right. The behaviour was not consistent between resumption and normal handshakes, and also not quite consistent with historical behaviour. The behaviour in various scenarios has been clarified and it has been updated to make it match historical behaviour as closely as possible. * Corrected the documentation of the return values from the EVP_DigestSign* set of functions. The documentation mentioned negative values for some errors, but this was never the case, so the mention of negative values was removed. * Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY. The presence of this system service is determined at run-time. * Added newline escaping functionality to a filename when using openssl dgst. This output format is to replicate the output format found in the '*sum' checksum programs. This aims to preserve backward compatibility. * Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just the first value. - Update bunch of patches as the internal crypto headers got reorganized - drop openssl-1_1-CVE-2019-1551.patch (upstream) - openssl dgst: default to SHA256 only when called without a digest, OBS-URL: https://build.opensuse.org/request/show/786956 OBS-URL: https://build.opensuse.org/package/show/security:tls/openssl-1_1?expand=0&rev=65
2020-03-20 18:43:35 +01:00
--- openssl-1.1.1d.orig/crypto/ec/ec_local.h
+++ openssl-1.1.1d/crypto/ec/ec_local.h
2020-01-24 12:52:58 +01:00
@@ -587,6 +587,11 @@ int ec_group_simple_order_bits(const EC_
*/
const EC_METHOD *EC_GFp_nistz256_method(void);
#endif
+#ifdef S390X_NISTP_ASM
+const EC_METHOD *EC_GFp_s390x_nistp256_method(void);
+const EC_METHOD *EC_GFp_s390x_nistp384_method(void);
+const EC_METHOD *EC_GFp_s390x_nistp521_method(void);
+#endif
size_t ec_key_simple_priv2oct(const EC_KEY *eckey,
unsigned char *buf, size_t len);
Index: openssl-1.1.1d/crypto/ec/ecp_s390x_nistp.c
===================================================================
--- /dev/null
+++ openssl-1.1.1d/crypto/ec/ecp_s390x_nistp.c
@@ -0,0 +1,197 @@
+/*
+ * Copyright 2019 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 <stdlib.h>
+#include <string.h>
+#include <openssl/err.h>
Accepting request 786956 from home:vitezslav_cizek:branches:security:tls - Update to 1.1.1e * Properly detect EOF while reading in libssl. Previously if we hit an EOF while reading in libssl then we would report an error back to the application (SSL_ERROR_SYSCALL) but errno would be 0. We now add an error to the stack (which means we instead return SSL_ERROR_SSL) and therefore give a hint as to what went wrong. * Check that ed25519 and ed448 are allowed by the security level. Previously signature algorithms not using an MD were not being checked that they were allowed by the security level. * Fixed SSL_get_servername() behaviour. The behaviour of SSL_get_servername() was not quite right. The behaviour was not consistent between resumption and normal handshakes, and also not quite consistent with historical behaviour. The behaviour in various scenarios has been clarified and it has been updated to make it match historical behaviour as closely as possible. * Corrected the documentation of the return values from the EVP_DigestSign* set of functions. The documentation mentioned negative values for some errors, but this was never the case, so the mention of negative values was removed. * Added a new method to gather entropy on VMS, based on SYS$GET_ENTROPY. The presence of this system service is determined at run-time. * Added newline escaping functionality to a filename when using openssl dgst. This output format is to replicate the output format found in the '*sum' checksum programs. This aims to preserve backward compatibility. * Print all values for a PKCS#12 attribute with 'openssl pkcs12', not just the first value. - Update bunch of patches as the internal crypto headers got reorganized - drop openssl-1_1-CVE-2019-1551.patch (upstream) - openssl dgst: default to SHA256 only when called without a digest, OBS-URL: https://build.opensuse.org/request/show/786956 OBS-URL: https://build.opensuse.org/package/show/security:tls/openssl-1_1?expand=0&rev=65
2020-03-20 18:43:35 +01:00
+#include "ec_local.h"
2020-01-24 12:52:58 +01:00
+#include "s390x_arch.h"
+
+/* Size of parameter blocks */
+#define S390X_SIZE_PARAM 4096
+
+/* Size of fields in parameter blocks */
+#define S390X_SIZE_P256 32
+#define S390X_SIZE_P384 48
+#define S390X_SIZE_P521 80
+
+/* Offsets of fields in PCC parameter blocks */
+#define S390X_OFF_RES_X(n) (0 * n)
+#define S390X_OFF_RES_Y(n) (1 * n)
+#define S390X_OFF_SRC_X(n) (2 * n)
+#define S390X_OFF_SRC_Y(n) (3 * n)
+#define S390X_OFF_SCALAR(n) (4 * n)
+
+static int ec_GFp_s390x_nistp_mul(const EC_GROUP *group, EC_POINT *r,
+ const BIGNUM *scalar,
+ size_t num, const EC_POINT *points[],
+ const BIGNUM *scalars[],
+ BN_CTX *ctx, unsigned int fc, int len)
+{
+ unsigned char param[S390X_SIZE_PARAM];
+ BIGNUM *x, *y;
+ const EC_POINT *point_ptr = NULL;
+ const BIGNUM *scalar_ptr = NULL;
+ BN_CTX *new_ctx = NULL;
+ int rc = -1;
+
+ if (ctx == NULL) {
+ ctx = new_ctx = BN_CTX_new();
+ if (ctx == NULL)
+ return 0;
+ }
+
+ BN_CTX_start(ctx);
+
+ x = BN_CTX_get(ctx);
+ y = BN_CTX_get(ctx);
+ if (x == NULL || y == NULL) {
+ rc = 0;
+ goto ret;
+ }
+
+ /*
+ * Use PCC for EC keygen and ECDH key derivation:
+ * scalar * generator and scalar * peer public key,
+ * scalar in [0,order).
+ */
+ if ((scalar != NULL && num == 0 && BN_is_negative(scalar) == 0)
+ || (scalar == NULL && num == 1 && BN_is_negative(scalars[0]) == 0)) {
+
+ if (num == 0) {
+ point_ptr = EC_GROUP_get0_generator(group);
+ scalar_ptr = scalar;
+ } else {
+ point_ptr = points[0];
+ scalar_ptr = scalars[0];
+ }
+
+ if (EC_POINT_is_at_infinity(group, point_ptr) == 1
+ || BN_is_zero(scalar_ptr)) {
+ rc = EC_POINT_set_to_infinity(group, r);
+ goto ret;
+ }
+
+ memset(&param, 0, sizeof(param));
+
+ if (group->meth->point_get_affine_coordinates(group, point_ptr,
+ x, y, ctx) != 1
+ || BN_bn2binpad(x, param + S390X_OFF_SRC_X(len), len) == -1
+ || BN_bn2binpad(y, param + S390X_OFF_SRC_Y(len), len) == -1
+ || BN_bn2binpad(scalar_ptr,
+ param + S390X_OFF_SCALAR(len), len) == -1
+ || s390x_pcc(fc, param) != 0
+ || BN_bin2bn(param + S390X_OFF_RES_X(len), len, x) == NULL
+ || BN_bin2bn(param + S390X_OFF_RES_Y(len), len, y) == NULL
+ || group->meth->point_set_affine_coordinates(group, r,
+ x, y, ctx) != 1)
+ goto ret;
+
+ rc = 1;
+ }
+
+ret:
+ /* Otherwise use default. */
+ if (rc == -1)
+ rc = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+ OPENSSL_cleanse(param, sizeof(param));
+ BN_CTX_end(ctx);
+ BN_CTX_free(new_ctx);
+ return rc;
+}
+
+#define EC_GFP_S390X_NISTP_METHOD(bits) \
+ \
+static int ec_GFp_s390x_nistp##bits##_mul(const EC_GROUP *group, \
+ EC_POINT *r, \
+ const BIGNUM *scalar, \
+ size_t num, \
+ const EC_POINT *points[], \
+ const BIGNUM *scalars[], \
+ BN_CTX *ctx) \
+{ \
+ return ec_GFp_s390x_nistp_mul(group, r, scalar, num, points, \
+ scalars, ctx, \
+ S390X_SCALAR_MULTIPLY_P##bits, \
+ S390X_SIZE_P##bits); \
+} \
+ \
+const EC_METHOD *EC_GFp_s390x_nistp##bits##_method(void) \
+{ \
+ static const EC_METHOD EC_GFp_s390x_nistp##bits##_meth = { \
+ EC_FLAGS_DEFAULT_OCT, \
+ NID_X9_62_prime_field, \
+ ec_GFp_simple_group_init, \
+ ec_GFp_simple_group_finish, \
+ ec_GFp_simple_group_clear_finish, \
+ ec_GFp_simple_group_copy, \
+ ec_GFp_simple_group_set_curve, \
+ ec_GFp_simple_group_get_curve, \
+ ec_GFp_simple_group_get_degree, \
+ ec_group_simple_order_bits, \
+ ec_GFp_simple_group_check_discriminant, \
+ ec_GFp_simple_point_init, \
+ ec_GFp_simple_point_finish, \
+ ec_GFp_simple_point_clear_finish, \
+ ec_GFp_simple_point_copy, \
+ ec_GFp_simple_point_set_to_infinity, \
+ ec_GFp_simple_set_Jprojective_coordinates_GFp, \
+ ec_GFp_simple_get_Jprojective_coordinates_GFp, \
+ ec_GFp_simple_point_set_affine_coordinates, \
+ ec_GFp_simple_point_get_affine_coordinates, \
+ NULL, /* point_set_compressed_coordinates */ \
+ NULL, /* point2oct */ \
+ NULL, /* oct2point */ \
+ ec_GFp_simple_add, \
+ ec_GFp_simple_dbl, \
+ ec_GFp_simple_invert, \
+ ec_GFp_simple_is_at_infinity, \
+ ec_GFp_simple_is_on_curve, \
+ ec_GFp_simple_cmp, \
+ ec_GFp_simple_make_affine, \
+ ec_GFp_simple_points_make_affine, \
+ ec_GFp_s390x_nistp##bits##_mul, \
+ NULL, /* precompute_mult */ \
+ NULL, /* have_precompute_mult */ \
+ ec_GFp_simple_field_mul, \
+ ec_GFp_simple_field_sqr, \
+ NULL, /* field_div */ \
+ ec_GFp_simple_field_inv, \
+ NULL, /* field_encode */ \
+ NULL, /* field_decode */ \
+ NULL, /* field_set_to_one */ \
+ ec_key_simple_priv2oct, \
+ ec_key_simple_oct2priv, \
+ NULL, /* set_private */ \
+ ec_key_simple_generate_key, \
+ ec_key_simple_check_key, \
+ ec_key_simple_generate_public_key, \
+ NULL, /* keycopy */ \
+ NULL, /* keyfinish */ \
+ ecdh_simple_compute_key, \
+ NULL, /* field_inverse_mod_ord */ \
+ ec_GFp_simple_blind_coordinates, \
+ ec_GFp_simple_ladder_pre, \
+ ec_GFp_simple_ladder_step, \
+ ec_GFp_simple_ladder_post \
+ }; \
+ static const EC_METHOD *ret; \
+ \
+ if (OPENSSL_s390xcap_P.pcc[1] \
+ & S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P##bits)) \
+ ret = &EC_GFp_s390x_nistp##bits##_meth; \
+ else \
+ ret = EC_GFp_mont_method(); \
+ \
+ return ret; \
+}
+
+EC_GFP_S390X_NISTP_METHOD(256)
+EC_GFP_S390X_NISTP_METHOD(384)
+EC_GFP_S390X_NISTP_METHOD(521)
Index: openssl-1.1.1d/Configurations/00-base-templates.conf
===================================================================
--- openssl-1.1.1d.orig/Configurations/00-base-templates.conf
+++ openssl-1.1.1d/Configurations/00-base-templates.conf
@@ -289,6 +289,7 @@ my %targets=(
template => 1,
cpuid_asm_src => "s390xcap.c s390xcpuid.S",
bn_asm_src => "asm/s390x.S s390x-mont.S s390x-gf2m.s",
+ ec_asm_src => "ecp_s390x_nistp.c",
aes_asm_src => "aes-s390x.S aes-ctr.fake aes-xts.fake",
sha1_asm_src => "sha1-s390x.S sha256-s390x.S sha512-s390x.S",
rc4_asm_src => "rc4-s390x.s",
Index: openssl-1.1.1d/Configure
===================================================================
--- openssl-1.1.1d.orig/Configure
+++ openssl-1.1.1d/Configure
@@ -1400,6 +1400,9 @@ unless ($disabled{asm}) {
if ($target{ec_asm_src} =~ /x25519/) {
push @{$config{lib_defines}}, "X25519_ASM";
}
+ if ($target{ec_asm_src} =~ /ecp_s390x_nistp/) {
+ push @{$config{lib_defines}}, "S390X_NISTP_ASM";
+ }
if ($target{padlock_asm_src} ne $table{DEFAULTS}->{padlock_asm_src}) {
push @{$config{dso_defines}}, "PADLOCK_ASM";
}