crypto/cryptlib.c: mask more capability bits upon FXSR bit flip.
authorAndy Polyakov <appro@openssl.org>
Wed, 30 Aug 2017 23:09:48 +0000 (01:09 +0200)
committerAndy Polyakov <appro@openssl.org>
Fri, 1 Sep 2017 06:50:49 +0000 (08:50 +0200)
OPENSSL_ia32cap.pod discusses possibility to disable operations on
XMM register bank. This formally means that this flag has to be checked
in combination with other flags. But it customarily isn't. But instead
of chasing all the cases we can flip more bits together with FXSR one.

Reviewed-by: Richard Levitte <levitte@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/4303)

(cherry picked from commit 6e5a853bda24e8aece325ecf5aa68b8ea832e414)

crypto/cryptlib.c
crypto/modes/gcm128.c

index 01b8ce5ed15703df6f587e2bb6c1c8b9aeb045f3..f011b4b6923cb0d7799a8310cdbda5e2f9adf97f 100644 (file)
@@ -46,12 +46,24 @@ void OPENSSL_cpuid_setup(void)
         if (!sscanf(env + off, "%lli", (long long *)&vec))
             vec = strtoul(env + off, NULL, 0);
 #  endif
-        if (off)
-            vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~vec;
-        else if (env[0] == ':')
+        if (off) {
+            IA32CAP mask = vec;
+            vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P) & ~mask;
+            if (mask & (1<<24)) {
+                /*
+                 * User disables FXSR bit, mask even other capabilities
+                 * that operate exclusively on XMM, so we don't have to
+                 * double-check all the time. We mask PCLMULQDQ, AMD XOP,
+                 * AES-NI and AVX. Formally speaking we don't have to
+                 * do it in x86_64 case, but we can safely assume that
+                 * x86_64 users won't actually flip this flag.
+                 */
+                vec &= ~((IA32CAP)(1<<1|1<<11|1<<25|1<<28) << 32);
+            }
+        } else if (env[0] == ':') {
             vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
+        }
 
-        OPENSSL_ia32cap_P[2] = 0;
         if ((env = strchr(env, ':'))) {
             unsigned int vecx;
             env++;
@@ -61,9 +73,12 @@ void OPENSSL_cpuid_setup(void)
                 OPENSSL_ia32cap_P[2] &= ~vecx;
             else
                 OPENSSL_ia32cap_P[2] = vecx;
+        } else {
+            OPENSSL_ia32cap_P[2] = 0;
         }
-    } else
+    } else {
         vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P);
+    }
 
     /*
      * |(1<<10) sets a reserved bit to signal that variable
index df9f654764da848d5869ebcf8e10140ad86f950f..a2b05c4d6c3f1349e0230154c2497943f928be1d 100644 (file)
@@ -747,8 +747,7 @@ void CRYPTO_gcm128_init(GCM128_CONTEXT *ctx, void *key, block128_f block)
 # endif
 # if    defined(GHASH_ASM_X86_OR_64)
 #  if   !defined(GHASH_ASM_X86) || defined(OPENSSL_IA32_SSE2)
-    if (OPENSSL_ia32cap_P[0] & (1 << 24) && /* check FXSR bit */
-        OPENSSL_ia32cap_P[1] & (1 << 1)) { /* check PCLMULQDQ bit */
+    if (OPENSSL_ia32cap_P[1] & (1 << 1)) { /* check PCLMULQDQ bit */
         if (((OPENSSL_ia32cap_P[1] >> 22) & 0x41) == 0x41) { /* AVX+MOVBE */
             gcm_init_avx(ctx->Htable, ctx->H.u);
             ctx->gmult = gcm_gmult_avx;