From b2fd38e6daa00ebb207245392ebdb3274f0560fe Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Wed, 11 Oct 2023 14:26:40 -0700 Subject: [PATCH] Remove `ArrayEncoding` usage from `Digest` and delete `ArrayEncoding`. --- src/digest.rs | 43 ++++++++++++++++++++++++------------------- src/endian.rs | 28 ---------------------------- 2 files changed, 24 insertions(+), 47 deletions(-) diff --git a/src/digest.rs b/src/digest.rs index 47ba631f28..fd935fe4d8 100644 --- a/src/digest.rs +++ b/src/digest.rs @@ -24,11 +24,7 @@ // The goal for this implementation is to drive the overhead as close to zero // as possible. -use crate::{ - c, cpu, debug, - endian::{ArrayEncoding, BigEndian}, - polyfill, -}; +use crate::{c, cpu, debug, polyfill}; use core::num::Wrapping; mod sha1; @@ -248,8 +244,7 @@ impl Digest { impl AsRef<[u8]> for Digest { #[inline(always)] fn as_ref(&self) -> &[u8] { - let as64 = unsafe { &self.value.as64 }; - &as64.as_byte_array()[..self.algorithm.output_len] + &self.value.0[..self.algorithm.output_len] } } @@ -456,10 +451,7 @@ union State { } #[derive(Clone, Copy)] -union Output { - as64: [BigEndian; 512 / 8 / core::mem::size_of::>()], - as32: [BigEndian; 256 / 8 / core::mem::size_of::>()], -} +struct Output([u8; MAX_OUTPUT_LEN]); /// The maximum block length ([`Algorithm::block_len()`]) of all the algorithms /// in this module. @@ -474,17 +466,30 @@ pub const MAX_OUTPUT_LEN: usize = 512 / 8; pub const MAX_CHAINING_LEN: usize = MAX_OUTPUT_LEN; fn sha256_format_output(input: State) -> Output { - let input = unsafe { &input.as32 }; - Output { - as32: input.map(BigEndian::from), - } + let input = unsafe { input.as32 }; + format_output::<_, _, { core::mem::size_of::() }>(input, u32::to_be_bytes) } fn sha512_format_output(input: State) -> Output { - let input = unsafe { &input.as64 }; - Output { - as64: input.map(BigEndian::from), - } + let input = unsafe { input.as64 }; + format_output::<_, _, { core::mem::size_of::() }>(input, u64::to_be_bytes) +} + +#[inline] +fn format_output(input: [Wrapping; sha2::CHAINING_WORDS], f: F) -> Output +where + F: Fn(T) -> [u8; N], + T: Copy, +{ + let mut output = Output([0; MAX_OUTPUT_LEN]); + output + .0 + .iter_mut() + .zip(input.iter().copied().map(|Wrapping(w)| f(w)).flatten()) + .for_each(|(o, i)| { + *o = i; + }); + output } /// The length of the output of SHA-1, in bytes. diff --git a/src/endian.rs b/src/endian.rs index 3849089106..f9b14c53f1 100644 --- a/src/endian.rs +++ b/src/endian.rs @@ -11,12 +11,6 @@ where const ZERO: Self; } -/// Work around the inability to implement `AsRef` for arrays of `Encoding`s -/// due to the coherence rules. -pub trait ArrayEncoding { - fn as_byte_array(&self) -> &T; -} - macro_rules! define_endian { ($endian:ident) => { #[derive(Clone, Copy)] @@ -25,21 +19,6 @@ macro_rules! define_endian { }; } -macro_rules! impl_array_encoding { - ($endian:ident, $base:ident, $elems:expr) => { - impl ArrayEncoding<[u8; $elems * core::mem::size_of::<$base>()]> - for [$endian<$base>; $elems] - { - #[inline] - fn as_byte_array(&self) -> &[u8; $elems * core::mem::size_of::<$base>()] { - let as_bytes_ptr = - self.as_ptr() as *const [u8; $elems * core::mem::size_of::<$base>()]; - unsafe { &*as_bytes_ptr } - } - } - }; -} - macro_rules! impl_endian { ($endian:ident, $base:ident, $to_endian:ident, $from_endian:ident, $size:expr) => { impl Encoding<$base> for $endian<$base> { @@ -80,18 +59,11 @@ macro_rules! impl_endian { $base::$from_endian(value) } } - - impl_array_encoding!($endian, $base, 1); - impl_array_encoding!($endian, $base, 2); - impl_array_encoding!($endian, $base, 3); - impl_array_encoding!($endian, $base, 4); - impl_array_encoding!($endian, $base, 8); }; } define_endian!(BigEndian); impl_endian!(BigEndian, u32, to_be, from_be, 4); -impl_endian!(BigEndian, u64, to_be, from_be, 8); #[cfg(test)] mod tests {