summaryrefslogtreecommitdiffstats
path: root/crypto/s390xcap.c
diff options
context:
space:
mode:
authorJuergen Christ <jchrist@linux.ibm.com>2023-01-20 17:43:59 +0100
committerTomas Mraz <tomas@openssl.org>2023-02-08 16:53:12 +0100
commit79040cf29e011c21789563d74da626b7465a0540 (patch)
treecf4db184af2d8fba461a64994a27635c41d1d51a /crypto/s390xcap.c
parentabf654645dee168b229f3fa6a365f6a8e4dd7c31 (diff)
S390x: Support ME and CRT offloading
S390x has to ability to offload modular exponentiation and CRT operations to Crypto Express Adapters. This possible performance optimization was not yet used by OpenSSL. Add support for offloading and implement an optimized version of RSA and DH with it. The environment variable OPENSSL_s390xcap now recognizes the token "nocex" to prevent offloading. Signed-off-by: Juergen Christ <jchrist@linux.ibm.com> Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: Tomas Mraz <tomas@openssl.org> (Merged from https://github.com/openssl/openssl/pull/20113)
Diffstat (limited to 'crypto/s390xcap.c')
-rw-r--r--crypto/s390xcap.c87
1 files changed, 84 insertions, 3 deletions
diff --git a/crypto/s390xcap.c b/crypto/s390xcap.c
index 59f0f3ef45..5d2e96805c 100644
--- a/crypto/s390xcap.c
+++ b/crypto/s390xcap.c
@@ -16,6 +16,15 @@
#include "crypto/ctype.h"
#include "s390x_arch.h"
+#if defined(OPENSSL_SYS_LINUX) && !defined(FIPS_MODULE)
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <fcntl.h>
+# include <asm/zcrypt.h>
+# include <sys/ioctl.h>
+# include <unistd.h>
+#endif
+
#if defined(__GLIBC__) && defined(__GLIBC_PREREQ)
# if __GLIBC_PREREQ(2, 16)
# include <sys/auxv.h>
@@ -67,19 +76,41 @@ void OPENSSL_vx_probe(void);
#endif
static const char *env;
-static int parse_env(struct OPENSSL_s390xcap_st *cap);
+static int parse_env(struct OPENSSL_s390xcap_st *cap, int *cex);
void OPENSSL_s390x_facilities(void);
void OPENSSL_s390x_functions(void);
struct OPENSSL_s390xcap_st OPENSSL_s390xcap_P;
+#ifdef S390X_MOD_EXP
+static int probe_cex(void);
+int OPENSSL_s390xcex;
+
+#if defined(__GNUC__)
+__attribute__ ((visibility("hidden")))
+#endif
+void OPENSSL_s390x_cleanup(void);
+
+#if defined(__GNUC__)
+__attribute__ ((visibility("hidden")))
+#endif
+void OPENSSL_s390x_cleanup(void)
+{
+ if (OPENSSL_s390xcex != -1) {
+ (void)close(OPENSSL_s390xcex);
+ OPENSSL_s390xcex = -1;
+ }
+}
+#endif
+
#if defined(__GNUC__) && defined(__linux)
__attribute__ ((visibility("hidden")))
#endif
void OPENSSL_cpuid_setup(void)
{
struct OPENSSL_s390xcap_st cap;
+ int cex = 1;
if (OPENSSL_s390xcap_P.stfle[0])
return;
@@ -140,7 +171,7 @@ void OPENSSL_cpuid_setup(void)
env = getenv("OPENSSL_s390xcap");
if (env != NULL) {
- if (!parse_env(&cap))
+ if (!parse_env(&cap, &cex))
env = NULL;
}
@@ -178,9 +209,52 @@ void OPENSSL_cpuid_setup(void)
OPENSSL_s390xcap_P.kdsa[0] &= cap.kdsa[0];
OPENSSL_s390xcap_P.kdsa[1] &= cap.kdsa[1];
}
+
+#ifdef S390X_MOD_EXP
+ if (cex == 0) {
+ OPENSSL_s390xcex = -1;
+ } else {
+ OPENSSL_s390xcex = open("/dev/z90crypt", O_RDWR | O_CLOEXEC);
+ if (probe_cex() == 1)
+ OPENSSL_atexit(OPENSSL_s390x_cleanup);
+ }
+#endif
}
-static int parse_env(struct OPENSSL_s390xcap_st *cap)
+#ifdef S390X_MOD_EXP
+static int probe_cex(void)
+{
+ struct ica_rsa_modexpo me;
+ const unsigned char inval[16] = {
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,2
+ };
+ const unsigned char modulus[16] = {
+ 0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,3
+ };
+ unsigned char res[16];
+ int olderrno;
+ int rc = 1;
+
+ me.inputdata = (unsigned char *)inval;
+ me.inputdatalength = sizeof(inval);
+ me.outputdata = (unsigned char *)res;
+ me.outputdatalength = sizeof(res);
+ me.b_key = (unsigned char *)inval;
+ me.n_modulus = (unsigned char *)modulus;
+ olderrno = errno;
+ if (ioctl(OPENSSL_s390xcex, ICARSAMODEXPO, &me) == -1) {
+ (void)close(OPENSSL_s390xcex);
+ OPENSSL_s390xcex = -1;
+ rc = 0;
+ }
+ errno = olderrno;
+ return rc;
+}
+#endif
+
+static int parse_env(struct OPENSSL_s390xcap_st *cap, int *cex)
{
/*-
* CPU model data
@@ -732,6 +806,13 @@ static int parse_env(struct OPENSSL_s390xcap_st *cap)
else if TOK_CPU(z15)
else if TOK_CPU(z16)
+ /* nocex to deactivate cex support */
+ else if (sscanf(tok_begin, " %" STR(LEN) "s %" STR(LEN) "s ",
+ tok[0], tok[1]) == 1
+ && !strcmp(tok[0], "nocex")) {
+ *cex = 0;
+ }
+
/* whitespace(ignored) or invalid tokens */
else {
while (*tok_begin != '\0') {