From ac6be586c2ff0c70f8a5bab6f1ed814955439770 Mon Sep 17 00:00:00 2001 From: Justin Smith Date: Wed, 1 May 2024 14:01:11 -0400 Subject: [PATCH 1/4] ppc64le: support OPENSSL_ppccap ENV variable --- crypto/fipsmodule/cpucap/cpu_intel.c | 4 +-- crypto/fipsmodule/cpucap/cpu_ppc64le.c | 45 ++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/crypto/fipsmodule/cpucap/cpu_intel.c b/crypto/fipsmodule/cpucap/cpu_intel.c index 5d5fa5eff6..e236e3e699 100644 --- a/crypto/fipsmodule/cpucap/cpu_intel.c +++ b/crypto/fipsmodule/cpucap/cpu_intel.c @@ -137,9 +137,9 @@ static void handle_cpu_env(uint32_t *out, const char *in) { int sscanf_result; uint64_t v; if (hex) { - sscanf_result = sscanf(in + invert + 2, "%" PRIx64, &v); + sscanf_result = sscanf(in + skip_first_byte + 2, "%" PRIx64, &v); } else { - sscanf_result = sscanf(in + invert, "%" PRIu64, &v); + sscanf_result = sscanf(in + skip_first_byte, "%" PRIu64, &v); } if (!sscanf_result) { diff --git a/crypto/fipsmodule/cpucap/cpu_ppc64le.c b/crypto/fipsmodule/cpucap/cpu_ppc64le.c index ab29ec5c93..e9e9891fe3 100644 --- a/crypto/fipsmodule/cpucap/cpu_ppc64le.c +++ b/crypto/fipsmodule/cpucap/cpu_ppc64le.c @@ -24,11 +24,56 @@ #define PPC_FEATURE2_HAS_VCRYPTO 0x02000000 #endif +static void handle_cpu_env(unsigned long *out, const char *in) { + OPENSSL_STATIC_ASSERT(sizeof(unsigned long) == 8, PPC64LE_UNSIGNED_LONG_NOT_8_BYTES); + + const int invert = in[0] == '~'; + const int or = in[0] == '|'; + const int skip_first_byte = (invert || or) ? 1 : 0; + const int hex = in[skip_first_byte] == '0' && in[skip_first_byte+1] == 'x'; + + int sscanf_result; + uint64_t v; + if (hex) { + sscanf_result = sscanf(in + skip_first_byte + 2, "%" PRIx64, &v); + } else { + sscanf_result = sscanf(in + skip_first_byte, "%" PRIu64, &v); + } + + if (!sscanf_result) { + return; + } + + if (invert) { + *out &= ~v; + } else if (or) { + *out |= v; + } else { + *out = v; + } +} + extern uint8_t OPENSSL_cpucap_initialized; void OPENSSL_cpuid_setup(void) { OPENSSL_ppc64le_hwcap2 = getauxval(AT_HWCAP2); OPENSSL_cpucap_initialized = 1; + + // OPENSSL_ppccap is a 64-bit hex string which may start with "0x". + // Prior to the value, a '~' or '|' may be given. + // + // If the '~' prefix is present: + // the value is inverted and ANDed with the probed CPUID result + // If the '|' prefix is present: + // the value is ORed with the probed CPUID result + // Otherwise: + // the value is taken as the result of the CPUID + const char *env; + env = getenv("OPENSSL_ppccap"); + if (env != NULL) { + handle_cpu_env(&OPENSSL_ppc64le_hwcap2, env); + } + } int CRYPTO_is_PPC64LE_vcrypto_capable(void) { From bd438fcff4cf66f465c268e1f6f4a472dd234f2a Mon Sep 17 00:00:00 2001 From: Justin Smith Date: Tue, 14 May 2024 11:17:57 -0400 Subject: [PATCH 2/4] Reject unsupported ppc capabilities --- crypto/fipsmodule/cpucap/cpu_intel.c | 30 ++++++++++++++++++++------ crypto/fipsmodule/cpucap/cpu_ppc64le.c | 24 +++++++++++++++------ 2 files changed, 42 insertions(+), 12 deletions(-) diff --git a/crypto/fipsmodule/cpucap/cpu_intel.c b/crypto/fipsmodule/cpucap/cpu_intel.c index e236e3e699..5e469ad2c4 100644 --- a/crypto/fipsmodule/cpucap/cpu_intel.c +++ b/crypto/fipsmodule/cpucap/cpu_intel.c @@ -133,6 +133,8 @@ static void handle_cpu_env(uint32_t *out, const char *in) { const int or = in[0] == '|'; const int skip_first_byte = invert || or; const int hex = in[skip_first_byte] == '0' && in[skip_first_byte+1] == 'x'; + uint32_t intelcap0 = out[0]; + uint32_t intelcap1 = out[1]; int sscanf_result; uint64_t v; @@ -146,15 +148,31 @@ static void handle_cpu_env(uint32_t *out, const char *in) { return; } + uint32_t reqcap0 = (uint32_t)(v & UINT32_MAX); + uint32_t reqcap1 = (uint32_t)(v >> 32); + + // Detect if the user is trying to use the environment variable to set + // a capability that is _not_ available on the CPU. + // The case of invert cannot enable an unexisting capability; + // it can only disable an existing one. + if (!invert && (intelcap0 || intelcap1)) { + if((~intelcap0 & reqcap0) || (~intelcap1 & reqcap1)) { + fprintf(stderr, + "Fatal Error: HW capability found: 0x%02X 0x%02X, but HW capability requested: 0x%02X 0x%02X.\n", + intelcap0, intelcap1, reqcap0, reqcap1); + abort(); + } + } + if (invert) { - out[0] &= ~v; - out[1] &= ~(v >> 32); + out[0] &= ~reqcap0; + out[1] &= ~reqcap1; } else if (or) { - out[0] |= v; - out[1] |= (v >> 32); + out[0] |= reqcap0; + out[1] |= reqcap1; } else { - out[0] = v; - out[1] = v >> 32; + out[0] = reqcap0; + out[1] = reqcap1; } } diff --git a/crypto/fipsmodule/cpucap/cpu_ppc64le.c b/crypto/fipsmodule/cpucap/cpu_ppc64le.c index e9e9891fe3..61fe953846 100644 --- a/crypto/fipsmodule/cpucap/cpu_ppc64le.c +++ b/crypto/fipsmodule/cpucap/cpu_ppc64le.c @@ -31,25 +31,37 @@ static void handle_cpu_env(unsigned long *out, const char *in) { const int or = in[0] == '|'; const int skip_first_byte = (invert || or) ? 1 : 0; const int hex = in[skip_first_byte] == '0' && in[skip_first_byte+1] == 'x'; + unsigned long ppccap = *out; int sscanf_result; - uint64_t v; + uint64_t reqcap; if (hex) { - sscanf_result = sscanf(in + skip_first_byte + 2, "%" PRIx64, &v); + sscanf_result = sscanf(in + skip_first_byte + 2, "%" PRIx64, &reqcap); } else { - sscanf_result = sscanf(in + skip_first_byte, "%" PRIu64, &v); + sscanf_result = sscanf(in + skip_first_byte, "%" PRIu64, &reqcap); } if (!sscanf_result) { return; } + // Detect if the user is trying to use the environment variable to set + // a capability that is _not_ available on the CPU. + // The case of invert cannot enable an unexisting capability; + // it can only disable an existing one. + if (!invert && ppccap && (~ppccap & reqcap)) { + fprintf(stderr, + "Fatal Error: HW capability found: 0x%02lX, but HW capability requested: 0x%02lX.\n", + ppccap, reqcap); + abort(); + } + if (invert) { - *out &= ~v; + *out &= ~reqcap; } else if (or) { - *out |= v; + *out |= reqcap; } else { - *out = v; + *out = reqcap; } } From 5cd1b450cdddafa080f40ba666df5fdfd162eaab Mon Sep 17 00:00:00 2001 From: Justin Smith Date: Tue, 14 May 2024 14:25:34 -0400 Subject: [PATCH 3/4] Allow Intel RDRAND to be set for testing regardless --- crypto/fipsmodule/cpucap/cpu_intel.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crypto/fipsmodule/cpucap/cpu_intel.c b/crypto/fipsmodule/cpucap/cpu_intel.c index 5e469ad2c4..078ab3955a 100644 --- a/crypto/fipsmodule/cpucap/cpu_intel.c +++ b/crypto/fipsmodule/cpucap/cpu_intel.c @@ -156,7 +156,8 @@ static void handle_cpu_env(uint32_t *out, const char *in) { // The case of invert cannot enable an unexisting capability; // it can only disable an existing one. if (!invert && (intelcap0 || intelcap1)) { - if((~intelcap0 & reqcap0) || (~intelcap1 & reqcap1)) { + // Still allow RDRAND bit to be set for testing + if((~(1u << 30 | intelcap0) & reqcap0) || (~intelcap1 & reqcap1)) { fprintf(stderr, "Fatal Error: HW capability found: 0x%02X 0x%02X, but HW capability requested: 0x%02X 0x%02X.\n", intelcap0, intelcap1, reqcap0, reqcap1); From 18015bf394261a35733b397f300b683087e6222e Mon Sep 17 00:00:00 2001 From: Justin Smith Date: Wed, 15 May 2024 10:59:31 -0400 Subject: [PATCH 4/4] Fix comment --- crypto/fipsmodule/cpucap/cpu_intel.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/fipsmodule/cpucap/cpu_intel.c b/crypto/fipsmodule/cpucap/cpu_intel.c index 078ab3955a..19b6540d02 100644 --- a/crypto/fipsmodule/cpucap/cpu_intel.c +++ b/crypto/fipsmodule/cpucap/cpu_intel.c @@ -156,7 +156,7 @@ static void handle_cpu_env(uint32_t *out, const char *in) { // The case of invert cannot enable an unexisting capability; // it can only disable an existing one. if (!invert && (intelcap0 || intelcap1)) { - // Still allow RDRAND bit to be set for testing + // Allow Intel indicator bit to be set for testing if((~(1u << 30 | intelcap0) & reqcap0) || (~intelcap1 & reqcap1)) { fprintf(stderr, "Fatal Error: HW capability found: 0x%02X 0x%02X, but HW capability requested: 0x%02X 0x%02X.\n",