diff --git a/.github/workflows/ghash.yml b/.github/workflows/ghash.yml index f927629..1d1b1aa 100644 --- a/.github/workflows/ghash.yml +++ b/.github/workflows/ghash.yml @@ -25,7 +25,7 @@ jobs: strategy: matrix: rust: - - 1.41.0 # MSRV + - 1.49.0 # MSRV - stable target: - thumbv7em-none-eabi @@ -54,7 +54,7 @@ jobs: strategy: matrix: rust: - - 1.41.0 # MSRV + - 1.49.0 # MSRV - stable steps: - uses: actions/checkout@v1 diff --git a/.github/workflows/polyval.yml b/.github/workflows/polyval.yml index d4c4c3f..bdc81c8 100644 --- a/.github/workflows/polyval.yml +++ b/.github/workflows/polyval.yml @@ -25,7 +25,7 @@ jobs: strategy: matrix: rust: - - 1.41.0 # MSRV + - 1.49.0 # MSRV - stable target: - thumbv7em-none-eabi @@ -52,7 +52,7 @@ jobs: include: # 32-bit Linux - target: i686-unknown-linux-gnu - rust: 1.41.0 # MSRV + rust: 1.49.0 # MSRV deps: sudo apt update && sudo apt install gcc-multilib - target: i686-unknown-linux-gnu rust: stable @@ -60,7 +60,7 @@ jobs: # 64-bit Linux - target: x86_64-unknown-linux-gnu - rust: 1.41.0 # MSRV + rust: 1.49.0 # MSRV - target: x86_64-unknown-linux-gnu rust: stable steps: @@ -89,7 +89,7 @@ jobs: include: # 32-bit Linux - target: i686-unknown-linux-gnu - rust: 1.41.0 # MSRV + rust: 1.49.0 # MSRV deps: sudo apt update && sudo apt install gcc-multilib - target: i686-unknown-linux-gnu rust: stable @@ -97,7 +97,7 @@ jobs: # 64-bit Linux - target: x86_64-unknown-linux-gnu - rust: 1.41.0 # MSRV + rust: 1.49.0 # MSRV - target: x86_64-unknown-linux-gnu rust: stable steps: @@ -125,7 +125,7 @@ jobs: include: # 32-bit Linux - target: i686-unknown-linux-gnu - rust: 1.41.0 # MSRV + rust: 1.49.0 # MSRV deps: sudo apt update && sudo apt install gcc-multilib - target: i686-unknown-linux-gnu rust: stable @@ -133,7 +133,7 @@ jobs: # 64-bit Linux - target: x86_64-unknown-linux-gnu - rust: 1.41.0 # MSRV + rust: 1.49.0 # MSRV - target: x86_64-unknown-linux-gnu rust: stable steps: @@ -159,13 +159,13 @@ jobs: include: # ARM64 - target: aarch64-unknown-linux-gnu - rust: 1.41.0 # MSRV + rust: 1.49.0 # MSRV - target: aarch64-unknown-linux-gnu rust: stable # PPC32 - target: powerpc-unknown-linux-gnu - rust: 1.41.0 # MSRV + rust: 1.49.0 # MSRV - target: powerpc-unknown-linux-gnu rust: stable diff --git a/Cargo.lock b/Cargo.lock index f3d2d35..8575cc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,7 +17,7 @@ dependencies = [ [[package]] name = "ghash" -version = "0.3.1" +version = "0.4.0-pre" dependencies = [ "hex-literal", "opaque-debug", @@ -63,7 +63,7 @@ dependencies = [ [[package]] name = "polyval" -version = "0.4.5" +version = "0.5.0-pre" dependencies = [ "cpuid-bool", "hex-literal", diff --git a/ghash/Cargo.toml b/ghash/Cargo.toml index b839d3c..e681c61 100644 --- a/ghash/Cargo.toml +++ b/ghash/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ghash" -version = "0.3.1" +version = "0.4.0-pre" authors = ["RustCrypto Developers"] license = "Apache-2.0 OR MIT" description = """ @@ -16,7 +16,7 @@ edition = "2018" [dependencies] opaque-debug = "0.3" -polyval = { version = "0.4.4", features = ["mulx"], path = "../polyval" } +polyval = { version = "=0.5.0-pre", features = ["mulx"], path = "../polyval" } zeroize = { version = "1", optional = true, default-features = false } [dev-dependencies] diff --git a/polyval/Cargo.toml b/polyval/Cargo.toml index a2fa75a..889eab1 100644 --- a/polyval/Cargo.toml +++ b/polyval/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "polyval" -version = "0.4.5" +version = "0.5.0-pre" authors = ["RustCrypto Developers"] license = "Apache-2.0 OR MIT" description = """ @@ -17,7 +17,7 @@ edition = "2018" [dependencies] opaque-debug = "0.3" universal-hash = { version = "0.4", default-features = false } -zeroize = { version = "1", optional = true, default-features = false } +zeroize = { version = "1.2", optional = true, default-features = false } [target.'cfg(any(target_arch = "x86_64", target_arch = "x86"))'.dependencies] cpuid-bool = "0.2" diff --git a/polyval/README.md b/polyval/README.md index 1aaec70..1c2ddff 100644 --- a/polyval/README.md +++ b/polyval/README.md @@ -52,7 +52,7 @@ dual licensed as above, without any additional terms or conditions. [docs-image]: https://docs.rs/polyval/badge.svg [docs-link]: https://docs.rs/polyval/ [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg -[rustc-image]: https://img.shields.io/badge/rustc-1.41+-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.49+-blue.svg [build-image]: https://github.com/RustCrypto/universal-hashes/workflows/polyval/badge.svg?branch=master&event=push [build-link]: https://github.com/RustCrypto/universal-hashes/actions?query=workflow%3Apolyval diff --git a/polyval/src/backend/autodetect.rs b/polyval/src/backend/autodetect.rs index 570a586..e093749 100644 --- a/polyval/src/backend/autodetect.rs +++ b/polyval/src/backend/autodetect.rs @@ -2,6 +2,7 @@ //! to the "soft" backend when it's unavailable. use crate::{backend, Block, Key}; +use core::mem::ManuallyDrop; use universal_hash::{consts::U16, NewUniversalHash, Output, UniversalHash}; cpuid_bool::new!(clmul_cpuid, "pclmulqdq", "sse4.1"); @@ -13,8 +14,8 @@ pub struct Polyval { } union Inner { - clmul: backend::clmul::Polyval, - soft: backend::soft::Polyval, + clmul: ManuallyDrop, + soft: ManuallyDrop, } impl NewUniversalHash for Polyval { @@ -26,11 +27,11 @@ impl NewUniversalHash for Polyval { let inner = if clmul_present { Inner { - clmul: backend::clmul::Polyval::new(h), + clmul: ManuallyDrop::new(backend::clmul::Polyval::new(h)), } } else { Inner { - soft: backend::soft::Polyval::new(h), + soft: ManuallyDrop::new(backend::soft::Polyval::new(h)), } }; @@ -45,27 +46,35 @@ impl UniversalHash for Polyval { #[inline] fn update(&mut self, x: &Block) { if self.token.get() { - unsafe { self.inner.clmul.update(x) } + unsafe { (*self.inner.clmul).update(x) } } else { - unsafe { self.inner.soft.update(x) } + unsafe { (*self.inner.soft).update(x) } } } /// Reset internal state fn reset(&mut self) { if self.token.get() { - unsafe { self.inner.clmul.reset() } + unsafe { (*self.inner.clmul).reset() } } else { - unsafe { self.inner.soft.reset() } + unsafe { (*self.inner.soft).reset() } } } /// Get POLYVAL result (i.e. computed `S` field element) fn finalize(self) -> Output { let output_bytes = if self.token.get() { - unsafe { self.inner.clmul.finalize().into_bytes() } + unsafe { + ManuallyDrop::into_inner(self.inner.clmul) + .finalize() + .into_bytes() + } } else { - unsafe { self.inner.soft.finalize().into_bytes() } + unsafe { + ManuallyDrop::into_inner(self.inner.soft) + .finalize() + .into_bytes() + } }; Output::new(output_bytes) @@ -75,12 +84,14 @@ impl UniversalHash for Polyval { impl Clone for Polyval { fn clone(&self) -> Self { let inner = if self.token.get() { + let clmul = unsafe { (*self.inner.clmul).clone() }; Inner { - clmul: unsafe { self.inner.clmul.clone() }, + clmul: ManuallyDrop::new(clmul), } } else { + let soft = unsafe { (*self.inner.soft).clone() }; Inner { - soft: unsafe { self.inner.soft.clone() }, + soft: ManuallyDrop::new(soft), } }; @@ -90,13 +101,3 @@ impl Clone for Polyval { } } } - -#[cfg(feature = "zeroize")] -impl Drop for Polyval { - fn drop(&mut self) { - use zeroize::Zeroize; - const SIZE: usize = core::mem::size_of::(); - let state = unsafe { &mut *(self as *mut Polyval as *mut [u8; SIZE]) }; - state.zeroize(); - } -} diff --git a/polyval/src/backend/clmul.rs b/polyval/src/backend/clmul.rs index e18b726..6da8792 100644 --- a/polyval/src/backend/clmul.rs +++ b/polyval/src/backend/clmul.rs @@ -13,13 +13,6 @@ use core::arch::x86_64::*; /// **POLYVAL**: GHASH-like universal hash over GF(2^128). #[derive(Clone)] -#[cfg_attr( - all( - any(target_arch = "x86", target_arch = "x86_64"), - not(feature = "force-soft") - ), - derive(Copy) -)] // TODO(tarcieri): switch to ManuallyDrop on MSRV 1.49+ pub struct Polyval { h: __m128i, y: __m128i, @@ -127,6 +120,15 @@ impl Polyval { } } +#[cfg(feature = "zeroize")] +impl Drop for Polyval { + fn drop(&mut self) { + use zeroize::Zeroize; + self.h.zeroize(); + self.y.zeroize(); + } +} + #[inline(always)] unsafe fn xor4(e1: __m128i, e2: __m128i, e3: __m128i, e4: __m128i) -> __m128i { _mm_xor_si128(_mm_xor_si128(e1, e2), _mm_xor_si128(e3, e4)) diff --git a/polyval/src/backend/soft32.rs b/polyval/src/backend/soft32.rs index 24169c7..6a09c58 100644 --- a/polyval/src/backend/soft32.rs +++ b/polyval/src/backend/soft32.rs @@ -25,8 +25,6 @@ //! In other words, if we bit-reverse (over 32 bits) the operands, then we //! bit-reverse (over 64 bits) the result. -// TODO(tarcieri): fix zeroize when we switch to ManuallyDrop on MSRV 1.49+ - use crate::{Block, Key}; use core::{ convert::TryInto, @@ -35,23 +33,17 @@ use core::{ }; use universal_hash::{consts::U16, NewUniversalHash, Output, UniversalHash}; +#[cfg(feature = "zeroize")] +use zeroize::Zeroize; + /// **POLYVAL**: GHASH-like universal hash over GF(2^128). -#[allow(non_snake_case)] #[derive(Clone)] -#[repr(align(16))] -#[cfg_attr( - all( - any(target_arch = "x86", target_arch = "x86_64"), - not(feature = "force-soft") - ), - derive(Copy) -)] // TODO(tarcieri): switch to ManuallyDrop on MSRV 1.49+ pub struct Polyval { /// GF(2^128) field element input blocks are multiplied by - H: U32x4, + h: U32x4, /// Field element representing the computed universal hash - S: U32x4, + s: U32x4, } impl NewUniversalHash for Polyval { @@ -60,8 +52,8 @@ impl NewUniversalHash for Polyval { /// Initialize POLYVAL with the given `H` field element fn new(h: &Key) -> Self { Self { - H: h.into(), - S: U32x4::default(), + h: h.into(), + s: U32x4::default(), } } } @@ -72,12 +64,12 @@ impl UniversalHash for Polyval { /// Input a field element `X` to be authenticated fn update(&mut self, x: &Block) { let x = U32x4::from(x); - self.S = (self.S + x) * self.H; + self.s = (self.s + x) * self.h; } /// Reset internal state fn reset(&mut self) { - self.S = U32x4::default(); + self.s = U32x4::default(); } /// Get POLYVAL result (i.e. computed `S` field element) @@ -86,7 +78,7 @@ impl UniversalHash for Polyval { for (chunk, i) in block .chunks_mut(4) - .zip(&[self.S.0, self.S.1, self.S.2, self.S.3]) + .zip(&[self.s.0, self.s.1, self.s.2, self.s.3]) { chunk.copy_from_slice(&i.to_le_bytes()); } @@ -95,6 +87,14 @@ impl UniversalHash for Polyval { } } +#[cfg(feature = "zeroize")] +impl Drop for Polyval { + fn drop(&mut self) { + self.h.zeroize(); + self.s.zeroize(); + } +} + /// 4 x `u32` values #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] struct U32x4(u32, u32, u32, u32); @@ -233,6 +233,16 @@ impl Mul for U32x4 { } } +#[cfg(feature = "zeroize")] +impl Zeroize for U32x4 { + fn zeroize(&mut self) { + self.0.zeroize(); + self.1.zeroize(); + self.2.zeroize(); + self.3.zeroize(); + } +} + /// Multiplication in GF(2)[X], truncated to the low 32-bits, with “holes” /// (sequences of zeroes) to avoid carry spilling. /// diff --git a/polyval/src/backend/soft64.rs b/polyval/src/backend/soft64.rs index 1922d39..fe159a4 100644 --- a/polyval/src/backend/soft64.rs +++ b/polyval/src/backend/soft64.rs @@ -5,8 +5,6 @@ //! //! Copyright (c) 2016 Thomas Pornin -// TODO(tarcieri): fix zeroize when we switch to ManuallyDrop on MSRV 1.49+ - use crate::{Block, Key}; use core::{ convert::TryInto, @@ -15,23 +13,17 @@ use core::{ }; use universal_hash::{consts::U16, NewUniversalHash, Output, UniversalHash}; +#[cfg(feature = "zeroize")] +use zeroize::Zeroize; + /// **POLYVAL**: GHASH-like universal hash over GF(2^128). -#[allow(non_snake_case)] #[derive(Clone)] -#[repr(align(16))] -#[cfg_attr( - all( - any(target_arch = "x86", target_arch = "x86_64"), - not(feature = "force-soft") - ), - derive(Copy) -)] // TODO(tarcieri): switch to ManuallyDrop on MSRV 1.49+ pub struct Polyval { /// GF(2^128) field element input blocks are multiplied by - H: U64x2, + h: U64x2, /// Field element representing the computed universal hash - S: U64x2, + s: U64x2, } impl NewUniversalHash for Polyval { @@ -40,8 +32,8 @@ impl NewUniversalHash for Polyval { /// Initialize POLYVAL with the given `H` field element fn new(h: &Key) -> Self { Self { - H: h.into(), - S: U64x2::default(), + h: h.into(), + s: U64x2::default(), } } } @@ -52,19 +44,19 @@ impl UniversalHash for Polyval { /// Input a field element `X` to be authenticated fn update(&mut self, x: &Block) { let x = U64x2::from(x); - self.S = (self.S + x) * self.H; + self.s = (self.s + x) * self.h; } /// Reset internal state fn reset(&mut self) { - self.S = U64x2::default(); + self.s = U64x2::default(); } /// Get POLYVAL result (i.e. computed `S` field element) fn finalize(self) -> Output { let mut block = Block::default(); - for (chunk, i) in block.chunks_mut(8).zip(&[self.S.0, self.S.1]) { + for (chunk, i) in block.chunks_mut(8).zip(&[self.s.0, self.s.1]) { chunk.copy_from_slice(&i.to_le_bytes()); } @@ -72,6 +64,14 @@ impl UniversalHash for Polyval { } } +#[cfg(feature = "zeroize")] +impl Drop for Polyval { + fn drop(&mut self) { + self.h.zeroize(); + self.s.zeroize(); + } +} + /// 2 x `u64` values #[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] struct U64x2(u64, u64); @@ -158,6 +158,14 @@ impl Mul for U64x2 { } } +#[cfg(feature = "zeroize")] +impl Zeroize for U64x2 { + fn zeroize(&mut self) { + self.0.zeroize(); + self.1.zeroize(); + } +} + /// Multiplication in GF(2)[X], truncated to the low 64-bits, with “holes” /// (sequences of zeroes) to avoid carry spilling. ///