diff options
Diffstat (limited to 'crypto/cpuid.c')
-rw-r--r-- | crypto/cpuid.c | 69 |
1 files changed, 42 insertions, 27 deletions
diff --git a/crypto/cpuid.c b/crypto/cpuid.c index 090f6fe03ecc..538a5a039f20 100644 --- a/crypto/cpuid.c +++ b/crypto/cpuid.c @@ -1,5 +1,5 @@ /* - * Copyright 1998-2021 The OpenSSL Project Authors. All Rights Reserved. + * Copyright 1998-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 @@ -7,14 +7,14 @@ * https://www.openssl.org/source/license.html */ -#include "e_os.h" +#include "internal/e_os.h" #include "crypto/cryptlib.h" #if defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ defined(__x86_64) || defined(__x86_64__) || \ defined(_M_AMD64) || defined(_M_X64) -extern unsigned int OPENSSL_ia32cap_P[4]; +extern unsigned int OPENSSL_ia32cap_P[OPENSSL_IA32CAP_P_MAX_INDEXES]; # if defined(OPENSSL_CPUID_OBJ) @@ -29,18 +29,18 @@ extern unsigned int OPENSSL_ia32cap_P[4]; */ # ifdef _WIN32 typedef WCHAR variant_char; - +# define OPENSSL_IA32CAP_P_MAX_CHAR_SIZE 256 static variant_char *ossl_getenv(const char *name) { /* * Since we pull only one environment variable, it's simpler to - * to just ignore |name| and use equivalent wide-char L-literal. + * just ignore |name| and use equivalent wide-char L-literal. * As well as to ignore excessively long values... */ - static WCHAR value[48]; - DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap", value, 48); + static WCHAR value[OPENSSL_IA32CAP_P_MAX_CHAR_SIZE]; + DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap", value, OPENSSL_IA32CAP_P_MAX_CHAR_SIZE); - return (len > 0 && len < 48) ? value : NULL; + return (len > 0 && len < OPENSSL_IA32CAP_P_MAX_CHAR_SIZE) ? value : NULL; } # else typedef char variant_char; @@ -71,7 +71,7 @@ static uint64_t ossl_strtouint64(const variant_char *str) base = 16, str++; } - while((digit = todigit(*str++)) < base) + while ((digit = todigit(*str++)) < base) ret = ret * base + digit; return ret; @@ -80,7 +80,7 @@ static uint64_t ossl_strtouint64(const variant_char *str) static variant_char *ossl_strchr(const variant_char *str, char srch) { variant_char c; - while((c = *str)) { + while ((c = *str)) { if (c == srch) return (variant_char *)str; str++; @@ -98,6 +98,7 @@ void OPENSSL_cpuid_setup(void) IA32CAP OPENSSL_ia32_cpuid(unsigned int *); IA32CAP vec; const variant_char *env; + int index = 2; if (trigger) return; @@ -126,23 +127,37 @@ void OPENSSL_cpuid_setup(void) vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); } - if ((env = ossl_strchr(env, ':')) != NULL) { - IA32CAP vecx; - + /* Processed indexes 0, 1 */ + if ((env = ossl_strchr(env, ':')) != NULL) env++; - off = (env[0] == '~') ? 1 : 0; - vecx = ossl_strtouint64(env + off); - if (off) { - OPENSSL_ia32cap_P[2] &= ~(unsigned int)vecx; - OPENSSL_ia32cap_P[3] &= ~(unsigned int)(vecx >> 32); - } else { - OPENSSL_ia32cap_P[2] = (unsigned int)vecx; - OPENSSL_ia32cap_P[3] = (unsigned int)(vecx >> 32); + for (; index < OPENSSL_IA32CAP_P_MAX_INDEXES; index += 2) { + if ((env != NULL) && (env[0] != '\0')) { + /* if env[0] == ':' current index is skipped */ + if (env[0] != ':') { + IA32CAP vecx; + + off = (env[0] == '~') ? 1 : 0; + vecx = ossl_strtouint64(env + off); + if (off) { + OPENSSL_ia32cap_P[index] &= ~(unsigned int)vecx; + OPENSSL_ia32cap_P[index + 1] &= ~(unsigned int)(vecx >> 32); + } else { + OPENSSL_ia32cap_P[index] = (unsigned int)vecx; + OPENSSL_ia32cap_P[index + 1] = (unsigned int)(vecx >> 32); + } + } + /* skip delimeter */ + if ((env = ossl_strchr(env, ':')) != NULL) + env++; + } else { /* zeroize the next two indexes */ + OPENSSL_ia32cap_P[index] = 0; + OPENSSL_ia32cap_P[index + 1] = 0; } - } else { - OPENSSL_ia32cap_P[2] = 0; - OPENSSL_ia32cap_P[3] = 0; } + + /* If AVX10 is disabled, zero out its detailed cap bits */ + if (!(OPENSSL_ia32cap_P[6] & (1 << 19))) + OPENSSL_ia32cap_P[9] = 0; } else { vec = OPENSSL_ia32_cpuid(OPENSSL_ia32cap_P); } @@ -156,7 +171,7 @@ void OPENSSL_cpuid_setup(void) OPENSSL_ia32cap_P[1] = (unsigned int)(vec >> 32); } # else -unsigned int OPENSSL_ia32cap_P[4]; +unsigned int OPENSSL_ia32cap_P[OPENSSL_IA32CAP_P_MAX_INDEXES]; # endif #endif @@ -173,7 +188,7 @@ void OPENSSL_cpuid_setup(void) */ /* - * The volatile is used to to ensure that the compiler generates code that reads + * The volatile is used to ensure that the compiler generates code that reads * all values from the array and doesn't try to optimize this away. The standard * doesn't actually require this behavior if the original data pointed to is * not volatile, but compilers do this in practice anyway. @@ -181,7 +196,7 @@ void OPENSSL_cpuid_setup(void) * There are also assembler versions of this function. */ # undef CRYPTO_memcmp -int CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len) +int CRYPTO_memcmp(const void *in_a, const void *in_b, size_t len) { size_t i; const volatile unsigned char *a = in_a; |