diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index edf0b140..de492484 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -26,7 +26,7 @@ jobs: strategy: matrix: rust: - - 1.60.0 # MSRV + - 1.61.0 # MSRV - stable target: - armv7a-none-eabi @@ -53,7 +53,7 @@ jobs: # 32-bit Linux - target: i686-unknown-linux-gnu platform: ubuntu-latest - rust: 1.60.0 # MSRV + rust: 1.61.0 # MSRV deps: sudo apt update && sudo apt install gcc-multilib - target: i686-unknown-linux-gnu platform: ubuntu-latest @@ -63,7 +63,7 @@ jobs: # 64-bit Linux - target: x86_64-unknown-linux-gnu platform: ubuntu-latest - rust: 1.60.0 # MSRV + rust: 1.61.0 # MSRV - target: x86_64-unknown-linux-gnu platform: ubuntu-latest rust: stable @@ -71,7 +71,7 @@ jobs: # 64-bit macOS x86_64 - target: x86_64-apple-darwin platform: macos-latest - rust: 1.60.0 # MSRV + rust: 1.61.0 # MSRV - target: x86_64-apple-darwin platform: macos-latest rust: stable @@ -79,7 +79,7 @@ jobs: # 64-bit Windows - target: x86_64-pc-windows-msvc platform: windows-latest - rust: 1.60.0 # MSRV + rust: 1.61.0 # MSRV - target: x86_64-pc-windows-msvc platform: windows-latest rust: stable @@ -102,7 +102,7 @@ jobs: include: # PPC32 - target: powerpc-unknown-linux-gnu - rust: 1.60.0 # MSRV + rust: 1.61.0 # MSRV - target: powerpc-unknown-linux-gnu rust: stable runs-on: ubuntu-latest @@ -116,13 +116,12 @@ jobs: - uses: RustCrypto/actions/cross-install@master - run: cross test --target ${{ matrix.target }} - # Feature-gated ARM64 SIMD register support (MSRV 1.59) aarch64: strategy: matrix: include: - target: aarch64-unknown-linux-gnu - rust: 1.60.0 + rust: 1.61.0 - target: aarch64-unknown-linux-gnu rust: stable runs-on: ubuntu-latest @@ -135,5 +134,4 @@ jobs: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - uses: RustCrypto/actions/cross-install@master - - run: cross test --target ${{ matrix.target }} --features aarch64 - run: cross test --target ${{ matrix.target }} --all-features diff --git a/README.md b/README.md index e468028d..8d6c53b7 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ This repository contains various utility crates used in the RustCrypto project. | [`inout`] | [![crates.io](https://img.shields.io/crates/v/inout.svg)](https://crates.io/crates/inout) | [![Documentation](https://docs.rs/inout/badge.svg)](https://docs.rs/inout) | ![MSRV 1.56][msrv-1.56] | Custom reference types for code generic over in-place and buffer-to-buffer modes of operation. | | [`opaque-debug`] | [![crates.io](https://img.shields.io/crates/v/opaque-debug.svg)](https://crates.io/crates/opaque-debug) | [![Documentation](https://docs.rs/opaque-debug/badge.svg)](https://docs.rs/opaque-debug) | ![MSRV 1.41][msrv-1.41] | Macro for opaque `Debug` trait implementation | | [`wycheproof2blb`] | | | | Utility for converting [Wycheproof] test vectors to the blobby format | -| [`zeroize`] | [![crates.io](https://img.shields.io/crates/v/zeroize.svg)](https://crates.io/crates/zeroize) | [![Documentation](https://docs.rs/zeroize/badge.svg)](https://docs.rs/zeroize) | ![MSRV 1.60][msrv-1.60] | Securely zero memory while avoiding compiler optimizations | +| [`zeroize`] | [![crates.io](https://img.shields.io/crates/v/zeroize.svg)](https://crates.io/crates/zeroize) | [![Documentation](https://docs.rs/zeroize/badge.svg)](https://docs.rs/zeroize) | ![MSRV 1.61][msrv-1.61] | Securely zero memory while avoiding compiler optimizations | ## License @@ -53,6 +53,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [msrv-1.57]: https://img.shields.io/badge/rustc-1.57.0+-blue.svg [msrv-1.59]: https://img.shields.io/badge/rustc-1.59.0+-blue.svg [msrv-1.60]: https://img.shields.io/badge/rustc-1.60.0+-blue.svg +[msrv-1.61]: https://img.shields.io/badge/rustc-1.61.0+-blue.svg [//]: # (crates) diff --git a/zeroize/Cargo.toml b/zeroize/Cargo.toml index ed6f5286..efc0a9ed 100644 --- a/zeroize/Cargo.toml +++ b/zeroize/Cargo.toml @@ -15,7 +15,7 @@ readme = "README.md" categories = ["cryptography", "memory-management", "no-std", "os"] keywords = ["memory", "memset", "secure", "volatile", "zero"] edition = "2021" -rust-version = "1.60" +rust-version = "1.61" [dependencies] serde = { version = "1.0", default-features = false, optional = true } @@ -23,7 +23,6 @@ zeroize_derive = { version = "1.3", path = "derive", optional = true } [features] default = ["alloc"] -aarch64 = [] alloc = [] derive = ["zeroize_derive"] std = ["alloc"] diff --git a/zeroize/README.md b/zeroize/README.md index 03b93abb..51b97d3f 100644 --- a/zeroize/README.md +++ b/zeroize/README.md @@ -36,7 +36,7 @@ thereof, implemented in pure Rust with no usage of FFI or assembly. ## Minimum Supported Rust Version -Rust **1.60** or newer. +Rust **1.61** or newer. In the future, we reserve the right to change MSRV (i.e. MSRV is out-of-scope for this crate's SemVer guarantees), however when we do it will be accompanied by @@ -64,7 +64,7 @@ dual licensed as above, without any additional terms or conditions. [docs-image]: https://docs.rs/zeroize/badge.svg [docs-link]: https://docs.rs/zeroize/ [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg -[rustc-image]: https://img.shields.io/badge/rustc-1.60+-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.61+-blue.svg [build-image]: https://github.com/RustCrypto/utils/actions/workflows/zeroize.yml/badge.svg [build-link]: https://github.com/RustCrypto/utils/actions/workflows/zeroize.yml diff --git a/zeroize/src/aarch64.rs b/zeroize/src/aarch64.rs index 07744d01..51a2f828 100644 --- a/zeroize/src/aarch64.rs +++ b/zeroize/src/aarch64.rs @@ -1,10 +1,8 @@ //! [`Zeroize`] impls for ARM64 SIMD registers. -//! -//! Gated behind the `aarch64` feature: MSRV 1.59 -//! (the overall crate is MSRV 1.60) use crate::{atomic_fence, volatile_write, Zeroize}; +#[allow(clippy::wildcard_imports)] use core::arch::aarch64::*; macro_rules! impl_zeroize_for_simd_register { @@ -22,7 +20,6 @@ macro_rules! impl_zeroize_for_simd_register { }; } -// TODO(tarcieri): other NEON register types? impl_zeroize_for_simd_register! { uint8x8_t, uint8x16_t, @@ -32,4 +29,22 @@ impl_zeroize_for_simd_register! { uint32x4_t, uint64x1_t, uint64x2_t, + int8x8_t, + int8x16_t, + int16x4_t, + int16x8_t, + int32x2_t, + int32x4_t, + int64x1_t, + int64x2_t, + float32x2_t, + float32x4_t, + float64x1_t, + float64x2_t, + poly8x8_t, + poly8x16_t, + poly16x4_t, + poly16x8_t, + poly64x1_t, + poly64x2_t, } diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index b67b5c95..849f1784 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -26,14 +26,15 @@ //! - No FFI or inline assembly! **WASM friendly** (and tested)! //! - `#![no_std]` i.e. **embedded-friendly**! //! - No functionality besides securely zeroing memory! +//! - Support for zeroing SIMD registers on `x86`, `x86_64`, `aarch64` and `wasm` targets! //! - (Optional) Custom derive support for zeroing complex structures //! //! ## Minimum Supported Rust Version //! -//! Requires Rust **1.60** or newer. +//! Requires Rust **1.61** or newer. //! //! In the future, we reserve the right to change MSRV (i.e. MSRV is out-of-scope -//! for this crate's SemVer guarantees), however when we do it will be accompanied +//! for this crate's `SemVer` guarantees), however when we do it will be accompanied //! by a minor version bump. //! //! ## Usage @@ -41,15 +42,13 @@ //! ``` //! use zeroize::Zeroize; //! -//! fn main() { -//! // Protip: don't embed secrets in your source code. -//! // This is just an example. -//! let mut secret = b"Air shield password: 1,2,3,4,5".to_vec(); -//! // [ ... ] open the air shield here +//! // Protip: don't embed secrets in your source code. +//! // This is just an example. +//! let mut secret = b"Air shield password: 1,2,3,4,5".to_vec(); +//! // [ ... ] open the air shield here //! -//! // Now that we're done using the secret, zero it out. -//! secret.zeroize(); -//! } +//! // Now that we're done using the secret, zero it out. +//! secret.zeroize(); //! ``` //! //! The [`Zeroize`] trait is impl'd on all of Rust's core scalar types including @@ -143,16 +142,14 @@ //! ``` //! use zeroize::Zeroizing; //! -//! fn main() { -//! let mut secret = Zeroizing::new([0u8; 5]); +//! let mut secret = Zeroizing::new([0u8; 5]); //! -//! // Set the air shield password -//! // Protip (again): don't embed secrets in your source code. -//! secret.copy_from_slice(&[1, 2, 3, 4, 5]); -//! assert_eq!(secret.as_ref(), &[1, 2, 3, 4, 5]); +//! // Set the air shield password +//! // Protip (again): don't embed secrets in your source code. +//! secret.copy_from_slice(&[1, 2, 3, 4, 5]); +//! assert_eq!(secret.as_ref(), &[1, 2, 3, 4, 5]); //! -//! // The contents of `secret` will be automatically zeroized on drop -//! } +//! // The contents of `secret` will be automatically zeroized on drop //! ``` //! //! ## What guarantees does this crate provide? @@ -208,16 +205,11 @@ //! //! //! -//! ## What about: clearing registers, mlock, mprotect, etc? +//! ## What about: mlock, mprotect, etc? //! //! This crate is focused on providing simple, unobtrusive support for reliably //! zeroing memory using the best approach possible on stable Rust. //! -//! Clearing registers is a difficult problem that can't easily be solved by -//! something like a crate, and requires either inline ASM or rustc support. -//! See for background on -//! this particular problem. -//! //! Other memory protection mechanisms are interesting and useful, but often //! overkill (e.g. defending against RAM scraping or attackers with swap access). //! In as much as there may be merit to these approaches, there are also many @@ -235,6 +227,8 @@ //! [good cryptographic hygiene]: https://github.com/veorq/cryptocoding#clean-memory-of-secret-data //! [`Ordering::SeqCst`]: core::sync::atomic::Ordering::SeqCst +#![allow(clippy::inline_always)] + #[cfg(feature = "alloc")] extern crate alloc; @@ -245,8 +239,10 @@ extern crate std; #[cfg_attr(docsrs, doc(cfg(feature = "zeroize_derive")))] pub use zeroize_derive::{Zeroize, ZeroizeOnDrop}; -#[cfg(all(feature = "aarch64", target_arch = "aarch64"))] +#[cfg(target_arch = "aarch64")] mod aarch64; +#[cfg(all(target_arch = "wasm32", target_family = "wasm"))] +mod wasm32; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod x86; @@ -318,10 +314,10 @@ impl_zeroize_with_default! { u8, u16, u32, u64, u128, usize } -/// `PhantomPinned` is zero sized so provide a ZeroizeOnDrop implementation. +/// [`PhantomPinned`] is zero sized so provide a [`ZeroizeOnDrop`] implementation. impl ZeroizeOnDrop for PhantomPinned {} -/// `()` is zero sized so provide a ZeroizeOnDrop implementation. +/// `()` is zero sized so provide a [`ZeroizeOnDrop`] implementation. impl ZeroizeOnDrop for () {} macro_rules! impl_zeroize_for_non_zero { @@ -399,7 +395,7 @@ where // Ensures self is None and that the value was dropped. Without the take, the drop // of the (zeroized) value isn't called, which might lead to a leak or other - // unexpected behavior. For example, if this were Option>, the above call to + // unexpected behavior. For example, if this were `Option>`, the above call to // zeroize would not free the allocated memory, but the the `take` call will. self.take(); } @@ -440,7 +436,7 @@ impl Zeroize for MaybeUninit { fn zeroize(&mut self) { // Safety: // `MaybeUninit` is valid for any byte pattern, including zeros. - unsafe { ptr::write_volatile(self, MaybeUninit::zeroed()) } + unsafe { ptr::write_volatile(self, Self::zeroed()) } atomic_fence(); } } @@ -458,12 +454,12 @@ impl Zeroize for [MaybeUninit] { fn zeroize(&mut self) { let ptr = self.as_mut_ptr().cast::>(); let size = self.len().checked_mul(mem::size_of::()).unwrap(); - assert!(size <= isize::MAX as usize); + assert!(isize::try_from(size).is_ok()); // Safety: // // This is safe, because every valid pointer is well aligned for u8 - // and it is backed by a single allocated object for at least `self.len() * size_pf::()` bytes. + // and it is backed by a single allocated object for at least `self.len() * size_of::()` bytes. // and 0 is a valid value for `MaybeUninit` // The memory of the slice should not wrap around the address space. unsafe { volatile_set(ptr, MaybeUninit::zeroed(), size) } @@ -484,7 +480,7 @@ where Z: DefaultIsZeroes, { fn zeroize(&mut self) { - assert!(self.len() <= isize::MAX as usize); + assert!(isize::try_from(self.len()).is_ok()); // Safety: // @@ -510,7 +506,7 @@ impl Zeroize for PhantomData { fn zeroize(&mut self) {} } -/// [`PhantomData` is always zero sized so provide a ZeroizeOnDrop implementation. +/// [`PhantomData`] is always zero sized so provide a [`ZeroizeOnDrop`] implementation. impl ZeroizeOnDrop for PhantomData {} macro_rules! impl_zeroize_tuple { @@ -622,8 +618,8 @@ impl Zeroize for CString { } } -/// `Zeroizing` is a a wrapper for any `Z: Zeroize` type which implements a -/// `Drop` handler which zeroizes dropped values. +/// [`Zeroizing`] is a a wrapper for any `Z: Zeroize` type which implements a +/// [`Drop`] handler which zeroizes dropped values. #[derive(Debug, Default, Eq, PartialEq)] pub struct Zeroizing(Z); @@ -631,10 +627,10 @@ impl Zeroizing where Z: Zeroize, { - /// Move value inside a `Zeroizing` wrapper which ensures it will be + /// Move value inside a [`Zeroizing`] wrapper which ensures it will be /// zeroized when it's dropped. #[inline(always)] - pub fn new(value: Z) -> Self { + pub const fn new(value: Z) -> Self { Self(value) } } @@ -657,8 +653,8 @@ where Z: Zeroize, { #[inline(always)] - fn from(value: Z) -> Zeroizing { - Zeroizing(value) + fn from(value: Z) -> Self { + Self(value) } } @@ -722,7 +718,7 @@ where Z: Zeroize, { fn drop(&mut self) { - self.0.zeroize() + self.0.zeroize(); } } @@ -798,7 +794,7 @@ unsafe fn volatile_set(dst: *mut T, src: T, count: usize) { /// Internal module used as support for `AssertZeroizeOnDrop`. #[doc(hidden)] pub mod __internal { - use super::*; + use super::{Zeroize, ZeroizeOnDrop}; /// Auto-deref workaround for deriving `ZeroizeOnDrop`. pub trait AssertZeroizeOnDrop { @@ -816,7 +812,7 @@ pub mod __internal { impl AssertZeroize for T { fn zeroize_or_on_drop(&mut self) { - self.zeroize() + self.zeroize(); } } } diff --git a/zeroize/src/wasm32.rs b/zeroize/src/wasm32.rs new file mode 100644 index 00000000..88442aa8 --- /dev/null +++ b/zeroize/src/wasm32.rs @@ -0,0 +1,22 @@ +//! [`Zeroize`] impls for WASM SIMD registers. + +use crate::{atomic_fence, volatile_write, Zeroize}; + +use core::arch::wasm32::v128; + +macro_rules! impl_zeroize_for_simd_register { + ($($type:ty),* $(,)?) => { + $( + #[cfg_attr(docsrs, doc(cfg(target_arch = "wasm32", target_family = "wasm")))] + impl Zeroize for $type { + #[inline] + fn zeroize(&mut self) { + volatile_write(self, unsafe { core::mem::zeroed() }); + atomic_fence(); + } + } + )+ + }; +} + +impl_zeroize_for_simd_register!(v128); diff --git a/zeroize/src/x86.rs b/zeroize/src/x86.rs index 5e4bfcb3..b5f10b4d 100644 --- a/zeroize/src/x86.rs +++ b/zeroize/src/x86.rs @@ -3,9 +3,11 @@ use crate::{atomic_fence, volatile_write, Zeroize}; #[cfg(target_arch = "x86")] +#[allow(clippy::wildcard_imports)] use core::arch::x86::*; #[cfg(target_arch = "x86_64")] +#[allow(clippy::wildcard_imports)] use core::arch::x86_64::*; macro_rules! impl_zeroize_for_simd_register {