]> git.ipfire.org Git - thirdparty/openssl.git/blobdiff - crypto/s390xcap.c
Raise an error on syscall failure in tls_retry_write_records
[thirdparty/openssl.git] / crypto / s390xcap.c
index 3e6aeae1df55b93685c42fd2e95402fff3bae068..7721b5c801a93490cbd764a72ad2de368267a181 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010-2018 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2010-2023 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
 #include <setjmp.h>
 #include <signal.h>
 #include "internal/cryptlib.h"
-#include "internal/ctype.h"
+#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>
-#  define OSSL_IMPLEMENT_GETAUXVAL
+#  if defined(HWCAP_S390_STFLE) && defined(HWCAP_S390_VX)
+#   define OSSL_IMPLEMENT_GETAUXVAL
+#  endif
 # endif
 #endif
 
             cap->NAME[1] = ~cap->NAME[1];                               \
     }
 
-#define TOK_CPU(NAME)                                                   \
+#define TOK_CPU_ALIAS(NAME, STRUCT_NAME)                                \
     (sscanf(tok_begin,                                                  \
             " %" STR(LEN) "s %" STR(LEN) "s ",                          \
             tok[0], tok[1]) == 1                                        \
      && !strcmp(tok[0], #NAME)) {                                       \
-            memcpy(cap, &NAME, sizeof(*cap));                           \
+            memcpy(cap, &STRUCT_NAME, sizeof(*cap));                    \
     }
 
+#define TOK_CPU(NAME) TOK_CPU_ALIAS(NAME, NAME)
+
 #ifndef OSSL_IMPLEMENT_GETAUXVAL
 static sigjmp_buf ill_jmp;
 static void ill_handler(int sig)
@@ -65,16 +78,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;
@@ -82,7 +120,7 @@ void OPENSSL_cpuid_setup(void)
     /* set a bit that will not be tested later */
     OPENSSL_s390xcap_P.stfle[0] |= S390X_CAPBIT(0);
 
-#ifdef OSSL_IMPLEMENT_GETAUXVAL
+#if defined(OSSL_IMPLEMENT_GETAUXVAL)
     {
         const unsigned long hwcap = getauxval(AT_HWCAP);
 
@@ -135,7 +173,7 @@ void OPENSSL_cpuid_setup(void)
 
     env = getenv("OPENSSL_s390xcap");
     if (env != NULL) {
-        if (!parse_env(&cap))
+        if (!parse_env(&cap, &cex))
             env = NULL;
     }
 
@@ -173,9 +211,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
+}
+
+#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)
+static int parse_env(struct OPENSSL_s390xcap_st *cap, int *cex)
 {
     /*-
      * CPU model data
@@ -646,17 +727,30 @@ static int parse_env(struct OPENSSL_s390xcap_st *cap)
         /*.pcc    = */{S390X_CAPBIT(S390X_QUERY),
                        S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P256)
                        | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P384)
-                       | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P521)},
+                       | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_P521)
+                       | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED25519)
+                       | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_ED448)
+                       | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X25519)
+                       | S390X_CAPBIT(S390X_SCALAR_MULTIPLY_X448)},
         /*.kdsa   = */{S390X_CAPBIT(S390X_QUERY)
                        | S390X_CAPBIT(S390X_ECDSA_VERIFY_P256)
                        | S390X_CAPBIT(S390X_ECDSA_VERIFY_P384)
                        | S390X_CAPBIT(S390X_ECDSA_VERIFY_P521)
                        | S390X_CAPBIT(S390X_ECDSA_SIGN_P256)
                        | S390X_CAPBIT(S390X_ECDSA_SIGN_P384)
-                       | S390X_CAPBIT(S390X_ECDSA_SIGN_P521),
+                       | S390X_CAPBIT(S390X_ECDSA_SIGN_P521)
+                       | S390X_CAPBIT(S390X_EDDSA_VERIFY_ED25519)
+                       | S390X_CAPBIT(S390X_EDDSA_VERIFY_ED448)
+                       | S390X_CAPBIT(S390X_EDDSA_SIGN_ED25519)
+                       | S390X_CAPBIT(S390X_EDDSA_SIGN_ED448),
                        0ULL},
     };
 
+    /*-
+     * z16 (2022) - z/Architecture POP
+     * Implements MSA and MSA1-9 (same as z15, no need to repeat).
+     */
+
     char *tok_begin, *tok_end, *buff, tok[S390X_STFLE_MAX][LEN + 1];
     int rc, off, i, n;
 
@@ -711,6 +805,14 @@ static int parse_env(struct OPENSSL_s390xcap_st *cap)
         else if TOK_CPU(z13)
         else if TOK_CPU(z14)
         else if TOK_CPU(z15)
+        else if TOK_CPU_ALIAS(z16, z15)
+
+        /* 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 {