Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions .github/workflows/zeroize.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
strategy:
matrix:
rust:
- 1.60.0 # MSRV
- 1.61.0 # MSRV
- stable
target:
- armv7a-none-eabi
Expand All @@ -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
Expand All @@ -63,23 +63,23 @@ 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

# 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

# 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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)

Expand Down
3 changes: 1 addition & 2 deletions zeroize/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,14 @@ 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 }
zeroize_derive = { version = "1.3", path = "derive", optional = true }

[features]
default = ["alloc"]
aarch64 = []
alloc = []
derive = ["zeroize_derive"]
std = ["alloc"]
Expand Down
4 changes: 2 additions & 2 deletions zeroize/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
23 changes: 19 additions & 4 deletions zeroize/src/aarch64.rs
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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,
Expand All @@ -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,
}
80 changes: 38 additions & 42 deletions zeroize/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,30 +26,29 @@
//! - 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
//!
//! ```
//! 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
Expand Down Expand Up @@ -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?
Expand Down Expand Up @@ -208,16 +205,11 @@
//!
//! <https://crates.io/crates/secrecy>
//!
//! ## 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 <https://github.com/rust-lang/rust/issues/17046> 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
Expand All @@ -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;

Expand All @@ -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;

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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<Vec<T>>, the above call to
// unexpected behavior. For example, if this were `Option<Vec<T>>`, the above call to
// zeroize would not free the allocated memory, but the the `take` call will.
self.take();
}
Expand Down Expand Up @@ -440,7 +436,7 @@ impl<Z> Zeroize for MaybeUninit<Z> {
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();
}
}
Expand All @@ -458,12 +454,12 @@ impl<Z> Zeroize for [MaybeUninit<Z>] {
fn zeroize(&mut self) {
let ptr = self.as_mut_ptr().cast::<MaybeUninit<u8>>();
let size = self.len().checked_mul(mem::size_of::<Z>()).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::<Z>()` bytes.
// and it is backed by a single allocated object for at least `self.len() * size_of::<Z>()` bytes.
// and 0 is a valid value for `MaybeUninit<Z>`
// The memory of the slice should not wrap around the address space.
unsafe { volatile_set(ptr, MaybeUninit::zeroed(), size) }
Expand All @@ -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:
//
Expand All @@ -510,7 +506,7 @@ impl<Z> Zeroize for PhantomData<Z> {
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<Z> ZeroizeOnDrop for PhantomData<Z> {}

macro_rules! impl_zeroize_tuple {
Expand Down Expand Up @@ -622,19 +618,19 @@ 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: Zeroize>(Z);

impl<Z> Zeroizing<Z>
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)
}
}
Expand All @@ -657,8 +653,8 @@ where
Z: Zeroize,
{
#[inline(always)]
fn from(value: Z) -> Zeroizing<Z> {
Zeroizing(value)
fn from(value: Z) -> Self {
Self(value)
}
}

Expand Down Expand Up @@ -722,7 +718,7 @@ where
Z: Zeroize,
{
fn drop(&mut self) {
self.0.zeroize()
self.0.zeroize();
}
}

Expand Down Expand Up @@ -798,7 +794,7 @@ unsafe fn volatile_set<T: Copy + Sized>(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 {
Expand All @@ -816,7 +812,7 @@ pub mod __internal {

impl<T: Zeroize + ?Sized> AssertZeroize for T {
fn zeroize_or_on_drop(&mut self) {
self.zeroize()
self.zeroize();
}
}
}
Loading