From c24c4bdff734b0441c7c9198c5fe4e37b7b35df7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Wed, 21 Jan 2026 14:37:59 +0000 Subject: [PATCH 1/2] Add sha2 support for non-x86_64 platforms via feature gate. --- Cargo.toml | 2 ++ src/lib.rs | 40 +++++++++++++++++++++++++--------------- src/sha2_impl.rs | 5 ++--- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 67b33d5..f1bb933 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ rust-version = "1.80.0" [dependencies] ring = { version = "0.17", optional = true } +sha2 = { version = "0.10", optional = true } [target.'cfg(target_arch = "x86_64")'.dependencies] cpufeatures = "0.2" @@ -28,3 +29,4 @@ wasm-bindgen-test = "0.3.33" default = ["zero_hash_cache", "ring"] zero_hash_cache = [] ring = ["dep:ring"] +sha2 = ["dep:sha2"] diff --git a/src/lib.rs b/src/lib.rs index b91b431..96f5685 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ mod sha2_impl; pub use self::DynamicContext as Context; -#[cfg(target_arch = "x86_64")] +#[cfg(any(target_arch = "x86_64", feature = "sha2"))] use sha2_impl::Sha2CrateImpl; #[cfg(feature = "zero_hash_cache")] @@ -98,7 +98,7 @@ impl Sha256 for RingImpl { /// Default dynamic implementation that switches between available implementations. pub enum DynamicImpl { - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", feature = "sha2"))] Sha2, #[cfg(feature = "ring")] Ring, @@ -123,16 +123,13 @@ impl DynamicImpl { /// Choose the best available implementation based on the currently executing CPU. #[inline(always)] pub fn best() -> Self { - #[cfg(all(not(feature = "ring"), not(target_arch = "x86_64")))] - { - compile_error!("Ring must be enabled on non-x86_64 architectures"); - } - - #[cfg(all(not(feature = "ring"), target_arch = "x86_64"))] + // If sha2 feature is enabled (non-x86_64), use sha2 + #[cfg(all(feature = "sha2", not(target_arch = "x86_64")))] { Self::Sha2 } + // On x86_64 with ring: check for SHA extensions #[cfg(all(feature = "ring", target_arch = "x86_64"))] if have_sha_extensions() { Self::Sha2 @@ -140,10 +137,23 @@ impl DynamicImpl { Self::Ring } - #[cfg(all(feature = "ring", not(target_arch = "x86_64")))] + // On x86_64 without ring: always use sha2 + #[cfg(all(not(feature = "ring"), target_arch = "x86_64"))] + { + Self::Sha2 + } + + // On non-x86_64 with ring but without sha2 feature: use ring + #[cfg(all(feature = "ring", not(target_arch = "x86_64"), not(feature = "sha2")))] { Self::Ring } + + // Compile error if no implementation available + #[cfg(all(not(feature = "ring"), not(target_arch = "x86_64"), not(feature = "sha2")))] + { + compile_error!("Either 'ring' or 'sha2' feature must be enabled on non-x86_64 architectures"); + } } } @@ -153,7 +163,7 @@ impl Sha256 for DynamicImpl { #[inline(always)] fn hash(&self, input: &[u8]) -> Vec { match self { - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", feature = "sha2"))] Self::Sha2 => Sha2CrateImpl.hash(input), #[cfg(feature = "ring")] Self::Ring => RingImpl.hash(input), @@ -163,7 +173,7 @@ impl Sha256 for DynamicImpl { #[inline(always)] fn hash_fixed(&self, input: &[u8]) -> [u8; HASH_LEN] { match self { - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", feature = "sha2"))] Self::Sha2 => Sha2CrateImpl.hash_fixed(input), #[cfg(feature = "ring")] Self::Ring => RingImpl.hash_fixed(input), @@ -175,7 +185,7 @@ impl Sha256 for DynamicImpl { /// /// This enum ends up being 8 bytes larger than the largest inner context. pub enum DynamicContext { - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", feature = "sha2"))] Sha2(sha2::Sha256), #[cfg(feature = "ring")] Ring(ring::digest::Context), @@ -184,7 +194,7 @@ pub enum DynamicContext { impl Sha256Context for DynamicContext { fn new() -> Self { match DynamicImpl::best() { - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", feature = "sha2"))] DynamicImpl::Sha2 => Self::Sha2(Sha256Context::new()), #[cfg(feature = "ring")] DynamicImpl::Ring => Self::Ring(Sha256Context::new()), @@ -193,7 +203,7 @@ impl Sha256Context for DynamicContext { fn update(&mut self, bytes: &[u8]) { match self { - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", feature = "sha2"))] Self::Sha2(ctxt) => Sha256Context::update(ctxt, bytes), #[cfg(feature = "ring")] Self::Ring(ctxt) => Sha256Context::update(ctxt, bytes), @@ -202,7 +212,7 @@ impl Sha256Context for DynamicContext { fn finalize(self) -> [u8; HASH_LEN] { match self { - #[cfg(target_arch = "x86_64")] + #[cfg(any(target_arch = "x86_64", feature = "sha2"))] Self::Sha2(ctxt) => Sha256Context::finalize(ctxt), #[cfg(feature = "ring")] Self::Ring(ctxt) => Sha256Context::finalize(ctxt), diff --git a/src/sha2_impl.rs b/src/sha2_impl.rs index 692c614..85f5b10 100644 --- a/src/sha2_impl.rs +++ b/src/sha2_impl.rs @@ -1,6 +1,5 @@ -// This implementation should only be compiled on x86_64 due to its dependency on the `sha2` and -// `cpufeatures` crates which do not compile on some architectures like RISC-V. -#![cfg(target_arch = "x86_64")] +// This implementation is compiled on x86_64 (always has sha2) or when the sha2 feature is enabled. +#![cfg(any(target_arch = "x86_64", feature = "sha2"))] use crate::{Sha256, Sha256Context, HASH_LEN}; use sha2::Digest; From 3b177075577336bcffee0306e3edca27deabda23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andrzej=20Bro=C5=84ski?= Date: Wed, 4 Feb 2026 15:06:57 +0100 Subject: [PATCH 2/2] Fix formatting. --- src/lib.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 96f5685..a41443b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -150,9 +150,15 @@ impl DynamicImpl { } // Compile error if no implementation available - #[cfg(all(not(feature = "ring"), not(target_arch = "x86_64"), not(feature = "sha2")))] + #[cfg(all( + not(feature = "ring"), + not(target_arch = "x86_64"), + not(feature = "sha2") + ))] { - compile_error!("Either 'ring' or 'sha2' feature must be enabled on non-x86_64 architectures"); + compile_error!( + "Either 'ring' or 'sha2' feature must be enabled on non-x86_64 architectures" + ); } } }