From 912b25ca56b0485525b9e02b1d856e484c04e89b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Fri, 3 Jul 2026 16:48:03 +0300 Subject: [PATCH 1/3] Tweak zeroization --- Cargo.lock | 44 ++++++++++++++++++++---------- ghash/Cargo.toml | 5 +--- ghash/src/lib.rs | 12 ++------ poly1305/src/backend/autodetect.rs | 26 +++--------------- poly1305/src/backend/soft.rs | 25 ++--------------- poly1305/src/lib.rs | 12 +++++++- polyval/src/backend/intrinsics.rs | 25 ----------------- polyval/src/backend/soft.rs | 11 -------- polyval/src/field_element.rs | 10 ------- polyval/src/lib.rs | 8 +++--- 10 files changed, 54 insertions(+), 124 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7394d34..a7c9dfe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -104,17 +104,27 @@ checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "libc", - "r-efi", + "r-efi 5.3.0", "wasip2", ] +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", +] + [[package]] name = "ghash" version = "0.6.0" dependencies = [ "hex-literal", "polyval", - "zeroize", ] [[package]] @@ -125,9 +135,9 @@ checksum = "e712f64ec3850b98572bffac52e2c6f282b29fe6c5fa6d42334b30be438d95c1" [[package]] name = "hybrid-array" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9155a582abd142abc056962c29e3ce5ff2ad5469f4246b537ed42c5deba857da" +checksum = "818356c5132c1fede50f837ca96afbe78ff42413047f4abb886217845e1b6c8c" dependencies = [ "typenum", ] @@ -226,9 +236,9 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.45" +version = "1.0.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" dependencies = [ "proc-macro2", ] @@ -239,6 +249,12 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r-efi" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" + [[package]] name = "rand" version = "0.9.4" @@ -265,7 +281,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom", + "getrandom 0.3.4", ] [[package]] @@ -310,9 +326,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.117" +version = "2.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" dependencies = [ "proc-macro2", "quote", @@ -326,7 +342,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom", + "getrandom 0.4.3", "once_cell", "rustix", "windows-sys", @@ -371,9 +387,9 @@ dependencies = [ [[package]] name = "wasip2" -version = "1.0.2+wasi-0.2.9" +version = "1.0.1+wasi-0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9517f9239f02c069db75e65f174b3da828fe5f5b945c4dd26bd25d89c03ebcf5" +checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7" dependencies = [ "wit-bindgen", ] @@ -395,9 +411,9 @@ dependencies = [ [[package]] name = "wit-bindgen" -version = "0.51.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59" [[package]] name = "zerocopy" diff --git a/ghash/Cargo.toml b/ghash/Cargo.toml index 319bdfd..e48ff2d 100644 --- a/ghash/Cargo.toml +++ b/ghash/Cargo.toml @@ -18,11 +18,8 @@ as in the AES-GCM authenticated encryption cipher. [dependencies] polyval = { version = "0.7", features = ["hazmat"] } -# optional dependencies -zeroize = { version = "1", optional = true, default-features = false } - [features] -zeroize = ["polyval/zeroize", "dep:zeroize"] +zeroize = ["polyval/zeroize"] [dev-dependencies] hex-literal = "1" diff --git a/ghash/src/lib.rs b/ghash/src/lib.rs index 75b2fe3..d24a991 100644 --- a/ghash/src/lib.rs +++ b/ghash/src/lib.rs @@ -15,9 +15,6 @@ use universal_hash::{ consts::U16, }; -#[cfg(feature = "zeroize")] -use zeroize::Zeroize; - /// GHASH keys (16-bytes) pub type Key = universal_hash::Key; @@ -42,13 +39,8 @@ impl GHash { /// Initialize GHASH with the given `H` field element as the key. #[inline] pub fn new(h: &Key) -> Self { - #[allow(unused_mut)] - let mut h_polyval = FieldElement::from(*h).reverse().mulx(); - #[allow(clippy::let_and_return)] - let result = Self(Polyval::new(&h_polyval.into())); - #[cfg(feature = "zeroize")] - h_polyval.zeroize(); - result + let h_polyval = FieldElement::from(*h).reverse().mulx(); + Self(Polyval::new(&h_polyval.into())) } } diff --git a/poly1305/src/backend/autodetect.rs b/poly1305/src/backend/autodetect.rs index 5a8efa5..13fba92 100644 --- a/poly1305/src/backend/autodetect.rs +++ b/poly1305/src/backend/autodetect.rs @@ -1,7 +1,7 @@ //! Autodetection support for AVX2 CPU intrinsics on x86 CPUs, with fallback //! to the "soft" backend when it's unavailable. -use universal_hash::{UhfClosure, UniversalHash, common::BlockSizeUser, consts::U16}; +use universal_hash::{UhfClosure, consts::U16}; use crate::{Block, Key, Tag, backend}; use core::mem::ManuallyDrop; @@ -18,10 +18,6 @@ union Inner { soft: ManuallyDrop, } -impl BlockSizeUser for State { - type BlockSize = U16; -} - impl State { /// Initialize Poly1305 [`State`] with the given key #[inline] @@ -50,10 +46,8 @@ impl State { unsafe { (*self.inner.soft).compute_block(block, partial) } } } -} -impl UniversalHash for State { - fn update_with_backend(&mut self, f: impl UhfClosure) { + pub(crate) fn update_with_backend(&mut self, f: impl UhfClosure) { if self.token.get() { unsafe { f.call(&mut *self.inner.avx2) } } else { @@ -61,13 +55,11 @@ impl UniversalHash for State { } } - /// Finalize output producing a [`Tag`] - #[inline] - fn finalize(mut self) -> Tag { + pub(crate) fn finalize(&mut self) -> Tag { if self.token.get() { unsafe { (*self.inner.avx2).finalize() } } else { - unsafe { (*self.inner.soft).finalize_mut() } + unsafe { (*self.inner.soft).finalize() } } } } @@ -90,13 +82,3 @@ impl Clone for State { } } } - -#[cfg(feature = "zeroize")] -impl Drop for State { - fn drop(&mut self) { - use zeroize::Zeroize; - const SIZE: usize = size_of::(); - let state = unsafe { &mut *core::ptr::from_mut::(self).cast::<[u8; SIZE]>() }; - state.zeroize(); - } -} diff --git a/poly1305/src/backend/soft.rs b/poly1305/src/backend/soft.rs index 0017f95..77903ef 100644 --- a/poly1305/src/backend/soft.rs +++ b/poly1305/src/backend/soft.rs @@ -13,7 +13,7 @@ // https://github.com/floodyberry/poly1305-donna use universal_hash::{ - UhfBackend, UhfClosure, UniversalHash, + UhfBackend, common::{BlockSizeUser, ParBlocksSizeUser}, consts::{U1, U16}, }; @@ -140,7 +140,7 @@ impl State { } /// Finalize output producing a [`Tag`] - pub(crate) fn finalize_mut(&mut self) -> Tag { + pub(crate) fn finalize(&mut self) -> Tag { // fully carry h let mut h0 = self.h[0]; let mut h1 = self.h[1]; @@ -232,16 +232,6 @@ impl State { } } -#[cfg(feature = "zeroize")] -impl Drop for State { - fn drop(&mut self) { - use zeroize::Zeroize; - self.r.zeroize(); - self.h.zeroize(); - self.pad.zeroize(); - } -} - impl BlockSizeUser for State { type BlockSize = U16; } @@ -255,14 +245,3 @@ impl UhfBackend for State { self.compute_block(block, false); } } - -impl UniversalHash for State { - fn update_with_backend(&mut self, f: impl UhfClosure) { - f.call(self); - } - - /// Finalize output producing a [`Tag`] - fn finalize(mut self) -> Tag { - self.finalize_mut() - } -} diff --git a/poly1305/src/lib.rs b/poly1305/src/lib.rs index a327de1..dca4d2b 100644 --- a/poly1305/src/lib.rs +++ b/poly1305/src/lib.rs @@ -85,7 +85,7 @@ impl UniversalHash for Poly1305 { } /// Get the hashed output - fn finalize(self) -> Tag { + fn finalize(mut self) -> Tag { self.state.finalize() } } @@ -119,6 +119,16 @@ impl Debug for Poly1305 { } } +impl Drop for Poly1305 { + fn drop(&mut self) { + // SAFETY: `Poly1305` satisfies the safety conditions of `zeroize_flat_type` + #[cfg(feature = "zeroize")] + unsafe { + zeroize::zeroize_flat_type(self); + } + } +} + #[cfg(all( any(target_arch = "x86", target_arch = "x86_64"), not(poly1305_backend = "soft"), diff --git a/polyval/src/backend/intrinsics.rs b/polyval/src/backend/intrinsics.rs index e373d08..2bbb8d4 100644 --- a/polyval/src/backend/intrinsics.rs +++ b/polyval/src/backend/intrinsics.rs @@ -10,9 +10,6 @@ use crate::{Block, Key, ParBlocks, Tag, field_element::FieldElement}; mod intrinsics_impl; use intrinsics_impl::InitToken; -#[cfg(feature = "zeroize")] -use zeroize::Zeroize; - /// State of a POLYVAL hash operation. #[derive(Clone)] pub(crate) struct State { @@ -88,14 +85,6 @@ impl State { } } -#[cfg(feature = "zeroize")] -impl Zeroize for State { - fn zeroize(&mut self) { - self.expanded_key.zeroize(); - self.acc.zeroize(); - } -} - /// Precomputed key material for POLYVAL using R/F algorithm /// /// Stores H and D values for each power, where D = swap(H) ⊕ (H0 × P1) @@ -118,17 +107,3 @@ pub(crate) struct ExpandedKey { /// D^4 d4: FieldElement, } - -#[cfg(feature = "zeroize")] -impl Zeroize for ExpandedKey { - fn zeroize(&mut self) { - self.h1.zeroize(); - self.d1.zeroize(); - self.h2.zeroize(); - self.d2.zeroize(); - self.h3.zeroize(); - self.d3.zeroize(); - self.h4.zeroize(); - self.d4.zeroize(); - } -} diff --git a/polyval/src/backend/soft.rs b/polyval/src/backend/soft.rs index 26605fc..af42431 100644 --- a/polyval/src/backend/soft.rs +++ b/polyval/src/backend/soft.rs @@ -5,9 +5,6 @@ use crate::{Block, Key, ParBlocks, Tag, field_element::FieldElement}; -#[cfg(feature = "zeroize")] -use zeroize::Zeroize; - /// State of a POLYVAL hash operation. #[derive(Clone)] #[allow(missing_copy_implementations)] @@ -49,11 +46,3 @@ impl State { self.y = FieldElement::default(); } } - -#[cfg(feature = "zeroize")] -impl Zeroize for State { - fn zeroize(&mut self) { - self.h.zeroize(); - self.y.zeroize(); - } -} diff --git a/polyval/src/field_element.rs b/polyval/src/field_element.rs index c767db3..0209b49 100644 --- a/polyval/src/field_element.rs +++ b/polyval/src/field_element.rs @@ -39,9 +39,6 @@ use core::{ ops::{Add, BitAnd, BitOr, BitXor, Mul, MulAssign, Shl}, }; -#[cfg(feature = "zeroize")] -use zeroize::Zeroize; - /// An element in POLYVAL's field. /// /// This type represents an element of the binary field GF(2^128) modulo the irreducible polynomial @@ -165,13 +162,6 @@ impl MulAssign for FieldElement { } } -#[cfg(feature = "zeroize")] -impl Zeroize for FieldElement { - fn zeroize(&mut self) { - self.0.zeroize(); - } -} - /// Multiplication in GF(2)[X], implemented generically for use with `u32` and `u64`. /// /// Uses "holes" (sequences of zeroes) to avoid carry spilling, as specified in the mask operand diff --git a/polyval/src/lib.rs b/polyval/src/lib.rs index 332764c..7c3d7ff 100644 --- a/polyval/src/lib.rs +++ b/polyval/src/lib.rs @@ -22,9 +22,6 @@ use universal_hash::{ consts::{U4, U16}, }; -#[cfg(feature = "zeroize")] -use zeroize::Zeroize; - /// Size of a POLYVAL block in bytes pub const BLOCK_SIZE: usize = 16; @@ -113,8 +110,11 @@ impl Debug for Polyval { impl Drop for Polyval { fn drop(&mut self) { + // SAFETY: `Polyval` satisfies the safety conditions of `zeroize_flat_type` #[cfg(feature = "zeroize")] - self.state.zeroize(); + unsafe { + zeroize::zeroize_flat_type(self); + } } } From c468df95e64bb7af8998e7d6255bafa565326d50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Fri, 3 Jul 2026 16:51:34 +0300 Subject: [PATCH 2/3] fix poly1305 --- poly1305/src/backend/soft.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/poly1305/src/backend/soft.rs b/poly1305/src/backend/soft.rs index 77903ef..177bd55 100644 --- a/poly1305/src/backend/soft.rs +++ b/poly1305/src/backend/soft.rs @@ -13,7 +13,7 @@ // https://github.com/floodyberry/poly1305-donna use universal_hash::{ - UhfBackend, + UhfBackend, UhfClosure, common::{BlockSizeUser, ParBlocksSizeUser}, consts::{U1, U16}, }; @@ -139,6 +139,11 @@ impl State { self.h[4] = h4; } + #[allow(unused, reason = "this method is used by some targets")] + pub(crate) fn update_with_backend(&mut self, f: impl UhfClosure) { + f.call(self); + } + /// Finalize output producing a [`Tag`] pub(crate) fn finalize(&mut self) -> Tag { // fully carry h From c122f47bd8b1c986e3b29b0fbad2fb578b50e56c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Fri, 3 Jul 2026 17:48:27 +0300 Subject: [PATCH 3/3] fix warning --- poly1305/src/fuzz.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/poly1305/src/fuzz.rs b/poly1305/src/fuzz.rs index eb20683..046897a 100644 --- a/poly1305/src/fuzz.rs +++ b/poly1305/src/fuzz.rs @@ -1,5 +1,3 @@ -use universal_hash::UniversalHash; - use crate::{Block, Key, backend}; /// Helper function for fuzzing the AVX2 backend.