cpu: Always use #[cfg] for target-arch-specific tests.

Previously we were relying in part on the compiler and linker to work
together to inline always-false guards around calls to architecture-
specific functions that might not even exist. However, this isn't
guaranteed to work, though so far it always has. Instead, use
compile-time logic to guard all architecture-specific calls.

To help ensure tihs happens, only expose `cpu::intel` on Intel targets
and similarly only expose `cpu::arm` on ARM targets.
This commit is contained in:
Brian Smith 2023-12-11 09:44:48 -08:00
parent 2d974347e0
commit 0395743dc1
7 changed files with 56 additions and 24 deletions

View File

@ -171,6 +171,7 @@ all-features = true
name = "ring"
[dependencies]
cfg-if = { version = "1.0.0", default-features = false }
getrandom = { version = "0.2.10" }
untrusted = { version = "0.9" }

View File

@ -395,14 +395,16 @@ fn detect_implementation(cpu_features: cpu::Features) -> Implementation {
)))]
let _cpu_features = cpu_features;
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
{
if cpu::intel::AES.available(cpu_features) || cpu::arm::AES.available(cpu_features) {
if cpu::arm::AES.available(cpu_features) {
return Implementation::HWAES;
}
}
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
{
if cpu::intel::AES.available(cpu_features) {
return Implementation::HWAES;
}
}

View File

@ -59,7 +59,7 @@ fn chacha20_poly1305_seal(
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
{
if cpu::intel::SSE41.available(cpu_features) || cpu::arm::NEON.available(cpu_features) {
if has_integrated(cpu_features) {
// XXX: BoringSSL uses `alignas(16)` on `key` instead of on the
// structure, but Rust can't do that yet; see
// https://github.com/rust-lang/rust/issues/73557.
@ -141,7 +141,7 @@ fn chacha20_poly1305_open(
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
{
if cpu::intel::SSE41.available(cpu_features) || cpu::arm::NEON.available(cpu_features) {
if has_integrated(cpu_features) {
// XXX: BoringSSL uses `alignas(16)` on `key` instead of on the
// structure, but Rust can't do that yet; see
// https://github.com/rust-lang/rust/issues/73557.
@ -204,6 +204,21 @@ fn chacha20_poly1305_open(
finish(auth, aad.as_ref().len(), in_out[src].len())
}
#[cfg(any(target_arch = "aarch64", target_arch = "x86_64"))]
#[allow(clippy::needless_return)]
#[inline(always)]
fn has_integrated(cpu_features: cpu::Features) -> bool {
#[cfg(target_arch = "aarch64")]
{
return cpu::arm::NEON.available(cpu_features);
}
#[cfg(target_arch = "x86_64")]
{
return cpu::intel::SSE41.available(cpu_features);
}
}
fn finish(mut auth: poly1305::Context, aad_len: usize, in_out_len: usize) -> Tag {
let block: [[u8; 8]; 2] = [aad_len, in_out_len]
.map(polyfill::u64_from_usize)

View File

@ -320,16 +320,16 @@ fn detect_implementation(cpu_features: cpu::Features) -> Implementation {
)))]
let _cpu_features = cpu_features;
#[cfg(any(
target_arch = "aarch64",
target_arch = "arm",
target_arch = "x86_64",
target_arch = "x86"
))]
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
{
if (cpu::intel::FXSR.available(cpu_features)
&& cpu::intel::PCLMULQDQ.available(cpu_features))
|| cpu::arm::PMULL.available(cpu_features)
if cpu::arm::PMULL.available(cpu_features) {
return Implementation::CLMUL;
}
}
#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
{
if cpu::intel::FXSR.available(cpu_features) && cpu::intel::PCLMULQDQ.available(cpu_features)
{
return Implementation::CLMUL;
}

View File

@ -44,5 +44,8 @@ pub(crate) fn features() -> Features {
Features(())
}
#[cfg(any(target_arch = "aarch64", target_arch = "arm"))]
pub mod arm;
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
pub mod intel;

View File

@ -51,16 +51,19 @@ impl Feature {
}
}
#[allow(dead_code)]
pub(crate) const ADX: Feature = Feature {
word: 2,
mask: 1 << 19,
};
#[allow(dead_code)]
pub(crate) const BMI1: Feature = Feature {
word: 2,
mask: 1 << 3,
};
#[allow(dead_code)]
pub(crate) const BMI2: Feature = Feature {
word: 2,
mask: 1 << 8,

View File

@ -157,12 +157,20 @@ fn encode_point(x: Elem<T>, y: Elem<T>, z: Elem<T>) -> EncodedPoint {
bytes
}
#[inline]
pub(super) fn has_fe25519_adx(cpu: cpu::Features) -> bool {
cfg!(all(target_arch = "x86_64", not(target_os = "windows")))
&& cpu::intel::ADX.available(cpu)
&& cpu::intel::BMI1.available(cpu)
&& cpu::intel::BMI2.available(cpu)
cfg_if::cfg_if! {
if #[cfg(all(target_arch = "x86_64", not(target_os = "windows")))] {
#[inline(always)]
pub(super) fn has_fe25519_adx(cpu: cpu::Features) -> bool {
cpu::intel::ADX.available(cpu)
&& cpu::intel::BMI1.available(cpu)
&& cpu::intel::BMI2.available(cpu)
}
} else {
#[inline(always)]
pub (super) fn has_fe25519_adx(_cpu: cpu::Features) -> bool {
false
}
}
}
prefixed_extern! {