From 7241c0f99e29899874a1daca6aeb8f9c2688f678 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 25 Mar 2022 19:30:54 -0600 Subject: [PATCH 001/116] CI: unpin `zeroize` nightly for `aarch64` testing (#754) It was pinned due to issues around `aarch64_target_feature` stabilization, but those have been resolved upstream. --- .github/workflows/zeroize.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index b9fbbee6..0747657f 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -3,6 +3,7 @@ name: zeroize on: pull_request: paths: + - ".github/workflows/zeroize.yml" - "zeroize/**" - "Cargo.*" push: @@ -72,7 +73,7 @@ jobs: matrix: include: - target: aarch64-unknown-linux-gnu - rust: nightly-2022-03-01 + rust: nightly runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 From aa6bb32ab8cc352b763afa8b0076421c177d739a Mon Sep 17 00:00:00 2001 From: Nicolas Abram Date: Wed, 30 Mar 2022 08:47:33 -0300 Subject: [PATCH 002/116] Fix MIRI error in inout_buf.rs (#755) See https://github.com/rust-lang/unsafe-code-guidelines/issues/133 Calling as_mut_ptr creates a unique reference, and as_ptr a shared reference. These 2 conflict, and one invalidates the other. Both ptr need to be reborrows of or be basically the same pointer. --- inout/src/inout_buf.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/inout/src/inout_buf.rs b/inout/src/inout_buf.rs index 0ab1b8dc..398fe793 100644 --- a/inout/src/inout_buf.rs +++ b/inout/src/inout_buf.rs @@ -18,9 +18,10 @@ pub struct InOutBuf<'inp, 'out, T> { impl<'a, T> From<&'a mut [T]> for InOutBuf<'a, 'a, T> { #[inline(always)] fn from(buf: &'a mut [T]) -> Self { + let out_ptr = buf.as_mut_ptr(); Self { - in_ptr: buf.as_ptr(), - out_ptr: buf.as_mut_ptr(), + in_ptr: out_ptr, + out_ptr: out_ptr, len: buf.len(), _pd: PhantomData, } From 81ef0b0620e22381d5e0b78472dcf80c3125b32b Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 31 Mar 2022 12:53:04 +0000 Subject: [PATCH 003/116] inout: release v0.1.3 (#756) --- inout/CHANGELOG.md | 6 ++++++ inout/Cargo.toml | 2 +- inout/src/inout.rs | 6 +++--- inout/src/inout_buf.rs | 12 ++++++------ inout/src/lib.rs | 2 +- inout/src/reserved.rs | 6 +++--- 6 files changed, 20 insertions(+), 14 deletions(-) diff --git a/inout/CHANGELOG.md b/inout/CHANGELOG.md index e40ad40d..d8a03b9c 100644 --- a/inout/CHANGELOG.md +++ b/inout/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.1.3 (2022-03-31) +### Fixed +- MIRI error in `From` impl for `InOutBuf` ([#755]) + +[#755]: https://github.com/RustCrypto/utils/pull/755 + ## 0.1.2 (2022-02-10) ### Changed - Use borrow instead of consuming in `InOutBufReserved::get_*_len()` methods ([#734]) diff --git a/inout/Cargo.toml b/inout/Cargo.toml index af4415e3..fe376c7b 100644 --- a/inout/Cargo.toml +++ b/inout/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "inout" -version = "0.1.2" # Also update html_root_url in lib.rs when bumping this +version = "0.1.3" # Also update html_root_url in lib.rs when bumping this description = "Custom reference types for code generic over in-place and buffer-to-buffer modes of operation." authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" diff --git a/inout/src/inout.rs b/inout/src/inout.rs index 8e798865..8fab6b03 100644 --- a/inout/src/inout.rs +++ b/inout/src/inout.rs @@ -78,10 +78,10 @@ impl<'inp, 'out, T: Clone> InOut<'inp, 'out, T> { impl<'a, T> From<&'a mut T> for InOut<'a, 'a, T> { #[inline(always)] fn from(val: &'a mut T) -> Self { - let out_ptr = val as *mut T; + let p = val as *mut T; Self { - in_ptr: out_ptr as *const T, - out_ptr, + in_ptr: p, + out_ptr: p, _pd: PhantomData, } } diff --git a/inout/src/inout_buf.rs b/inout/src/inout_buf.rs index 398fe793..70f89af0 100644 --- a/inout/src/inout_buf.rs +++ b/inout/src/inout_buf.rs @@ -18,10 +18,10 @@ pub struct InOutBuf<'inp, 'out, T> { impl<'a, T> From<&'a mut [T]> for InOutBuf<'a, 'a, T> { #[inline(always)] fn from(buf: &'a mut [T]) -> Self { - let out_ptr = buf.as_mut_ptr(); + let p = buf.as_mut_ptr(); Self { - in_ptr: out_ptr, - out_ptr: out_ptr, + in_ptr: p, + out_ptr: p, len: buf.len(), _pd: PhantomData, } @@ -32,10 +32,10 @@ impl<'a, T> InOutBuf<'a, 'a, T> { /// Create `InOutBuf` from a single mutable reference. #[inline(always)] pub fn from_mut(val: &'a mut T) -> InOutBuf<'a, 'a, T> { - let out_ptr = val as *mut T; + let p = val as *mut T; Self { - in_ptr: out_ptr as *const T, - out_ptr, + in_ptr: p, + out_ptr: p, len: 1, _pd: PhantomData, } diff --git a/inout/src/lib.rs b/inout/src/lib.rs index 2a92be1e..a8312635 100644 --- a/inout/src/lib.rs +++ b/inout/src/lib.rs @@ -5,7 +5,7 @@ #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg", - html_root_url = "https://docs.rs/inout/0.1.2" + html_root_url = "https://docs.rs/inout/0.1.3" )] #![allow(clippy::needless_lifetimes)] #![cfg_attr(docsrs, feature(doc_cfg))] diff --git a/inout/src/reserved.rs b/inout/src/reserved.rs index d437106b..3d0dc84f 100644 --- a/inout/src/reserved.rs +++ b/inout/src/reserved.rs @@ -28,11 +28,11 @@ impl<'a, T> InOutBufReserved<'a, 'a, T> { if msg_len > buf.len() { return Err(OutIsTooSmallError); } - let out_ptr = buf.as_mut_ptr(); + let p = buf.as_mut_ptr(); let out_len = buf.len(); Ok(Self { - in_ptr: out_ptr as *const T, - out_ptr, + in_ptr: p, + out_ptr: p, in_len: msg_len, out_len, _pd: PhantomData, From 3bd76980b0bba7fa2b9072eee2f76cd5b6dd99b5 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 31 Mar 2022 14:19:49 +0000 Subject: [PATCH 004/116] Unify workspaces (#757) Also removes all uses of `html_root_url` and relevant notes from Cargo.toml. --- .github/workflows/blobby.yml | 4 ++- .github/workflows/block-buffer.yml | 10 +++++--- .github/workflows/cmov.yml | 6 ++--- .github/workflows/cpufeatures.yml | 18 ++++++++++---- .github/workflows/dbl.yml | 8 ++++-- .github/workflows/hex-literal.yml | 8 ++++-- .github/workflows/opaque-debug.yml | 8 ++++-- .github/workflows/zeroize.yml | 16 ++++++++---- Cargo.lock | 27 +++++++++++++++----- Cargo.toml | 5 ++++ blobby/Cargo.toml | 2 +- blobby/src/lib.rs | 3 +-- block-buffer/Cargo.toml | 2 +- block-buffer/src/lib.rs | 3 +-- block-padding/Cargo.toml | 6 +---- block-padding/src/lib.rs | 3 +-- cmov/Cargo.toml | 2 +- collectable/Cargo.toml | 2 +- collectable/src/lib.rs | 3 +-- cpufeatures/Cargo.toml | 2 +- dbl/Cargo.toml | 2 +- dbl/src/lib.rs | 3 +-- hex-literal/Cargo.toml | 2 +- hex-literal/src/lib.rs | 3 +-- inout/Cargo.lock | 40 ------------------------------ inout/Cargo.toml | 6 +---- inout/src/lib.rs | 3 +-- inout/src/reserved.rs | 1 + opaque-debug/Cargo.toml | 2 +- opaque-debug/src/lib.rs | 3 +-- wycheproof2blb/Cargo.toml | 2 +- wycheproof2blb/src/main.rs | 3 +-- 32 files changed, 102 insertions(+), 106 deletions(-) delete mode 100644 inout/Cargo.lock diff --git a/.github/workflows/blobby.yml b/.github/workflows/blobby.yml index 923d731c..334d98e8 100644 --- a/.github/workflows/blobby.yml +++ b/.github/workflows/blobby.yml @@ -32,7 +32,9 @@ jobs: profile: minimal toolchain: ${{ matrix.rust }} override: true - - run: cargo test --release + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo test minimal-versions: uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master diff --git a/.github/workflows/block-buffer.yml b/.github/workflows/block-buffer.yml index 29ed2613..2f2bdd06 100644 --- a/.github/workflows/block-buffer.yml +++ b/.github/workflows/block-buffer.yml @@ -36,7 +36,9 @@ jobs: toolchain: ${{ matrix.rust }} target: ${{ matrix.target }} override: true - - run: cargo build --release --target ${{ matrix.target }} + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo build --target ${{ matrix.target }} minimal-versions: uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master @@ -58,5 +60,7 @@ jobs: profile: minimal toolchain: ${{ matrix.rust }} override: true - - run: cargo test --release - - run: cargo test --all-features --release + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo test + - run: cargo test --all-features diff --git a/.github/workflows/cmov.yml b/.github/workflows/cmov.yml index 5a6292b2..2a5eb194 100644 --- a/.github/workflows/cmov.yml +++ b/.github/workflows/cmov.yml @@ -42,7 +42,7 @@ jobs: target: ${{ matrix.target }} override: true - uses: RustCrypto/actions/cargo-hack-install@master - - run: cargo build --release --target ${{ matrix.target }} + - run: cargo build --target ${{ matrix.target }} test: strategy: @@ -80,7 +80,7 @@ jobs: profile: minimal override: true - run: ${{ matrix.deps }} - - run: cargo test --release + - run: cargo test # Cross-compiled tests cross: @@ -110,4 +110,4 @@ jobs: profile: minimal override: true - uses: RustCrypto/actions/cross-install@master - - run: cross test --release --target ${{ matrix.target }} + - run: cross test --target ${{ matrix.target }} diff --git a/.github/workflows/cpufeatures.yml b/.github/workflows/cpufeatures.yml index bbf409b6..53bf39ec 100644 --- a/.github/workflows/cpufeatures.yml +++ b/.github/workflows/cpufeatures.yml @@ -50,8 +50,10 @@ jobs: target: ${{ matrix.target }} override: true profile: minimal + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml - run: ${{ matrix.deps }} - - run: cargo test --target ${{ matrix.target }} --release + - run: cargo test --target ${{ matrix.target }} # macOS tests macos: @@ -70,7 +72,9 @@ jobs: toolchain: ${{ matrix.toolchain }} target: x86_64-apple-darwin override: true - - run: cargo test --release + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo test # Windows tests windows: @@ -93,7 +97,9 @@ jobs: toolchain: ${{ matrix.toolchain }} target: ${{ matrix.target }} override: true - - run: cargo test --target ${{ matrix.target }} --release + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo test --target ${{ matrix.target }} # Cross-compiled tests cross: @@ -116,5 +122,7 @@ jobs: target: ${{ matrix.target }} override: true profile: minimal - - run: cargo install cross - - run: cross test --target ${{ matrix.target }} --release + - uses: RustCrypto/actions/cross-install@master + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cross test --target ${{ matrix.target }} diff --git a/.github/workflows/dbl.yml b/.github/workflows/dbl.yml index 478f7659..0ca2b092 100644 --- a/.github/workflows/dbl.yml +++ b/.github/workflows/dbl.yml @@ -36,7 +36,9 @@ jobs: toolchain: ${{ matrix.rust }} target: ${{ matrix.target }} override: true - - run: cargo build --release --target ${{ matrix.target }} + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo build --target ${{ matrix.target }} minimal-versions: uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master @@ -58,4 +60,6 @@ jobs: profile: minimal toolchain: ${{ matrix.rust }} override: true - - run: cargo test --release + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo test diff --git a/.github/workflows/hex-literal.yml b/.github/workflows/hex-literal.yml index 130dcd49..f20315b8 100644 --- a/.github/workflows/hex-literal.yml +++ b/.github/workflows/hex-literal.yml @@ -36,7 +36,9 @@ jobs: toolchain: ${{ matrix.rust }} target: ${{ matrix.target }} override: true - - run: cargo build --release --target ${{ matrix.target }} + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo build --target ${{ matrix.target }} minimal-versions: uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master @@ -58,4 +60,6 @@ jobs: profile: minimal toolchain: ${{ matrix.rust }} override: true - - run: cargo test --release + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo test diff --git a/.github/workflows/opaque-debug.yml b/.github/workflows/opaque-debug.yml index 09955d71..f2f2550a 100644 --- a/.github/workflows/opaque-debug.yml +++ b/.github/workflows/opaque-debug.yml @@ -36,7 +36,9 @@ jobs: toolchain: ${{ matrix.rust }} target: ${{ matrix.target }} override: true - - run: cargo build --release --target ${{ matrix.target }} + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo build --target ${{ matrix.target }} minimal-versions: uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master @@ -58,4 +60,6 @@ jobs: profile: minimal toolchain: ${{ matrix.rust }} override: true - - run: cargo test --release + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo test diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index 0747657f..d7126922 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -38,7 +38,9 @@ jobs: target: ${{ matrix.target }} override: true profile: minimal - - run: cargo build --no-default-features --release --target ${{ matrix.target }} + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo build --no-default-features --target ${{ matrix.target }} minimal-versions: uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master @@ -64,8 +66,10 @@ jobs: toolchain: ${{ matrix.toolchain }} override: true profile: minimal - - run: cargo test --release - - run: cargo test --release --features alloc,derive + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cargo test + - run: cargo test --features alloc,derive # Feature-gated ARM64 SIMD register support (nightly-only) aarch64: @@ -86,5 +90,7 @@ jobs: profile: minimal override: true - uses: RustCrypto/actions/cross-install@master - - run: cross test --release --target ${{ matrix.target }} --features aarch64 - - run: cross test --release --target ${{ matrix.target }} --all-features + # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates + - run: rm ../Cargo.toml + - run: cross test --target ${{ matrix.target }} --features aarch64 + - run: cross test --target ${{ matrix.target }} --all-features diff --git a/Cargo.lock b/Cargo.lock index 22e58439..3aa04126 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,6 +16,13 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-padding" +version = "0.3.2" +dependencies = [ + "generic-array", +] + [[package]] name = "cmov" version = "0.1.1" @@ -58,6 +65,14 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" name = "hex-literal" version = "0.3.4" +[[package]] +name = "inout" +version = "0.1.3" +dependencies = [ + "block-padding", + "generic-array", +] + [[package]] name = "itoa" version = "1.0.1" @@ -66,9 +81,9 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] name = "libc" -version = "0.2.119" +version = "0.2.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf2e165bb3457c8e098ea76f3e3bc9db55f87aa90d52d0e6be741470916aaa4" +checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" [[package]] name = "opaque-debug" @@ -85,9 +100,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "864d3e96a899863136fc6e99f3d7cae289dafe43bf2c5ac19b70df7210c0a145" +checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" dependencies = [ "proc-macro2", ] @@ -131,9 +146,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.86" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a65b3f4ffa0092e9887669db0eae07941f023991ab58ea44da8fe8e2d511c6b" +checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 1f3a386b..1336109e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,13 +2,18 @@ members = [ "blobby", "block-buffer", + "block-padding", "collectable", "cmov", "cpufeatures", "dbl", "hex-literal", + "inout", "opaque-debug", "wycheproof2blb", "zeroize", "zeroize/derive" ] + +[profile.dev] +opt-level = 2 diff --git a/blobby/Cargo.toml b/blobby/Cargo.toml index b8a12904..88416986 100644 --- a/blobby/Cargo.toml +++ b/blobby/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "blobby" -version = "0.3.1" # Also update html_root_url in lib.rs when bumping this +version = "0.3.1" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Iterator over simple binary blob storage" diff --git a/blobby/src/lib.rs b/blobby/src/lib.rs index 8affa46b..b7d1737b 100644 --- a/blobby/src/lib.rs +++ b/blobby/src/lib.rs @@ -46,8 +46,7 @@ #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_root_url = "https://docs.rs/blobby/0.3.1" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] extern crate alloc; diff --git a/block-buffer/Cargo.toml b/block-buffer/Cargo.toml index 680674a1..6696b571 100644 --- a/block-buffer/Cargo.toml +++ b/block-buffer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "block-buffer" -version = "0.10.2" # Also update html_root_url in lib.rs when bumping this +version = "0.10.2" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Buffer type for block processing of data" diff --git a/block-buffer/src/lib.rs b/block-buffer/src/lib.rs index ebe73695..cc19b7c3 100644 --- a/block-buffer/src/lib.rs +++ b/block-buffer/src/lib.rs @@ -2,8 +2,7 @@ #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_root_url = "https://docs.rs/block-buffer/0.10.2" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #![warn(missing_docs, rust_2018_idioms)] diff --git a/block-padding/Cargo.toml b/block-padding/Cargo.toml index 7ea62c89..e8d66f02 100644 --- a/block-padding/Cargo.toml +++ b/block-padding/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "block-padding" -version = "0.3.2" # Also update html_root_url in lib.rs when bumping this +version = "0.3.2" description = "Padding and unpadding of messages divided into blocks." authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -11,10 +11,6 @@ repository = "https://github.com/RustCrypto/utils" keywords = ["padding", "pkcs7", "ansix923", "iso7816"] categories = ["cryptography", "no-std"] -# Hack to allow this crate to coexist with pre-2021 edition crates -[workspace] -members = ["."] - [dependencies] generic-array = "0.14" diff --git a/block-padding/src/lib.rs b/block-padding/src/lib.rs index 2daa3ea2..3cbc164e 100644 --- a/block-padding/src/lib.rs +++ b/block-padding/src/lib.rs @@ -6,8 +6,7 @@ #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_root_url = "https://docs.rs/block-padding/0.3.2" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #![cfg_attr(docsrs, feature(doc_cfg))] #![warn(missing_docs, rust_2018_idioms)] diff --git a/cmov/Cargo.toml b/cmov/Cargo.toml index fde85aed..581f4b4d 100644 --- a/cmov/Cargo.toml +++ b/cmov/Cargo.toml @@ -13,5 +13,5 @@ repository = "https://github.com/RustCrypto/utils/tree/master/cmov" categories = ["cryptography", "hardware-support", "no-std"] keywords = ["crypto", "intrinsics"] readme = "README.md" -edition = "2018" # Can't bump to 2021 due to pre-1.56 MSRV crates in the same workspace +edition = "2021" rust-version = "1.59" diff --git a/collectable/Cargo.toml b/collectable/Cargo.toml index 8ab88ff9..9c2e081f 100644 --- a/collectable/Cargo.toml +++ b/collectable/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "collectable" -version = "0.0.2" # Also update html_root_url in lib.rs when bumping this +version = "0.0.2" authors = ["RustCrypto Developers"] license = "Apache-2.0 OR MIT" edition = "2018" diff --git a/collectable/src/lib.rs b/collectable/src/lib.rs index 69b1c8e4..9d2d693a 100644 --- a/collectable/src/lib.rs +++ b/collectable/src/lib.rs @@ -6,8 +6,7 @@ #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_root_url = "https://docs.rs/collectable/0.0.2" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #[cfg(feature = "alloc")] diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index f5ab619b..fa590c68 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cpufeatures" -version = "0.2.2" # Also update html_root_url in lib.rs when bumping this +version = "0.2.2" description = """ Lightweight runtime CPU feature detection for x86/x86_64 and aarch64 with no_std support and support for mobile targets including Android and iOS diff --git a/dbl/Cargo.toml b/dbl/Cargo.toml index d683e840..5b29c45c 100644 --- a/dbl/Cargo.toml +++ b/dbl/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "dbl" -version = "0.3.2" # Also update html_root_url in lib.rs when bumping this +version = "0.3.2" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Double operation in Galois Field (GF)" diff --git a/dbl/src/lib.rs b/dbl/src/lib.rs index fe77c87c..66fd555c 100644 --- a/dbl/src/lib.rs +++ b/dbl/src/lib.rs @@ -2,8 +2,7 @@ #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_root_url = "https://docs.rs/dbl/0.3.2" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #![forbid(unsafe_code)] diff --git a/hex-literal/Cargo.toml b/hex-literal/Cargo.toml index eb64b85b..e3d36833 100644 --- a/hex-literal/Cargo.toml +++ b/hex-literal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hex-literal" -version = "0.3.4" # Also update html_root_url in lib.rs when bumping this +version = "0.3.4" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Procedural macro for converting hexadecimal string to byte array at compile time." diff --git a/hex-literal/src/lib.rs b/hex-literal/src/lib.rs index afdc533f..a69ec333 100644 --- a/hex-literal/src/lib.rs +++ b/hex-literal/src/lib.rs @@ -48,8 +48,7 @@ //! ``` #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_root_url = "https://docs.rs/hex-literal/0.3.4" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] mod comments; diff --git a/inout/Cargo.lock b/inout/Cargo.lock deleted file mode 100644 index 2455765e..00000000 --- a/inout/Cargo.lock +++ /dev/null @@ -1,40 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "block-padding" -version = "0.3.1" -dependencies = [ - "generic-array", -] - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" -dependencies = [ - "typenum", - "version_check", -] - -[[package]] -name = "inout" -version = "0.1.2" -dependencies = [ - "block-padding", - "generic-array", -] - -[[package]] -name = "typenum" -version = "1.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" - -[[package]] -name = "version_check" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" diff --git a/inout/Cargo.toml b/inout/Cargo.toml index fe376c7b..8195a870 100644 --- a/inout/Cargo.toml +++ b/inout/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "inout" -version = "0.1.3" # Also update html_root_url in lib.rs when bumping this +version = "0.1.3" description = "Custom reference types for code generic over in-place and buffer-to-buffer modes of operation." authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" @@ -10,10 +10,6 @@ documentation = "https://docs.rs/inout" repository = "https://github.com/RustCrypto/utils" keywords = ["custom-reference"] -# Hack to allow this crate to coexist with pre-2021 edition crates -[workspace] -members = ["."] - [dependencies] generic-array = "0.14" block-padding = { version = "0.3", path = "../block-padding", optional = true } diff --git a/inout/src/lib.rs b/inout/src/lib.rs index a8312635..cb5dc4b1 100644 --- a/inout/src/lib.rs +++ b/inout/src/lib.rs @@ -4,8 +4,7 @@ #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg", - html_root_url = "https://docs.rs/inout/0.1.3" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg" )] #![allow(clippy::needless_lifetimes)] #![cfg_attr(docsrs, feature(doc_cfg))] diff --git a/inout/src/reserved.rs b/inout/src/reserved.rs index 3d0dc84f..553eac1c 100644 --- a/inout/src/reserved.rs +++ b/inout/src/reserved.rs @@ -202,6 +202,7 @@ impl<'inp, 'out, BS: ArrayLength> PaddedInOutBuf<'inp, 'out, BS> { /// /// For paddings with `P::TYPE = PadType::Reversible` it always returns `Some`. #[inline(always)] + #[allow(clippy::needless_option_as_deref)] pub fn get_tail_block<'a>(&'a mut self) -> Option>> { match self.tail_out.as_deref_mut() { Some(out_block) => Some((&self.tail_in, out_block).into()), diff --git a/opaque-debug/Cargo.toml b/opaque-debug/Cargo.toml index 3c48611c..d2d788e6 100644 --- a/opaque-debug/Cargo.toml +++ b/opaque-debug/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "opaque-debug" -version = "0.3.0" # Also update html_root_url in lib.rs when bumping this +version = "0.3.0" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Macro for opaque Debug trait implementation" diff --git a/opaque-debug/src/lib.rs b/opaque-debug/src/lib.rs index 86163ad6..e4e5b7b5 100644 --- a/opaque-debug/src/lib.rs +++ b/opaque-debug/src/lib.rs @@ -2,8 +2,7 @@ #![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_root_url = "https://docs.rs/opaque-debug/0.3.0" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] #[doc(hidden)] diff --git a/wycheproof2blb/Cargo.toml b/wycheproof2blb/Cargo.toml index 5bd025b3..c125d521 100644 --- a/wycheproof2blb/Cargo.toml +++ b/wycheproof2blb/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "wycheproof2blb" -version = "0.1.0" # Also update html_root_url in lib.rs when bumping this +version = "0.1.0" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "A utility for converting Wycheproof test vectors to the blobby format" diff --git a/wycheproof2blb/src/main.rs b/wycheproof2blb/src/main.rs index 11082812..267c76dc 100644 --- a/wycheproof2blb/src/main.rs +++ b/wycheproof2blb/src/main.rs @@ -1,8 +1,7 @@ //! Tool to convert Wycheproof test vectors to raw hex format #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", - html_root_url = "https://docs.rs/wycheproof2blb/0.1.0" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] use std::io::Write; From 86455d547f86ebb1e20844ba938f0063e2b5bbbf Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Wed, 20 Apr 2022 12:11:47 -0400 Subject: [PATCH 005/116] feat: make `Zeroizing` transparent for cheap conversions (#761) Sometimes libraries want to be generic across types like `Vec` and `Box<[u8]>`. Therefore, they use bounds like `T: AsRef<[u8]>`. The `Zeroizing>` type should be transparently equivalent to `Vec` in this regard. This allows `Zeroizing` to be used with all such bounds. Signed-off-by: Nathaniel McCallum --- zeroize/src/lib.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index 5006fb61..ceca6068 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -580,6 +580,26 @@ where } } +impl AsRef for Zeroizing +where + T: ?Sized, + Z: AsRef + Zeroize, +{ + fn as_ref(&self) -> &T { + self.0.as_ref() + } +} + +impl AsMut for Zeroizing +where + T: ?Sized, + Z: AsMut + Zeroize, +{ + fn as_mut(&mut self) -> &mut T { + self.0.as_mut() + } +} + impl Zeroize for Zeroizing where Z: Zeroize, @@ -700,6 +720,9 @@ mod tests { #[cfg(feature = "alloc")] use alloc::boxed::Box; + #[cfg(feature = "alloc")] + use alloc::vec::Vec; + #[derive(Clone, Debug, PartialEq)] struct ZeroizedOnDrop(u64); @@ -865,4 +888,16 @@ mod tests { boxed_arr.zeroize(); assert_eq!(boxed_arr.as_ref(), &[0u8; 3]); } + + #[cfg(feature = "alloc")] + #[test] + fn asref() { + let mut buffer: Zeroizing> = Default::default(); + let _asmut: &mut [u8] = buffer.as_mut(); + let _asref: &[u8] = buffer.as_ref(); + + let mut buffer: Zeroizing> = Default::default(); + let _asmut: &mut [u8] = buffer.as_mut(); + let _asref: &[u8] = buffer.as_ref(); + } } From a729d1f5fb10eb1490305703cf47bc4d2356b8ab Mon Sep 17 00:00:00 2001 From: robinhundt <24554122+robinhundt@users.noreply.github.com> Date: Thu, 28 Apr 2022 17:29:40 +0200 Subject: [PATCH 006/116] Implement Zeroize for std::ffi::CString (#759) This implements Zeroize for std::ffi::CString. As CString is not in allocate but in std, a new optional std feature is added to depend on the std library. --- .github/workflows/zeroize.yml | 2 +- zeroize/Cargo.toml | 1 + zeroize/src/lib.rs | 67 ++++++++++++++++++++++++++++++++--- 3 files changed, 64 insertions(+), 6 deletions(-) diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index d7126922..c67bf1e7 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -69,7 +69,7 @@ jobs: # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo test - - run: cargo test --features alloc,derive + - run: cargo test --features alloc,derive,std # Feature-gated ARM64 SIMD register support (nightly-only) aarch64: diff --git a/zeroize/Cargo.toml b/zeroize/Cargo.toml index 29d6cd99..a1477903 100644 --- a/zeroize/Cargo.toml +++ b/zeroize/Cargo.toml @@ -24,6 +24,7 @@ default = ["alloc"] aarch64 = [] alloc = [] derive = ["zeroize_derive"] +std = ["alloc"] [package.metadata.docs.rs] all-features = true diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index ceca6068..a8b34b8b 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -61,7 +61,13 @@ //! impl'd for `Vec` for the above types as well as `String`, where it provides //! [`Vec::clear`] / [`String::clear`]-like behavior (truncating to zero-length) //! but ensures the backing memory is securely zeroed with some caveats. -//! (NOTE: see "Stack/Heap Zeroing Notes" for important `Vec`/`String` details) +//! +//! With the `std` feature enabled (which it is **not** by default), [`Zeroize`] +//! is also implemented for [`CString`]. After calling `zeroize()` on a `CString`, +//! it will its internal buffer will contain exactly one nul byte. The backing +//! memory is zeroed by converting it to a `Vec` and back into a `CString`. +//! (NOTE: see "Stack/Heap Zeroing Notes" for important `Vec`/`String`/`CString` details) +//! //! //! The [`DefaultIsZeroes`] marker trait can be impl'd on types which also //! impl [`Default`], which implements [`Zeroize`] by overwriting a value with @@ -191,10 +197,10 @@ //! [`Pin`][`core::pin::Pin`] can be leveraged in conjunction with this crate //! to ensure data kept on the stack isn't moved. //! -//! The `Zeroize` impls for `Vec` and `String` zeroize the entire capacity of -//! their backing buffer, but cannot guarantee copies of the data were not -//! previously made by buffer reallocation. It's therefore important when -//! attempting to zeroize such buffers to initialize them to the correct +//! The `Zeroize` impls for `Vec`, `String` and `CString` zeroize the entire +//! capacity of their backing buffer, but cannot guarantee copies of the data +//! were not previously made by buffer reallocation. It's therefore important +//! when attempting to zeroize such buffers to initialize them to the correct //! capacity, and take care to prevent subsequent reallocation. //! //! The `secrecy` crate provides higher-level abstractions for eliminating @@ -233,6 +239,9 @@ #[cfg_attr(test, macro_use)] extern crate alloc; +#[cfg(feature = "std")] +extern crate std; + #[cfg(feature = "zeroize_derive")] #[cfg_attr(docsrs, doc(cfg(feature = "zeroize_derive")))] pub use zeroize_derive::{Zeroize, ZeroizeOnDrop}; @@ -253,6 +262,9 @@ use core::{ops, ptr, slice::IterMut, sync::atomic}; #[cfg(feature = "alloc")] use alloc::{boxed::Box, string::String, vec::Vec}; +#[cfg(feature = "std")] +use std::ffi::CString; + /// Trait for securely erasing types from memory pub trait Zeroize { /// Zero out this object from memory using Rust intrinsics which ensure the @@ -511,6 +523,27 @@ impl Zeroize for String { } } +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +impl Zeroize for CString { + fn zeroize(&mut self) { + // mem::take uses replace internally to swap the pointer + // Unfortunately this results in an allocation for a Box::new(&[0]) as CString must + // contain a trailing zero byte + let this = std::mem::take(self); + // - CString::into_bytes calls ::into_vec which takes ownership of the heap pointer + // as a Vec + // - Calling .zeroize() on the resulting vector clears out the bytes + // From: https://github.com/RustCrypto/utils/pull/759#issuecomment-1087976570 + let mut buf = this.into_bytes(); + buf.zeroize(); + // expect() should never fail, because zeroize() truncates the Vec + let zeroed = CString::new(buf).expect("buf not truncated"); + // Replace self by the zeroed CString to maintain the original ptr of the buffer + let _ = std::mem::replace(self, zeroed); + } +} + /// Fallible trait for representing cases where zeroization may or may not be /// possible. /// @@ -723,6 +756,9 @@ mod tests { #[cfg(feature = "alloc")] use alloc::vec::Vec; + #[cfg(feature = "std")] + use std::ffi::CString; + #[derive(Clone, Debug, PartialEq)] struct ZeroizedOnDrop(u64); @@ -881,6 +917,27 @@ mod tests { assert!(as_vec.iter().all(|byte| *byte == 0)); } + #[cfg(feature = "std")] + #[test] + fn zeroize_c_string() { + let mut cstring = CString::new("Hello, world!").expect("CString::new failed"); + let orig_len = cstring.as_bytes().len(); + let orig_ptr = cstring.as_bytes().as_ptr(); + cstring.zeroize(); + // This doesn't quite test that the original memory has been cleared, but only that + // cstring now owns an empty buffer + assert!(cstring.as_bytes().is_empty()); + for i in 0..orig_len { + unsafe { + // Using a simple deref, only one iteration of the loop is performed + // presumably because after zeroize, the internal buffer has a length of one/ + // `read_volatile` seems to "fix" this + // Note that this is very likely UB + assert_eq!(orig_ptr.add(i).read_volatile(), 0); + } + } + } + #[cfg(feature = "alloc")] #[test] fn zeroize_box() { From c30341abc22067053dcab4b7dc710dc9d5565046 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 30 Apr 2022 19:29:39 -0600 Subject: [PATCH 007/116] zeroize v1.5.5 (#763) --- Cargo.lock | 2 +- zeroize/CHANGELOG.md | 8 ++++++++ zeroize/Cargo.toml | 2 +- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3aa04126..810649a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,7 +197,7 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.4" +version = "1.5.5" dependencies = [ "zeroize_derive", ] diff --git a/zeroize/CHANGELOG.md b/zeroize/CHANGELOG.md index 6615e378..50acf39d 100644 --- a/zeroize/CHANGELOG.md +++ b/zeroize/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.5.5 (2022-04-30) +### Added +- Impl `Zeroize` for std::ffi::CString ([#759]) +- `AsRef` and `AsMut` impls for `Zeroizing` ([#761]) + +[#759]: https://github.com/RustCrypto/utils/pull/759 +[#761]: https://github.com/RustCrypto/utils/pull/761 + ## 1.5.4 (2022-03-16) ### Added - Nightly-only upport for zeroizing ARM64 SIMD registers ([#749]) diff --git a/zeroize/Cargo.toml b/zeroize/Cargo.toml index a1477903..b7f0be23 100644 --- a/zeroize/Cargo.toml +++ b/zeroize/Cargo.toml @@ -7,7 +7,7 @@ operation will not be 'optimized away' by the compiler. Uses a portable pure Rust implementation that works everywhere, even WASM! """ -version = "1.5.4" +version = "1.5.5" authors = ["The RustCrypto Project Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/zeroize" From 4601ef2d4d63781702d6bc1bfb0ad84a33fe1ad7 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 7 May 2022 11:43:30 -0600 Subject: [PATCH 008/116] hybrid-array: hybrid typenum/const-generic arrays (#707) This crate provides a `generic-array`-inspired array type which uses some of the ideas from `crypto-bigint` to provide type-level conversions between const generics and typenum-based arrays. I originally looked at trying to add this sort of thing as an afterthought to `generic-array`, but felt that it would really be helpful if it were the core abstraction everything else is built on. Also `generic-array` is full of huge swaths of complicated `unsafe` code which is completely unnecessary in the setup used in this crate, which merely uses the type system to map to Rust's underlying array types. It provides an `Array` type similar to `GenericArray` along with an `Array` trait which can be used to map const generic parameters to underlying array types. Macros are used to write the `Array`/`ArraySize` trait impls for the following array sizes: - 0-64 - 96 - 128 - 192 - 256 - 384 - 448 - 512 - 768 - 896 - 1024 - 2048 - 8192 This is a smaller range of sizes than what `generic-array` supports due to `typenum` type alias definitions. It is necessary to make the const generic linkage work. The overall API is *much* closer to `core::array` than `GenericArray` is. For example, `GenericArray` has a panicking `From` providing `TryFrom`-like behavior, and confusingly receives the blanket impl of `TryFrom`, so people can mistakenly use `TryFrom` expecting a fallible API only to get the blanket impl of `From` and a panic in the event of an error. Everywhere possible, it uses const generic implementations of traits rather than macro-based implementations in order to improve compile times and keep the macro-based parts to a minimum. This includes: - `AsRef<[T; N]>` - `AsMut<[T; N]>` - `Borrow<[T; N]>` - `BorrowMut` - `From<[T; N]>` - `Index` - `IndexMut` - `TryFrom<&[T]>` --- .github/workflows/hybrid-array.yml | 64 +++++ Cargo.lock | 7 + Cargo.toml | 1 + hybrid-array/CHANGELOG.md | 6 + hybrid-array/Cargo.toml | 19 ++ hybrid-array/LICENSE-APACHE | 201 +++++++++++++++ hybrid-array/LICENSE-MIT | 25 ++ hybrid-array/README.md | 47 ++++ hybrid-array/src/lib.rs | 391 +++++++++++++++++++++++++++++ 9 files changed, 761 insertions(+) create mode 100644 .github/workflows/hybrid-array.yml create mode 100644 hybrid-array/CHANGELOG.md create mode 100644 hybrid-array/Cargo.toml create mode 100644 hybrid-array/LICENSE-APACHE create mode 100644 hybrid-array/LICENSE-MIT create mode 100644 hybrid-array/README.md create mode 100644 hybrid-array/src/lib.rs diff --git a/.github/workflows/hybrid-array.yml b/.github/workflows/hybrid-array.yml new file mode 100644 index 00000000..991686cd --- /dev/null +++ b/.github/workflows/hybrid-array.yml @@ -0,0 +1,64 @@ +name: hybrid-array + +on: + pull_request: + paths: + - ".github/workflows/hybrid-array.yml" + - "hybrid-array/**" + - "Cargo.*" + push: + branches: main + +defaults: + run: + working-directory: hybrid-array + +env: + CARGO_INCREMENTAL: 0 + RUSTFLAGS: "-Dwarnings" + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + rust: + - 1.56.0 # MSRV + - stable + target: + - armv7a-none-eabi + - thumbv7em-none-eabi + - wasm32-unknown-unknown + steps: + - uses: actions/checkout@v2 + - uses: RustCrypto/actions/cargo-cache@master + - uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust }} + target: ${{ matrix.target }} + override: true + profile: minimal + - run: cargo build --no-default-features --target ${{ matrix.target }} + + minimal-versions: + uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master + with: + working-directory: ${{ github.workflow }} + + test: + strategy: + matrix: + toolchain: + - 1.56.0 # MSRV + - stable + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: RustCrypto/actions/cargo-cache@master + - uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + override: true + profile: minimal + - run: cargo test + - run: cargo test --all-features diff --git a/Cargo.lock b/Cargo.lock index 810649a5..c1531caf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -65,6 +65,13 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" name = "hex-literal" version = "0.3.4" +[[package]] +name = "hybrid-array" +version = "0.0.0" +dependencies = [ + "typenum", +] + [[package]] name = "inout" version = "0.1.3" diff --git a/Cargo.toml b/Cargo.toml index 1336109e..42cc18c1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,6 +8,7 @@ members = [ "cpufeatures", "dbl", "hex-literal", + "hybrid-array", "inout", "opaque-debug", "wycheproof2blb", diff --git a/hybrid-array/CHANGELOG.md b/hybrid-array/CHANGELOG.md new file mode 100644 index 00000000..1d013ff9 --- /dev/null +++ b/hybrid-array/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/hybrid-array/Cargo.toml b/hybrid-array/Cargo.toml new file mode 100644 index 00000000..ddd46e57 --- /dev/null +++ b/hybrid-array/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "hybrid-array" +version = "0.0.0" # Also update html_root_url in lib.rs when bumping this +description = """ +Hybrid typenum-based and const generic array types designed to provide the +flexibility of typenum-based expressions while also allowing interoperability +and a transition path to const generics +""" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +documentation = "https://docs.rs/hybrid-array" +repository = "https://github.com/RustCrypto/utils" +categories = ["no-std"] +readme = "README.md" +edition = "2021" +rust-version = "1.56" + +[dependencies] +typenum = "1.10" diff --git a/hybrid-array/LICENSE-APACHE b/hybrid-array/LICENSE-APACHE new file mode 100644 index 00000000..78173fa2 --- /dev/null +++ b/hybrid-array/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/hybrid-array/LICENSE-MIT b/hybrid-array/LICENSE-MIT new file mode 100644 index 00000000..e4cbf938 --- /dev/null +++ b/hybrid-array/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2022 The RustCrypto Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/hybrid-array/README.md b/hybrid-array/README.md new file mode 100644 index 00000000..f7430bbc --- /dev/null +++ b/hybrid-array/README.md @@ -0,0 +1,47 @@ +# [RustCrypto]: Hybrid Const Generic / Typenum Arrays + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] +[![Build Status][build-image]][build-link] + +Hybrid array type combining const generics with the expressiveness of +[`typenum`]-based constraints, providing an alternative to [`generic-array`] +and a incremental transition path to const generics. + +[Documentation][docs-link] + +## License + +Licensed under either of: + + * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) + * [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/hybrid-array.svg +[crate-link]: https://crates.io/crates/hybrid-array +[docs-image]: https://docs.rs/hybrid-array/badge.svg +[docs-link]: https://docs.rs/hybrid-array/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.56+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils +[build-image]: https://github.com/RustCrypto/utils/workflows/hybrid-array/badge.svg?branch=master&event=push +[build-link]: https://github.com/RustCrypto/utils/actions/workflows/hybrid-array.yml + +[//]: # (general links) + +[RustCrypto]: https://github.com/rustcrypto +[RustCrypto/utils#378]: https://github.com/RustCrypto/utils/issues/378 diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs new file mode 100644 index 00000000..f2f6f769 --- /dev/null +++ b/hybrid-array/src/lib.rs @@ -0,0 +1,391 @@ +#![no_std] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![doc = include_str!("../README.md")] +#![doc( + html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", + html_root_url = "https://docs.rs/hybrid-array/0.0.0" +)] +#![forbid(unsafe_code, clippy::unwrap_used)] +#![warn(missing_docs, rust_2018_idioms)] + +pub use typenum; + +use core::{ + array::{IntoIter, TryFromSliceError}, + borrow::{Borrow, BorrowMut}, + ops::{Index, IndexMut, Range}, + slice::{Iter, IterMut}, +}; +use typenum::Unsigned; + +/// Array operations which are const generic over a given array size. +pub trait ArrayOps: + AsRef<[T; N]> + + AsMut<[T; N]> + + Borrow<[T; N]> + + BorrowMut<[T; N]> + + From<[T; N]> + + Index + + Index> + + IndexMut + + IndexMut> + + IntoIterator + + Sized +{ + /// Size of an array as a `usize`. + /// + /// Not to be confused with [`ArrayOps::Size`], which is `typenum`-based. + const SIZE: usize; + + /// [`ArraySize`] type: `typenum`-provided [`Unsigned`] integer. + /// + /// Not to be confused with [`ArrayOps::SIZE`], which is a `usize`. + type Size: ArraySize; + + /// Returns a reference to the inner array. + fn as_array_ref(&self) -> &[T; N]; + + /// Returns a mutable reference to the inner array. + fn as_array_mut(&mut self) -> &mut [T; N]; + + /// Create array from Rust's core array type. + fn from_core_array(arr: [T; N]) -> Self; + + /// Create array where each array element `T` is returned by the `cb` call. + fn from_fn(mut cb: F) -> Self + where + F: FnMut(usize) -> T, + { + let mut idx = 0; + Self::from_core_array([(); N].map(|_| { + let res = cb(idx); + idx += 1; + res + })) + } + + /// Create array from a slice. + fn from_slice(slice: &[T]) -> Result + where + T: Copy; + + /// Returns an iterator over the array. + #[inline] + fn iter(&self) -> Iter<'_, T> { + self.as_ref().iter() + } + + /// Returns an iterator that allows modifying each value. + #[inline] + fn iter_mut(&mut self) -> IterMut<'_, T> { + self.as_mut().iter_mut() + } + + /// Returns an array of the same size as `self`, with function `f` applied to each element + /// in order. + fn map(self, f: F) -> [U; N] + where + F: FnMut(T) -> U; +} + +/// Trait which associates a [`usize`] size and `ArrayType` with a +/// `typenum`-provided [`Unsigned`] integer. +pub trait ArraySize: Unsigned { + /// Array type which corresponds to this size. + type ArrayType: AsRef<[T]> + AsMut<[T]> + IntoArray + Sized; +} + +/// Convert the given type into an [`Array`]. +pub trait IntoArray { + /// Size of the [`Array`]. + type Size: ArraySize; + + /// Convert into the `hybrid-array` crate's [`Array`] type. + fn into_hybrid_array(self) -> Array; +} + +macro_rules! impl_array_size { + ($($len:expr => $ty:ident),+) => { + $( + impl ArrayOps for Array { + const SIZE: usize = $len; + type Size = typenum::$ty; + + fn as_array_ref(&self) -> &[T; $len] { + &self.0 + } + + fn as_array_mut(&mut self) -> &mut [T; $len] { + &mut self.0 + } + + #[inline] + fn from_core_array(arr: [T; $len]) -> Self { + Self(arr) + } + + #[inline] + fn from_slice(slice: &[T]) -> Result + where + T: Copy + { + slice.try_into().map(Self) + } + + #[inline] + fn map(self, f: F) -> [U; $len] + where + F: FnMut(T) -> U + { + self.0.map(f) + } + } + + impl ArraySize for typenum::$ty { + type ArrayType = [T; $len]; + } + + impl IntoArray for [T; $len] { + type Size = typenum::$ty; + + fn into_hybrid_array(self) -> Array { + Array::from_core_array(self) + } + } + + impl IntoIterator for Array { + type Item = T; + type IntoIter = IntoIter; + + /// Creates a consuming iterator, that is, one that moves each value out of + /// the array (from start to end). The array cannot be used after calling + /// this unless `T` implements `Copy`, so the whole array is copied. + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } + } + + impl<'a, T> IntoIterator for &'a Array { + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } + } + + impl<'a, T> IntoIterator for &'a mut Array { + type Item = &'a mut T; + type IntoIter = IterMut<'a, T>; + + #[inline] + fn into_iter(self) -> IterMut<'a, T> { + self.iter_mut() + } + } + )+ + }; +} + +impl_array_size! { + 0 => U0, + 1 => U1, + 2 => U2, + 3 => U3, + 4 => U4, + 5 => U5, + 6 => U6, + 7 => U7, + 8 => U8, + 9 => U9, + 10 => U10, + 11 => U11, + 12 => U12, + 13 => U13, + 14 => U14, + 15 => U15, + 16 => U16, + 17 => U17, + 18 => U18, + 19 => U19, + 20 => U20, + 21 => U21, + 22 => U22, + 23 => U23, + 24 => U24, + 25 => U25, + 26 => U26, + 27 => U27, + 28 => U28, + 29 => U29, + 30 => U30, + 31 => U31, + 32 => U32, + 33 => U33, + 34 => U34, + 35 => U35, + 36 => U36, + 37 => U37, + 38 => U38, + 39 => U39, + 40 => U40, + 41 => U41, + 42 => U42, + 43 => U43, + 44 => U44, + 45 => U45, + 46 => U46, + 47 => U47, + 48 => U48, + 49 => U49, + 50 => U50, + 51 => U51, + 52 => U52, + 53 => U53, + 54 => U54, + 55 => U55, + 56 => U56, + 57 => U57, + 58 => U58, + 59 => U59, + 60 => U60, + 61 => U61, + 62 => U62, + 63 => U63, + 64 => U64, + 96 => U96, + 128 => U128, + 192 => U192, + 256 => U256, + 384 => U384, + 448 => U448, + 512 => U512, + 768 => U768, + 896 => U896, + 1024 => U1024, + 2048 => U2048, + 4096 => U4096, + 8192 => U8192 +} + +/// Hybrid typenum-based and const generic array type. +/// +/// Provides the flexibility of typenum-based expressions while also +/// allowing interoperability and a transition path to const generics. +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] +#[repr(transparent)] +pub struct Array>(pub U::ArrayType); + +impl Array +where + U: ArraySize, +{ + /// Returns a slice containing the entire array. Equivalent to `&s[..]`. + #[inline] + pub fn as_slice(&self) -> &[T] { + self.0.as_ref() + } + + /// Returns a mutable slice containing the entire array. Equivalent to `&mut s[..]`. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [T] { + self.0.as_mut() + } +} + +impl AsRef<[T; N]> for Array +where + Self: ArrayOps, + U: ArraySize, +{ + #[inline] + fn as_ref(&self) -> &[T; N] { + self.as_array_ref() + } +} + +impl AsMut<[T; N]> for Array +where + Self: ArrayOps, + U: ArraySize, +{ + #[inline] + fn as_mut(&mut self) -> &mut [T; N] { + self.as_array_mut() + } +} + +impl Borrow<[T; N]> for Array +where + Self: ArrayOps, + U: ArraySize, +{ + #[inline] + fn borrow(&self) -> &[T; N] { + self.as_array_ref() + } +} + +impl BorrowMut<[T; N]> for Array +where + Self: ArrayOps, + U: ArraySize, +{ + #[inline] + fn borrow_mut(&mut self) -> &mut [T; N] { + self.as_array_mut() + } +} + +impl From<[T; N]> for Array +where + Self: ArrayOps, + U: ArraySize, +{ + #[inline] + fn from(arr: [T; N]) -> Array { + Self::from_core_array(arr) + } +} + +impl Index for Array +where + [T]: Index, + U: ArraySize, +{ + type Output = <[T] as Index>::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + Index::index(self.as_slice(), index) + } +} + +impl IndexMut for Array +where + [T]: IndexMut, + U: ArraySize, +{ + #[inline] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + IndexMut::index_mut(self.as_mut_slice(), index) + } +} + +impl<'a, T, U> TryFrom<&'a [T]> for Array +where + T: Copy, + U: ArraySize, + U::ArrayType: TryFrom<&'a [T], Error = TryFromSliceError>, +{ + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: &'a [T]) -> Result, TryFromSliceError> { + U::ArrayType::try_from(slice).map(Self) + } +} + +/// Byte array type. +pub type ByteArray = Array; From 629e25f1a15d9d074e97d6a4170df845a2cc5025 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 7 May 2022 16:20:09 -0600 Subject: [PATCH 009/116] hybrid-array v0.1.0 (#764) --- Cargo.lock | 2 +- hybrid-array/CHANGELOG.md | 3 +++ hybrid-array/Cargo.toml | 7 ++++--- hybrid-array/README.md | 28 +++++++++++++++++++++++----- hybrid-array/src/lib.rs | 25 ++++++++++++++++++++----- 5 files changed, 51 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1531caf..cb8a8256 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -67,7 +67,7 @@ version = "0.3.4" [[package]] name = "hybrid-array" -version = "0.0.0" +version = "0.1.0" dependencies = [ "typenum", ] diff --git a/hybrid-array/CHANGELOG.md b/hybrid-array/CHANGELOG.md index 1d013ff9..2dac4530 100644 --- a/hybrid-array/CHANGELOG.md +++ b/hybrid-array/CHANGELOG.md @@ -4,3 +4,6 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## 0.1.0 (2022-05-07) +- Initial release diff --git a/hybrid-array/Cargo.toml b/hybrid-array/Cargo.toml index ddd46e57..cfdb9754 100644 --- a/hybrid-array/Cargo.toml +++ b/hybrid-array/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hybrid-array" -version = "0.0.0" # Also update html_root_url in lib.rs when bumping this +version = "0.1.0" # Also update html_root_url in lib.rs when bumping this description = """ Hybrid typenum-based and const generic array types designed to provide the flexibility of typenum-based expressions while also allowing interoperability @@ -9,8 +9,9 @@ and a transition path to const generics authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" documentation = "https://docs.rs/hybrid-array" -repository = "https://github.com/RustCrypto/utils" -categories = ["no-std"] +repository = "https://github.com/RustCrypto/utils/tree/master/hybrid-array" +categories = ["no-std", "data-structures"] +keywords = ["generic-array"] readme = "README.md" edition = "2021" rust-version = "1.56" diff --git a/hybrid-array/README.md b/hybrid-array/README.md index f7430bbc..98457779 100644 --- a/hybrid-array/README.md +++ b/hybrid-array/README.md @@ -2,10 +2,11 @@ [![crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] +[![Build Status][build-image]][build-link] +[![Safety Dance][safety-image]][safety-link] ![Apache2/MIT licensed][license-image] ![Rust Version][rustc-image] [![Project Chat][chat-image]][chat-link] -[![Build Status][build-image]][build-link] Hybrid array type combining const generics with the expressiveness of [`typenum`]-based constraints, providing an alternative to [`generic-array`] @@ -13,6 +14,17 @@ and a incremental transition path to const generics. [Documentation][docs-link] +## About + +This crate uses `typenum` to enable the following features which aren't yet +possible with the stable implementation of const generics: + +- [#60551: Associated constants in traits can not be used in const generics][rust-issue-60551] +- [#76560: Complex generic constants: `feature(generic_const_exprs)`][rust-issue-76560] + +Internally the crate is built on const generics and provides traits which make +it possible to convert between const generic types and `typenum` types. + ## License Licensed under either of: @@ -30,18 +42,24 @@ dual licensed as above, without any additional terms or conditions. [//]: # (badges) -[crate-image]: https://img.shields.io/crates/v/hybrid-array.svg +[crate-image]: https://buildstats.info/crate/hybrid-array [crate-link]: https://crates.io/crates/hybrid-array [docs-image]: https://docs.rs/hybrid-array/badge.svg [docs-link]: https://docs.rs/hybrid-array/ +[build-image]: https://github.com/RustCrypto/utils/workflows/hybrid-array/badge.svg?branch=master&event=push +[build-link]: https://github.com/RustCrypto/utils/actions/workflows/hybrid-array.yml +[safety-image]: https://img.shields.io/badge/unsafe-forbidden-success.svg +[safety-link]: https://github.com/rust-secure-code/safety-dance/ [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg [rustc-image]: https://img.shields.io/badge/rustc-1.56+-blue.svg [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils -[build-image]: https://github.com/RustCrypto/utils/workflows/hybrid-array/badge.svg?branch=master&event=push -[build-link]: https://github.com/RustCrypto/utils/actions/workflows/hybrid-array.yml -[//]: # (general links) +[//]: # (links) [RustCrypto]: https://github.com/rustcrypto [RustCrypto/utils#378]: https://github.com/RustCrypto/utils/issues/378 +[`typenum`]: https://github.com/paholg/typenum +[`generic-array`]: https://github.com/fizyk20/generic-array +[rust-issue-60551]: https://github.com/rust-lang/rust/issues/60551 +[rust-issue-76560]: https://github.com/rust-lang/rust/issues/76560 diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index f2f6f769..f673ebc7 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -3,11 +3,26 @@ #![doc = include_str!("../README.md")] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", - html_root_url = "https://docs.rs/hybrid-array/0.0.0" + html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" +)] +#![forbid(unsafe_code)] +#![warn( + clippy::cast_lossless, + clippy::cast_possible_truncation, + clippy::cast_possible_wrap, + clippy::cast_precision_loss, + clippy::cast_sign_loss, + clippy::checked_conversions, + clippy::implicit_saturating_sub, + clippy::integer_arithmetic, + clippy::panic, + clippy::panic_in_result_fn, + clippy::unwrap_used, + missing_docs, + rust_2018_idioms, + unused_lifetimes, + unused_qualifications )] -#![forbid(unsafe_code, clippy::unwrap_used)] -#![warn(missing_docs, rust_2018_idioms)] pub use typenum; @@ -60,7 +75,7 @@ pub trait ArrayOps: let mut idx = 0; Self::from_core_array([(); N].map(|_| { let res = cb(idx); - idx += 1; + idx = idx.saturating_add(1); // TODO(tarcieri): better overflow handling? res })) } From 7db8e3131a0f0d8cf1c3f4a84e7716e6601c8bf4 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 7 May 2022 16:28:12 -0600 Subject: [PATCH 010/116] hybrid-array: fix build badge in README.md --- hybrid-array/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hybrid-array/README.md b/hybrid-array/README.md index 98457779..a9db69ef 100644 --- a/hybrid-array/README.md +++ b/hybrid-array/README.md @@ -46,7 +46,7 @@ dual licensed as above, without any additional terms or conditions. [crate-link]: https://crates.io/crates/hybrid-array [docs-image]: https://docs.rs/hybrid-array/badge.svg [docs-link]: https://docs.rs/hybrid-array/ -[build-image]: https://github.com/RustCrypto/utils/workflows/hybrid-array/badge.svg?branch=master&event=push +[build-image]: https://github.com/RustCrypto/utils/workflows/hybrid-array/badge.svg [build-link]: https://github.com/RustCrypto/utils/actions/workflows/hybrid-array.yml [safety-image]: https://img.shields.io/badge/unsafe-forbidden-success.svg [safety-link]: https://github.com/rust-secure-code/safety-dance/ From 7583f2ed9ca523ccecb32cc0ce16718cdadcef7c Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 27 May 2022 18:22:50 -0600 Subject: [PATCH 011/116] wycheproof2blb: secp384r1 support (#767) Adds support for extracting secp384r1 test vectors from Wycheproof, in order to test the `p384` crate. --- wycheproof2blb/src/ecdsa.rs | 2 +- wycheproof2blb/src/main.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/wycheproof2blb/src/ecdsa.rs b/wycheproof2blb/src/ecdsa.rs index edb69089..2e0fc706 100644 --- a/wycheproof2blb/src/ecdsa.rs +++ b/wycheproof2blb/src/ecdsa.rs @@ -55,7 +55,7 @@ pub fn generator(data: &[u8], algorithm: &str, _key_size: u32) -> Vec let mut infos = vec![]; for g in &suite.test_groups { assert_eq!(g.key.curve, algorithm); - assert_eq!(g.sha, "SHA-256"); + assert!(matches!(g.sha.as_str(), "SHA-256" | "SHA-384")); for tc in &g.tests { if tc.case.result == crate::wycheproof::CaseResult::Acceptable { // TODO: figure out what to do with test cases that pass but which have weak params diff --git a/wycheproof2blb/src/main.rs b/wycheproof2blb/src/main.rs index 267c76dc..fc5b9996 100644 --- a/wycheproof2blb/src/main.rs +++ b/wycheproof2blb/src/main.rs @@ -121,6 +121,10 @@ fn main() { file: "ecdsa_secp256k1_sha256_test.json", generator: ecdsa::generator, }, + "secp384r1" => Algorithm { + file: "ecdsa_secp384r1_sha384_test.json", + generator: ecdsa::generator, + }, _ => panic!("Unrecognized algorithm '{}'", algorithm), }; From 7820fe75707410f095f9a12a486fa46427c86453 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 31 May 2022 09:40:56 -0600 Subject: [PATCH 012/116] build(deps): bump proc-macro2 from 1.0.36 to 1.0.39 (#766) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.36 to 1.0.39. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.36...1.0.39) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb8a8256..71800cf4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -98,11 +98,11 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.36" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7342d5883fbccae1cc37a2353b09c87c9b0f3afd73f5fb9bba687a1f733b029" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" dependencies = [ - "unicode-xid", + "unicode-ident", ] [[package]] @@ -180,6 +180,12 @@ version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" + [[package]] name = "unicode-xid" version = "0.2.2" From 08127c2cba2fd726aa55ef938c15afb019ccfdbb Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 1 Jun 2022 20:48:41 -0600 Subject: [PATCH 013/116] fiat-constify: initial crate (#768) This crate is a tool for transforming `fiat-crypto`-generated field arithmetic into `const fn` form. It performs mechanical translation to the parsed AST of the code, making some assumptions about how it's structured and rewriting the usages of mutable references into a functional form. Manual tests confirm the output from the p386 base field compiles. --- .github/workflows/fiat-constify.yml | 37 +++ Cargo.lock | 9 + Cargo.toml | 1 + fiat-constify/CHANGELOG.md | 6 + fiat-constify/Cargo.toml | 21 ++ fiat-constify/LICENSE-APACHE | 201 +++++++++++++ fiat-constify/LICENSE-MIT | 25 ++ fiat-constify/README.md | 59 ++++ fiat-constify/src/main.rs | 426 ++++++++++++++++++++++++++++ 9 files changed, 785 insertions(+) create mode 100644 .github/workflows/fiat-constify.yml create mode 100644 fiat-constify/CHANGELOG.md create mode 100644 fiat-constify/Cargo.toml create mode 100644 fiat-constify/LICENSE-APACHE create mode 100644 fiat-constify/LICENSE-MIT create mode 100644 fiat-constify/README.md create mode 100644 fiat-constify/src/main.rs diff --git a/.github/workflows/fiat-constify.yml b/.github/workflows/fiat-constify.yml new file mode 100644 index 00000000..d7fd7e50 --- /dev/null +++ b/.github/workflows/fiat-constify.yml @@ -0,0 +1,37 @@ +name: fiat-constify + +on: + pull_request: + paths: + - ".github/workflows/fiat-constify.yml" + - "fiat-constify/**" + - "Cargo.*" + push: + branches: main + +defaults: + run: + working-directory: fiat-constify + +env: + CARGO_INCREMENTAL: 0 + RUSTFLAGS: "-Dwarnings" + +jobs: + test: + strategy: + matrix: + toolchain: + - 1.56.0 # MSRV + - stable + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: RustCrypto/actions/cargo-cache@master + - uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.toolchain }} + override: true + profile: minimal + - run: cargo test + - run: cargo test --all-features diff --git a/Cargo.lock b/Cargo.lock index 71800cf4..dd7f1cd4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,6 +45,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "fiat-constify" +version = "0.0.0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "generic-array" version = "0.14.5" diff --git a/Cargo.toml b/Cargo.toml index 42cc18c1..58a96615 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,7 @@ members = [ "cmov", "cpufeatures", "dbl", + "fiat-constify", "hex-literal", "hybrid-array", "inout", diff --git a/fiat-constify/CHANGELOG.md b/fiat-constify/CHANGELOG.md new file mode 100644 index 00000000..1d013ff9 --- /dev/null +++ b/fiat-constify/CHANGELOG.md @@ -0,0 +1,6 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/fiat-constify/Cargo.toml b/fiat-constify/Cargo.toml new file mode 100644 index 00000000..2c2b46a3 --- /dev/null +++ b/fiat-constify/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "fiat-constify" +version = "0.0.0" # Also update html_root_url in lib.rs when bumping this +description = """ +Postprocessor for fiat-crypto generated field implementations which rewrites +them as `const fn` +""" +authors = ["RustCrypto Developers"] +license = "MIT OR Apache-2.0" +documentation = "https://docs.rs/fiat-constify" +repository = "https://github.com/RustCrypto/utils/tree/master/fiat-constify" +categories = ["cryptography"] +keywords = ["fiat-crypto", "field"] +readme = "README.md" +edition = "2021" +rust-version = "1.56" + +[dependencies] +proc-macro2 = "1" +quote = "1" +syn = { version = "1", features = ["extra-traits", "full"] } diff --git a/fiat-constify/LICENSE-APACHE b/fiat-constify/LICENSE-APACHE new file mode 100644 index 00000000..78173fa2 --- /dev/null +++ b/fiat-constify/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/fiat-constify/LICENSE-MIT b/fiat-constify/LICENSE-MIT new file mode 100644 index 00000000..e4cbf938 --- /dev/null +++ b/fiat-constify/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2022 The RustCrypto Project Developers + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/fiat-constify/README.md b/fiat-constify/README.md new file mode 100644 index 00000000..4ff98419 --- /dev/null +++ b/fiat-constify/README.md @@ -0,0 +1,59 @@ +# [RustCrypto]: `const fn` postprocessor for `fiat-crypto` + +[![crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +[![Build Status][build-image]][build-link] +[![Safety Dance][safety-image]][safety-link] +![Apache2/MIT licensed][license-image] +![Rust Version][rustc-image] +[![Project Chat][chat-image]][chat-link] + +Postprocessor for [fiat-crypto] generated field implementations which rewrites +them as `const fn`. + +[Documentation][docs-link] + +## About + +This crate is a workaround for [mit-plv/fiat-crypto#1086] which provides a +mechanical postprocessing step for [fiat-crypto] generated field +implementations. + +It removes `&mut` references which aren't yet stable with `const fn`, instead +allocating and returning an array on the stack for results. + +## License + +Licensed under either of: + +- [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) +- [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://buildstats.info/crate/fiat-constify +[crate-link]: https://crates.io/crates/fiat-constify +[docs-image]: https://docs.rs/fiat-constify/badge.svg +[docs-link]: https://docs.rs/fiat-constify/ +[build-image]: https://github.com/RustCrypto/utils/workflows/fiat-constify/badge.svg +[build-link]: https://github.com/RustCrypto/utils/actions/workflows/fiat-constify.yml +[safety-image]: https://img.shields.io/badge/unsafe-forbidden-success.svg +[safety-link]: https://github.com/rust-secure-code/safety-dance/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.56+-blue.svg +[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg +[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils + +[//]: # (links) + +[RustCrypto]: https://github.com/rustcrypto +[fiat-crypto]: https://github.com/mit-plv/fiat-crypto/ +[mit-plv/fiat-crypto#1086]: https://github.com/mit-plv/fiat-crypto/issues/1086 diff --git a/fiat-constify/src/main.rs b/fiat-constify/src/main.rs new file mode 100644 index 00000000..531ff0a4 --- /dev/null +++ b/fiat-constify/src/main.rs @@ -0,0 +1,426 @@ +//! Postprocessor for fiat-crypto generated field implementations which rewrites +//! them as `const fn`. +//! +//! Usage: fiat-constify /path/to/field_impl.rs + +#![allow(clippy::single_match, clippy::new_without_default)] + +use proc_macro2::Span; +use quote::{quote, ToTokens}; +use std::{collections::BTreeMap as Map, env, fs, ops::Deref}; +use syn::{ + punctuated::Punctuated, + token::{Bang, Brace, Bracket, Colon, Const, Eq, Let, Mut, Paren, Pound, RArrow, Semi}, + AttrStyle, Attribute, Block, Expr, ExprAssign, ExprCall, ExprLit, ExprPath, ExprReference, + ExprRepeat, ExprTuple, FnArg, Ident, Item, ItemFn, ItemType, Lit, LitInt, Local, Pat, PatIdent, + PatTuple, PatType, Path, PathArguments, PathSegment, ReturnType, Stmt, Type, TypeArray, + TypePath, TypeReference, TypeTuple, UnOp, +}; + +fn main() -> Result<(), Box> { + let args = env::args().collect::>(); + + if args.len() != 2 { + panic!("Usage: fiat-constify /path/to/field_impl.rs") + } + + let code = fs::read_to_string(&args[1])?; + let mut ast = syn::parse_file(&code)?; + + // Add lint attributes + ast.attrs.push(build_attribute( + "allow", + &[ + "dead_code", + "rustdoc::broken_intra_doc_links", + "unused_assignments", + "unused_mut", + "unused_variables", + ], + )); + + let mut type_registry = TypeRegistry::new(); + + // Iterate over functions, transforming them into `const fn` + for item in &mut ast.items { + match item { + Item::Fn(func) => rewrite_fn_as_const(func, &type_registry), + Item::Type(ty) => type_registry.add(ty), + _ => (), + } + } + + println!("#![doc = \" fiat-crypto output postprocessed by fiat-constify: https://github.com/rustcrypto/utils\"]"); + println!("{}", ast.into_token_stream()); + Ok(()) +} + +/// Build a toplevel attribute with the given name and comma-separated values. +fn build_attribute(name: &str, values: &[&str]) -> Attribute { + let span = Span::call_site(); + let values = values + .iter() + .map(|value| build_path(value)) + .collect::>(); + + Attribute { + pound_token: Pound { spans: [span] }, + style: AttrStyle::Inner(Bang { spans: [span] }), + bracket_token: Bracket { span }, + path: build_path(name), + tokens: quote! { (#(#values),*) }, + } +} + +/// Parse a path from a double-colon-delimited string. +fn build_path(path: &str) -> Path { + let span = Span::call_site(); + let mut segments = Punctuated::new(); + + for segment in path.split("::") { + segments.push(PathSegment { + ident: Ident::new(segment, span), + arguments: PathArguments::None, + }); + } + + Path { + leading_colon: None, + segments, + } +} + +/// Get an `Ident` from a `Pat::Ident`. +fn get_ident_from_pat(pat: &Pat) -> Ident { + match pat { + Pat::Ident(pat_ident) => pat_ident.ident.clone(), + other => panic!("unexpected `Pat`: {:?} (expecting `Pat::Ident`)", other), + } +} + +/// Rewrite a fiat-crypto generated `fn` as a `const fn`, making the necessary +/// transformations to the code in order for it to work in that context. +fn rewrite_fn_as_const(func: &mut ItemFn, type_registry: &TypeRegistry) { + let span = Span::call_site(); + + // Mark function as being `const fn`. + func.sig.constness = Some(Const { span }); + + // Transform mutable arguments into return values. + let mut inputs = Punctuated::new(); + let mut outputs = Outputs::new(); + + for arg in &func.sig.inputs { + // Transform mutable function arguments into return values + if let FnArg::Typed(t) = arg { + match &*t.ty { + Type::Reference(TypeReference { + mutability: Some(_), // look for mutable references + elem, + .. + }) => { + outputs.add(get_ident_from_pat(&t.pat), elem.deref().clone()); + continue; + } + _ => (), + } + } + + // If the argument wasn't a mutable reference, add it as an input. + inputs.push(arg.clone()); + } + + // Replace inputs with ones where the mutable references have been filtered out + func.sig.inputs = inputs; + func.sig.output = outputs.to_return_type(); + func.block = Box::new(rewrite_fn_body(&func.block.stmts, &outputs, type_registry)); +} + +/// Rewrite the function body, adding let bindings with `Default::default()` +/// values for outputs, removing mutable references, and adding a return +/// value/tuple. +fn rewrite_fn_body(statements: &[Stmt], outputs: &Outputs, registry: &TypeRegistry) -> Block { + let span = Span::call_site(); + let mut stmts = Vec::new(); + + stmts.extend(outputs.to_let_bindings(registry).into_iter()); + + for stmt in statements { + let mut stmt = stmt.clone(); + rewrite_fn_stmt(&mut stmt); + stmts.push(stmt.clone()); + } + + stmts.push(outputs.to_return_value()); + + Block { + brace_token: Brace { span }, + stmts, + } +} + +/// Rewrite an expression in the function body, transforming mutable reference +/// operations into value assignments. +fn rewrite_fn_stmt(stmt: &mut Stmt) { + match stmt { + Stmt::Semi(expr, _) => match expr { + Expr::Assign(ExprAssign { left, .. }) => match *left.clone() { + Expr::Unary(unary) => { + // Remove deref since we're removing mutable references + if matches!(unary.op, UnOp::Deref(_)) { + *left = unary.expr; + } + } + _ => (), + }, + Expr::Call(call) => { + *stmt = Stmt::Local(rewrite_fn_call(call.clone())); + } + _ => (), + }, + _ => (), + } +} + +/// Rewrite a function call, removing the mutable reference arguments and +/// let-binding return values for them instead. +fn rewrite_fn_call(mut call: ExprCall) -> Local { + let mut args = Punctuated::new(); + let mut output = Punctuated::new(); + + for arg in &call.args { + if let Expr::Reference(ExprReference { + mutability: Some(_), + expr, + .. + }) = arg + { + match expr.deref() { + Expr::Path(ExprPath { + path: Path { segments, .. }, + .. + }) => { + assert_eq!(segments.len(), 1, "expected only one segment in fn arg"); + let ident = segments.first().unwrap().ident.clone(); + + output.push(Pat::Ident(PatIdent { + attrs: Vec::new(), + by_ref: None, + mutability: None, + ident, + subpat: None, + })); + } + other => panic!("unexpected expr in fn arg: {:?}", other), + } + + continue; + } + + args.push(arg.clone()); + } + + // Overwrite call arguments with the ones that aren't mutable references + call.args = args; + + let span = Span::call_site(); + + let pat = Pat::Tuple(PatTuple { + attrs: Vec::new(), + paren_token: Paren { span }, + elems: output, + }); + + Local { + attrs: Vec::new(), + let_token: Let { span }, + pat, + init: Some((Eq { spans: [span] }, Box::new(Expr::Call(call)))), + semi_token: Semi { spans: [span] }, + } +} + +/// Registry of types defined by the module being processed. +pub struct TypeRegistry(Map); + +impl TypeRegistry { + /// Create a new type registry. + pub fn new() -> Self { + Self(Map::new()) + } + + /// Add a type to the type registry. + pub fn add(&mut self, item_type: &ItemType) { + if self + .0 + .insert(item_type.ident.clone(), item_type.ty.deref().clone()) + .is_some() + { + panic!("duplicate type name: {}", &item_type.ident); + } + } + + /// Get a type from the registry by its ident. + pub fn get(&self, ident: &Ident) -> Option<&Type> { + self.0.get(ident) + } +} + +/// Output values, which in regular `fiat-crypto` are passed as mutable references, e.g.: +/// +/// ``` +/// out1: &mut ..., out2: &mut ... +/// ``` +/// +/// This type stores the outputs and uses them to build the return type +/// (i.e. `Signature::output`), `let mut` bindings in place of the mutable +/// references, and a return value instead of using side effects to write to +/// mutable references. +#[derive(Debug)] +pub struct Outputs(Map); + +impl Outputs { + /// Create new output storage. + pub fn new() -> Self { + Self(Map::new()) + } + + /// Add an output variable with the given name and type. + /// + /// Panics if the name is duplicated. + pub fn add(&mut self, name: Ident, ty: Type) { + if self.0.insert(name.clone(), ty).is_some() { + panic!("duplicate output name: {}", name); + } + } + + /// Generate `let mut outN: Ty = ` bindings at the start + /// of the function. + pub fn to_let_bindings(&self, registry: &TypeRegistry) -> Vec { + let span = Span::call_site(); + + self.0 + .iter() + .map(|(ident, ty)| { + Stmt::Local(Local { + attrs: Vec::new(), + let_token: Let { span }, + pat: Pat::Type(PatType { + attrs: Vec::new(), + pat: Box::new(Pat::Ident(PatIdent { + attrs: Vec::new(), + by_ref: None, + mutability: Some(Mut { span }), + ident: ident.clone(), + subpat: None, + })), + colon_token: Colon { spans: [span] }, + ty: Box::new(ty.clone()), + }), + init: Some((Eq { spans: [span] }, Box::new(default_for(ty, registry)))), + semi_token: Semi { spans: [span] }, + }) + }) + .collect() + } + + /// Finish annotating outputs, updating the provided `Signature`. + pub fn to_return_type(&self) -> ReturnType { + let span = Span::call_site(); + let rarrow = RArrow { + spans: [span, span], + }; + + let ret = match self.0.len() { + 0 => panic!("expected at least one output"), + 1 => self.0.values().next().unwrap().clone(), + _ => { + let mut elems = Punctuated::new(); + + for ty in self.0.values() { + elems.push(ty.clone()); + } + + Type::Tuple(TypeTuple { + paren_token: Paren { span }, + elems, + }) + } + }; + + ReturnType::Type(rarrow, Box::new(ret)) + } + + /// Generate the return value for the statement as a tuple of the outputs. + pub fn to_return_value(&self) -> Stmt { + let span = Span::call_site(); + + let mut elems = self.0.iter().map(|(ident, _)| { + let mut segments = Punctuated::new(); + segments.push(PathSegment { + ident: ident.clone(), + arguments: PathArguments::None, + }); + + let path = Path { + leading_colon: None, + segments, + }; + + Expr::Path(ExprPath { + attrs: Vec::new(), + qself: None, + path, + }) + }); + + if elems.len() == 1 { + Stmt::Expr(elems.next().unwrap()) + } else { + Stmt::Expr(Expr::Tuple(ExprTuple { + attrs: Vec::new(), + paren_token: Paren { span }, + elems: elems.collect(), + })) + } + } +} + +/// Get a default value for the given type. +fn default_for(ty: &Type, registry: &TypeRegistry) -> Expr { + let span = Span::call_site(); + let zero = Expr::Lit(ExprLit { + attrs: Vec::new(), + lit: Lit::Int(LitInt::new("0", span)), + }); + + match ty { + Type::Array(TypeArray { len, .. }) => Expr::Repeat(ExprRepeat { + attrs: Vec::new(), + bracket_token: Bracket { span }, + expr: Box::new(zero), + semi_token: Semi { spans: [span] }, + len: Box::new(len.clone()), + }), + Type::Path(TypePath { path, .. }) => { + assert_eq!( + path.segments.len(), + 1, + "wasn't expecting multiple segments in path" + ); + + let ident = path.segments.first().unwrap().ident.clone(); + + // Attempt to look up type in the registry + if let Some(registry_ty) = registry.get(&ident) { + // If we got a type from the registry, recurse + default_for(registry_ty, registry) + } else if matches!(ident.to_string().as_str(), "u8" | "u32" | "u64") { + zero + } else { + panic!("unsupported type: {:?}", ty) + } + } + _ => panic!("don't know how to build default value for {:?}", ty), + } +} From 855d0cafa00867dbcdf94e9f8a745df8ddbf2620 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 9 Jun 2022 11:25:27 -0600 Subject: [PATCH 014/116] fiat-constify: add clippy allows (#769) Adds `allow` directives for the following: - `clippy::identity_op` - `clippy::unnecessary_cast` --- fiat-constify/src/main.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fiat-constify/src/main.rs b/fiat-constify/src/main.rs index 531ff0a4..fb1bd406 100644 --- a/fiat-constify/src/main.rs +++ b/fiat-constify/src/main.rs @@ -31,6 +31,8 @@ fn main() -> Result<(), Box> { ast.attrs.push(build_attribute( "allow", &[ + "clippy::identity_op", + "clippy::unnecessary_cast", "dead_code", "rustdoc::broken_intra_doc_links", "unused_assignments", From 9270ee927f17a682d59dcbf13d0676b7f0251a51 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 16 Jun 2022 17:10:15 -0600 Subject: [PATCH 015/116] zeroize: formatting fixups (#770) Reorder code in terms of precedence; add whitespace --- zeroize/src/lib.rs | 249 +++++++++++++++++++++++++-------------------- 1 file changed, 139 insertions(+), 110 deletions(-) diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index a8b34b8b..f19abb7d 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -251,56 +251,38 @@ mod aarch64; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod x86; -use core::marker::{PhantomData, PhantomPinned}; -use core::mem::{self, MaybeUninit}; -use core::num::{ - NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, - NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, +use core::{ + marker::{PhantomData, PhantomPinned}, + mem::{self, MaybeUninit}, + num::{ + NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, + NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, + }, + ops, ptr, + slice::IterMut, + sync::atomic, }; -use core::{ops, ptr, slice::IterMut, sync::atomic}; #[cfg(feature = "alloc")] -use alloc::{boxed::Box, string::String, vec::Vec}; +use { + alloc::{boxed::Box, string::String, vec::Vec}, + core::slice, +}; #[cfg(feature = "std")] use std::ffi::CString; -/// Trait for securely erasing types from memory +/// Trait for securely erasing values from memory. pub trait Zeroize { /// Zero out this object from memory using Rust intrinsics which ensure the /// zeroization operation is not "optimized away" by the compiler. fn zeroize(&mut self); } -/// Marker trait signifying that this type will [`zeroize`](Zeroize::zeroize) itself on [`Drop`]. +/// Marker trait signifying that this type will [`Zeroize::zeroize`] itself on [`Drop`]. pub trait ZeroizeOnDrop {} -#[doc(hidden)] -pub mod __internal { - use super::*; - - /// Auto-deref workaround for deriving `ZeroizeOnDrop`. - pub trait AssertZeroizeOnDrop { - fn zeroize_or_on_drop(self); - } - - impl AssertZeroizeOnDrop for &&mut T { - fn zeroize_or_on_drop(self) {} - } - - /// Auto-deref workaround for deriving `ZeroizeOnDrop`. - pub trait AssertZeroize { - fn zeroize_or_on_drop(&mut self); - } - - impl AssertZeroize for T { - fn zeroize_or_on_drop(&mut self) { - self.zeroize() - } - } -} - -/// Marker trait for types whose `Default` is the desired zeroization result +/// Marker trait for types whose [`Default`] is the desired zeroization result pub trait DefaultIsZeroes: Copy + Default + Sized {} impl Zeroize for Z @@ -319,19 +301,24 @@ macro_rules! impl_zeroize_with_default { }; } -impl_zeroize_with_default!(i8, i16, i32, i64, i128, isize); -impl_zeroize_with_default!(u8, u16, u32, u64, u128, usize); -impl_zeroize_with_default!(f32, f64, char, bool); +#[rustfmt::skip] +impl_zeroize_with_default! { + bool, char, + f32, f64, + i8, i16, i32, i64, i128, isize, + u8, u16, u32, u64, u128, usize +} macro_rules! impl_zeroize_for_non_zero { ($($type:ty),+) => { - $(impl Zeroize for $type - { - fn zeroize(&mut self) { - volatile_write(self, unsafe { <$type>::new_unchecked(1) }); - atomic_fence(); + $( + impl Zeroize for $type { + fn zeroize(&mut self) { + volatile_write(self, unsafe { <$type>::new_unchecked(1) }); + atomic_fence(); + } } - })+ + )+ }; } @@ -341,9 +328,7 @@ impl_zeroize_for_non_zero!( NonZeroI32, NonZeroI64, NonZeroI128, - NonZeroIsize -); -impl_zeroize_for_non_zero!( + NonZeroIsize, NonZeroU8, NonZeroU16, NonZeroU32, @@ -352,7 +337,7 @@ impl_zeroize_for_non_zero!( NonZeroUsize ); -/// Implement `Zeroize` on arrays of types that impl `Zeroize` +/// Impl [`Zeroize`] on arrays of types that impl [`Zeroize`]. impl Zeroize for [Z; N] where Z: Zeroize, @@ -361,7 +346,8 @@ where self.iter_mut().zeroize(); } } -/// Implement `ZeroizeOnDrop` on arrays of types that impl `ZeroizeOnDrop` + +/// Impl [`ZeroizeOnDrop`] on arrays of types that impl [`ZeroizeOnDrop`]. impl ZeroizeOnDrop for [Z; N] where Z: ZeroizeOnDrop {} impl<'a, Z> Zeroize for IterMut<'a, Z> @@ -417,16 +403,21 @@ where impl ZeroizeOnDrop for Option where Z: ZeroizeOnDrop {} -/// Impl `Zeroize` on slices of MaybeUninit types +/// Impl [`Zeroize`] on slices of [`MaybeUninit`] types. +/// /// This impl can eventually be optimized using an memset intrinsic, -/// such as `core::intrinsics::volatile_set_memory`. -/// This fills the slice with zeros -/// Note that this ignore invariants that Z might have, because MaybeUninit removes all invariants. +/// such as [`core::intrinsics::volatile_set_memory`]. +/// +/// This fills the slice with zeroes. +/// +/// Note that this ignore invariants that `Z` might have, because +/// [`MaybeUninit`] removes all invariants. impl Zeroize for [MaybeUninit] { fn zeroize(&mut self) { let ptr = self.as_mut_ptr() as *mut MaybeUninit; let size = self.len().checked_mul(mem::size_of::()).unwrap(); - assert!(size <= core::isize::MAX as usize); + assert!(size <= isize::MAX as usize); + // Safety: // // This is safe, because every valid pointer is well aligned for u8 @@ -438,20 +429,21 @@ impl Zeroize for [MaybeUninit] { } } -/// Impl `Zeroize` on slices of types that can be zeroized with `Default`. +/// Impl [`Zeroize`] on slices of types that can be zeroized with [`Default`]. /// /// This impl can eventually be optimized using an memset intrinsic, -/// such as `core::intrinsics::volatile_set_memory`. For that reason the blanket -/// impl on slices is bounded by `DefaultIsZeroes`. +/// such as [`core::intrinsics::volatile_set_memory`]. For that reason the +/// blanket impl on slices is bounded by [`DefaultIsZeroes`]. /// /// To zeroize a mut slice of `Z: Zeroize` which does not impl -/// `DefaultIsZeroes`, call `iter_mut().zeroize()`. +/// [`DefaultIsZeroes`], call `iter_mut().zeroize()`. impl Zeroize for [Z] where Z: DefaultIsZeroes, { fn zeroize(&mut self) { - assert!(self.len() <= core::isize::MAX as usize); + assert!(self.len() <= isize::MAX as usize); + // Safety: // // This is safe, because the slice is well aligned and is backed by a single allocated @@ -463,6 +455,65 @@ where } } +/// [`PhantomData`] is always zero sized so provide a [`Zeroize`] implementation. +impl Zeroize for PhantomData { + fn zeroize(&mut self) {} +} + +/// [`PhantomData` is always zero sized so provide a ZeroizeOnDrop implementation. +impl ZeroizeOnDrop for PhantomData {} + +/// `PhantomPinned` is zero sized so provide a Zeroize implementation. +impl Zeroize for PhantomPinned { + fn zeroize(&mut self) {} +} + +/// `PhantomPinned` is zero sized so provide a ZeroizeOnDrop implementation. +impl ZeroizeOnDrop for PhantomPinned {} + +/// `()` is zero sized so provide a Zeroize implementation. +impl Zeroize for () { + fn zeroize(&mut self) {} +} + +/// `()` is zero sized so provide a ZeroizeOnDrop implementation. +impl ZeroizeOnDrop for () {} + +/// Generic implementation of Zeroize for tuples up to 10 parameters. +impl Zeroize for (A,) { + fn zeroize(&mut self) { + self.0.zeroize(); + } +} + +/// Generic implementation of ZeroizeOnDrop for tuples up to 10 parameters. +impl ZeroizeOnDrop for (A,) {} + +macro_rules! impl_zeroize_tuple { + ( $( $type_name:ident ),+ ) => { + impl<$($type_name: Zeroize),+> Zeroize for ($($type_name),+) { + fn zeroize(&mut self) { + #[allow(non_snake_case)] + let ($($type_name),+) = self; + $($type_name.zeroize());+ + } + } + + impl<$($type_name: ZeroizeOnDrop),+> ZeroizeOnDrop for ($($type_name),+) { } + } +} + +// Generic implementations for tuples up to 10 parameters. +impl_zeroize_tuple!(A, B); +impl_zeroize_tuple!(A, B, C); +impl_zeroize_tuple!(A, B, C, D); +impl_zeroize_tuple!(A, B, C, D, E); +impl_zeroize_tuple!(A, B, C, D, E, F); +impl_zeroize_tuple!(A, B, C, D, E, F, G); +impl_zeroize_tuple!(A, B, C, D, E, F, G, H); +impl_zeroize_tuple!(A, B, C, D, E, F, G, H, I); +impl_zeroize_tuple!(A, B, C, D, E, F, G, H, I, J); + #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl Zeroize for Vec @@ -474,12 +525,12 @@ where /// Ensures the entire capacity of the `Vec` is zeroed. Cannot ensure that /// previous reallocations did not leave values on the heap. fn zeroize(&mut self) { - use core::slice; // Zeroize all the initialized elements. self.iter_mut().zeroize(); // Set the Vec's length to 0 and drop all the elements. self.clear(); + // Zero the full capacity of `Vec`. // Safety: // @@ -490,6 +541,7 @@ where let uninit_slice = unsafe { slice::from_raw_parts_mut(self.as_mut_ptr() as *mut MaybeUninit, self.capacity()) }; + uninit_slice.zeroize(); } } @@ -530,17 +582,20 @@ impl Zeroize for CString { // mem::take uses replace internally to swap the pointer // Unfortunately this results in an allocation for a Box::new(&[0]) as CString must // contain a trailing zero byte - let this = std::mem::take(self); + let this = mem::take(self); + // - CString::into_bytes calls ::into_vec which takes ownership of the heap pointer // as a Vec // - Calling .zeroize() on the resulting vector clears out the bytes // From: https://github.com/RustCrypto/utils/pull/759#issuecomment-1087976570 let mut buf = this.into_bytes(); buf.zeroize(); + // expect() should never fail, because zeroize() truncates the Vec let zeroed = CString::new(buf).expect("buf not truncated"); + // Replace self by the zeroed CString to maintain the original ptr of the buffer - let _ = std::mem::replace(self, zeroed); + let _ = mem::replace(self, zeroed); } } @@ -685,6 +740,7 @@ unsafe fn volatile_set(dst: *mut T, src: T, count: usize) { // allocation pointed to by `dst`, because `count <= isize::MAX` and because // `dst.add(count)` must not wrap around the address space. let ptr = dst.add(i); + // Safety: // // This is safe, because the pointer is valid and because `dst` is well aligned for `T` and @@ -693,56 +749,31 @@ unsafe fn volatile_set(dst: *mut T, src: T, count: usize) { } } -/// `PhantomData` is always zero sized so provide a Zeroize implementation. -impl Zeroize for PhantomData { - fn zeroize(&mut self) {} -} -/// `PhantomData` is always zero sized so provide a ZeroizeOnDrop implementation. -impl ZeroizeOnDrop for PhantomData {} -/// `PhantomPinned` is zero sized so provide a Zeroize implementation. -impl Zeroize for PhantomPinned { - fn zeroize(&mut self) {} -} -/// `PhantomPinned` is zero sized so provide a ZeroizeOnDrop implementation. -impl ZeroizeOnDrop for PhantomPinned {} -/// `()` is zero sized so provide a Zeroize implementation. -impl Zeroize for () { - fn zeroize(&mut self) {} -} -/// `()` is zero sized so provide a ZeroizeOnDrop implementation. -impl ZeroizeOnDrop for () {} +/// Internal module used as support for `AssertZeroizeOnDrop`. +#[doc(hidden)] +pub mod __internal { + use super::*; -/// Generic implementation of Zeroize for tuples up to 10 parameters. -impl Zeroize for (A,) { - fn zeroize(&mut self) { - self.0.zeroize(); + /// Auto-deref workaround for deriving `ZeroizeOnDrop`. + pub trait AssertZeroizeOnDrop { + fn zeroize_or_on_drop(self); } -} -/// Generic implementation of ZeroizeOnDrop for tuples up to 10 parameters. -impl ZeroizeOnDrop for (A,) {} -macro_rules! impl_zeroize_tuple { - ( $( $type_name:ident )+ ) => { - impl<$($type_name: Zeroize),+> Zeroize for ($($type_name),+) { - fn zeroize(&mut self) { - #[allow(non_snake_case)] - let ($($type_name),+) = self; - $($type_name.zeroize());+ - } - } - impl<$($type_name: ZeroizeOnDrop),+> ZeroizeOnDrop for ($($type_name),+) { } + impl AssertZeroizeOnDrop for &&mut T { + fn zeroize_or_on_drop(self) {} + } + + /// Auto-deref workaround for deriving `ZeroizeOnDrop`. + pub trait AssertZeroize { + fn zeroize_or_on_drop(&mut self); + } + + impl AssertZeroize for T { + fn zeroize_or_on_drop(&mut self) { + self.zeroize() + } } } -// Generic implementations for tuples up to 10 parameters. -impl_zeroize_tuple! { A B } -impl_zeroize_tuple! { A B C } -impl_zeroize_tuple! { A B C D } -impl_zeroize_tuple! { A B C D E } -impl_zeroize_tuple! { A B C D E F } -impl_zeroize_tuple! { A B C D E F G } -impl_zeroize_tuple! { A B C D E F G H } -impl_zeroize_tuple! { A B C D E F G H I } -impl_zeroize_tuple! { A B C D E F G H I L } #[cfg(test)] mod tests { @@ -784,9 +815,7 @@ mod tests { NonZeroI32, NonZeroI64, NonZeroI128, - NonZeroIsize - ); - non_zero_test!( + NonZeroIsize, NonZeroU8, NonZeroU16, NonZeroU32, From 4d0c62e53071003cbf4efa0fec05da5ffbe8b18e Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 16 Jun 2022 17:32:46 -0600 Subject: [PATCH 016/116] zeroize: factor integration tests into `tests/` (#771) --- zeroize/src/lib.rs | 214 --------------------------------------- zeroize/tests/zeroize.rs | 208 +++++++++++++++++++++++++++++++++++++ 2 files changed, 208 insertions(+), 214 deletions(-) create mode 100644 zeroize/tests/zeroize.rs diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index f19abb7d..d27ec41c 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -236,7 +236,6 @@ //! [`Ordering::SeqCst`]: core::sync::atomic::Ordering::SeqCst #[cfg(feature = "alloc")] -#[cfg_attr(test, macro_use)] extern crate alloc; #[cfg(feature = "std")] @@ -774,216 +773,3 @@ pub mod __internal { } } } - -#[cfg(test)] -mod tests { - use super::*; - - use core::mem::size_of; - - #[cfg(feature = "alloc")] - use alloc::boxed::Box; - - #[cfg(feature = "alloc")] - use alloc::vec::Vec; - - #[cfg(feature = "std")] - use std::ffi::CString; - - #[derive(Clone, Debug, PartialEq)] - struct ZeroizedOnDrop(u64); - - impl Drop for ZeroizedOnDrop { - fn drop(&mut self) { - self.0.zeroize(); - } - } - - #[test] - fn non_zero() { - macro_rules! non_zero_test { - ($($type:ty),+) => { - $(let mut value = <$type>::new(42).unwrap(); - value.zeroize(); - assert_eq!(value.get(), 1);)+ - }; - } - - non_zero_test!( - NonZeroI8, - NonZeroI16, - NonZeroI32, - NonZeroI64, - NonZeroI128, - NonZeroIsize, - NonZeroU8, - NonZeroU16, - NonZeroU32, - NonZeroU64, - NonZeroU128, - NonZeroUsize - ); - } - - #[test] - fn zeroize_byte_arrays() { - let mut arr = [42u8; 137]; - arr.zeroize(); - assert_eq!(arr.as_ref(), [0u8; 137].as_ref()); - } - - #[test] - fn zeroize_on_drop_byte_arrays() { - let mut arr = [ZeroizedOnDrop(42); 1]; - unsafe { core::ptr::drop_in_place(&mut arr) }; - assert_eq!(arr.as_ref(), [ZeroizedOnDrop(0); 1].as_ref()); - } - - #[test] - fn zeroize_maybeuninit_byte_arrays() { - let mut arr = [MaybeUninit::new(42u64); 64]; - arr.zeroize(); - let arr_init: [u64; 64] = unsafe { core::mem::transmute(arr) }; - assert_eq!(arr_init, [0u64; 64]); - } - - #[test] - fn zeroize_check_zerosize_types() { - // Since we assume these types have zero size, we test this holds for - // the current version of Rust. - assert_eq!(size_of::<()>(), 0); - assert_eq!(size_of::(), 0); - assert_eq!(size_of::>(), 0); - } - - #[test] - fn zeroize_check_tuple() { - let mut tup1 = (42u8,); - tup1.zeroize(); - assert_eq!(tup1, (0u8,)); - - let mut tup2 = (42u8, 42u8); - tup2.zeroize(); - assert_eq!(tup2, (0u8, 0u8)); - } - - #[test] - fn zeroize_on_drop_check_tuple() { - let mut tup1 = (ZeroizedOnDrop(42),); - unsafe { core::ptr::drop_in_place(&mut tup1) }; - assert_eq!(tup1, (ZeroizedOnDrop(0),)); - - let mut tup2 = (ZeroizedOnDrop(42), ZeroizedOnDrop(42)); - unsafe { core::ptr::drop_in_place(&mut tup2) }; - assert_eq!(tup2, (ZeroizedOnDrop(0), ZeroizedOnDrop(0))); - } - - #[cfg(feature = "alloc")] - #[test] - fn zeroize_vec() { - let mut vec = vec![42; 3]; - vec.zeroize(); - assert!(vec.is_empty()); - } - - #[cfg(feature = "alloc")] - #[test] - fn zeroize_vec_entire_capacity() { - #[derive(Clone)] - struct PanicOnNonZeroDrop(u64); - - impl Zeroize for PanicOnNonZeroDrop { - fn zeroize(&mut self) { - self.0 = 0; - } - } - - impl Drop for PanicOnNonZeroDrop { - fn drop(&mut self) { - if self.0 != 0 { - panic!("dropped non-zeroized data"); - } - } - } - - // Ensure that the entire capacity of the vec is zeroized and that no unitinialized data - // is ever interpreted as initialized - let mut vec = vec![PanicOnNonZeroDrop(42); 2]; - - unsafe { - vec.set_len(1); - } - - vec.zeroize(); - - unsafe { - vec.set_len(2); - } - - drop(vec); - } - - #[cfg(feature = "alloc")] - #[test] - fn zeroize_string() { - let mut string = String::from("Hello, world!"); - string.zeroize(); - assert!(string.is_empty()); - } - - #[cfg(feature = "alloc")] - #[test] - fn zeroize_string_entire_capacity() { - let mut string = String::from("Hello, world!"); - string.truncate(5); - - string.zeroize(); - - // convert the string to a vec to easily access the unused capacity - let mut as_vec = string.into_bytes(); - unsafe { as_vec.set_len(as_vec.capacity()) }; - - assert!(as_vec.iter().all(|byte| *byte == 0)); - } - - #[cfg(feature = "std")] - #[test] - fn zeroize_c_string() { - let mut cstring = CString::new("Hello, world!").expect("CString::new failed"); - let orig_len = cstring.as_bytes().len(); - let orig_ptr = cstring.as_bytes().as_ptr(); - cstring.zeroize(); - // This doesn't quite test that the original memory has been cleared, but only that - // cstring now owns an empty buffer - assert!(cstring.as_bytes().is_empty()); - for i in 0..orig_len { - unsafe { - // Using a simple deref, only one iteration of the loop is performed - // presumably because after zeroize, the internal buffer has a length of one/ - // `read_volatile` seems to "fix" this - // Note that this is very likely UB - assert_eq!(orig_ptr.add(i).read_volatile(), 0); - } - } - } - - #[cfg(feature = "alloc")] - #[test] - fn zeroize_box() { - let mut boxed_arr = Box::new([42u8; 3]); - boxed_arr.zeroize(); - assert_eq!(boxed_arr.as_ref(), &[0u8; 3]); - } - - #[cfg(feature = "alloc")] - #[test] - fn asref() { - let mut buffer: Zeroizing> = Default::default(); - let _asmut: &mut [u8] = buffer.as_mut(); - let _asref: &[u8] = buffer.as_ref(); - - let mut buffer: Zeroizing> = Default::default(); - let _asmut: &mut [u8] = buffer.as_mut(); - let _asref: &[u8] = buffer.as_ref(); - } -} diff --git a/zeroize/tests/zeroize.rs b/zeroize/tests/zeroize.rs new file mode 100644 index 00000000..b59eabcc --- /dev/null +++ b/zeroize/tests/zeroize.rs @@ -0,0 +1,208 @@ +//! zeroize integration tests. + +use std::{ + marker::{PhantomData, PhantomPinned}, + mem::{size_of, MaybeUninit}, + num::*, +}; +use zeroize::*; + +#[cfg(feature = "std")] +use std::ffi::CString; + +#[derive(Clone, Debug, PartialEq)] +struct ZeroizedOnDrop(u64); + +impl Drop for ZeroizedOnDrop { + fn drop(&mut self) { + self.0.zeroize(); + } +} + +#[test] +fn non_zero() { + macro_rules! non_zero_test { + ($($type:ty),+) => { + $(let mut value = <$type>::new(42).unwrap(); + value.zeroize(); + assert_eq!(value.get(), 1);)+ + }; + } + + non_zero_test!( + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroIsize, + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, + NonZeroUsize + ); +} + +#[test] +fn zeroize_byte_arrays() { + let mut arr = [42u8; 137]; + arr.zeroize(); + assert_eq!(arr.as_ref(), [0u8; 137].as_ref()); +} + +#[test] +fn zeroize_on_drop_byte_arrays() { + let mut arr = [ZeroizedOnDrop(42); 1]; + unsafe { core::ptr::drop_in_place(&mut arr) }; + assert_eq!(arr.as_ref(), [ZeroizedOnDrop(0); 1].as_ref()); +} + +#[test] +fn zeroize_maybeuninit_byte_arrays() { + let mut arr = [MaybeUninit::new(42u64); 64]; + arr.zeroize(); + let arr_init: [u64; 64] = unsafe { core::mem::transmute(arr) }; + assert_eq!(arr_init, [0u64; 64]); +} + +#[test] +fn zeroize_check_zerosize_types() { + // Since we assume these types have zero size, we test this holds for + // the current version of Rust. + assert_eq!(size_of::<()>(), 0); + assert_eq!(size_of::(), 0); + assert_eq!(size_of::>(), 0); +} + +#[test] +fn zeroize_check_tuple() { + let mut tup1 = (42u8,); + tup1.zeroize(); + assert_eq!(tup1, (0u8,)); + + let mut tup2 = (42u8, 42u8); + tup2.zeroize(); + assert_eq!(tup2, (0u8, 0u8)); +} + +#[test] +fn zeroize_on_drop_check_tuple() { + let mut tup1 = (ZeroizedOnDrop(42),); + unsafe { core::ptr::drop_in_place(&mut tup1) }; + assert_eq!(tup1, (ZeroizedOnDrop(0),)); + + let mut tup2 = (ZeroizedOnDrop(42), ZeroizedOnDrop(42)); + unsafe { core::ptr::drop_in_place(&mut tup2) }; + assert_eq!(tup2, (ZeroizedOnDrop(0), ZeroizedOnDrop(0))); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_vec() { + let mut vec = vec![42; 3]; + vec.zeroize(); + assert!(vec.is_empty()); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_vec_entire_capacity() { + #[derive(Clone)] + struct PanicOnNonZeroDrop(u64); + + impl Zeroize for PanicOnNonZeroDrop { + fn zeroize(&mut self) { + self.0 = 0; + } + } + + impl Drop for PanicOnNonZeroDrop { + fn drop(&mut self) { + if self.0 != 0 { + panic!("dropped non-zeroized data"); + } + } + } + + // Ensure that the entire capacity of the vec is zeroized and that no unitinialized data + // is ever interpreted as initialized + let mut vec = vec![PanicOnNonZeroDrop(42); 2]; + + unsafe { + vec.set_len(1); + } + + vec.zeroize(); + + unsafe { + vec.set_len(2); + } + + drop(vec); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_string() { + let mut string = String::from("Hello, world!"); + string.zeroize(); + assert!(string.is_empty()); +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_string_entire_capacity() { + let mut string = String::from("Hello, world!"); + string.truncate(5); + + string.zeroize(); + + // convert the string to a vec to easily access the unused capacity + let mut as_vec = string.into_bytes(); + unsafe { as_vec.set_len(as_vec.capacity()) }; + + assert!(as_vec.iter().all(|byte| *byte == 0)); +} + +#[cfg(feature = "std")] +#[test] +fn zeroize_c_string() { + let mut cstring = CString::new("Hello, world!").expect("CString::new failed"); + let orig_len = cstring.as_bytes().len(); + let orig_ptr = cstring.as_bytes().as_ptr(); + cstring.zeroize(); + // This doesn't quite test that the original memory has been cleared, but only that + // cstring now owns an empty buffer + assert!(cstring.as_bytes().is_empty()); + for i in 0..orig_len { + unsafe { + // Using a simple deref, only one iteration of the loop is performed + // presumably because after zeroize, the internal buffer has a length of one/ + // `read_volatile` seems to "fix" this + // Note that this is very likely UB + assert_eq!(orig_ptr.add(i).read_volatile(), 0); + } + } +} + +#[cfg(feature = "alloc")] +#[test] +fn zeroize_box() { + let mut boxed_arr = Box::new([42u8; 3]); + boxed_arr.zeroize(); + assert_eq!(boxed_arr.as_ref(), &[0u8; 3]); +} + +#[cfg(feature = "alloc")] +#[test] +fn asref() { + let mut buffer: Zeroizing> = Default::default(); + let _asmut: &mut [u8] = buffer.as_mut(); + let _asref: &[u8] = buffer.as_ref(); + + let mut buffer: Zeroizing> = Default::default(); + let _asmut: &mut [u8] = buffer.as_mut(); + let _asref: &[u8] = buffer.as_ref(); +} From fdad462f2b3a78f5751e91cdd3ee3698fd28dc39 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 16 Jun 2022 17:46:52 -0600 Subject: [PATCH 017/116] zeroize: add `#[inline(always)]` annotations (#772) --- zeroize/src/lib.rs | 42 +++++++++++++++++++++++++----------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index d27ec41c..a0132094 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -284,6 +284,19 @@ pub trait ZeroizeOnDrop {} /// Marker trait for types whose [`Default`] is the desired zeroization result pub trait DefaultIsZeroes: Copy + Default + Sized {} +/// Fallible trait for representing cases where zeroization may or may not be +/// possible. +/// +/// This is primarily useful for scenarios like reference counted data, where +/// zeroization is only possible when the last reference is dropped. +pub trait TryZeroize { + /// Try to zero out this object from memory using Rust intrinsics which + /// ensure the zeroization operation is not "optimized away" by the + /// compiler. + #[must_use] + fn try_zeroize(&mut self) -> bool; +} + impl Zeroize for Z where Z: DefaultIsZeroes, @@ -598,19 +611,6 @@ impl Zeroize for CString { } } -/// Fallible trait for representing cases where zeroization may or may not be -/// possible. -/// -/// This is primarily useful for scenarios like reference counted data, where -/// zeroization is only possible when the last reference is dropped. -pub trait TryZeroize { - /// Try to zero out this object from memory using Rust intrinsics which - /// ensure the zeroization operation is not "optimized away" by the - /// compiler. - #[must_use] - fn try_zeroize(&mut self) -> bool; -} - /// `Zeroizing` is a a wrapper for any `Z: Zeroize` type which implements a /// `Drop` handler which zeroizes dropped values. #[derive(Debug, Default, Eq, PartialEq)] @@ -622,16 +622,19 @@ where { /// Move value inside a `Zeroizing` wrapper which ensures it will be /// zeroized when it's dropped. + #[inline(always)] pub fn new(value: Z) -> Self { - value.into() + Self(value) } } impl Clone for Zeroizing { + #[inline(always)] fn clone(&self) -> Self { Self(self.0.clone()) } + #[inline(always)] fn clone_from(&mut self, source: &Self) { self.0.zeroize(); self.0.clone_from(&source.0); @@ -642,6 +645,7 @@ impl From for Zeroizing where Z: Zeroize, { + #[inline(always)] fn from(value: Z) -> Zeroizing { Zeroizing(value) } @@ -653,6 +657,7 @@ where { type Target = Z; + #[inline(always)] fn deref(&self) -> &Z { &self.0 } @@ -662,6 +667,7 @@ impl ops::DerefMut for Zeroizing where Z: Zeroize, { + #[inline(always)] fn deref_mut(&mut self) -> &mut Z { &mut self.0 } @@ -672,6 +678,7 @@ where T: ?Sized, Z: AsRef + Zeroize, { + #[inline(always)] fn as_ref(&self) -> &T { self.0.as_ref() } @@ -682,6 +689,7 @@ where T: ?Sized, Z: AsMut + Zeroize, { + #[inline(always)] fn as_mut(&mut self) -> &mut T { self.0.as_mut() } @@ -710,13 +718,13 @@ where /// Use fences to prevent accesses from being reordered before this /// point, which should hopefully help ensure that all accessors /// see zeroes after this point. -#[inline] +#[inline(always)] fn atomic_fence() { atomic::compiler_fence(atomic::Ordering::SeqCst); } /// Perform a volatile write to the destination -#[inline] +#[inline(always)] fn volatile_write(dst: &mut T, src: T) { unsafe { ptr::write_volatile(dst, src) } } @@ -729,7 +737,7 @@ fn volatile_write(dst: &mut T, src: T) { /// `count` must not be larger than an `isize`. /// `dst` being offset by `mem::size_of:: * count` bytes must not wrap around the address space. /// Also `dst` must be properly aligned. -#[inline] +#[inline(always)] unsafe fn volatile_set(dst: *mut T, src: T, count: usize) { // TODO(tarcieri): use `volatile_set_memory` when stabilized for i in 0..count { From a511710067eecfcebf5adaf1217b4796fb06006b Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 21 Jun 2022 11:46:48 -0600 Subject: [PATCH 018/116] zeroize: add CI for 32-bit environments (#775) Uses a 32-bit Linux target --- .github/workflows/zeroize.yml | 47 ++++++++++++++++++++++++++++------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index c67bf1e7..5fde9b51 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -50,24 +50,53 @@ jobs: test: strategy: matrix: - platform: - - ubuntu-latest - - macos-latest - - windows-latest - toolchain: - - 1.51.0 # MSRV - - stable + include: + # 32-bit Linux + - target: i686-unknown-linux-gnu + platform: ubuntu-latest + rust: 1.51.0 # MSRV + deps: sudo apt update && sudo apt install gcc-multilib + - target: i686-unknown-linux-gnu + platform: ubuntu-latest + rust: stable + deps: sudo apt update && sudo apt install gcc-multilib + + # 64-bit Linux + - target: x86_64-unknown-linux-gnu + platform: ubuntu-latest + rust: 1.51.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.51.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.51.0 # MSRV + - target: x86_64-pc-windows-msvc + platform: windows-latest + rust: stable runs-on: ${{ matrix.platform }} steps: - uses: actions/checkout@v2 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: - toolchain: ${{ matrix.toolchain }} - override: true + toolchain: ${{ matrix.rust }} + target: ${{ matrix.target }} profile: minimal + override: true # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml + - run: ${{ matrix.deps }} - run: cargo test - run: cargo test --features alloc,derive,std From cee7946fd766ce57cfa8a1467139c254edba5078 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 29 Jun 2022 13:26:59 -0600 Subject: [PATCH 019/116] zeroize: add `#[ignore]` to flaky CString test (#776) This test relies on UB and is flaking out in certain cases: https://github.com/RustCrypto/utils/issues/774 It's unclear if the test failure indicates a genuine bug in the implementation, or is the result of a test with UB. However, in the meantime it shouldn't block users who would just like the test suite to run reliably. --- zeroize/tests/zeroize.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/zeroize/tests/zeroize.rs b/zeroize/tests/zeroize.rs index b59eabcc..32281c1c 100644 --- a/zeroize/tests/zeroize.rs +++ b/zeroize/tests/zeroize.rs @@ -166,7 +166,9 @@ fn zeroize_string_entire_capacity() { assert!(as_vec.iter().all(|byte| *byte == 0)); } +// TODO(tarcieri): debug flaky test (with potential UB?) See: RustCrypto/utils#774 #[cfg(feature = "std")] +#[ignore] #[test] fn zeroize_c_string() { let mut cstring = CString::new("Hello, world!").expect("CString::new failed"); From d9dedc6cff63fd5d132d03f3500e0dd6258fd67f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jun 2022 13:34:16 -0600 Subject: [PATCH 020/116] build(deps): bump proc-macro2 from 1.0.39 to 1.0.40 (#773) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.39 to 1.0.40. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.39...1.0.40) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dd7f1cd4..a51c8bba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,9 +107,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" dependencies = [ "unicode-ident", ] From 846ae596590941ee87844b54cff8bfbaf3f6bc42 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 29 Jun 2022 13:54:10 -0600 Subject: [PATCH 021/116] zeroize v1.5.6 (#777) --- Cargo.lock | 2 +- zeroize/CHANGELOG.md | 12 ++++++++++++ zeroize/Cargo.toml | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a51c8bba..38f8f783 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -219,7 +219,7 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.5" +version = "1.5.6" dependencies = [ "zeroize_derive", ] diff --git a/zeroize/CHANGELOG.md b/zeroize/CHANGELOG.md index 50acf39d..e98d2bcc 100644 --- a/zeroize/CHANGELOG.md +++ b/zeroize/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.5.6 (2022-06-29) +### Added +- `#[inline(always)]` annotations ([#772]) +- `#[ignore]` attribute on flaky CString test ([#776]) + +### Changed +- Factor integration tests into `tests/` ([#771]) + +[#771]: https://github.com/RustCrypto/utils/pull/771 +[#772]: https://github.com/RustCrypto/utils/pull/772 +[#776]: https://github.com/RustCrypto/utils/pull/776 + ## 1.5.5 (2022-04-30) ### Added - Impl `Zeroize` for std::ffi::CString ([#759]) diff --git a/zeroize/Cargo.toml b/zeroize/Cargo.toml index b7f0be23..71a32137 100644 --- a/zeroize/Cargo.toml +++ b/zeroize/Cargo.toml @@ -7,7 +7,7 @@ operation will not be 'optimized away' by the compiler. Uses a portable pure Rust implementation that works everywhere, even WASM! """ -version = "1.5.5" +version = "1.5.6" authors = ["The RustCrypto Project Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/zeroize" From f096d5f1bb3a59dcb0a7f37290d7c38eb9786a75 Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Wed, 20 Jul 2022 10:08:43 -0400 Subject: [PATCH 022/116] feat: add serde support (#780) This (optional) feature implements Serialize/Deserialize for Zeroizing when the inner type implements these traits. This makes it possible to use Zeroizing in serde contexts. Signed-off-by: Nathaniel McCallum --- Cargo.lock | 1 + zeroize/Cargo.toml | 1 + zeroize/src/lib.rs | 28 ++++++++++++++++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 38f8f783..18d67366 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -221,6 +221,7 @@ dependencies = [ name = "zeroize" version = "1.5.6" dependencies = [ + "serde", "zeroize_derive", ] diff --git a/zeroize/Cargo.toml b/zeroize/Cargo.toml index 71a32137..4eec8179 100644 --- a/zeroize/Cargo.toml +++ b/zeroize/Cargo.toml @@ -17,6 +17,7 @@ keywords = ["memory", "memset", "secure", "volatile", "zero"] edition = "2018" [dependencies] +serde = { version = "1.0", default-features = false, optional = true } zeroize_derive = { version = "1.3", path = "derive", optional = true } [features] diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index a0132094..5ee0f2c9 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -715,6 +715,34 @@ where } } +#[cfg(feature = "serde")] +impl serde::Serialize for Zeroizing +where + Z: Zeroize + serde::Serialize, +{ + #[inline(always)] + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.serialize(serializer) + } +} + +#[cfg(feature = "serde")] +impl<'de, Z> serde::Deserialize<'de> for Zeroizing +where + Z: Zeroize + serde::Deserialize<'de>, +{ + #[inline(always)] + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + Ok(Self(Z::deserialize(deserializer)?)) + } +} + /// Use fences to prevent accesses from being reordered before this /// point, which should hopefully help ensure that all accessors /// see zeroes after this point. From f4baab74f887dc38d27496ea7f989830b06f7a84 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 20 Jul 2022 15:58:04 -0600 Subject: [PATCH 023/116] zeroize v1.5.7 (#782) --- Cargo.lock | 2 +- zeroize/CHANGELOG.md | 6 ++++++ zeroize/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18d67366..4c7ea884 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -219,7 +219,7 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.6" +version = "1.5.7" dependencies = [ "serde", "zeroize_derive", diff --git a/zeroize/CHANGELOG.md b/zeroize/CHANGELOG.md index e98d2bcc..83f89587 100644 --- a/zeroize/CHANGELOG.md +++ b/zeroize/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.5.7 (2022-07-20) +### Added +- Optional `serde` support ([#780]) + +[#780]: https://github.com/RustCrypto/utils/pull/780 + ## 1.5.6 (2022-06-29) ### Added - `#[inline(always)]` annotations ([#772]) diff --git a/zeroize/Cargo.toml b/zeroize/Cargo.toml index 4eec8179..3efc8f4f 100644 --- a/zeroize/Cargo.toml +++ b/zeroize/Cargo.toml @@ -7,7 +7,7 @@ operation will not be 'optimized away' by the compiler. Uses a portable pure Rust implementation that works everywhere, even WASM! """ -version = "1.5.6" +version = "1.5.7" authors = ["The RustCrypto Project Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/zeroize" From 2b4de619a35676693ea67b10044130161c41b202 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Jul 2022 22:29:48 -0600 Subject: [PATCH 024/116] build(deps): bump proc-macro2 from 1.0.40 to 1.0.42 (#783) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.40 to 1.0.42. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.40...1.0.42) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4c7ea884..d40503ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,9 +107,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b" dependencies = [ "unicode-ident", ] From 7a083ff3d25685d6e6429e8b4a0593c648c8e996 Mon Sep 17 00:00:00 2001 From: Daniel Cogan Date: Mon, 1 Aug 2022 20:12:44 -0400 Subject: [PATCH 025/116] update libc deps to 0.2.95 (#789) --- cpufeatures/Cargo.toml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index fa590c68..31b328c8 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -15,10 +15,10 @@ edition = "2018" readme = "README.md" [target.aarch64-apple-darwin.dependencies] -libc = "0.2.68" +libc = "0.2.95" [target.'cfg(all(target_arch = "aarch64", target_os = "linux"))'.dependencies] -libc = "0.2.68" +libc = "0.2.95" [target.aarch64-linux-android.dependencies] -libc = "0.2.68" +libc = "0.2.95" From 81536ee278943c128c033813227c3bd57639e20a Mon Sep 17 00:00:00 2001 From: daxpedda Date: Thu, 4 Aug 2022 00:50:19 +0200 Subject: [PATCH 026/116] Fix deriving `ZeroizeOnDrop` on items with generics (#787) --- zeroize/derive/src/lib.rs | 2 +- zeroize/tests/zeroize_derive.rs | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/zeroize/derive/src/lib.rs b/zeroize/derive/src/lib.rs index 1efc3b4d..baf69901 100644 --- a/zeroize/derive/src/lib.rs +++ b/zeroize/derive/src/lib.rs @@ -71,7 +71,7 @@ fn derive_zeroize(mut s: synstructure::Structure<'_>) -> TokenStream { fn derive_zeroize_on_drop(mut s: synstructure::Structure<'_>) -> TokenStream { let zeroizers = generate_fields(&mut s, quote! { zeroize_or_on_drop }); - let drop_impl = s.gen_impl(quote! { + let drop_impl = s.add_bounds(AddBounds::None).gen_impl(quote! { gen impl Drop for @Self { fn drop(&mut self) { use zeroize::__internal::AssertZeroize; diff --git a/zeroize/tests/zeroize_derive.rs b/zeroize/tests/zeroize_derive.rs index 4e0fdc61..96c10c32 100644 --- a/zeroize/tests/zeroize_derive.rs +++ b/zeroize/tests/zeroize_derive.rs @@ -315,3 +315,13 @@ fn derive_deref() { } assert_eq!(&value.0 .0, &[0, 0, 0]) } + +#[test] +#[cfg(feature = "alloc")] +fn derive_zeroize_on_drop_generic() { + #[derive(ZeroizeOnDrop)] + struct Y(Box); + + #[derive(ZeroizeOnDrop)] + struct Z(Vec); +} From 8e74aa5b4bd2d1f7c3428649b7c9578592f10f0b Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Mon, 8 Aug 2022 05:25:32 -0700 Subject: [PATCH 027/116] cpufeatures: Disable all target features under miri (#779) Miri is an interpreter, and though it tries to emulate the target CPU it does not support any target features. --- cpufeatures/src/lib.rs | 5 +++++ cpufeatures/src/miri.rs | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 cpufeatures/src/miri.rs diff --git a/cpufeatures/src/lib.rs b/cpufeatures/src/lib.rs index 08b6e528..b6c7c10b 100644 --- a/cpufeatures/src/lib.rs +++ b/cpufeatures/src/lib.rs @@ -59,13 +59,18 @@ html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] +#[cfg(not(miri))] #[cfg(all(target_arch = "aarch64"))] #[doc(hidden)] pub mod aarch64; +#[cfg(not(miri))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod x86; +#[cfg(miri)] +mod miri; + #[cfg(not(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")))] compile_error!("This crate works only on `aarch64`, `x86`, and `x86-64` targets."); diff --git a/cpufeatures/src/miri.rs b/cpufeatures/src/miri.rs new file mode 100644 index 00000000..8dff21c1 --- /dev/null +++ b/cpufeatures/src/miri.rs @@ -0,0 +1,20 @@ +//! Minimal miri support. +//! +//! Miri is an interpreter, and though it tries to emulate the target CPU +//! it does not support any target features. + +#[macro_export] +#[doc(hidden)] +macro_rules! __unless_target_features { + ($($tf:tt),+ => $body:expr ) => { + false + }; +} + +#[macro_export] +#[doc(hidden)] +macro_rules! __detect_target_features { + ($($tf:tt),+) => { + false + }; +} From b637d94b473f20e9bda837767fe90f5fd8f2866f Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 18 Aug 2022 09:57:46 +0000 Subject: [PATCH 028/116] cpufeatures: check AVX availability when detecting AVX2 and FMA (#792) --- Cargo.lock | 2 +- cpufeatures/CHANGELOG.md | 10 ++++++++++ cpufeatures/Cargo.toml | 2 +- cpufeatures/src/x86.rs | 17 +++++++++++++---- 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d40503ef..55dca974 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,7 +33,7 @@ version = "0.0.2" [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.3" dependencies = [ "libc", ] diff --git a/cpufeatures/CHANGELOG.md b/cpufeatures/CHANGELOG.md index e2961e71..2a401c6b 100644 --- a/cpufeatures/CHANGELOG.md +++ b/cpufeatures/CHANGELOG.md @@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.3 (2022-08-18) +### Changed +- Update `libc` version to v0.2.95 ([#789]) +- Disable all target features under MIRI ([#779]) +- Check AVX availability when detecting AVX2 and FMA ([#792]) + +[#779]: https://github.com/RustCrypto/utils/pull/779 +[#789]: https://github.com/RustCrypto/utils/pull/789 +[#792]: https://github.com/RustCrypto/utils/pull/792 + ## 0.2.2 (2022-03-18) ### Added - Support for Android on `aarch64` ([#752]) diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index 31b328c8..3bd70f0b 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cpufeatures" -version = "0.2.2" +version = "0.2.3" description = """ Lightweight runtime CPU feature detection for x86/x86_64 and aarch64 with no_std support and support for mobile targets including Android and iOS diff --git a/cpufeatures/src/x86.rs b/cpufeatures/src/x86.rs index 37e20ef6..e21131bf 100644 --- a/cpufeatures/src/x86.rs +++ b/cpufeatures/src/x86.rs @@ -46,17 +46,26 @@ macro_rules! __detect_target_features { } macro_rules! __expand_check_macro { - ($(($name:tt, $i:expr, $reg:ident, $offset:expr)),* $(,)?) => { + ($(($name:tt $(, $i:expr, $reg:ident, $offset:expr)*)),* $(,)?) => { #[macro_export] #[doc(hidden)] macro_rules! check { $( - ($cr:expr, $name) => { ($cr[$i].$reg & (1 << $offset) != 0) }; + ($cr:expr, $name) => { + true + $( + & ($cr[$i].$reg & (1 << $offset) != 0) + )* + }; )* } }; } +// Note that according to the [Intel manual][0] AVX2 and FMA require +// that we check availability of AVX before using them. +// +// [0]: https://www.intel.com/content/dam/develop/external/us/en/documents/36945 __expand_check_macro! { ("mmx", 0, edx, 23), ("sse", 0, edx, 25), @@ -64,7 +73,7 @@ __expand_check_macro! { ("sse3", 0, ecx, 0), ("pclmulqdq", 0, ecx, 1), ("ssse3", 0, ecx, 9), - ("fma", 0, ecx, 12), + ("fma", 0, ecx, 28, 0, ecx, 12), ("sse4.1", 0, ecx, 19), ("sse4.2", 0, ecx, 20), ("popcnt", 0, ecx, 23), @@ -73,7 +82,7 @@ __expand_check_macro! { ("rdrand", 0, ecx, 30), ("sgx", 1, ebx, 2), ("bmi1", 1, ebx, 3), - ("avx2", 1, ebx, 5), + ("avx2", 0, ecx, 28, 1, ebx, 5), ("bmi2", 1, ebx, 8), ("rdseed", 1, ebx, 18), ("adx", 1, ebx, 19), From 276a4572b79f97379dd046386978b5886d0a760b Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 18 Aug 2022 15:05:14 +0000 Subject: [PATCH 029/116] Update Cargo.lock (#794) --- Cargo.lock | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 55dca974..9c61b4e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.5" +version = "0.14.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" dependencies = [ "typenum", "version_check", @@ -91,15 +91,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" +checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" [[package]] name = "libc" -version = "0.2.121" +version = "0.2.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efaa7b300f3b5fe8eb6bf21ce3895e1751d9665086af2d64b42f19701015ff4f" +checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" [[package]] name = "opaque-debug" @@ -107,42 +107,42 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.42" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c278e965f1d8cf32d6e0e96de3d3e79712178ae67986d9cf9151f51e95aac89b" +checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.17" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632d02bff7f874a36f33ea8bb416cd484b90cc66c1194b1a1110d067a7013f58" +checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" +checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "serde" -version = "1.0.136" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce31e24b01e1e524df96f1c2fdd054405f8d7376249a5110886fb4b658484789" +checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.136" +version = "1.0.143" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08597e7152fcd306f41838ed3e37be9eaeed2b61c42e2117266a554fab4662f9" +checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" dependencies = [ "proc-macro2", "quote", @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95" +checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" dependencies = [ "itoa", "ryu", @@ -162,13 +162,13 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.90" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "704df27628939572cd88d33f171cd6f896f4eaca85252c6e0a72d8d8287ee86f" +checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" dependencies = [ "proc-macro2", "quote", - "unicode-xid", + "unicode-ident", ] [[package]] @@ -191,15 +191,15 @@ checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "version_check" From f58e39e9279a891a5aea74d2b4d766c9bd62e101 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Mon, 22 Aug 2022 16:27:35 +0000 Subject: [PATCH 030/116] cpufeatures: release v0.2.4 (#796) --- Cargo.lock | 14 +++++++------- cpufeatures/CHANGELOG.md | 6 ++++++ cpufeatures/Cargo.toml | 2 +- 3 files changed, 14 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9c61b4e0..0684895e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,7 +33,7 @@ version = "0.0.2" [[package]] name = "cpufeatures" -version = "0.2.3" +version = "0.2.4" dependencies = [ "libc", ] @@ -131,18 +131,18 @@ checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "serde" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -151,9 +151,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa", "ryu", diff --git a/cpufeatures/CHANGELOG.md b/cpufeatures/CHANGELOG.md index 2a401c6b..53aca1db 100644 --- a/cpufeatures/CHANGELOG.md +++ b/cpufeatures/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.4 (2022-08-22) +- Re-release v0.2.3 without any changes to fix [#795] ([#796]) + +[#795]: https://github.com/RustCrypto/utils/issues/795 +[#796]: https://github.com/RustCrypto/utils/pull/796 + ## 0.2.3 (2022-08-18) ### Changed - Update `libc` version to v0.2.95 ([#789]) diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index 3bd70f0b..b5a72330 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cpufeatures" -version = "0.2.3" +version = "0.2.4" description = """ Lightweight runtime CPU feature detection for x86/x86_64 and aarch64 with no_std support and support for mobile targets including Android and iOS From 1261e29ff91aeb26b010832ea6a855c0f360ea04 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 25 Aug 2022 14:28:39 -0600 Subject: [PATCH 031/116] zeroize: note `aarch64` crate feature works on stable (#797) The required APIs are stable as of Rust 1.59. Unfortunately we can't yet enable it by default as the overall crate's MSRV is 1.51. It will be possible if we bump MSRV to >=1.59. This commit also adjusts the CI job to test the `aarch64` feature works on `1.59.0` and `stable` compilers. --- .github/workflows/zeroize.yml | 8 +++++--- zeroize/src/aarch64.rs | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index 5fde9b51..656962c5 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -98,15 +98,17 @@ jobs: - run: rm ../Cargo.toml - run: ${{ matrix.deps }} - run: cargo test - - run: cargo test --features alloc,derive,std + - run: cargo test --all-features - # Feature-gated ARM64 SIMD register support (nightly-only) + # Feature-gated ARM64 SIMD register support (MSRV 1.59) aarch64: strategy: matrix: include: - target: aarch64-unknown-linux-gnu - rust: nightly + rust: 1.59.0 + - target: aarch64-unknown-linux-gnu + rust: stable runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 diff --git a/zeroize/src/aarch64.rs b/zeroize/src/aarch64.rs index fc6c8f23..956f6487 100644 --- a/zeroize/src/aarch64.rs +++ b/zeroize/src/aarch64.rs @@ -1,7 +1,7 @@ //! [`Zeroize`] impls for ARM64 SIMD registers. //! -//! Support for this is gated behind an `aarch64` feature because -//! support for `core::arch::aarch64` is currently nightly-only. +//! Gated behind the `aarch64` feature: MSRV 1.59 +//! (the overall crate is MSRV 1.51) use crate::{atomic_fence, volatile_write, Zeroize}; From b858f0c8f4959a88e836764e48f5495fbe9243c4 Mon Sep 17 00:00:00 2001 From: Kriskras99 Date: Mon, 29 Aug 2022 16:23:52 +0200 Subject: [PATCH 032/116] block-padding: fix small typo in docstring (#798) --- block-padding/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block-padding/src/lib.rs b/block-padding/src/lib.rs index 3cbc164e..76cf993e 100644 --- a/block-padding/src/lib.rs +++ b/block-padding/src/lib.rs @@ -25,7 +25,7 @@ pub enum PadType { Reversible, /// Ambiguous padding Ambiguous, - /// No padding, message must be mutliple of block size + /// No padding, message must be multiple of block size NoPadding, } From 1cc82d57d74ca75f6324f234e63a57b59e537bb8 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Sun, 4 Sep 2022 20:46:30 +0000 Subject: [PATCH 033/116] Add workaround for CPUID bug in std (#800) --- Cargo.lock | 2 +- cpufeatures/CHANGELOG.md | 7 +++++++ cpufeatures/Cargo.toml | 2 +- cpufeatures/src/x86.rs | 21 ++++++++++++++++++--- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0684895e..3b2b2842 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -33,7 +33,7 @@ version = "0.0.2" [[package]] name = "cpufeatures" -version = "0.2.4" +version = "0.2.5" dependencies = [ "libc", ] diff --git a/cpufeatures/CHANGELOG.md b/cpufeatures/CHANGELOG.md index 53aca1db..dae3dd11 100644 --- a/cpufeatures/CHANGELOG.md +++ b/cpufeatures/CHANGELOG.md @@ -5,6 +5,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.5 (2022-09-04) +### Fixed +- Add workaround for [CPUID bug] in `std` ([#800]) + +[CPUID bug]: https://github.com/rust-lang/rust/issues/101346 +[#800]: https://github.com/RustCrypto/utils/pull/800 + ## 0.2.4 (2022-08-22) - Re-release v0.2.3 without any changes to fix [#795] ([#796]) diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index b5a72330..d42f9dca 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cpufeatures" -version = "0.2.4" +version = "0.2.5" description = """ Lightweight runtime CPU feature detection for x86/x86_64 and aarch64 with no_std support and support for mobile targets including Android and iOS diff --git a/cpufeatures/src/x86.rs b/cpufeatures/src/x86.rs index e21131bf..c973b744 100644 --- a/cpufeatures/src/x86.rs +++ b/cpufeatures/src/x86.rs @@ -33,12 +33,27 @@ macro_rules! __unless_target_features { macro_rules! __detect_target_features { ($($tf:tt),+) => {{ #[cfg(target_arch = "x86")] - use core::arch::x86::{__cpuid, __cpuid_count}; + use core::arch::x86::{__cpuid, __cpuid_count, CpuidResult}; #[cfg(target_arch = "x86_64")] - use core::arch::x86_64::{__cpuid, __cpuid_count}; + use core::arch::x86_64::{__cpuid, __cpuid_count, CpuidResult}; + + // These wrappers are workarounds around + // https://github.com/rust-lang/rust/issues/101346 + // + // DO NOT remove it until MSRV is bumped to a version + // with the issue fix (at least 1.64). + #[inline(never)] + unsafe fn cpuid(leaf: u32) -> CpuidResult { + __cpuid(leaf) + } + + #[inline(never)] + unsafe fn cpuid_count(leaf: u32, sub_leaf: u32) -> CpuidResult { + __cpuid_count(leaf, sub_leaf) + } let cr = unsafe { - [__cpuid(1), __cpuid_count(7, 0)] + [cpuid(1), cpuid_count(7, 0)] }; $($crate::check!(cr, $tf) & )+ true From ce0ab191c2636ed9f72ac847f21b72b61743b5a7 Mon Sep 17 00:00:00 2001 From: Ruslan Piasetskyi Date: Sun, 4 Sep 2022 23:31:44 +0200 Subject: [PATCH 034/116] block-buffer: add try_new method (#799) try_new creates BlockBuffer or returns an error. --- block-buffer/src/lib.rs | 28 ++++++++++++++++++++++++---- block-buffer/tests/mod.rs | 8 ++++++++ 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/block-buffer/src/lib.rs b/block-buffer/src/lib.rs index cc19b7c3..b7386784 100644 --- a/block-buffer/src/lib.rs +++ b/block-buffer/src/lib.rs @@ -8,7 +8,7 @@ pub use generic_array; -use core::{marker::PhantomData, slice}; +use core::{fmt, marker::PhantomData, slice}; use generic_array::{ typenum::{IsLess, Le, NonZero, U256}, ArrayLength, GenericArray, @@ -40,6 +40,16 @@ pub type EagerBuffer = BlockBuffer; /// Lazy block buffer. pub type LazyBuffer = BlockBuffer; +/// Block buffer error. +#[derive(Copy, Clone, Eq, PartialEq, Debug)] +pub struct Error; + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + f.write_str("Block buffer error") + } +} + /// Buffer for block processing of data. #[derive(Debug)] pub struct BlockBuffer @@ -95,15 +105,25 @@ where /// If slice length is not valid for used buffer kind. #[inline(always)] pub fn new(buf: &[u8]) -> Self { + Self::try_new(buf).unwrap() + } + + /// Create new buffer from slice. + /// + /// Returns an error if slice length is not valid for used buffer kind. + #[inline(always)] + pub fn try_new(buf: &[u8]) -> Result { let pos = buf.len(); - assert!(Kind::invariant(pos, BlockSize::USIZE)); + if !Kind::invariant(pos, BlockSize::USIZE) { + return Err(Error); + } let mut buffer = Block::::default(); buffer[..pos].copy_from_slice(buf); - Self { + Ok(Self { buffer, pos: pos as u8, _pd: PhantomData, - } + }) } /// Digest data in `input` in blocks of size `BlockSize` using diff --git a/block-buffer/tests/mod.rs b/block-buffer/tests/mod.rs index 6dfa1ae1..ee08f979 100644 --- a/block-buffer/tests/mod.rs +++ b/block-buffer/tests/mod.rs @@ -186,3 +186,11 @@ fn test_eager_paddings() { [0x42, 0xff, 0x10, 0x11], ); } + +#[test] +fn test_try_new() { + assert!(EagerBuffer::::try_new(&[0; 3]).is_ok()); + assert!(EagerBuffer::::try_new(&[0; 4]).is_err()); + assert!(LazyBuffer::::try_new(&[0; 4]).is_ok()); + assert!(LazyBuffer::::try_new(&[0; 5]).is_err()); +} From 02a49a322dbadb27dc6c155f979ea7a1018ae9e4 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Sun, 4 Sep 2022 21:49:08 +0000 Subject: [PATCH 035/116] Release block-buffer v0.10.3 (#801) --- Cargo.lock | 2 +- block-buffer/CHANGELOG.md | 6 ++++++ block-buffer/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3b2b2842..593b32ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,7 +11,7 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" dependencies = [ "generic-array", ] diff --git a/block-buffer/CHANGELOG.md b/block-buffer/CHANGELOG.md index 13c6a936..8f1fd1c0 100644 --- a/block-buffer/CHANGELOG.md +++ b/block-buffer/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.10.3 (2022-09-04) +### Added +- `try_new` method ([#799]) + +[#799]: https://github.com/RustCrypto/utils/pull/799 + ## 0.10.2 (2021-02-08) ### Fixed - Eliminate unreachable panic in `LazyBuffer::digest_blocks` ([#731]) diff --git a/block-buffer/Cargo.toml b/block-buffer/Cargo.toml index 6696b571..fc095c8d 100644 --- a/block-buffer/Cargo.toml +++ b/block-buffer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "block-buffer" -version = "0.10.2" +version = "0.10.3" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Buffer type for block processing of data" From 193e7ad59ec81317bafbdbd9f9014b3dc89f9935 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Mon, 5 Sep 2022 10:27:24 +0000 Subject: [PATCH 036/116] cpufeatures: yank old v0.2.x releases (#802) --- cpufeatures/CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpufeatures/CHANGELOG.md b/cpufeatures/CHANGELOG.md index dae3dd11..2f89603d 100644 --- a/cpufeatures/CHANGELOG.md +++ b/cpufeatures/CHANGELOG.md @@ -12,13 +12,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [CPUID bug]: https://github.com/rust-lang/rust/issues/101346 [#800]: https://github.com/RustCrypto/utils/pull/800 -## 0.2.4 (2022-08-22) +## 0.2.4 (2022-08-22) [YANKED] - Re-release v0.2.3 without any changes to fix [#795] ([#796]) [#795]: https://github.com/RustCrypto/utils/issues/795 [#796]: https://github.com/RustCrypto/utils/pull/796 -## 0.2.3 (2022-08-18) +## 0.2.3 (2022-08-18) [YANKED] ### Changed - Update `libc` version to v0.2.95 ([#789]) - Disable all target features under MIRI ([#779]) @@ -28,7 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#789]: https://github.com/RustCrypto/utils/pull/789 [#792]: https://github.com/RustCrypto/utils/pull/792 -## 0.2.2 (2022-03-18) +## 0.2.2 (2022-03-18) [YANKED] ### Added - Support for Android on `aarch64` ([#752]) @@ -38,7 +38,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#600]: https://github.com/RustCrypto/utils/pull/600 [#752]: https://github.com/RustCrypto/utils/pull/752 -## 0.2.1 (2021-08-26) +## 0.2.1 (2021-08-26) [YANKED] ### Changed - Revert [#583] "Use from_bytes_with_nul for string check" ([#597]) From 251075fb19cbf11dbc70892292ba7fb329abcd50 Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Fri, 30 Sep 2022 15:36:23 +0200 Subject: [PATCH 037/116] Extend Dependabot configuration to keep GitHub Actions up to date (#807) --- .github/dependabot.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 5cde1657..397bdaa4 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,3 +5,8 @@ updates: schedule: interval: daily open-pull-requests-limit: 10 +- package-ecosystem: github-actions + directory: "/" + schedule: + interval: weekly + open-pull-requests-limit: 10 From 67f4b983a0c04bd241fee9d59b93122ae70ebe25 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Sep 2022 08:06:17 -0600 Subject: [PATCH 038/116] build(deps): bump actions/checkout from 2 to 3 (#808) Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/blobby.yml | 2 +- .github/workflows/block-buffer.yml | 4 ++-- .github/workflows/block-padding.yml | 4 ++-- .github/workflows/cmov.yml | 6 +++--- .github/workflows/cpufeatures.yml | 8 ++++---- .github/workflows/dbl.yml | 4 ++-- .github/workflows/fiat-constify.yml | 2 +- .github/workflows/hex-literal.yml | 4 ++-- .github/workflows/hybrid-array.yml | 4 ++-- .github/workflows/inout.yml | 4 ++-- .github/workflows/opaque-debug.yml | 4 ++-- .github/workflows/security-audit.yml | 2 +- .github/workflows/workspace.yml | 4 ++-- .github/workflows/zeroize.yml | 6 +++--- 14 files changed, 29 insertions(+), 29 deletions(-) diff --git a/.github/workflows/blobby.yml b/.github/workflows/blobby.yml index 334d98e8..d9a6d568 100644 --- a/.github/workflows/blobby.yml +++ b/.github/workflows/blobby.yml @@ -25,7 +25,7 @@ jobs: - 1.39.0 # MSRV - stable steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/block-buffer.yml b/.github/workflows/block-buffer.yml index 2f2bdd06..2aba09d4 100644 --- a/.github/workflows/block-buffer.yml +++ b/.github/workflows/block-buffer.yml @@ -28,7 +28,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -53,7 +53,7 @@ jobs: - 1.41.0 # MSRV - stable steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/block-padding.yml b/.github/workflows/block-padding.yml index 36e20d18..b9d7939c 100644 --- a/.github/workflows/block-padding.yml +++ b/.github/workflows/block-padding.yml @@ -28,7 +28,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -51,7 +51,7 @@ jobs: - 1.56.0 # MSRV - stable steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/cmov.yml b/.github/workflows/cmov.yml index 2a5eb194..1546b19c 100644 --- a/.github/workflows/cmov.yml +++ b/.github/workflows/cmov.yml @@ -33,7 +33,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -71,7 +71,7 @@ jobs: runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -101,7 +101,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/cpufeatures.yml b/.github/workflows/cpufeatures.yml index 53bf39ec..e4b4df44 100644 --- a/.github/workflows/cpufeatures.yml +++ b/.github/workflows/cpufeatures.yml @@ -42,7 +42,7 @@ jobs: rust: stable runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -64,7 +64,7 @@ jobs: - stable runs-on: macos-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -89,7 +89,7 @@ jobs: toolchain: stable runs-on: windows-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -114,7 +114,7 @@ jobs: rust: stable runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/dbl.yml b/.github/workflows/dbl.yml index 0ca2b092..0a653f90 100644 --- a/.github/workflows/dbl.yml +++ b/.github/workflows/dbl.yml @@ -28,7 +28,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -53,7 +53,7 @@ jobs: - 1.41.0 # MSRV - stable steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/fiat-constify.yml b/.github/workflows/fiat-constify.yml index d7fd7e50..1153d519 100644 --- a/.github/workflows/fiat-constify.yml +++ b/.github/workflows/fiat-constify.yml @@ -26,7 +26,7 @@ jobs: - stable runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/hex-literal.yml b/.github/workflows/hex-literal.yml index f20315b8..cfaa5153 100644 --- a/.github/workflows/hex-literal.yml +++ b/.github/workflows/hex-literal.yml @@ -28,7 +28,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -53,7 +53,7 @@ jobs: - 1.45.0 # MSRV - stable steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/hybrid-array.yml b/.github/workflows/hybrid-array.yml index 991686cd..8c7ed69c 100644 --- a/.github/workflows/hybrid-array.yml +++ b/.github/workflows/hybrid-array.yml @@ -30,7 +30,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -53,7 +53,7 @@ jobs: - stable runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/inout.yml b/.github/workflows/inout.yml index 886e007a..2176b6d3 100644 --- a/.github/workflows/inout.yml +++ b/.github/workflows/inout.yml @@ -28,7 +28,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -52,7 +52,7 @@ jobs: - 1.56.0 # MSRV - stable steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/opaque-debug.yml b/.github/workflows/opaque-debug.yml index f2f2550a..80c89610 100644 --- a/.github/workflows/opaque-debug.yml +++ b/.github/workflows/opaque-debug.yml @@ -28,7 +28,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -53,7 +53,7 @@ jobs: - 1.41.0 # MSRV - stable steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 4042a37d..d5126406 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -13,7 +13,7 @@ jobs: name: Security Audit runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: Cache cargo bin uses: actions/cache@v1 with: diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index 2f230a9d..ea421cf3 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -13,7 +13,7 @@ jobs: clippy: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -26,7 +26,7 @@ jobs: rustfmt: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: actions-rs/toolchain@v1 with: toolchain: stable diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index 656962c5..54abeb14 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -30,7 +30,7 @@ jobs: - thumbv7em-none-eabi - wasm32-unknown-unknown steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -86,7 +86,7 @@ jobs: rust: stable runs-on: ${{ matrix.platform }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: @@ -111,7 +111,7 @@ jobs: rust: stable runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - run: ${{ matrix.deps }} - uses: actions-rs/toolchain@v1 From e05a820fc7292286c65aeaf79c49ae4f7c32b61b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 30 Sep 2022 08:06:24 -0600 Subject: [PATCH 039/116] build(deps): bump actions/cache from 1 to 3 (#809) Bumps [actions/cache](https://github.com/actions/cache) from 1 to 3. - [Release notes](https://github.com/actions/cache/releases) - [Changelog](https://github.com/actions/cache/blob/main/RELEASES.md) - [Commits](https://github.com/actions/cache/compare/v1...v3) --- updated-dependencies: - dependency-name: actions/cache dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/security-audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index d5126406..6bc14e9e 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Cache cargo bin - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ~/.cargo/bin key: ${{ runner.os }}-cargo-audit-v0.12.0 From 52f9125385de64649e6e381f2bfdb311623121e7 Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Mon, 3 Oct 2022 12:19:37 +0200 Subject: [PATCH 040/116] Fix some typos (#806) --- block-buffer/src/lib.rs | 4 ++-- block-buffer/src/sealed.rs | 2 +- block-padding/src/lib.rs | 4 ++-- hex-literal/src/lib.rs | 2 +- opaque-debug/src/lib.rs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/block-buffer/src/lib.rs b/block-buffer/src/lib.rs index b7386784..ac9055e3 100644 --- a/block-buffer/src/lib.rs +++ b/block-buffer/src/lib.rs @@ -215,13 +215,13 @@ where self.set_pos_unchecked(pos); } - /// Return size of the internall buffer in bytes. + /// Return size of the internal buffer in bytes. #[inline(always)] pub fn size(&self) -> usize { BlockSize::USIZE } - /// Return number of remaining bytes in the internall buffer. + /// Return number of remaining bytes in the internal buffer. #[inline(always)] pub fn remaining(&self) -> usize { self.size() - self.get_pos() diff --git a/block-buffer/src/sealed.rs b/block-buffer/src/sealed.rs index 371a8b70..247dec23 100644 --- a/block-buffer/src/sealed.rs +++ b/block-buffer/src/sealed.rs @@ -7,7 +7,7 @@ pub trait Sealed { /// buffer code this function always returns true. fn invariant(pos: usize, block_size: usize) -> bool; - /// Split input data into slice fo blocks and tail. + /// Split input data into slice of blocks and tail. fn split_blocks>(data: &[u8]) -> (&[Block], &[u8]); } diff --git a/block-padding/src/lib.rs b/block-padding/src/lib.rs index 76cf993e..0779b79c 100644 --- a/block-padding/src/lib.rs +++ b/block-padding/src/lib.rs @@ -47,12 +47,12 @@ pub trait Padding> { /// Unpad data in the `block`. /// - /// Returns `Err(UnpadError)` if the block containts malformed padding. + /// Returns `Err(UnpadError)` if the block contains malformed padding. fn unpad(block: &Block) -> Result<&[u8], UnpadError>; /// Unpad data in the `blocks`. /// - /// Returns `Err(UnpadError)` if the block containts malformed padding. + /// Returns `Err(UnpadError)` if the block contains malformed padding. fn unpad_blocks(blocks: &[Block]) -> Result<&[u8], UnpadError> { let bs = BlockSize::USIZE; let res_len = match (blocks.last(), Self::TYPE) { diff --git a/hex-literal/src/lib.rs b/hex-literal/src/lib.rs index a69ec333..5399d3f3 100644 --- a/hex-literal/src/lib.rs +++ b/hex-literal/src/lib.rs @@ -32,7 +32,7 @@ //! // it's possible to use several literals (results will be concatenated) //! let bytes2 = hex!( //! "00010203 04050607" // first half -//! "08090a0b 0c0d0e0f" // second hald +//! "08090a0b 0c0d0e0f" // second half //! ); //! assert_eq!(bytes2, bytes); //! diff --git a/opaque-debug/src/lib.rs b/opaque-debug/src/lib.rs index e4e5b7b5..3b48b071 100644 --- a/opaque-debug/src/lib.rs +++ b/opaque-debug/src/lib.rs @@ -11,7 +11,7 @@ pub extern crate core as __core; /// Macro for defining opaque `Debug` implementation. /// /// It will use the following format: "StructName { ... }". While it's -/// convinient to have it (e.g. for including into other structs), it could be +/// convenient to have it (e.g. for including into other structs), it could be /// undesirable to leak internal state, which can happen for example through /// uncareful logging. #[macro_export] From 1fcabe0e70c0cdfce57ee366280e62e693ee1e20 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 17 Oct 2022 09:23:28 -0600 Subject: [PATCH 041/116] build(deps): bump proc-macro2 from 1.0.43 to 1.0.47 (#811) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.43 to 1.0.47. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.43...1.0.47) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 593b32ab..4ddde8ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -107,9 +107,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.43" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab" +checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" dependencies = [ "unicode-ident", ] From b898588b13e8005cd8860089f108bed09f86bd87 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 18 Oct 2022 15:00:05 -0600 Subject: [PATCH 042/116] zeroize_derive: yank 1.1.1, 1.2.0, 1.2.1, 1.2.2 (#812) These releases misspecified their version requirement for `synstructure` and are not compatible with releases prior to v0.12.2. This breaks `-Z minimal-versions` builds for downstream dependencies. See dalek-cryptography/ed25519-dalek#219 --- zeroize/derive/CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zeroize/derive/CHANGELOG.md b/zeroize/derive/CHANGELOG.md index 1ecaef26..ab376146 100644 --- a/zeroize/derive/CHANGELOG.md +++ b/zeroize/derive/CHANGELOG.md @@ -25,7 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 [#699]: https://github.com/RustCrypto/utils/pull/699 [#700]: https://github.com/RustCrypto/utils/pull/700 -## 1.2.2 (2021-11-04) +## 1.2.2 (2021-11-04) [YANKED] ### Added - `#[zeroize(skip)]` attribute ([#654]) @@ -35,12 +35,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Moved to `RustCrypto/utils` repository -## 1.2.0 (2021-09-21) +## 1.2.0 (2021-09-21) [YANKED] ### Changed - Bump MSRV to 1.51+ - Reject `#[zeroize(drop)]` on struct/enum fields, enum variants -## 1.1.1 (2021-10-09) +## 1.1.1 (2021-10-09) [YANKED] ### Changed - Backport 1.2.0 `#[zeroize(drop)]` fixes but with a 1.47+ MSRV. From f56a234cfdf2fd4ba6eb575fa55da0b895673162 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 30 Nov 2022 14:08:15 -0700 Subject: [PATCH 043/116] zeroize_derive v1.3.3 (#817) --- Cargo.lock | 2 +- zeroize/derive/CHANGELOG.md | 6 ++++++ zeroize/derive/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4ddde8ae..82025578 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,7 +227,7 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.2" +version = "1.3.3" dependencies = [ "proc-macro2", "quote", diff --git a/zeroize/derive/CHANGELOG.md b/zeroize/derive/CHANGELOG.md index ab376146..41913423 100644 --- a/zeroize/derive/CHANGELOG.md +++ b/zeroize/derive/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.3.3 (2022-11-30) +### Fixed +- Deriving `ZeroizeOnDrop` on items with generics ([#787]) + +[#787]: https://github.com/RustCrypto/utils/pull/787 + ## 1.3.2 (2022-02-18) ### Fixed - Min versions build ([#732]) diff --git a/zeroize/derive/Cargo.toml b/zeroize/derive/Cargo.toml index 4bac91a3..c33fbcf3 100644 --- a/zeroize/derive/Cargo.toml +++ b/zeroize/derive/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "zeroize_derive" description = "Custom derive support for zeroize" -version = "1.3.2" +version = "1.3.3" authors = ["The RustCrypto Project Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/zeroize/derive" From c809e3d7b3895f1254f44039105baf2c9905c132 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 1 Dec 2022 14:23:20 -0700 Subject: [PATCH 044/116] zeroize: impl `Zeroize` for `core::num::Wrapping` (#818) Closes #803 --- zeroize/src/lib.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index 5ee0f2c9..3cb58224 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -254,8 +254,8 @@ use core::{ marker::{PhantomData, PhantomPinned}, mem::{self, MaybeUninit}, num::{ - NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, NonZeroU128, - NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, + self, NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize, + NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize, }, ops, ptr, slice::IterMut, @@ -349,6 +349,15 @@ impl_zeroize_for_non_zero!( NonZeroUsize ); +impl Zeroize for num::Wrapping +where + Z: Zeroize, +{ + fn zeroize(&mut self) { + self.0.zeroize(); + } +} + /// Impl [`Zeroize`] on arrays of types that impl [`Zeroize`]. impl Zeroize for [Z; N] where From aeda63e800ca3cb7f0b2764ffdb1d87259d149b5 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 5 Dec 2022 21:19:44 -0700 Subject: [PATCH 045/116] build(deps): bump typenum from 1.15.0 to 1.16.0 (#820) Bumps [typenum](https://github.com/paholg/typenum) from 1.15.0 to 1.16.0. - [Release notes](https://github.com/paholg/typenum/releases) - [Changelog](https://github.com/paholg/typenum/blob/main/CHANGELOG.md) - [Commits](https://github.com/paholg/typenum/compare/v1.15.0...v1.16.0) --- updated-dependencies: - dependency-name: typenum dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- hybrid-array/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 82025578..f5c0b4ef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" diff --git a/hybrid-array/Cargo.toml b/hybrid-array/Cargo.toml index cfdb9754..9ca231e9 100644 --- a/hybrid-array/Cargo.toml +++ b/hybrid-array/Cargo.toml @@ -17,4 +17,4 @@ edition = "2021" rust-version = "1.56" [dependencies] -typenum = "1.10" +typenum = "1.16" From eb01b6239c6d29898dcf7254a8a792df0a6bca14 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Mon, 19 Dec 2022 20:22:36 +0300 Subject: [PATCH 046/116] block-buffer v0.11 (#823) --- .github/workflows/block-buffer.yml | 4 +- Cargo.lock | 64 ++++--- block-buffer/CHANGELOG.md | 17 ++ block-buffer/Cargo.toml | 8 +- block-buffer/src/lib.rs | 233 ++++++++++++------------- block-buffer/src/read.rs | 148 ++++++++++++++++ block-buffer/src/sealed.rs | 40 ++++- block-buffer/tests/mod.rs | 270 ++++++++++++++++++++++------- 8 files changed, 571 insertions(+), 213 deletions(-) create mode 100644 block-buffer/src/read.rs diff --git a/.github/workflows/block-buffer.yml b/.github/workflows/block-buffer.yml index 2aba09d4..7ea492b2 100644 --- a/.github/workflows/block-buffer.yml +++ b/.github/workflows/block-buffer.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: rust: - - 1.41.0 # MSRV + - 1.56.0 # MSRV - stable target: - thumbv7em-none-eabi @@ -50,7 +50,7 @@ jobs: strategy: matrix: rust: - - 1.41.0 # MSRV + - 1.56.0 # MSRV - stable steps: - uses: actions/checkout@v3 diff --git a/Cargo.lock b/Cargo.lock index f5c0b4ef..b7428d0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,9 +11,11 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.11.0-pre" dependencies = [ + "crypto-common", "generic-array", + "hex-literal 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -38,6 +40,16 @@ dependencies = [ "libc", ] +[[package]] +name = "crypto-common" +version = "0.2.0-pre" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6faaa83e7700e0832cbbf84854d4c356270526907d9b14fab927fc7a9b5befb8" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "dbl" version = "0.3.2" @@ -74,6 +86,12 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" name = "hex-literal" version = "0.3.4" +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hybrid-array" version = "0.1.0" @@ -91,15 +109,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "libc" -version = "0.2.132" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "opaque-debug" @@ -107,42 +125,42 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "serde" -version = "1.0.144" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" dependencies = [ "proc-macro2", "quote", @@ -151,9 +169,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "itoa", "ryu", @@ -162,9 +180,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.99" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -191,15 +209,15 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "version_check" diff --git a/block-buffer/CHANGELOG.md b/block-buffer/CHANGELOG.md index 8f1fd1c0..14fa050b 100644 --- a/block-buffer/CHANGELOG.md +++ b/block-buffer/CHANGELOG.md @@ -4,6 +4,23 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## UNRELEASED +### Added +- `ReadBuffer` type ([#823]) +- `serialize` and `deserialize` methods ([#823]) + +### Changed +- Supported block sizes are now bounded by the `crypto_common::BlockSizes` trait, + which is implemented for types from `U1` to `U255` ([#823]) +- Size of `EagerBuffer` is equal to buffer size, while previously it was equal + to buffer size plus one byte ([#823]) +- Edition changed to 2021 and MSRV bumped to 1.56 ([#823]) + +### Removed +- `EagerBuffer::set_data` method. Use the `ReadBuffer` type instead. ([#823]) + +[#823]: https://github.com/RustCrypto/utils/pull/823 + ## 0.10.3 (2022-09-04) ### Added - `try_new` method ([#799]) diff --git a/block-buffer/Cargo.toml b/block-buffer/Cargo.toml index fc095c8d..7b121f95 100644 --- a/block-buffer/Cargo.toml +++ b/block-buffer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "block-buffer" -version = "0.10.3" +version = "0.11.0-pre" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Buffer type for block processing of data" @@ -8,8 +8,12 @@ documentation = "https://docs.rs/block-buffer" repository = "https://github.com/RustCrypto/utils" keywords = ["block", "buffer"] categories = ["cryptography", "no-std"] -edition = "2018" +edition = "2021" readme = "README.md" [dependencies] +crypto-common = "0.2.0-pre" generic-array = "0.14" + +[dev-dependencies] +hex-literal = "0.3.3" diff --git a/block-buffer/src/lib.rs b/block-buffer/src/lib.rs index ac9055e3..61438e71 100644 --- a/block-buffer/src/lib.rs +++ b/block-buffer/src/lib.rs @@ -8,16 +8,21 @@ pub use generic_array; -use core::{fmt, marker::PhantomData, slice}; +use core::{fmt, ops::Add, slice}; +pub use crypto_common::Block; +use crypto_common::{BlockSizeUser, BlockSizes}; use generic_array::{ - typenum::{IsLess, Le, NonZero, U256}, + typenum::{Add1, B1}, ArrayLength, GenericArray, }; +mod read; mod sealed; -/// Block on which `BlockBuffer` operates. -pub type Block = GenericArray; +pub use read::ReadBuffer; + +/// Block with additional one byte +type BlockP1 = GenericArray>; /// Trait for buffer kinds. pub trait BufferKind: sealed::Sealed {} @@ -33,6 +38,7 @@ pub struct Eager {} pub struct Lazy {} impl BufferKind for Eager {} + impl BufferKind for Lazy {} /// Eager block buffer. @@ -52,53 +58,36 @@ impl fmt::Display for Error { /// Buffer for block processing of data. #[derive(Debug)] -pub struct BlockBuffer -where - BlockSize: ArrayLength + IsLess, - Le: NonZero, - Kind: BufferKind, -{ - buffer: Block, - pos: u8, - _pd: PhantomData, +pub struct BlockBuffer { + buffer: Block, + pos: K::Pos, +} + +impl BlockSizeUser for BlockBuffer { + type BlockSize = BS; } -impl Default for BlockBuffer -where - BlockSize: ArrayLength + IsLess, - Le: NonZero, - Kind: BufferKind, -{ +impl Default for BlockBuffer { + #[inline] fn default() -> Self { Self { buffer: Default::default(), - pos: 0, - _pd: PhantomData, + pos: Default::default(), } } } -impl Clone for BlockBuffer -where - BlockSize: ArrayLength + IsLess, - Le: NonZero, - Kind: BufferKind, -{ +impl Clone for BlockBuffer { + #[inline] fn clone(&self) -> Self { Self { buffer: self.buffer.clone(), - pos: self.pos, - _pd: PhantomData, + pos: self.pos.clone(), } } } -impl BlockBuffer -where - BlockSize: ArrayLength + IsLess, - Le: NonZero, - Kind: BufferKind, -{ +impl BlockBuffer { /// Create new buffer from slice. /// /// # Panics @@ -114,26 +103,19 @@ where #[inline(always)] pub fn try_new(buf: &[u8]) -> Result { let pos = buf.len(); - if !Kind::invariant(pos, BlockSize::USIZE) { + if !K::invariant(pos, BS::USIZE) { return Err(Error); } - let mut buffer = Block::::default(); - buffer[..pos].copy_from_slice(buf); - Ok(Self { - buffer, - pos: pos as u8, - _pd: PhantomData, - }) + let mut res = Self::default(); + res.buffer[..pos].copy_from_slice(buf); + K::set_pos(&mut res.buffer, &mut res.pos, pos); + Ok(res) } /// Digest data in `input` in blocks of size `BlockSize` using /// the `compress` function, which accepts slice of blocks. #[inline] - pub fn digest_blocks( - &mut self, - mut input: &[u8], - mut compress: impl FnMut(&[Block]), - ) { + pub fn digest_blocks(&mut self, mut input: &[u8], mut compress: impl FnMut(&[Block])) { let pos = self.get_pos(); // using `self.remaining()` for some reason // prevents panic elimination @@ -146,7 +128,7 @@ where // `pos + n` which results in it inserting unreachable // panic branches. Using `unreachable_unchecked` in `get_pos` // we convince compiler that `BlockSize - pos` never underflows. - if Kind::invariant(n, rem) { + if K::invariant(n, rem) { // double slicing allows to remove panic branches self.buffer[pos..][..n].copy_from_slice(input); self.set_pos_unchecked(pos + n); @@ -159,7 +141,7 @@ where compress(slice::from_ref(&self.buffer)); } - let (blocks, leftover) = Kind::split_blocks(input); + let (blocks, leftover) = K::split_blocks(input); if !blocks.is_empty() { compress(blocks); } @@ -177,18 +159,19 @@ where /// Pad remaining data with zeros and return resulting block. #[inline(always)] - pub fn pad_with_zeros(&mut self) -> &mut Block { + pub fn pad_with_zeros(&mut self) -> Block { let pos = self.get_pos(); - self.buffer[pos..].iter_mut().for_each(|b| *b = 0); + let mut res = self.buffer.clone(); + res[pos..].iter_mut().for_each(|b| *b = 0); self.set_pos_unchecked(0); - &mut self.buffer + res } /// Return current cursor position. #[inline(always)] pub fn get_pos(&self) -> usize { - let pos = self.pos as usize; - if !Kind::invariant(pos, BlockSize::USIZE) { + let pos = K::get_pos(&self.buffer, &self.pos); + if !K::invariant(pos, BS::USIZE) { debug_assert!(false); // SAFETY: `pos` never breaks the invariant unsafe { @@ -209,8 +192,8 @@ where /// # Panics /// If `pos` is bigger or equal to block size. #[inline] - pub fn set(&mut self, buf: Block, pos: usize) { - assert!(Kind::invariant(pos, BlockSize::USIZE)); + pub fn set(&mut self, buf: Block, pos: usize) { + assert!(K::invariant(pos, BS::USIZE)); self.buffer = buf; self.set_pos_unchecked(pos); } @@ -218,7 +201,7 @@ where /// Return size of the internal buffer in bytes. #[inline(always)] pub fn size(&self) -> usize { - BlockSize::USIZE + BS::USIZE } /// Return number of remaining bytes in the internal buffer. @@ -229,51 +212,12 @@ where #[inline(always)] fn set_pos_unchecked(&mut self, pos: usize) { - debug_assert!(Kind::invariant(pos, BlockSize::USIZE)); - self.pos = pos as u8; + debug_assert!(K::invariant(pos, BS::USIZE)); + K::set_pos(&mut self.buffer, &mut self.pos, pos) } } -impl BlockBuffer -where - BlockSize: ArrayLength + IsLess, - Le: NonZero, -{ - /// Set `data` to generated blocks. - #[inline] - pub fn set_data( - &mut self, - mut data: &mut [u8], - mut process_blocks: impl FnMut(&mut [Block]), - ) { - let pos = self.get_pos(); - let r = self.remaining(); - let n = data.len(); - if pos != 0 { - if n < r { - // double slicing allows to remove panic branches - data.copy_from_slice(&self.buffer[pos..][..n]); - self.set_pos_unchecked(pos + n); - return; - } - let (left, right) = data.split_at_mut(r); - data = right; - left.copy_from_slice(&self.buffer[pos..]); - } - - let (blocks, leftover) = to_blocks_mut(data); - process_blocks(blocks); - - let n = leftover.len(); - if n != 0 { - let mut block = Default::default(); - process_blocks(slice::from_mut(&mut block)); - leftover.copy_from_slice(&block[..n]); - self.buffer = block; - } - self.set_pos_unchecked(n); - } - +impl BlockBuffer { /// Compress remaining data after padding it with `delim`, zeros and /// the `suffix` bytes. If there is not enough unused space, `compress` /// will be called twice. @@ -281,13 +225,8 @@ where /// # Panics /// If suffix length is bigger than block size. #[inline(always)] - pub fn digest_pad( - &mut self, - delim: u8, - suffix: &[u8], - mut compress: impl FnMut(&Block), - ) { - if suffix.len() > BlockSize::USIZE { + pub fn digest_pad(&mut self, delim: u8, suffix: &[u8], mut compress: impl FnMut(&Block)) { + if suffix.len() > BS::USIZE { panic!("suffix is too long"); } let pos = self.get_pos(); @@ -299,7 +238,7 @@ where let n = self.size() - suffix.len(); if self.size() - pos - 1 < suffix.len() { compress(&self.buffer); - let mut block = Block::::default(); + let mut block = Block::::default(); block[n..].copy_from_slice(suffix); compress(&block); } else { @@ -312,33 +251,85 @@ where /// Pad message with 0x80, zeros and 64-bit message length using /// big-endian byte order. #[inline] - pub fn len64_padding_be(&mut self, data_len: u64, compress: impl FnMut(&Block)) { + pub fn len64_padding_be(&mut self, data_len: u64, compress: impl FnMut(&Block)) { self.digest_pad(0x80, &data_len.to_be_bytes(), compress); } /// Pad message with 0x80, zeros and 64-bit message length using /// little-endian byte order. #[inline] - pub fn len64_padding_le(&mut self, data_len: u64, compress: impl FnMut(&Block)) { + pub fn len64_padding_le(&mut self, data_len: u64, compress: impl FnMut(&Block)) { self.digest_pad(0x80, &data_len.to_le_bytes(), compress); } /// Pad message with 0x80, zeros and 128-bit message length using /// big-endian byte order. #[inline] - pub fn len128_padding_be(&mut self, data_len: u128, compress: impl FnMut(&Block)) { + pub fn len128_padding_be(&mut self, data_len: u128, compress: impl FnMut(&Block)) { self.digest_pad(0x80, &data_len.to_be_bytes(), compress); } + + /// Serialize buffer into a byte array. + #[inline] + pub fn serialize(&self) -> Block { + let mut res = self.buffer.clone(); + let pos = self.get_pos(); + // zeroize "garbage" data + for b in res[pos..BS::USIZE - 1].iter_mut() { + *b = 0; + } + res + } + + /// Deserialize buffer from a byte array. + #[inline] + pub fn deserialize(buffer: &Block) -> Result { + let pos = buffer[BS::USIZE - 1] as usize; + if !::invariant(pos, BS::USIZE) { + return Err(Error); + } + if buffer[pos..BS::USIZE - 1].iter().any(|&b| b != 0) { + return Err(Error); + } + Ok(Self { + buffer: buffer.clone(), + pos: Default::default(), + }) + } } -/// Split message into mutable slice of parallel blocks, blocks, and leftover bytes. -#[inline(always)] -fn to_blocks_mut>(data: &mut [u8]) -> (&mut [Block], &mut [u8]) { - let nb = data.len() / N::USIZE; - let (left, right) = data.split_at_mut(nb * N::USIZE); - let p = left.as_mut_ptr() as *mut Block; - // SAFETY: we guarantee that `blocks` does not point outside of `data`, and `p` is valid for - // mutation - let blocks = unsafe { slice::from_raw_parts_mut(p, nb) }; - (blocks, right) +impl BlockBuffer { + /// Serialize buffer into a byte array. + #[inline] + pub fn serialize(&self) -> BlockP1 + where + BS: Add, + Add1: ArrayLength, + { + let mut res = BlockP1::::default(); + res[0] = self.pos; + let data = self.get_data(); + res[1..][..data.len()].copy_from_slice(data); + res + } + + /// Deserialize buffer from a byte array. + #[inline] + pub fn deserialize(buffer: &BlockP1) -> Result + where + BS: Add, + Add1: ArrayLength, + { + let pos = buffer[0]; + if !::invariant(pos as usize, BS::USIZE) { + return Err(Error); + } + if buffer[1..][pos as usize..].iter().any(|&b| b != 0) { + return Err(Error); + } + Ok(Self { + buffer: GenericArray::clone_from_slice(&buffer[1..]), + pos, + }) + } } diff --git a/block-buffer/src/read.rs b/block-buffer/src/read.rs new file mode 100644 index 00000000..fa9237a1 --- /dev/null +++ b/block-buffer/src/read.rs @@ -0,0 +1,148 @@ +use super::{Block, Error}; +use core::{fmt, slice}; +use crypto_common::{BlockSizeUser, BlockSizes}; + +/// Buffer for reading block-generated data. +pub struct ReadBuffer { + // The first byte of the block is used as position. + buffer: Block, +} + +impl BlockSizeUser for ReadBuffer { + type BlockSize = BS; +} + +impl fmt::Debug for ReadBuffer { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ReadBuffer") + .field("remaining_data", &self.get_pos()) + .finish() + } +} + +impl Default for ReadBuffer { + #[inline] + fn default() -> Self { + let mut buffer = Block::::default(); + buffer[0] = BS::U8; + Self { buffer } + } +} + +impl Clone for ReadBuffer { + #[inline] + fn clone(&self) -> Self { + Self { + buffer: self.buffer.clone(), + } + } +} + +impl ReadBuffer { + /// Return current cursor position. + #[inline(always)] + pub fn get_pos(&self) -> usize { + let pos = self.buffer[0]; + if pos == 0 || pos > BS::U8 { + debug_assert!(false); + // SAFETY: `pos` never breaks the invariant + unsafe { + core::hint::unreachable_unchecked(); + } + } + pos as usize + } + + /// Return size of the internal buffer in bytes. + #[inline(always)] + pub fn size(&self) -> usize { + BS::USIZE + } + + /// Return number of remaining bytes in the internal buffer. + #[inline(always)] + pub fn remaining(&self) -> usize { + self.size() - self.get_pos() + } + + #[inline(always)] + fn set_pos_unchecked(&mut self, pos: usize) { + debug_assert!(pos <= BS::USIZE); + self.buffer[0] = pos as u8; + } + + /// Write remaining data inside buffer into `data`, fill remaining space + /// in `data` with blocks generated by `gen_block`, and save leftover data + /// from the last generated block into buffer for future use. + #[inline] + pub fn read(&mut self, mut data: &mut [u8], mut gen_block: impl FnMut(&mut Block)) { + let pos = self.get_pos(); + let r = self.remaining(); + let n = data.len(); + + if r != 0 { + if n < r { + // double slicing allows to remove panic branches + data.copy_from_slice(&self.buffer[pos..][..n]); + self.set_pos_unchecked(pos + n); + return; + } + let (left, right) = data.split_at_mut(r); + data = right; + left.copy_from_slice(&self.buffer[pos..]); + } + + let (blocks, leftover) = Self::to_blocks_mut(data); + for block in blocks { + gen_block(block); + } + + let n = leftover.len(); + if n != 0 { + let mut block = Default::default(); + gen_block(&mut block); + leftover.copy_from_slice(&block[..n]); + self.buffer = block; + self.set_pos_unchecked(n); + } else { + self.set_pos_unchecked(BS::USIZE); + } + } + + /// Serialize buffer into a byte array. + #[inline] + pub fn serialize(&self) -> Block { + let mut res = self.buffer.clone(); + let pos = self.get_pos(); + // zeroize "garbage" data + for b in res[1..pos].iter_mut() { + *b = 0; + } + res + } + + /// Deserialize buffer from a byte array. + #[inline] + pub fn deserialize(buffer: &Block) -> Result { + let pos = buffer[0]; + if pos == 0 || pos > BS::U8 || buffer[1..pos as usize].iter().any(|&b| b != 0) { + Err(Error) + } else { + Ok(Self { + buffer: buffer.clone(), + }) + } + } + + /// Split message into mutable slice of parallel blocks, blocks, and leftover bytes. + #[inline(always)] + fn to_blocks_mut(data: &mut [u8]) -> (&mut [Block], &mut [u8]) { + let nb = data.len() / BS::USIZE; + let (left, right) = data.split_at_mut(nb * BS::USIZE); + let p = left.as_mut_ptr() as *mut Block; + // SAFETY: we guarantee that `blocks` does not point outside of `data`, and `p` is valid for + // mutation + let blocks = unsafe { slice::from_raw_parts_mut(p, nb) }; + (blocks, right) + } +} diff --git a/block-buffer/src/sealed.rs b/block-buffer/src/sealed.rs index 247dec23..cc7b3ef6 100644 --- a/block-buffer/src/sealed.rs +++ b/block-buffer/src/sealed.rs @@ -1,31 +1,48 @@ -use super::{ArrayLength, Block}; use core::slice; +use generic_array::{ArrayLength, GenericArray}; /// Sealed trait for buffer kinds. pub trait Sealed { + type Pos: Default + Clone; + + fn get_pos(buf: &[u8], pos: &Self::Pos) -> usize; + + fn set_pos(buf_val: &mut [u8], pos: &mut Self::Pos, val: usize); + /// Invariant guaranteed by a buffer kind, i.e. with correct /// buffer code this function always returns true. fn invariant(pos: usize, block_size: usize) -> bool; /// Split input data into slice of blocks and tail. - fn split_blocks>(data: &[u8]) -> (&[Block], &[u8]); + fn split_blocks>(data: &[u8]) -> (&[GenericArray], &[u8]); } impl Sealed for super::Eager { + type Pos = (); + + fn get_pos(buf: &[u8], _pos: &Self::Pos) -> usize { + buf[buf.len() - 1] as usize + } + + fn set_pos(buf: &mut [u8], _pos: &mut Self::Pos, val: usize) { + debug_assert!(val <= u8::MAX as usize); + buf[buf.len() - 1] = val as u8; + } + #[inline(always)] fn invariant(pos: usize, block_size: usize) -> bool { pos < block_size } #[inline(always)] - fn split_blocks>(data: &[u8]) -> (&[Block], &[u8]) { + fn split_blocks>(data: &[u8]) -> (&[GenericArray], &[u8]) { let nb = data.len() / N::USIZE; let blocks_len = nb * N::USIZE; let tail_len = data.len() - blocks_len; // SAFETY: we guarantee that created slices do not point // outside of `data` unsafe { - let blocks_ptr = data.as_ptr() as *const Block; + let blocks_ptr = data.as_ptr() as *const GenericArray; let tail_ptr = data.as_ptr().add(blocks_len); ( slice::from_raw_parts(blocks_ptr, nb), @@ -36,13 +53,24 @@ impl Sealed for super::Eager { } impl Sealed for super::Lazy { + type Pos = u8; + + fn get_pos(_buf_val: &[u8], pos: &Self::Pos) -> usize { + *pos as usize + } + + fn set_pos(_buf_val: &mut [u8], pos: &mut Self::Pos, val: usize) { + debug_assert!(val <= u8::MAX as usize); + *pos = val as u8; + } + #[inline(always)] fn invariant(pos: usize, block_size: usize) -> bool { pos <= block_size } #[inline(always)] - fn split_blocks>(data: &[u8]) -> (&[Block], &[u8]) { + fn split_blocks>(data: &[u8]) -> (&[GenericArray], &[u8]) { if data.is_empty() { return (&[], &[]); } @@ -56,7 +84,7 @@ impl Sealed for super::Lazy { // SAFETY: we guarantee that created slices do not point // outside of `data` unsafe { - let blocks_ptr = data.as_ptr() as *const Block; + let blocks_ptr = data.as_ptr() as *const GenericArray; let tail_ptr = data.as_ptr().add(blocks_len); ( slice::from_raw_parts(blocks_ptr, nb), diff --git a/block-buffer/tests/mod.rs b/block-buffer/tests/mod.rs index ee08f979..da2a651b 100644 --- a/block-buffer/tests/mod.rs +++ b/block-buffer/tests/mod.rs @@ -1,7 +1,11 @@ use block_buffer::{ - generic_array::typenum::{U10, U16, U24, U4, U8}, - Block, EagerBuffer, LazyBuffer, + generic_array::{ + typenum::{U10, U16, U24, U4, U8}, + GenericArray, + }, + Block, EagerBuffer, LazyBuffer, ReadBuffer, }; +use hex_literal::hex; #[test] fn test_eager_digest_pad() { @@ -73,32 +77,35 @@ fn test_lazy_digest_pad() { } #[test] -fn test_eager_set_data() { - let mut buf = EagerBuffer::::default(); +fn test_read() { + type Buf = ReadBuffer; + let mut buf = Buf::default(); let mut n = 0u8; - let mut gen = |blocks: &mut [Block]| { - for block in blocks { - block.iter_mut().for_each(|b| *b = n); - n += 1; - } + let mut gen = |block: &mut Block| { + block.iter_mut().for_each(|b| *b = n); + n += 1; }; let mut out = [0u8; 6]; - buf.set_data(&mut out, &mut gen); + buf.read(&mut out, &mut gen); assert_eq!(out, [0, 0, 0, 0, 1, 1]); assert_eq!(buf.get_pos(), 2); + assert_eq!(buf.remaining(), 2); let mut out = [0u8; 3]; - buf.set_data(&mut out, &mut gen); + buf.read(&mut out, &mut gen); assert_eq!(out, [1, 1, 2]); assert_eq!(buf.get_pos(), 1); + assert_eq!(buf.remaining(), 3); let mut out = [0u8; 3]; - buf.set_data(&mut out, &mut gen); + buf.read(&mut out, &mut gen); assert_eq!(out, [2, 2, 2]); + assert_eq!(buf.get_pos(), 4); + assert_eq!(buf.remaining(), 0); + assert_eq!(n, 3); - assert_eq!(buf.get_pos(), 0); } #[test] @@ -112,20 +119,8 @@ fn test_eager_paddings() { buf_be.len64_padding_be(len, |block| out_be.extend(block)); buf_le.len64_padding_le(len, |block| out_le.extend(block)); - assert_eq!( - out_be, - [ - 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - ], - ); - assert_eq!( - out_le, - [ - 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - ], - ); + assert_eq!(out_be, hex!("42800000000000000001020304050607")); + assert_eq!(out_le, hex!("42800000000000000706050403020100")); let mut buf_be = EagerBuffer::::new(&[0x42]); let mut buf_le = buf_be.clone(); @@ -134,14 +129,8 @@ fn test_eager_paddings() { buf_be.len64_padding_be(len, |block| out_be.extend(block)); buf_le.len64_padding_le(len, |block| out_le.extend(block)); - assert_eq!( - out_be, - [0x42, 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], - ); - assert_eq!( - out_le, - [0x42, 0x80, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00], - ); + assert_eq!(out_be, hex!("42800001020304050607")); + assert_eq!(out_le, hex!("42800706050403020100")); let mut buf = EagerBuffer::::new(&[0x42]); let mut out = Vec::::new(); @@ -149,42 +138,24 @@ fn test_eager_paddings() { buf.len128_padding_be(len, |block| out.extend(block)); assert_eq!( out, - [ - 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - ], + hex!("42800000000000000000000000000000000102030405060708090a0b0c0d0e0f"), ); let mut buf = EagerBuffer::::new(&[0x42]); let mut out = Vec::::new(); let len = 0x0001_0203_0405_0607_0809_0a0b_0c0d_0e0f; buf.len128_padding_be(len, |block| out.extend(block)); - assert_eq!( - out, - [ - 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - ], - ); + assert_eq!(out, hex!("4280000000000000000102030405060708090a0b0c0d0e0f")); let mut buf = EagerBuffer::::new(&[0x42]); let mut out = Vec::::new(); - buf.digest_pad(0xff, &[0x10, 0x11, 0x12], |block| out.extend(block)); - assert_eq!( - out, - [0x42, 0xff, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12], - ); + buf.digest_pad(0xff, &hex!("101112"), |block| out.extend(block)); + assert_eq!(out, hex!("42ff000000101112")); let mut buf = EagerBuffer::::new(&[0x42]); let mut out = Vec::::new(); - buf.digest_pad(0xff, &[0x10, 0x11], |block| out.extend(block)); - assert_eq!( - out, - [0x42, 0xff, 0x10, 0x11], - ); + buf.digest_pad(0xff, &hex!("1011"), |block| out.extend(block)); + assert_eq!(out, hex!("42ff1011")); } #[test] @@ -194,3 +165,184 @@ fn test_try_new() { assert!(LazyBuffer::::try_new(&[0; 4]).is_ok()); assert!(LazyBuffer::::try_new(&[0; 5]).is_err()); } + +#[test] +fn test_eager_serialize() { + type Buf = EagerBuffer; + + let mut buf1 = Buf::default(); + let ser0 = buf1.serialize(); + assert_eq!(&ser0[..], &[0, 0, 0, 0]); + assert_eq!(Buf::deserialize(&ser0).unwrap().serialize(), ser0); + + buf1.digest_blocks(&[41, 42], |_| {}); + + let ser1 = buf1.serialize(); + assert_eq!(&ser1[..], &[41, 42, 0, 2]); + + let mut buf2 = Buf::deserialize(&ser1).unwrap(); + assert_eq!(buf1.serialize(), ser1); + + buf1.digest_blocks(&[43], |_| {}); + buf2.digest_blocks(&[43], |_| {}); + + let ser2 = buf1.serialize(); + assert_eq!(&ser2[..], &[41, 42, 43, 3]); + assert_eq!(buf1.serialize(), ser2); + + let mut buf3 = Buf::deserialize(&ser2).unwrap(); + assert_eq!(buf3.serialize(), ser2); + + buf1.digest_blocks(&[44], |_| {}); + buf2.digest_blocks(&[44], |_| {}); + buf3.digest_blocks(&[44], |_| {}); + + let ser3 = buf1.serialize(); + assert_eq!(&ser3[..], &[0, 0, 0, 0]); + assert_eq!(buf2.serialize(), ser3); + assert_eq!(buf3.serialize(), ser3); + + // Invalid position + let buf = GenericArray::from_slice(&[0, 0, 0, 4]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[0, 0, 0, 10]); + assert!(Buf::deserialize(buf).is_err()); + // "Garbage" bytes are not zeroized + let buf = GenericArray::from_slice(&[1, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[0, 1, 0, 1]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[0, 0, 1, 2]); + assert!(Buf::deserialize(buf).is_err()); +} + +#[test] +fn test_lazy_serialize() { + type Buf = LazyBuffer; + + let mut buf1 = Buf::default(); + let ser0 = buf1.serialize(); + assert_eq!(&ser0[..], &[0, 0, 0, 0, 0]); + assert_eq!(Buf::deserialize(&ser0).unwrap().serialize(), ser0); + + buf1.digest_blocks(&[41, 42], |_| {}); + + let ser1 = buf1.serialize(); + assert_eq!(&ser1[..], &[2, 41, 42, 0, 0]); + + let mut buf2 = Buf::deserialize(&ser1).unwrap(); + assert_eq!(buf1.serialize(), ser1); + + buf1.digest_blocks(&[43], |_| {}); + buf2.digest_blocks(&[43], |_| {}); + + let ser2 = buf1.serialize(); + assert_eq!(&ser2[..], &[3, 41, 42, 43, 0]); + assert_eq!(buf1.serialize(), ser2); + + let mut buf3 = Buf::deserialize(&ser2).unwrap(); + assert_eq!(buf3.serialize(), ser2); + + buf1.digest_blocks(&[44], |_| {}); + buf2.digest_blocks(&[44], |_| {}); + buf3.digest_blocks(&[44], |_| {}); + + let ser3 = buf1.serialize(); + assert_eq!(&ser3[..], &[4, 41, 42, 43, 44]); + assert_eq!(buf2.serialize(), ser3); + assert_eq!(buf3.serialize(), ser3); + + buf1.digest_blocks(&[45], |_| {}); + buf2.digest_blocks(&[45], |_| {}); + buf3.digest_blocks(&[45], |_| {}); + + let ser4 = buf1.serialize(); + assert_eq!(&ser4[..], &[1, 45, 0, 0, 0]); + assert_eq!(buf2.serialize(), ser4); + assert_eq!(buf3.serialize(), ser4); + + // Invalid position + let buf = GenericArray::from_slice(&[10, 0, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[5, 0, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + // "Garbage" bytes are not zeroized + let buf = GenericArray::from_slice(&[0, 1, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[1, 0, 1, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[2, 0, 0, 1, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[3, 0, 0, 0, 1]); + assert!(Buf::deserialize(buf).is_err()); +} + +#[test] +fn test_read_serialize() { + type Buf = ReadBuffer; + + let mut n = 42u8; + let mut gen = |block: &mut Block| { + block.iter_mut().for_each(|b| { + *b = n; + n += 1; + }); + }; + + let mut buf1 = Buf::default(); + let ser0 = buf1.serialize(); + assert_eq!(&ser0[..], &[4, 0, 0, 0]); + assert_eq!(Buf::deserialize(&ser0).unwrap().serialize(), ser0); + + buf1.read(&mut [0; 2], &mut gen); + + let ser1 = buf1.serialize(); + assert_eq!(&ser1[..], &[2, 0, 44, 45]); + + let mut buf2 = Buf::deserialize(&ser1).unwrap(); + assert_eq!(buf1.serialize(), ser1); + + buf1.read(&mut [0; 1], &mut gen); + buf2.read(&mut [0; 1], &mut gen); + + let ser2 = buf1.serialize(); + assert_eq!(&ser2[..], &[3, 0, 0, 45]); + assert_eq!(buf1.serialize(), ser2); + + let mut buf3 = Buf::deserialize(&ser2).unwrap(); + assert_eq!(buf3.serialize(), ser2); + + buf1.read(&mut [0; 1], &mut gen); + buf2.read(&mut [0; 1], &mut gen); + buf3.read(&mut [0; 1], &mut gen); + + let ser3 = buf1.serialize(); + assert_eq!(&ser3[..], &[4, 0, 0, 0]); + assert_eq!(buf2.serialize(), ser3); + assert_eq!(buf3.serialize(), ser3); + + buf1.read(&mut [0; 1], &mut gen); + buf2.read(&mut [0; 1], &mut gen); + buf3.read(&mut [0; 1], &mut gen); + + // note that each buffer calls `gen`, so they get filled + // with different data + assert_eq!(&buf1.serialize()[..], &[1, 47, 48, 49]); + assert_eq!(&buf2.serialize()[..], &[1, 51, 52, 53]); + assert_eq!(&buf3.serialize()[..], &[1, 55, 56, 57]); + + // Invalid position + let buf = GenericArray::from_slice(&[0, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[5, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[10, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + // "Garbage" bytes are not zeroized + let buf = GenericArray::from_slice(&[2, 1, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[3, 0, 1, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[4, 0, 0, 1]); + assert!(Buf::deserialize(buf).is_err()); +} From 246d56a7b404811b68377289cb84cbfa69d5e348 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 8 Jan 2023 12:54:39 -0700 Subject: [PATCH 047/116] CI: disable macOS builds on MSRV (#827) There are currently build failures on `master` for `cpufeatures` and `zeroize`, which test on macOS runners: https://github.com/RustCrypto/utils/actions/runs/3733690805/jobs/6594187401#step:6:13 = note: ld: in /Users/runner/.rustup/toolchains/1.40.0-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libgetopts-1988d9ef7be544ff.rlib(rust.metadata.bin), archive member 'rust.metadata.bin' with length 198423 is not mach-o or llvm bitcode file '/Users/runner/.rustup/toolchains/1.40.0-x86_64-apple-darwin/lib/rustlib/x86_64-apple-darwin/lib/libgetopts-1988d9ef7be544ff.rlib' It seems these older rustc versions do not support linking with the latest macOS compilers. The build on `stable` works, so we can continue to test macOS, just not that these two crates are MSRV compatible on macOS. --- .github/workflows/cpufeatures.yml | 3 ++- .github/workflows/zeroize.yml | 7 ++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/.github/workflows/cpufeatures.yml b/.github/workflows/cpufeatures.yml index e4b4df44..09300979 100644 --- a/.github/workflows/cpufeatures.yml +++ b/.github/workflows/cpufeatures.yml @@ -60,7 +60,8 @@ jobs: strategy: matrix: toolchain: - - 1.40.0 # MSRV + # TODO(tarcieri): try re-enabling this when we bump MSRV + # - 1.40.0 # MSRV - stable runs-on: macos-latest steps: diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index 54abeb14..c30b19db 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -70,9 +70,10 @@ jobs: rust: stable # 64-bit macOS x86_64 - - target: x86_64-apple-darwin - platform: macos-latest - rust: 1.51.0 # MSRV + # TODO(tarcieri): try re-enabling this when we bump MSRV + # - target: x86_64-apple-darwin + # platform: macos-latest + # rust: 1.51.0 # MSRV - target: x86_64-apple-darwin platform: macos-latest rust: stable From 2a55b8965cc10b755464fa153d480a51aa76dbd6 Mon Sep 17 00:00:00 2001 From: David Cook Date: Sat, 14 Jan 2023 07:46:44 -0600 Subject: [PATCH 048/116] Fix doc typo in dbl (#828) --- dbl/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dbl/src/lib.rs b/dbl/src/lib.rs index 66fd555c..bddc565a 100644 --- a/dbl/src/lib.rs +++ b/dbl/src/lib.rs @@ -31,7 +31,7 @@ pub trait Dbl { #[must_use] fn dbl(self) -> Self; - /// Reverse double block. (alternatively: divbide block by x) + /// Reverse double block. (alternatively: divide block by x) /// /// If least significant bit of the block equals to zero will return /// `block>>1`, otherwise `(block>>1)^(1<>1)` From ebf7d04fe9909f6f3be2d4a5c2836e72e7c08fdf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 17 Jan 2023 07:39:45 -0700 Subject: [PATCH 049/116] build(deps): bump proc-macro2 from 1.0.49 to 1.0.50 (#829) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.49 to 1.0.50. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.49...1.0.50) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b7428d0a..cada6f4f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,9 +125,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.49" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" +checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" dependencies = [ "unicode-ident", ] From 8c8bbf76e0545024c53f5f2eb54b6288adc1e7f3 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 20 Jan 2023 21:59:39 -0700 Subject: [PATCH 050/116] cmov: redesigned trait-based API (#830) Replaces the existing API with a `Cmov` trait which is impl'd for all of the unsigned integer types. On x86 platforms this adds support for using both EAX and RAX register operands. On aarch64 platforms it adds support for using both W0 and X0 register operands. Support for `u8` is impl'd generically via upcasting, and support for `u128` is impl'd generically by splitting the value into two `u64`s and doing two selections. Platform-by-platform support is now split into `aarch64`, `x86`, and `portable` backend modules. --- Cargo.lock | 2 +- cmov/Cargo.toml | 2 +- cmov/src/aarch64.rs | 90 ++++++++++++++++++++++ cmov/src/lib.rs | 177 ++++++++++++------------------------------- cmov/src/portable.rs | 67 ++++++++++++++++ cmov/src/x86.rs | 62 +++++++++++++++ cmov/tests/lib.rs | 149 ++++++++++++++++++++++++++++++++++++ 7 files changed, 420 insertions(+), 129 deletions(-) create mode 100644 cmov/src/aarch64.rs create mode 100644 cmov/src/portable.rs create mode 100644 cmov/src/x86.rs create mode 100644 cmov/tests/lib.rs diff --git a/Cargo.lock b/Cargo.lock index cada6f4f..c5efa063 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "cmov" -version = "0.1.1" +version = "0.2.0-pre" [[package]] name = "collectable" diff --git a/cmov/Cargo.toml b/cmov/Cargo.toml index 581f4b4d..6b05109b 100644 --- a/cmov/Cargo.toml +++ b/cmov/Cargo.toml @@ -6,7 +6,7 @@ constant-time and not be rewritten as branches by the compiler. Provides wrappers for the CMOV family of instructions on x86/x86_64 and CSEL on AArch64. """ -version = "0.1.1" +version = "0.2.0-pre" authors = ["RustCrypto Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/cmov" diff --git a/cmov/src/aarch64.rs b/cmov/src/aarch64.rs new file mode 100644 index 00000000..eb294617 --- /dev/null +++ b/cmov/src/aarch64.rs @@ -0,0 +1,90 @@ +use crate::{Cmov, Condition}; +use core::arch::asm; + +macro_rules! csel { + ($cmp:expr, $csel:expr, $dst:expr, $src:expr, $condition:expr) => { + unsafe { + asm! { + $cmp, + $csel, + in(reg) $condition, + inlateout(reg) *$dst, + in(reg) $src, + in(reg) *$dst, + options(pure, nomem, nostack), + }; + } + }; +} + +impl Cmov for u16 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + csel!( + "cmp {0:w}, 0", + "csel {1:w}, {2:w}, {3:w}, EQ", + self, + value, + condition + ); + } + + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + csel!( + "cmp {0:w}, 0", + "csel {1:w}, {2:w}, {3:w}, NE", + self, + value, + condition + ); + } +} + +impl Cmov for u32 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + csel!( + "cmp {0:w}, 0", + "csel {1:w}, {2:w}, {3:w}, EQ", + self, + value, + condition + ); + } + + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + csel!( + "cmp {0:w}, 0", + "csel {1:w}, {2:w}, {3:w}, NE", + self, + value, + condition + ); + } +} + +impl Cmov for u64 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + csel!( + "cmp {0:x}, 0", + "csel {1:x}, {2:x}, {3:x}, EQ", + self, + value, + condition + ); + } + + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + csel!( + "cmp {0:x}, 0", + "csel {1:x}, {2:x}, {3:x}, NE", + self, + value, + condition + ); + } +} diff --git a/cmov/src/lib.rs b/cmov/src/lib.rs index c72cda99..907e3658 100644 --- a/cmov/src/lib.rs +++ b/cmov/src/lib.rs @@ -6,146 +6,69 @@ )] #![warn(missing_docs, rust_2018_idioms, unused_qualifications)] -#[cfg(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64"))] -use core::arch::asm; - -/// Move if zero. -/// -/// Uses a `test` instruction to check if the given `condition` value is -/// equal to zero, then calls `cmovz` (a.k.a. `cmove`) to conditionally move -/// `src` to `dst` when `condition` is equal to zero. +#[cfg(target_arch = "aarch64")] +mod aarch64; +#[cfg(not(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")))] +mod portable; #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -#[inline(always)] -pub fn cmovz(condition: usize, src: usize, dst: &mut usize) { - unsafe { - asm! { - "test {0}, {0}", - "cmovz {1}, {2}", - in(reg) condition, - inlateout(reg) *dst, - in(reg) src, - options(pure, nomem, nostack), - }; - } -} +mod x86; -/// Move if zero. -/// -/// Uses a `cmp` instruction to check if the given `condition` value is -/// equal to zero, then calls `csel` to conditionally move -/// `src` to `dst` when `condition` is equal to zero. -#[cfg(any(target_arch = "aarch64"))] -#[inline(always)] -pub fn cmovz(condition: usize, src: usize, dst: &mut usize) { - unsafe { - asm! { - "cmp {0}, 0", - "csel {1}, {2}, {3}, EQ", - in(reg) condition, - inlateout(reg) *dst, - in(reg) src, - in(reg) *dst, - options(pure, nomem, nostack), - }; - } +/// Condition +pub type Condition = u8; + +/// Conditional move +pub trait Cmov { + /// Move if zero. + /// + /// Uses a `cmp` instruction to check if the given `condition` value is + /// equal to zero, and if so, conditionally moves `value` to `self` + /// when `condition` is equal to zero. + fn cmovz(&mut self, value: Self, condition: Condition); + + /// Move if non-zero. + /// + /// Uses a `test` instruction to check if the given `condition` value is + /// equal to zero, conditionally moves `value` to `self` when `condition` is + /// equal to zero. + fn cmovnz(&mut self, value: Self, condition: Condition); } -/// Move if not zero. -/// -/// Uses a `cmp` instruction to check if the given `condition` value is not -/// equal to zero, then calls `csel` to conditionally move -/// `src` to `dst` when `condition` is nonzero. -#[cfg(any(target_arch = "aarch64"))] -#[inline(always)] -pub fn cmovnz(condition: usize, src: usize, dst: &mut usize) { - unsafe { - asm! { - "cmp {0}, 0", - "csel {1}, {2}, {3}, NE", - in(reg) condition, - inlateout(reg) *dst, - in(reg) src, - in(reg) *dst, - options(pure, nomem, nostack), - }; +impl Cmov for u8 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + let mut tmp = *self as u16; + tmp.cmovz(value as u16, condition); + *self = tmp as u8; } -} -/// Move if not zero. -/// -/// Uses a `test` instruction to check if the given `condition` value is not -/// equal to zero, then calls `cmovnz` (a.k.a. `cmovne`) to conditionally move -/// `src` to `dst` when `condition` is nonzero. -#[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -#[inline(always)] -pub fn cmovnz(condition: usize, src: usize, dst: &mut usize) { - unsafe { - asm! { - "test {0}, {0}", - "cmovnz {1}, {2}", - in(reg) condition, - inlateout(reg) *dst, - in(reg) src, - options(pure, nomem, nostack), - }; + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + let mut tmp = *self as u16; + tmp.cmovnz(value as u16, condition); + *self = tmp as u8; } } -/// Move if zero (portable fallback implementation). -/// -/// This implementation is based on portable bitwise arithmetic but cannot -/// guarantee that the resulting generated assembly is free of branch -/// instructions. -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")))] -#[inline(never)] -pub fn cmovz(condition: usize, src: usize, dst: &mut usize) { - let mask = (1 ^ is_non_zero(condition)).wrapping_sub(1); - *dst = (*dst & mask) | (src & !mask); -} +impl Cmov for u128 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + let mut lo = (*self & u64::MAX as u128) as u64; + let mut hi = (*self >> 64) as u64; -/// Move if not zero (portable fallback implementation). -/// -/// This implementation is based on portable bitwise arithmetic but cannot -/// guarantee that the resulting generated assembly is free of branch -/// instructions. -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")))] -#[inline(never)] -pub fn cmovnz(condition: usize, src: usize, dst: &mut usize) { - let mask = is_non_zero(condition).wrapping_sub(1); - *dst = (*dst & mask) | (src & !mask); -} + lo.cmovz((value & u64::MAX as u128) as u64, condition); + hi.cmovz((value >> 64) as u64, condition); -/// Check if the given condition value is non-zero -/// -/// # Returns -/// - `condition` is zero: `0` -/// - `condition` is non-zero: `1` -#[cfg(not(any(target_arch = "x86", target_arch = "x86_64", target_arch = "aarch64")))] -#[inline(always)] -fn is_non_zero(condition: usize) -> usize { - const SHIFT_BITS: usize = core::mem::size_of::() - 1; - ((condition | (!condition).wrapping_add(1)) >> SHIFT_BITS) & 1 -} + *self = (lo as u128) | (hi as u128) << 64; + } -#[cfg(test)] -mod tests { - use super::*; + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + let mut lo = (*self & u64::MAX as u128) as u64; + let mut hi = (*self >> 64) as u64; - #[test] - fn cmovz_works() { - let mut n = 24; - cmovz(42, 42, &mut n); - assert_eq!(n, 24); - cmovz(0, 42, &mut n); - assert_eq!(n, 42); - } + lo.cmovnz((value & u64::MAX as u128) as u64, condition); + hi.cmovnz((value >> 64) as u64, condition); - #[test] - fn cmovnz_works() { - let mut n = 24; - cmovnz(0, 42, &mut n); - assert_eq!(n, 24); - cmovnz(42, 42, &mut n); - assert_eq!(n, 42); + *self = (lo as u128) | (hi as u128) << 64; } } diff --git a/cmov/src/portable.rs b/cmov/src/portable.rs new file mode 100644 index 00000000..7bce46eb --- /dev/null +++ b/cmov/src/portable.rs @@ -0,0 +1,67 @@ +//! Portable "best effort" implementation of `Cmov`. +//! +//! This implementation is based on portable bitwise arithmetic but cannot +//! guarantee that the resulting generated assembly is free of branch +//! instructions. + +// TODO(tarcieri): more optimized implementation for small integers + +use crate::{Cmov, Condition}; + +impl Cmov for u16 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + let mut tmp = *self as u64; + tmp.cmovz(value as u64, condition); + *self = tmp as u16; + } + + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + let mut tmp = *self as u64; + tmp.cmovnz(value as u64, condition); + *self = tmp as u16; + } +} + +impl Cmov for u32 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + let mut tmp = *self as u64; + tmp.cmovz(value as u64, condition); + *self = tmp as u32; + } + + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + let mut tmp = *self as u64; + tmp.cmovnz(value as u64, condition); + *self = tmp as u32; + } +} + +impl Cmov for u64 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + let mask = (1 ^ is_non_zero(condition)).wrapping_sub(1); + *self = (*self & mask) | (value & !mask); + } + + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + let mask = is_non_zero(condition).wrapping_sub(1); + *self = (*self & mask) | (value & !mask); + } +} + +/// Check if the given condition value is non-zero +/// +/// # Returns +/// - `condition` is zero: `0` +/// - `condition` is non-zero: `1` +#[inline(always)] +fn is_non_zero(condition: Condition) -> u64 { + const SHIFT_BITS: usize = core::mem::size_of::() - 1; + let condition = condition as u64; + ((condition | (!condition).wrapping_add(1)) >> SHIFT_BITS) & 1 +} diff --git a/cmov/src/x86.rs b/cmov/src/x86.rs new file mode 100644 index 00000000..cc4c60b2 --- /dev/null +++ b/cmov/src/x86.rs @@ -0,0 +1,62 @@ +//! From "AMD64 Architecture Programmer’s Manual, Volume 1: Application Programming" +//! (Rev. 3.23 - October 2020) page 46: +//! +//! +//! +//! > The CMOVcc instructions conditionally copy a word, doubleword, or +//! > quadword from a register or memory location to a register location. +//! > The source and destination must be of the same size. + +use crate::{Cmov, Condition}; +use core::arch::asm; + +macro_rules! cmov { + ($instruction:expr, $dst:expr, $src:expr, $condition:expr) => { + unsafe { + asm! { + "test {0}, {0}", + $instruction, + in(reg_byte) $condition, + inlateout(reg) *$dst, + in(reg) $src, + options(pure, nomem, nostack), + }; + } + }; +} + +impl Cmov for u16 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + cmov!("cmovz {1:e}, {2:e}", self, value, condition); + } + + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + cmov!("cmovnz {1:e}, {2:e}", self, value, condition); + } +} + +impl Cmov for u32 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + cmov!("cmovz {1:e}, {2:e}", self, value, condition); + } + + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + cmov!("cmovnz {1:e}, {2:e}", self, value, condition); + } +} + +impl Cmov for u64 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + cmov!("cmovz {1:r}, {2:r}", self, value, condition); + } + + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + cmov!("cmovnz {1:r}, {2:r}", self, value, condition); + } +} diff --git a/cmov/tests/lib.rs b/cmov/tests/lib.rs new file mode 100644 index 00000000..3a321a4c --- /dev/null +++ b/cmov/tests/lib.rs @@ -0,0 +1,149 @@ +mod u8 { + use cmov::Cmov; + + #[test] + fn cmovz_works() { + let mut n = 0x11u8; + + for cond in 1..0xFF { + n.cmovz(0x22, cond); + assert_eq!(n, 0x11); + } + + n.cmovz(0x22, 0); + assert_eq!(n, 0x22); + } + + #[test] + fn cmovnz_works() { + let mut n = 0x11u8; + n.cmovnz(0x22, 0); + assert_eq!(n, 0x11); + + for cond in 1..0xFF { + let mut n = 0x11u8; + n.cmovnz(0x22, cond); + assert_eq!(n, 0x22); + } + } +} + +mod u16 { + use cmov::Cmov; + + #[test] + fn cmovz_works() { + let mut n = 0x1111u16; + + for cond in 1..0xFF { + n.cmovz(0x2222, cond); + assert_eq!(n, 0x1111); + } + + n.cmovz(0x2222, 0); + assert_eq!(n, 0x2222); + } + + #[test] + fn cmovnz_works() { + let mut n = 0x1111u16; + n.cmovnz(0x2222, 0); + assert_eq!(n, 0x1111); + + for cond in 1..0xFF { + let mut n = 0x1111u16; + n.cmovnz(0x2222, cond); + assert_eq!(n, 0x2222); + } + } +} + +mod u32 { + use cmov::Cmov; + + #[test] + fn cmovz_works() { + let mut n = 0x11111111u32; + + for cond in 1..0xFF { + n.cmovz(0x22222222, cond); + assert_eq!(n, 0x11111111); + } + + n.cmovz(0x22222222, 0); + assert_eq!(n, 0x22222222); + } + + #[test] + fn cmovnz_works() { + let mut n = 0x11111111u32; + n.cmovnz(0x22222222, 0); + assert_eq!(n, 0x11111111); + + for cond in 1..0xFF { + let mut n = 0x11111111u32; + n.cmovnz(0x22222222, cond); + assert_eq!(n, 0x22222222); + } + } +} + +mod u64 { + use cmov::Cmov; + + #[test] + fn cmovz_works() { + let mut n = 0x11111111_11111111u64; + + for cond in 1..0xFF { + n.cmovz(0x22222222_22222222, cond); + assert_eq!(n, 0x11111111_11111111); + } + + n.cmovz(0x22222222_22222222, 0); + assert_eq!(n, 0x22222222_22222222); + } + + #[test] + fn cmovnz_works() { + let mut n = 0x11111111_11111111u64; + n.cmovnz(0x22222222_22222222, 0); + assert_eq!(n, 0x11111111_11111111); + + for cond in 1..0xFF { + let mut n = 0x11111111_11111111u64; + n.cmovnz(0x22222222_22222222, cond); + assert_eq!(n, 0x22222222_22222222); + } + } +} + +mod u128 { + use cmov::Cmov; + + #[test] + fn cmovz_works() { + let mut n = 0x11111111_11111111_22222222_22222222u128; + + for cond in 1..0xFF { + n.cmovz(0x22222222_22222222_33333333_33333333, cond); + assert_eq!(n, 0x11111111_11111111_22222222_22222222); + } + + n.cmovz(0x22222222_22222222_33333333_33333333, 0); + assert_eq!(n, 0x22222222_22222222_33333333_33333333); + } + + #[test] + fn cmovnz_works() { + let mut n = 0x11111111_11111111_22222222_22222222u128; + n.cmovnz(0x22222222_22222222_33333333_33333333, 0); + assert_eq!(n, 0x11111111_11111111_22222222_22222222); + + for cond in 1..0xFF { + let mut n = 0x11111111_11111111u128; + n.cmovnz(0x22222222_22222222_33333333_33333333, cond); + assert_eq!(n, 0x22222222_22222222_33333333_33333333); + } + } +} From 92f47b9380452f9abd875f0251436cef99c0f59d Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 12 Feb 2023 10:23:17 -0700 Subject: [PATCH 051/116] fiat-constify: fix rustdoc lint warning in output (#836) The link to the utils repo should be angle-bracketed to make the rustdoc linter happy. --- fiat-constify/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fiat-constify/src/main.rs b/fiat-constify/src/main.rs index fb1bd406..a0df28a1 100644 --- a/fiat-constify/src/main.rs +++ b/fiat-constify/src/main.rs @@ -52,7 +52,7 @@ fn main() -> Result<(), Box> { } } - println!("#![doc = \" fiat-crypto output postprocessed by fiat-constify: https://github.com/rustcrypto/utils\"]"); + println!("#![doc = \" fiat-crypto output postprocessed by fiat-constify: \"]"); println!("{}", ast.into_token_stream()); Ok(()) } From 91c2c216a5017d444dfd718c198ad3a3e31452c6 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 16 Feb 2023 17:26:12 +0200 Subject: [PATCH 052/116] doc: remove extraneous words (#838) --- zeroize/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index 3cb58224..36631223 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -64,7 +64,7 @@ //! //! With the `std` feature enabled (which it is **not** by default), [`Zeroize`] //! is also implemented for [`CString`]. After calling `zeroize()` on a `CString`, -//! it will its internal buffer will contain exactly one nul byte. The backing +//! its internal buffer will contain exactly one nul byte. The backing //! memory is zeroed by converting it to a `Vec` and back into a `CString`. //! (NOTE: see "Stack/Heap Zeroing Notes" for important `Vec`/`String`/`CString` details) //! From 754487eb626b236af135b3dacc35f7b53561c7ec Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 26 Feb 2023 13:02:59 -0700 Subject: [PATCH 053/116] CI: use Rust 1.67 for `clippy` (#840) This is primarily to unblock #839 --- .github/workflows/workspace.yml | 2 +- fiat-constify/src/main.rs | 2 +- inout/src/inout.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index ea421cf3..c64c40aa 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -17,7 +17,7 @@ jobs: - uses: RustCrypto/actions/cargo-cache@master - uses: actions-rs/toolchain@v1 with: - toolchain: 1.59.0 # Highest MSRV in repo + toolchain: 1.67.0 # Pinned to prevent breakages components: clippy override: true profile: minimal diff --git a/fiat-constify/src/main.rs b/fiat-constify/src/main.rs index a0df28a1..c26a5c2c 100644 --- a/fiat-constify/src/main.rs +++ b/fiat-constify/src/main.rs @@ -357,7 +357,7 @@ impl Outputs { pub fn to_return_value(&self) -> Stmt { let span = Span::call_site(); - let mut elems = self.0.iter().map(|(ident, _)| { + let mut elems = self.0.keys().map(|ident| { let mut segments = Punctuated::new(); segments.push(PathSegment { ident: ident.clone(), diff --git a/inout/src/inout.rs b/inout/src/inout.rs index 8fab6b03..4cdad404 100644 --- a/inout/src/inout.rs +++ b/inout/src/inout.rs @@ -71,7 +71,7 @@ impl<'inp, 'out, T: Clone> InOut<'inp, 'out, T> { /// Clone input value and return it. #[inline(always)] pub fn clone_in(&self) -> T { - unsafe { (&*self.in_ptr).clone() } + unsafe { (*self.in_ptr).clone() } } } From 0256fff4d67edb4956f5200b877f41038c4ef7e7 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 26 Feb 2023 13:28:58 -0700 Subject: [PATCH 054/116] cmov v0.2.0 (#839) --- .github/workflows/cmov.yml | 14 +++++++------- Cargo.lock | 2 +- cmov/CHANGELOG.md | 14 ++++++++++++++ cmov/Cargo.toml | 4 ++-- cmov/README.md | 9 +++++---- cmov/src/lib.rs | 1 + 6 files changed, 30 insertions(+), 14 deletions(-) diff --git a/.github/workflows/cmov.yml b/.github/workflows/cmov.yml index 1546b19c..b5ec37da 100644 --- a/.github/workflows/cmov.yml +++ b/.github/workflows/cmov.yml @@ -27,7 +27,7 @@ jobs: strategy: matrix: rust: - - 1.59.0 # MSRV + - 1.60.0 # MSRV - stable target: - thumbv7em-none-eabi @@ -51,23 +51,23 @@ jobs: # 32-bit Linux - target: i686-unknown-linux-gnu platform: ubuntu-latest - rust: 1.59.0 # MSRV + rust: 1.60.0 # MSRV deps: sudo apt update && sudo apt install gcc-multilib # 64-bit Linux - target: x86_64-unknown-linux-gnu platform: ubuntu-latest - rust: 1.59.0 # MSRV + rust: 1.60.0 # MSRV # 64-bit Windows - target: x86_64-pc-windows-msvc platform: windows-latest - rust: 1.59.0 # MSRV + rust: 1.60.0 # MSRV # 64-bit macOS - target: x86_64-apple-darwin platform: macos-latest - rust: 1.59.0 # MSRV + rust: 1.60.0 # MSRV runs-on: ${{ matrix.platform }} steps: @@ -89,13 +89,13 @@ jobs: include: # ARM64 - target: aarch64-unknown-linux-gnu - rust: 1.59.0 # MSRV + rust: 1.60.0 # MSRV - target: aarch64-unknown-linux-gnu rust: stable # PPC32 - target: powerpc-unknown-linux-gnu - rust: 1.59.0 # MSRV + rust: 1.60.0 # MSRV - target: powerpc-unknown-linux-gnu rust: stable diff --git a/Cargo.lock b/Cargo.lock index c5efa063..5b9a513a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "cmov" -version = "0.2.0-pre" +version = "0.2.0" [[package]] name = "collectable" diff --git a/cmov/CHANGELOG.md b/cmov/CHANGELOG.md index ccb98bf2..9350f141 100644 --- a/cmov/CHANGELOG.md +++ b/cmov/CHANGELOG.md @@ -4,6 +4,20 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.0 (2023-02-26) +### Added +- `Condition` alias for `u8` ([#830]) + +### Changed +- Redesigned trait-based API ([#830]) + - Built around a `Cmov` trait + - Trait is impl'd for `u8`, `u16`, `u32`, `u64`, `u128` + - Accepts a `Condition` (i.e. `u8`) as a predicate +- MSRV 1.60 ([#839]) + +[#830]: https://github.com/RustCrypto/utils/pull/830 +[#839]: https://github.com/RustCrypto/utils/pull/839 + ## 0.1.1 (2022-03-02) ### Added - `cmovz`/`cmovnz`-alike support for AArch64 targets ([#744]) diff --git a/cmov/Cargo.toml b/cmov/Cargo.toml index 6b05109b..a0c2eacb 100644 --- a/cmov/Cargo.toml +++ b/cmov/Cargo.toml @@ -6,7 +6,7 @@ constant-time and not be rewritten as branches by the compiler. Provides wrappers for the CMOV family of instructions on x86/x86_64 and CSEL on AArch64. """ -version = "0.2.0-pre" +version = "0.2.0" authors = ["RustCrypto Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/cmov" @@ -14,4 +14,4 @@ categories = ["cryptography", "hardware-support", "no-std"] keywords = ["crypto", "intrinsics"] readme = "README.md" edition = "2021" -rust-version = "1.59" +rust-version = "1.60" diff --git a/cmov/README.md b/cmov/README.md index a708126f..cdd55319 100644 --- a/cmov/README.md +++ b/cmov/README.md @@ -1,4 +1,4 @@ -# [RustCrypto]: Conditional Move Intrinsics +# [RustCrypto]: CMOV (Conditional Move) [![Crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] @@ -10,7 +10,8 @@ Conditional move CPU intrinsics which are guaranteed to execute in constant-time and not be rewritten as branches by the compiler. Provides wrappers for the [CMOV family] of instructions on x86/x86_64 and -the [CSEL] instruction on AArch64 CPUs. +the [CSEL] instruction on AArch64 CPUs, along with a portable fallback +implementation for other CPU architectures. [Documentation][docs-link] @@ -50,7 +51,7 @@ Please open an issue with your desired CPU architecture if this interests you. ## Minimum Supported Rust Version -Rust **1.59** or newer. +Rust **1.60** 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 @@ -78,7 +79,7 @@ dual licensed as above, without any additional terms or conditions. [docs-image]: https://docs.rs/cmov/badge.svg [docs-link]: https://docs.rs/cmov/ [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg -[msrv-image]: https://img.shields.io/badge/rustc-1.59+-blue.svg +[msrv-image]: https://img.shields.io/badge/rustc-1.60+-blue.svg [build-image]: https://github.com/RustCrypto/utils/actions/workflows/cmov.yml/badge.svg [build-link]: https://github.com/RustCrypto/utils/actions/workflows/cmov.yml diff --git a/cmov/src/lib.rs b/cmov/src/lib.rs index 907e3658..c899cf95 100644 --- a/cmov/src/lib.rs +++ b/cmov/src/lib.rs @@ -17,6 +17,7 @@ mod x86; pub type Condition = u8; /// Conditional move +// TODO(tarcieri): make one of `cmovz`/`cmovnz` a provided method which calls the other? pub trait Cmov { /// Move if zero. /// From d7b383d85def928c04ec3eee434d3f6a1a43d563 Mon Sep 17 00:00:00 2001 From: Nugine Date: Fri, 3 Mar 2023 00:08:09 +0800 Subject: [PATCH 055/116] zeroize: impl Zeroize for `str` and `Box` (#842) --- zeroize/src/lib.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index 36631223..4e006578 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -476,6 +476,14 @@ where } } +impl Zeroize for str { + fn zeroize(&mut self) { + // Safety: + // A zeroized byte slice is a valid UTF-8 string. + unsafe { self.as_bytes_mut().zeroize() } + } +} + /// [`PhantomData`] is always zero sized so provide a [`Zeroize`] implementation. impl Zeroize for PhantomData { fn zeroize(&mut self) {} @@ -588,6 +596,14 @@ where #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl ZeroizeOnDrop for Box<[Z]> where Z: ZeroizeOnDrop {} +#[cfg(feature = "alloc")] +#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] +impl Zeroize for Box { + fn zeroize(&mut self) { + self.as_mut().zeroize(); + } +} + #[cfg(feature = "alloc")] #[cfg_attr(docsrs, doc(cfg(feature = "alloc")))] impl Zeroize for String { From e4a2627bfab37d382573b5732e68b004062dfa2d Mon Sep 17 00:00:00 2001 From: Yoshiya Hinosawa Date: Fri, 10 Mar 2023 18:23:42 +0900 Subject: [PATCH 056/116] docs: fix typo in doc of `pad` (#845) --- block-padding/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block-padding/src/lib.rs b/block-padding/src/lib.rs index 0779b79c..3f2fc67e 100644 --- a/block-padding/src/lib.rs +++ b/block-padding/src/lib.rs @@ -41,7 +41,7 @@ pub trait Padding> { /// stored in the block is equal to `pos`). /// /// # Panics - /// If `pos` is bigger than `BlockSize`. Most paddin algorithms also + /// If `pos` is bigger than `BlockSize`. Most padding algorithms also /// panic if they are equal. fn pad(block: &mut Block, pos: usize); From 9c27e5b2430f42193bd2b80e16e94f96c711babb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 12 Mar 2023 20:10:07 -0600 Subject: [PATCH 057/116] build(deps): bump proc-macro2 from 1.0.50 to 1.0.51 (#835) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.50 to 1.0.51. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.50...1.0.51) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b9a513a..6a2bc7e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,9 +125,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.50" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2" +checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" dependencies = [ "unicode-ident", ] From bb022c838c12516659d10c4c9ae1d29a69ee0844 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 13 Mar 2023 07:50:23 -0600 Subject: [PATCH 058/116] build(deps): bump proc-macro2 from 1.0.51 to 1.0.52 (#847) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.51 to 1.0.52. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.51...1.0.52) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6a2bc7e9..d70ff0d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,9 +125,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.51" +version = "1.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6" +checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" dependencies = [ "unicode-ident", ] From 06427069ee676fb185d6738d327dfe9353f17346 Mon Sep 17 00:00:00 2001 From: ComplexSpaces Date: Sat, 18 Mar 2023 12:16:17 -0500 Subject: [PATCH 059/116] Support dynamic feature detection on iOS and derivative platforms (#848) --- cpufeatures/Cargo.toml | 2 +- cpufeatures/src/aarch64.rs | 42 +++++++------------------------------- 2 files changed, 8 insertions(+), 36 deletions(-) diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index d42f9dca..4022d0a1 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -14,7 +14,7 @@ categories = ["no-std"] edition = "2018" readme = "README.md" -[target.aarch64-apple-darwin.dependencies] +[target.'cfg(all(target_arch = "aarch64", target_vendor = "apple"))'.dependencies] libc = "0.2.95" [target.'cfg(all(target_arch = "aarch64", target_os = "linux"))'.dependencies] diff --git a/cpufeatures/src/aarch64.rs b/cpufeatures/src/aarch64.rs index 6efdde1a..2c9a044b 100644 --- a/cpufeatures/src/aarch64.rs +++ b/cpufeatures/src/aarch64.rs @@ -37,8 +37,8 @@ pub fn getauxval_hwcap() -> u64 { unsafe { libc::getauxval(libc::AT_HWCAP) } } -// MacOS runtime detection of target CPU features using `sysctlbyname`. -#[cfg(target_os = "macos")] +// Apple platform's runtime detection of target CPU features using `sysctlbyname`. +#[cfg(target_vendor = "apple")] #[macro_export] #[doc(hidden)] macro_rules! __detect_target_features { @@ -87,7 +87,7 @@ pub mod hwcaps { pub const SHA3: c_ulong = libc::HWCAP_SHA3 | libc::HWCAP_SHA512; } -// macOS `check!` macro. +// Apple OS (macOS, iOS, watchOS, and tvOS) `check!` macro. // // NOTE: several of these instructions (e.g. `aes`, `sha2`) can be assumed to // be present on all Apple ARM64 hardware. @@ -98,7 +98,7 @@ pub mod hwcaps { // // See discussion on this issue for more information: // -#[cfg(target_os = "macos")] +#[cfg(target_vendor = "apple")] #[macro_export] #[doc(hidden)] macro_rules! check { @@ -117,8 +117,8 @@ macro_rules! check { }; } -/// macOS helper function for calling `sysctlbyname`. -#[cfg(target_os = "macos")] +/// Apple helper function for calling `sysctlbyname`. +#[cfg(target_vendor = "apple")] pub unsafe fn sysctlbyname(name: &[u8]) -> bool { assert_eq!( name.last().cloned(), @@ -143,36 +143,8 @@ pub unsafe fn sysctlbyname(name: &[u8]) -> bool { value != 0 } -// iOS `check!` macro. -// -// Unfortunately iOS does not provide access to the `sysctl(3)` API which means -// we can only return static values for CPU features which can be assumed to -// be present on all Apple ARM64 hardware. -// -// See discussion on this issue for more information: -// -#[cfg(target_os = "ios")] -#[macro_export] -#[doc(hidden)] -macro_rules! check { - ("aes") => { - true - }; - ("sha2") => { - true - }; - ("sha3") => { - false - }; -} - // On other targets, runtime CPU feature detection is unavailable -#[cfg(not(any( - target_os = "ios", - target_os = "linux", - target_os = "android", - target_os = "macos" -)))] +#[cfg(not(any(target_vendor = "apple", target_os = "linux", target_os = "android",)))] #[macro_export] #[doc(hidden)] macro_rules! __detect_target_features { From b2926b21a0c65039b458a96a2ccd8ce4d38017cb Mon Sep 17 00:00:00 2001 From: Dirk Stolle Date: Tue, 21 Mar 2023 02:55:18 +0100 Subject: [PATCH 060/116] Replace unmaintained actions-rs/* actions in CI workflows (#852) Basically all of the `actions-rs/*` actions are unmaintained. See for more information. Due to their age they generate several warnings in CI runs. To get rid of some of those warnings the occurrences of `actions-rs/toolchain` are replaced by `dtolnay/rust-toolchain`, and the occurrences of `actions-rs/cargo` are replaced by direct invocations of `cargo`. --- .github/workflows/blobby.yml | 4 +--- .github/workflows/block-buffer.yml | 10 +++------- .github/workflows/block-padding.yml | 10 +++------- .github/workflows/cmov.yml | 18 ++++++------------ .github/workflows/cpufeatures.yml | 24 ++++++++---------------- .github/workflows/dbl.yml | 10 +++------- .github/workflows/fiat-constify.yml | 4 +--- .github/workflows/hex-literal.yml | 10 +++------- .github/workflows/hybrid-array.yml | 10 +++------- .github/workflows/inout.yml | 10 +++------- .github/workflows/opaque-debug.yml | 10 +++------- .github/workflows/workspace.yml | 13 +++---------- .github/workflows/zeroize.yml | 18 ++++++------------ 13 files changed, 46 insertions(+), 105 deletions(-) diff --git a/.github/workflows/blobby.yml b/.github/workflows/blobby.yml index d9a6d568..b7407895 100644 --- a/.github/workflows/blobby.yml +++ b/.github/workflows/blobby.yml @@ -27,11 +27,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - override: true # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo test diff --git a/.github/workflows/block-buffer.yml b/.github/workflows/block-buffer.yml index 7ea492b2..73cfe835 100644 --- a/.github/workflows/block-buffer.yml +++ b/.github/workflows/block-buffer.yml @@ -30,12 +30,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true + targets: ${{ matrix.target }} # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo build --target ${{ matrix.target }} @@ -55,11 +53,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - override: true # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo test diff --git a/.github/workflows/block-padding.yml b/.github/workflows/block-padding.yml index b9d7939c..2160c150 100644 --- a/.github/workflows/block-padding.yml +++ b/.github/workflows/block-padding.yml @@ -30,12 +30,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true + targets: ${{ matrix.target }} - run: cargo build --target ${{ matrix.target }} minimal-versions: @@ -53,9 +51,7 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - override: true - run: cargo test diff --git a/.github/workflows/cmov.yml b/.github/workflows/cmov.yml index b5ec37da..5d521412 100644 --- a/.github/workflows/cmov.yml +++ b/.github/workflows/cmov.yml @@ -35,12 +35,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true + targets: ${{ matrix.target }} - uses: RustCrypto/actions/cargo-hack-install@master - run: cargo build --target ${{ matrix.target }} @@ -73,12 +71,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - profile: minimal - override: true + targets: ${{ matrix.target }} - run: ${{ matrix.deps }} - run: cargo test @@ -103,11 +99,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - profile: minimal - override: true + targets: ${{ matrix.target }} - uses: RustCrypto/actions/cross-install@master - run: cross test --target ${{ matrix.target }} diff --git a/.github/workflows/cpufeatures.yml b/.github/workflows/cpufeatures.yml index 09300979..1161033e 100644 --- a/.github/workflows/cpufeatures.yml +++ b/.github/workflows/cpufeatures.yml @@ -44,12 +44,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true - profile: minimal + targets: ${{ matrix.target }} # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: ${{ matrix.deps }} @@ -67,12 +65,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.toolchain }} - target: x86_64-apple-darwin - override: true + targets: x86_64-apple-darwin # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo test @@ -92,12 +88,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.toolchain }} - target: ${{ matrix.target }} - override: true + targets: ${{ matrix.target }} # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo test --target ${{ matrix.target }} @@ -117,12 +111,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true - profile: minimal + targets: ${{ matrix.target }} - uses: RustCrypto/actions/cross-install@master # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml diff --git a/.github/workflows/dbl.yml b/.github/workflows/dbl.yml index 0a653f90..c470862d 100644 --- a/.github/workflows/dbl.yml +++ b/.github/workflows/dbl.yml @@ -30,12 +30,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true + targets: ${{ matrix.target }} # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo build --target ${{ matrix.target }} @@ -55,11 +53,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - override: true # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo test diff --git a/.github/workflows/fiat-constify.yml b/.github/workflows/fiat-constify.yml index 1153d519..cf0d50d1 100644 --- a/.github/workflows/fiat-constify.yml +++ b/.github/workflows/fiat-constify.yml @@ -28,10 +28,8 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.toolchain }} - override: true - profile: minimal - run: cargo test - run: cargo test --all-features diff --git a/.github/workflows/hex-literal.yml b/.github/workflows/hex-literal.yml index cfaa5153..133e36ef 100644 --- a/.github/workflows/hex-literal.yml +++ b/.github/workflows/hex-literal.yml @@ -30,12 +30,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true + targets: ${{ matrix.target }} # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo build --target ${{ matrix.target }} @@ -55,11 +53,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - override: true # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo test diff --git a/.github/workflows/hybrid-array.yml b/.github/workflows/hybrid-array.yml index 8c7ed69c..0db8798d 100644 --- a/.github/workflows/hybrid-array.yml +++ b/.github/workflows/hybrid-array.yml @@ -32,12 +32,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true - profile: minimal + targets: ${{ matrix.target }} - run: cargo build --no-default-features --target ${{ matrix.target }} minimal-versions: @@ -55,10 +53,8 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.toolchain }} - override: true - profile: minimal - run: cargo test - run: cargo test --all-features diff --git a/.github/workflows/inout.yml b/.github/workflows/inout.yml index 2176b6d3..6412ccdb 100644 --- a/.github/workflows/inout.yml +++ b/.github/workflows/inout.yml @@ -30,12 +30,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true + targets: ${{ matrix.target }} - run: cargo build --target ${{ matrix.target }} - run: cargo build --features block-padding --target ${{ matrix.target }} @@ -54,11 +52,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - override: true - run: cargo test - run: cargo test --features block-padding - run: cargo test --all-features diff --git a/.github/workflows/opaque-debug.yml b/.github/workflows/opaque-debug.yml index 80c89610..12a6664d 100644 --- a/.github/workflows/opaque-debug.yml +++ b/.github/workflows/opaque-debug.yml @@ -30,12 +30,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true + targets: ${{ matrix.target }} # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo build --target ${{ matrix.target }} @@ -55,11 +53,9 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: - profile: minimal toolchain: ${{ matrix.rust }} - override: true # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo test diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index c64c40aa..f8e79b03 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -15,25 +15,18 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: 1.67.0 # Pinned to prevent breakages components: clippy - override: true - profile: minimal - run: cargo clippy --all --all-features -- -D warnings rustfmt: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: stable components: rustfmt - profile: minimal - override: true - - uses: actions-rs/cargo@v1 - with: - command: fmt - args: --all -- --check + - run: cargo fmt --all -- --check diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index c30b19db..e99cb3db 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -32,12 +32,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - override: true - profile: minimal + targets: ${{ matrix.target }} # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: cargo build --no-default-features --target ${{ matrix.target }} @@ -89,12 +87,10 @@ jobs: steps: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - profile: minimal - override: true + targets: ${{ matrix.target }} # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: ${{ matrix.deps }} @@ -115,12 +111,10 @@ jobs: - uses: actions/checkout@v3 - uses: RustCrypto/actions/cargo-cache@master - run: ${{ matrix.deps }} - - uses: actions-rs/toolchain@v1 + - uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust }} - target: ${{ matrix.target }} - profile: minimal - override: true + targets: ${{ matrix.target }} - uses: RustCrypto/actions/cross-install@master # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml From d771c90b01898c2faff64e014edd2299438f7952 Mon Sep 17 00:00:00 2001 From: Joyce Date: Fri, 24 Mar 2023 12:43:46 -0300 Subject: [PATCH 061/116] Add SECURITY.md (#855) --- SECURITY.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..fa3e88b0 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,13 @@ +# Security Policy + +## Supported Versions + +Security updates are applied only to the most recent release. + +## Reporting a Vulnerability + +If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released. + +Please disclose it at [security advisory](https://github.com/RustCrypto/utils/security/advisories/new). + +This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure. From b05b15afa08e9d51402dbc5f7fb5b7a9f088eece Mon Sep 17 00:00:00 2001 From: jake <77554505+brxken128@users.noreply.github.com> Date: Fri, 24 Mar 2023 17:38:51 +0000 Subject: [PATCH 062/116] cmov: fix builds on `x86` (32-bit) targets (#863) --- cmov/src/x86.rs | 26 ++++++++++++++++++++++++++ cmov/tests/lib.rs | 44 ++++++++++++++++++++++---------------------- 2 files changed, 48 insertions(+), 22 deletions(-) diff --git a/cmov/src/x86.rs b/cmov/src/x86.rs index cc4c60b2..aa0fe129 100644 --- a/cmov/src/x86.rs +++ b/cmov/src/x86.rs @@ -49,6 +49,7 @@ impl Cmov for u32 { } } +#[cfg(target_arch = "x86_64")] impl Cmov for u64 { #[inline(always)] fn cmovz(&mut self, value: Self, condition: Condition) { @@ -60,3 +61,28 @@ impl Cmov for u64 { cmov!("cmovnz {1:r}, {2:r}", self, value, condition); } } + +#[cfg(target_arch = "x86")] +impl Cmov for u64 { + #[inline(always)] + fn cmovz(&mut self, value: Self, condition: Condition) { + let mut lo = (*self & u32::MAX as u64) as u32; + let mut hi = (*self >> 32) as u32; + + lo.cmovz((value & u32::MAX as u64) as u32, condition); + hi.cmovz((value >> 32) as u32, condition); + + *self = (lo as u64) | (hi as u64) << 32; + } + + #[inline(always)] + fn cmovnz(&mut self, value: Self, condition: Condition) { + let mut lo = (*self & u32::MAX as u64) as u32; + let mut hi = (*self >> 32) as u32; + + lo.cmovnz((value & u32::MAX as u64) as u32, condition); + hi.cmovnz((value >> 32) as u32, condition); + + *self = (lo as u64) | (hi as u64) << 32; + } +} diff --git a/cmov/tests/lib.rs b/cmov/tests/lib.rs index 3a321a4c..a7f7ad4a 100644 --- a/cmov/tests/lib.rs +++ b/cmov/tests/lib.rs @@ -93,27 +93,27 @@ mod u64 { #[test] fn cmovz_works() { - let mut n = 0x11111111_11111111u64; + let mut n = 0x1111_1111_1111_1111_u64; for cond in 1..0xFF { - n.cmovz(0x22222222_22222222, cond); - assert_eq!(n, 0x11111111_11111111); + n.cmovz(0x2222_2222_2222_2222, cond); + assert_eq!(n, 0x1111_1111_1111_1111); } - n.cmovz(0x22222222_22222222, 0); - assert_eq!(n, 0x22222222_22222222); + n.cmovz(0x2222_2222_2222_2222, 0); + assert_eq!(n, 0x2222_2222_2222_2222); } #[test] fn cmovnz_works() { - let mut n = 0x11111111_11111111u64; - n.cmovnz(0x22222222_22222222, 0); - assert_eq!(n, 0x11111111_11111111); + let mut n = 0x1111_1111_1111_1111_u64; + n.cmovnz(0x2222_2222_2222_2222, 0); + assert_eq!(n, 0x1111_1111_1111_1111); for cond in 1..0xFF { - let mut n = 0x11111111_11111111u64; - n.cmovnz(0x22222222_22222222, cond); - assert_eq!(n, 0x22222222_22222222); + let mut n = 0x1111_1111_1111_1111_u64; + n.cmovnz(0x2222_2222_2222_2222, cond); + assert_eq!(n, 0x2222_2222_2222_2222); } } } @@ -123,27 +123,27 @@ mod u128 { #[test] fn cmovz_works() { - let mut n = 0x11111111_11111111_22222222_22222222u128; + let mut n = 0x1111_1111_1111_1111_2222_2222_2222_2222_u128; for cond in 1..0xFF { - n.cmovz(0x22222222_22222222_33333333_33333333, cond); - assert_eq!(n, 0x11111111_11111111_22222222_22222222); + n.cmovz(0x2222_2222_2222_2222_3333_3333_3333_3333, cond); + assert_eq!(n, 0x1111_1111_1111_1111_2222_2222_2222_2222); } - n.cmovz(0x22222222_22222222_33333333_33333333, 0); - assert_eq!(n, 0x22222222_22222222_33333333_33333333); + n.cmovz(0x2222_2222_2222_2222_3333_3333_3333_3333, 0); + assert_eq!(n, 0x2222_2222_2222_2222_3333_3333_3333_3333); } #[test] fn cmovnz_works() { - let mut n = 0x11111111_11111111_22222222_22222222u128; - n.cmovnz(0x22222222_22222222_33333333_33333333, 0); - assert_eq!(n, 0x11111111_11111111_22222222_22222222); + let mut n = 0x1111_1111_1111_1111_2222_2222_2222_2222_u128; + n.cmovnz(0x2222_2222_2222_2222_3333_3333_3333_3333, 0); + assert_eq!(n, 0x1111_1111_1111_1111_2222_2222_2222_2222); for cond in 1..0xFF { - let mut n = 0x11111111_11111111u128; - n.cmovnz(0x22222222_22222222_33333333_33333333, cond); - assert_eq!(n, 0x22222222_22222222_33333333_33333333); + let mut n = 0x1111_1111_1111_1111_u128; + n.cmovnz(0x2222_2222_2222_2222_3333_3333_3333_3333, cond); + assert_eq!(n, 0x2222_2222_2222_2222_3333_3333_3333_3333); } } } From 1ffdfbecbe55818c7c7a1e0c6472244e9c546a2f Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 24 Mar 2023 13:58:19 -0600 Subject: [PATCH 063/116] cpufeatures: add support for detecting AVX-512 (#862) Adds support for detecting the following features: - `avx512f` - `avx512dq` - `avx512ifma` - `avx512pf` - `avx512er` - `avx512cd` - `avx512bw` - `avx512vl` CPUID bitflags obtained from this table: https://en.wikichip.org/wiki/x86/avx-512#Detection Closes #815 --- cpufeatures/src/x86.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/cpufeatures/src/x86.rs b/cpufeatures/src/x86.rs index c973b744..a60fa0d3 100644 --- a/cpufeatures/src/x86.rs +++ b/cpufeatures/src/x86.rs @@ -99,7 +99,15 @@ __expand_check_macro! { ("bmi1", 1, ebx, 3), ("avx2", 0, ecx, 28, 1, ebx, 5), ("bmi2", 1, ebx, 8), + ("avx512f", 1, ebx, 16), + ("avx512dq", 1, ebx, 17), ("rdseed", 1, ebx, 18), ("adx", 1, ebx, 19), + ("avx512ifma", 1, ebx, 21), + ("avx512pf", 1, ebx, 26), + ("avx512er", 1, ebx, 27), + ("avx512cd", 1, ebx, 28), ("sha", 1, ebx, 29), + ("avx512bw", 1, ebx, 30), + ("avx512vl", 1, ebx, 31), } From 552f6ea52960763d3ddcb8abdb03ddb3326c666d Mon Sep 17 00:00:00 2001 From: jake <77554505+brxken128@users.noreply.github.com> Date: Fri, 24 Mar 2023 20:00:28 +0000 Subject: [PATCH 064/116] cmov, fiat-constify, hybrid-array, zeroize: fix CI targets and branches (#861) - include `--target` in CI - rename `main` -> `master` & add `cmov` workflow path --- .github/workflows/cmov.yml | 3 ++- .github/workflows/fiat-constify.yml | 2 +- .github/workflows/hybrid-array.yml | 4 ++-- .github/workflows/zeroize.yml | 8 ++++---- 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/.github/workflows/cmov.yml b/.github/workflows/cmov.yml index 5d521412..9b736012 100644 --- a/.github/workflows/cmov.yml +++ b/.github/workflows/cmov.yml @@ -3,6 +3,7 @@ name: cmov on: pull_request: paths: + - ".github/workflows/cmov.yml" - "cmov/**" - "Cargo.*" push: @@ -76,7 +77,7 @@ jobs: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - run: ${{ matrix.deps }} - - run: cargo test + - run: cargo test --target ${{ matrix.target }} # Cross-compiled tests cross: diff --git a/.github/workflows/fiat-constify.yml b/.github/workflows/fiat-constify.yml index cf0d50d1..8e4cfe11 100644 --- a/.github/workflows/fiat-constify.yml +++ b/.github/workflows/fiat-constify.yml @@ -7,7 +7,7 @@ on: - "fiat-constify/**" - "Cargo.*" push: - branches: main + branches: master defaults: run: diff --git a/.github/workflows/hybrid-array.yml b/.github/workflows/hybrid-array.yml index 0db8798d..ae98cefb 100644 --- a/.github/workflows/hybrid-array.yml +++ b/.github/workflows/hybrid-array.yml @@ -7,7 +7,7 @@ on: - "hybrid-array/**" - "Cargo.*" push: - branches: main + branches: master defaults: run: @@ -41,7 +41,7 @@ jobs: minimal-versions: uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: - working-directory: ${{ github.workflow }} + working-directory: ${{ github.workflow }} test: strategy: diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index e99cb3db..491d51c2 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -7,7 +7,7 @@ on: - "zeroize/**" - "Cargo.*" push: - branches: main + branches: master defaults: run: @@ -43,7 +43,7 @@ jobs: minimal-versions: uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master with: - working-directory: ${{ github.workflow }} + working-directory: ${{ github.workflow }} test: strategy: @@ -94,8 +94,8 @@ jobs: # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - run: rm ../Cargo.toml - run: ${{ matrix.deps }} - - run: cargo test - - run: cargo test --all-features + - run: cargo test --target ${{ matrix.target }} + - run: cargo test --target ${{ matrix.target }} --all-features # Feature-gated ARM64 SIMD register support (MSRV 1.59) aarch64: From 9ad34485d6809c4840b26b633f3151b1f6270cdc Mon Sep 17 00:00:00 2001 From: jake <77554505+brxken128@users.noreply.github.com> Date: Fri, 24 Mar 2023 20:01:36 +0000 Subject: [PATCH 065/116] add `miri` support by forcing the `portable` backend (#864) --- cmov/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cmov/src/lib.rs b/cmov/src/lib.rs index c899cf95..471db6f4 100644 --- a/cmov/src/lib.rs +++ b/cmov/src/lib.rs @@ -6,10 +6,15 @@ )] #![warn(missing_docs, rust_2018_idioms, unused_qualifications)] +#[cfg(not(miri))] #[cfg(target_arch = "aarch64")] mod aarch64; -#[cfg(not(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")))] +#[cfg(any( + not(any(target_arch = "aarch64", target_arch = "x86", target_arch = "x86_64")), + miri +))] mod portable; +#[cfg(not(miri))] #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] mod x86; From dc26334124b6aa0487a9dfdeecd93e48d4334b8c Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 24 Mar 2023 19:59:05 -0600 Subject: [PATCH 066/116] cpufeatures: document unstable target features (#866) Document which target feature names have not yet been stabilized and are subject to change --- cpufeatures/src/lib.rs | 55 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/cpufeatures/src/lib.rs b/cpufeatures/src/lib.rs index b6c7c10b..63c1c7a9 100644 --- a/cpufeatures/src/lib.rs +++ b/cpufeatures/src/lib.rs @@ -2,13 +2,54 @@ //! as a stopgap until Rust [RFC 2725] adding first-class target feature detection //! macros to `libcore` is implemented. //! -//! Supported target architectures: -//! - `aarch64`: Linux and macOS/M4 only (ARM64 does not support OS-independent feature detection) -//! - Target features: `aes`, `sha2`, `sha3` -//! - `x86`/`x86_64`: OS independent and `no_std`-friendly -//! - Target features: `adx`, `aes`, `avx`, `avx2`, `bmi1`, `bmi2`, `fma`, -//! `mmx`, `pclmulqdq`, `popcnt`, `rdrand`, `rdseed`, `sgx`, `sha`, `sse`, -//! `sse2`, `sse3`, `sse4.1`, `sse4.2`, `ssse3` +//! +//! # Supported target architectures +//! +//! *NOTE: target features with an asterisk are unstable and subject to change +//! to match upstream name changes in the Rust standard library. +//! +//! ## `aarch64` +//! +//! Linux, iOS, and macOS/ARM only (ARM64 does not support OS-independent feature detection) +//! +//! Target features: +//! - `aes`* +//! - `sha2`* +//! - `sha3`* +//! +//! ## `x86`/`x86_64` +//! +//! OS independent and `no_std`-friendly +//! +//! Target features: +//! - `adx` +//! - `aes` +//! - `avx` +//! - `avx2` +//! - `avx512bw`* +//! - `avx512cd`* +//! - `avx512dq`* +//! - `avx512er`* +//! - `avx512f`* +//! - `avx512ifma`* +//! - `avx512pf`* +//! - `avx512vl`* +//! - `bmi1` +//! - `bmi2` +//! - `fma`, +//! - `mmx` +//! - `pclmulqdq` +//! - `popcnt` +//! - `rdrand` +//! - `rdseed` +//! - `sgx` +//! - `sha` +//! - `sse` +//! - `sse2` +//! - `sse3` +//! - `sse4.1` +//! - `sse4.2` +//! - `ssse3` //! //! If you would like detection support for a target feature which is not on //! this list, please [open a GitHub issue][gh]. From 861da36d1d09cf2282a0811e52e0c0fa8f916ad7 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Fri, 24 Mar 2023 20:46:51 -0600 Subject: [PATCH 067/116] cpufeatures v0.2.6 (#867) --- Cargo.lock | 2 +- cpufeatures/CHANGELOG.md | 8 ++++++++ cpufeatures/Cargo.toml | 4 ++-- cpufeatures/README.md | 34 +++++++++++++++++++++++++--------- cpufeatures/src/lib.rs | 8 +++++--- 5 files changed, 41 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d70ff0d0..024a2bf0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,7 +35,7 @@ version = "0.0.2" [[package]] name = "cpufeatures" -version = "0.2.5" +version = "0.2.6" dependencies = [ "libc", ] diff --git a/cpufeatures/CHANGELOG.md b/cpufeatures/CHANGELOG.md index 2f89603d..71acc5de 100644 --- a/cpufeatures/CHANGELOG.md +++ b/cpufeatures/CHANGELOG.md @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.6 (2023-03-24) +### Added +- Support dynamic feature detection on iOS and derivative platforms ([#848]) +- Support for detecting AVX-512 target features ([#862]) + +[#848]: https://github.com/RustCrypto/utils/issues/848 +[#862]: https://github.com/RustCrypto/utils/pull/862 + ## 0.2.5 (2022-09-04) ### Fixed - Add workaround for [CPUID bug] in `std` ([#800]) diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index 4022d0a1..58eec221 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cpufeatures" -version = "0.2.5" +version = "0.2.6" description = """ Lightweight runtime CPU feature detection for x86/x86_64 and aarch64 with no_std support and support for mobile targets including Android and iOS @@ -10,7 +10,7 @@ license = "MIT OR Apache-2.0" documentation = "https://docs.rs/cpufeatures" repository = "https://github.com/RustCrypto/utils" keywords = ["cpuid", "target-feature"] -categories = ["no-std"] +categories = ["hardware-support", "no-std"] edition = "2018" readme = "README.md" diff --git a/cpufeatures/README.md b/cpufeatures/README.md index 5a5bb406..273789d7 100644 --- a/cpufeatures/README.md +++ b/cpufeatures/README.md @@ -18,20 +18,24 @@ macro. ## Supported architectures -### `aarch64`: Android, iOS, Linux, and macOS/M4 only +# Supported target architectures -Note: ARM64 does not support OS-independent feature detection, so support must -be implemented on an OS-by-OS basis. +*NOTE: target features with an asterisk are unstable (nightly-only) and subject +to change to match upstream name changes in the Rust standard library. + +## `aarch64` + +Linux, iOS, and macOS/ARM only (ARM64 does not support OS-independent feature detection) Target features: -- `aes` -- `sha2` -- `sha3` +- `aes`* +- `sha2`* +- `sha3`* -Note: please open a GitHub Issue to request support for additional features. +## `x86`/`x86_64` -### `x86`/`x86_64`: OS independent and `no_std`-friendly +OS independent and `no_std`-friendly Target features: @@ -39,9 +43,17 @@ Target features: - `aes` - `avx` - `avx2` +- `avx512bw`* +- `avx512cd`* +- `avx512dq`* +- `avx512er`* +- `avx512f`* +- `avx512ifma`* +- `avx512pf`* +- `avx512vl`* - `bmi1` - `bmi2` -- `fma` +- `fma`, - `mmx` - `pclmulqdq` - `popcnt` @@ -56,6 +68,9 @@ Target features: - `sse4.2` - `ssse3` +If you would like detection support for a target feature which is not on +this list, please [open a GitHub issue]. + ## License Licensed under either of: @@ -88,3 +103,4 @@ dual licensed as above, without any additional terms or conditions. [RustCrypto]: https://github.com/rustcrypto [RustCrypto/utils#378]: https://github.com/RustCrypto/utils/issues/378 +[open a GitHub issue]: https://github.com/RustCrypto/utils/issues/new?title=cpufeatures:%20requesting%20support%20for%20CHANGEME%20target%20feature diff --git a/cpufeatures/src/lib.rs b/cpufeatures/src/lib.rs index 63c1c7a9..dfd1feab 100644 --- a/cpufeatures/src/lib.rs +++ b/cpufeatures/src/lib.rs @@ -2,17 +2,18 @@ //! as a stopgap until Rust [RFC 2725] adding first-class target feature detection //! macros to `libcore` is implemented. //! -//! //! # Supported target architectures //! -//! *NOTE: target features with an asterisk are unstable and subject to change -//! to match upstream name changes in the Rust standard library. +//! *NOTE: target features with an asterisk are unstable (nightly-only) and +//! subject to change to match upstream name changes in the Rust standard +//! library. //! //! ## `aarch64` //! //! Linux, iOS, and macOS/ARM only (ARM64 does not support OS-independent feature detection) //! //! Target features: +//! //! - `aes`* //! - `sha2`* //! - `sha3`* @@ -22,6 +23,7 @@ //! OS independent and `no_std`-friendly //! //! Target features: +//! //! - `adx` //! - `aes` //! - `avx` From 569eb926ea6f401eccda32aa65743174eaf371be Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 25 Mar 2023 15:35:48 -0600 Subject: [PATCH 068/116] zeroize: 2021 edition upgrade; MSRV 1.56 (#869) Since #858 needs MSRV 1.56 anyway, this goes ahead and bumps the edition for `zeroize` and `zeroize_derive` to 2021. This also lets us remove a number of hacks in CI, including commented-out tests. --- .github/workflows/zeroize.yml | 21 +++++++-------------- Cargo.lock | 4 ++-- zeroize/Cargo.toml | 7 ++++--- zeroize/README.md | 4 ++-- zeroize/derive/Cargo.toml | 5 +++-- zeroize/derive/README.md | 4 ++-- 6 files changed, 20 insertions(+), 25 deletions(-) diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index 491d51c2..240df4e1 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -23,7 +23,7 @@ jobs: strategy: matrix: rust: - - 1.51.0 # MSRV + - 1.56.0 # MSRV - stable target: - armv7a-none-eabi @@ -36,8 +36,6 @@ jobs: with: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: cargo build --no-default-features --target ${{ matrix.target }} minimal-versions: @@ -52,7 +50,7 @@ jobs: # 32-bit Linux - target: i686-unknown-linux-gnu platform: ubuntu-latest - rust: 1.51.0 # MSRV + rust: 1.56.0 # MSRV deps: sudo apt update && sudo apt install gcc-multilib - target: i686-unknown-linux-gnu platform: ubuntu-latest @@ -62,16 +60,15 @@ jobs: # 64-bit Linux - target: x86_64-unknown-linux-gnu platform: ubuntu-latest - rust: 1.51.0 # MSRV + rust: 1.56.0 # MSRV - target: x86_64-unknown-linux-gnu platform: ubuntu-latest rust: stable # 64-bit macOS x86_64 - # TODO(tarcieri): try re-enabling this when we bump MSRV - # - target: x86_64-apple-darwin - # platform: macos-latest - # rust: 1.51.0 # MSRV + - target: x86_64-apple-darwin + platform: macos-latest + rust: 1.56.0 # MSRV - target: x86_64-apple-darwin platform: macos-latest rust: stable @@ -79,7 +76,7 @@ jobs: # 64-bit Windows - target: x86_64-pc-windows-msvc platform: windows-latest - rust: 1.51.0 # MSRV + rust: 1.56.0 # MSRV - target: x86_64-pc-windows-msvc platform: windows-latest rust: stable @@ -91,8 +88,6 @@ jobs: with: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: ${{ matrix.deps }} - run: cargo test --target ${{ matrix.target }} - run: cargo test --target ${{ matrix.target }} --all-features @@ -116,7 +111,5 @@ jobs: toolchain: ${{ matrix.rust }} targets: ${{ matrix.target }} - uses: RustCrypto/actions/cross-install@master - # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates - - run: rm ../Cargo.toml - run: cross test --target ${{ matrix.target }} --features aarch64 - run: cross test --target ${{ matrix.target }} --all-features diff --git a/Cargo.lock b/Cargo.lock index 024a2bf0..ba8070ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -237,7 +237,7 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.5.7" +version = "1.6.0-pre" dependencies = [ "serde", "zeroize_derive", @@ -245,7 +245,7 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.3.3" +version = "1.4.0-pre" dependencies = [ "proc-macro2", "quote", diff --git a/zeroize/Cargo.toml b/zeroize/Cargo.toml index 3efc8f4f..380a6a50 100644 --- a/zeroize/Cargo.toml +++ b/zeroize/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "zeroize" +version = "1.6.0-pre" description = """ Securely clear secrets from memory with a simple trait built on stable Rust primitives which guarantee memory is zeroed using an @@ -7,18 +8,18 @@ operation will not be 'optimized away' by the compiler. Uses a portable pure Rust implementation that works everywhere, even WASM! """ -version = "1.5.7" authors = ["The RustCrypto Project Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/zeroize" readme = "README.md" categories = ["cryptography", "memory-management", "no-std", "os"] keywords = ["memory", "memset", "secure", "volatile", "zero"] -edition = "2018" +edition = "2021" +rust-version = "1.56" [dependencies] serde = { version = "1.0", default-features = false, optional = true } -zeroize_derive = { version = "1.3", path = "derive", optional = true } +zeroize_derive = { version = "=1.4.0-pre", path = "derive", optional = true } [features] default = ["alloc"] diff --git a/zeroize/README.md b/zeroize/README.md index 4f71ab43..0156ac03 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.51** or newer. +Rust **1.56** 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.51+-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.56+-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/derive/Cargo.toml b/zeroize/derive/Cargo.toml index c33fbcf3..9f8a5887 100644 --- a/zeroize/derive/Cargo.toml +++ b/zeroize/derive/Cargo.toml @@ -1,14 +1,15 @@ [package] name = "zeroize_derive" description = "Custom derive support for zeroize" -version = "1.3.3" +version = "1.4.0-pre" authors = ["The RustCrypto Project Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/zeroize/derive" readme = "README.md" categories = ["cryptography", "memory-management", "no-std", "os"] keywords = ["memory", "memset", "secure", "volatile", "zero"] -edition = "2018" +edition = "2021" +rust-version = "1.56" [lib] proc-macro = true diff --git a/zeroize/derive/README.md b/zeroize/derive/README.md index d5b16e37..9eb4bfb1 100644 --- a/zeroize/derive/README.md +++ b/zeroize/derive/README.md @@ -13,7 +13,7 @@ See [zeroize] crate for documentation. ## Minimum Supported Rust Version -Rust **1.51** or newer. +Rust **1.56** 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 @@ -39,7 +39,7 @@ dual licensed as above, without any additional terms or conditions. [crate-image]: https://img.shields.io/crates/v/zeroize_derive.svg [crate-link]: https://crates.io/crates/zeroize_derive [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg -[rustc-image]: https://img.shields.io/badge/rustc-1.51+-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.56+-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 From a958f76baa228a1f06b639569dcdc5c0cad373bc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 25 Mar 2023 16:12:59 -0600 Subject: [PATCH 069/116] build(deps): bump proc-macro2 from 1.0.52 to 1.0.53 (#857) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.52 to 1.0.53. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.52...1.0.53) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ba8070ab..4b4b6f8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,9 +125,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.52" +version = "1.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73" dependencies = [ "unicode-ident", ] From fc010a560073b5a37c951c990c2a2439dc9dc9af Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 25 Mar 2023 17:20:41 -0600 Subject: [PATCH 070/116] cmov: make `Cmov::cmovz` a provided method (#871) This makes it easier to implement the `Cmov` trait for foreign types. It additionally makes the `value` argument an `&Self` reference, which should make it easier to impl the trait for non-`Copy` types where it's desirable to avoid a move. Note: breaking change --- Cargo.lock | 2 +- cmov/Cargo.toml | 2 +- cmov/src/aarch64.rs | 36 ++++++++++++++--------------- cmov/src/lib.rs | 38 ++++++++++++++++--------------- cmov/src/portable.rs | 28 +++++++++++------------ cmov/src/x86.rs | 54 ++++++++++++++++++++++---------------------- cmov/tests/lib.rs | 40 ++++++++++++++++---------------- 7 files changed, 101 insertions(+), 99 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b4b6f8b..8f1fc1a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "cmov" -version = "0.2.0" +version = "0.3.0-pre" [[package]] name = "collectable" diff --git a/cmov/Cargo.toml b/cmov/Cargo.toml index a0c2eacb..a185a365 100644 --- a/cmov/Cargo.toml +++ b/cmov/Cargo.toml @@ -6,7 +6,7 @@ constant-time and not be rewritten as branches by the compiler. Provides wrappers for the CMOV family of instructions on x86/x86_64 and CSEL on AArch64. """ -version = "0.2.0" +version = "0.3.0-pre" authors = ["RustCrypto Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/cmov" diff --git a/cmov/src/aarch64.rs b/cmov/src/aarch64.rs index eb294617..700b4b47 100644 --- a/cmov/src/aarch64.rs +++ b/cmov/src/aarch64.rs @@ -19,23 +19,23 @@ macro_rules! csel { impl Cmov for u16 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { + fn cmovnz(&mut self, value: &Self, condition: Condition) { csel!( "cmp {0:w}, 0", - "csel {1:w}, {2:w}, {3:w}, EQ", + "csel {1:w}, {2:w}, {3:w}, NE", self, - value, + *value, condition ); } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { + fn cmovz(&mut self, value: &Self, condition: Condition) { csel!( "cmp {0:w}, 0", - "csel {1:w}, {2:w}, {3:w}, NE", + "csel {1:w}, {2:w}, {3:w}, EQ", self, - value, + *value, condition ); } @@ -43,23 +43,23 @@ impl Cmov for u16 { impl Cmov for u32 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { + fn cmovnz(&mut self, value: &Self, condition: Condition) { csel!( "cmp {0:w}, 0", - "csel {1:w}, {2:w}, {3:w}, EQ", + "csel {1:w}, {2:w}, {3:w}, NE", self, - value, + *value, condition ); } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { + fn cmovz(&mut self, value: &Self, condition: Condition) { csel!( "cmp {0:w}, 0", - "csel {1:w}, {2:w}, {3:w}, NE", + "csel {1:w}, {2:w}, {3:w}, EQ", self, - value, + *value, condition ); } @@ -67,23 +67,23 @@ impl Cmov for u32 { impl Cmov for u64 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { + fn cmovnz(&mut self, value: &Self, condition: Condition) { csel!( "cmp {0:x}, 0", - "csel {1:x}, {2:x}, {3:x}, EQ", + "csel {1:x}, {2:x}, {3:x}, NE", self, - value, + *value, condition ); } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { + fn cmovz(&mut self, value: &Self, condition: Condition) { csel!( "cmp {0:x}, 0", - "csel {1:x}, {2:x}, {3:x}, NE", + "csel {1:x}, {2:x}, {3:x}, EQ", self, - value, + *value, condition ); } diff --git a/cmov/src/lib.rs b/cmov/src/lib.rs index 471db6f4..1a9d9634 100644 --- a/cmov/src/lib.rs +++ b/cmov/src/lib.rs @@ -24,56 +24,58 @@ pub type Condition = u8; /// Conditional move // TODO(tarcieri): make one of `cmovz`/`cmovnz` a provided method which calls the other? pub trait Cmov { - /// Move if zero. - /// - /// Uses a `cmp` instruction to check if the given `condition` value is - /// equal to zero, and if so, conditionally moves `value` to `self` - /// when `condition` is equal to zero. - fn cmovz(&mut self, value: Self, condition: Condition); - /// Move if non-zero. /// /// Uses a `test` instruction to check if the given `condition` value is /// equal to zero, conditionally moves `value` to `self` when `condition` is /// equal to zero. - fn cmovnz(&mut self, value: Self, condition: Condition); + fn cmovnz(&mut self, value: &Self, condition: Condition); + + /// Move if zero. + /// + /// Uses a `cmp` instruction to check if the given `condition` value is + /// equal to zero, and if so, conditionally moves `value` to `self` + /// when `condition` is equal to zero. + fn cmovz(&mut self, value: &Self, condition: Condition) { + self.cmovnz(value, !condition) + } } impl Cmov for u8 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { + fn cmovnz(&mut self, value: &Self, condition: Condition) { let mut tmp = *self as u16; - tmp.cmovz(value as u16, condition); + tmp.cmovnz(&(*value as u16), condition); *self = tmp as u8; } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { + fn cmovz(&mut self, value: &Self, condition: Condition) { let mut tmp = *self as u16; - tmp.cmovnz(value as u16, condition); + tmp.cmovz(&(*value as u16), condition); *self = tmp as u8; } } impl Cmov for u128 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { + fn cmovnz(&mut self, value: &Self, condition: Condition) { let mut lo = (*self & u64::MAX as u128) as u64; let mut hi = (*self >> 64) as u64; - lo.cmovz((value & u64::MAX as u128) as u64, condition); - hi.cmovz((value >> 64) as u64, condition); + lo.cmovnz(&((*value & u64::MAX as u128) as u64), condition); + hi.cmovnz(&((*value >> 64) as u64), condition); *self = (lo as u128) | (hi as u128) << 64; } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { + fn cmovz(&mut self, value: &Self, condition: Condition) { let mut lo = (*self & u64::MAX as u128) as u64; let mut hi = (*self >> 64) as u64; - lo.cmovnz((value & u64::MAX as u128) as u64, condition); - hi.cmovnz((value >> 64) as u64, condition); + lo.cmovz(&((*value & u64::MAX as u128) as u64), condition); + hi.cmovz(&((*value >> 64) as u64), condition); *self = (lo as u128) | (hi as u128) << 64; } diff --git a/cmov/src/portable.rs b/cmov/src/portable.rs index 7bce46eb..f793a0c7 100644 --- a/cmov/src/portable.rs +++ b/cmov/src/portable.rs @@ -10,47 +10,47 @@ use crate::{Cmov, Condition}; impl Cmov for u16 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { + fn cmovnz(&mut self, value: &Self, condition: Condition) { let mut tmp = *self as u64; - tmp.cmovz(value as u64, condition); + tmp.cmovnz(&(*value as u64), condition); *self = tmp as u16; } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { + fn cmovz(&mut self, value: &Self, condition: Condition) { let mut tmp = *self as u64; - tmp.cmovnz(value as u64, condition); + tmp.cmovz(&(*value as u64), condition); *self = tmp as u16; } } impl Cmov for u32 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { + fn cmovnz(&mut self, value: &Self, condition: Condition) { let mut tmp = *self as u64; - tmp.cmovz(value as u64, condition); + tmp.cmovnz(&(*value as u64), condition); *self = tmp as u32; } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { + fn cmovz(&mut self, value: &Self, condition: Condition) { let mut tmp = *self as u64; - tmp.cmovnz(value as u64, condition); + tmp.cmovz(&(*value as u64), condition); *self = tmp as u32; } } impl Cmov for u64 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { - let mask = (1 ^ is_non_zero(condition)).wrapping_sub(1); - *self = (*self & mask) | (value & !mask); + fn cmovnz(&mut self, value: &Self, condition: Condition) { + let mask = is_non_zero(condition).wrapping_sub(1); + *self = (*self & mask) | (*value & !mask); } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { - let mask = is_non_zero(condition).wrapping_sub(1); - *self = (*self & mask) | (value & !mask); + fn cmovz(&mut self, value: &Self, condition: Condition) { + let mask = (1 ^ is_non_zero(condition)).wrapping_sub(1); + *self = (*self & mask) | (*value & !mask); } } diff --git a/cmov/src/x86.rs b/cmov/src/x86.rs index aa0fe129..9b49ecf4 100644 --- a/cmov/src/x86.rs +++ b/cmov/src/x86.rs @@ -27,62 +27,62 @@ macro_rules! cmov { impl Cmov for u16 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { - cmov!("cmovz {1:e}, {2:e}", self, value, condition); + fn cmovnz(&mut self, value: &Self, condition: Condition) { + cmov!("cmovnz {1:e}, {2:e}", self, *value, condition); } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { - cmov!("cmovnz {1:e}, {2:e}", self, value, condition); + fn cmovz(&mut self, value: &Self, condition: Condition) { + cmov!("cmovz {1:e}, {2:e}", self, *value, condition); } } impl Cmov for u32 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { - cmov!("cmovz {1:e}, {2:e}", self, value, condition); + fn cmovnz(&mut self, value: &Self, condition: Condition) { + cmov!("cmovnz {1:e}, {2:e}", self, *value, condition); } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { - cmov!("cmovnz {1:e}, {2:e}", self, value, condition); - } -} - -#[cfg(target_arch = "x86_64")] -impl Cmov for u64 { - #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { - cmov!("cmovz {1:r}, {2:r}", self, value, condition); - } - - #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { - cmov!("cmovnz {1:r}, {2:r}", self, value, condition); + fn cmovz(&mut self, value: &Self, condition: Condition) { + cmov!("cmovz {1:e}, {2:e}", self, *value, condition); } } #[cfg(target_arch = "x86")] impl Cmov for u64 { #[inline(always)] - fn cmovz(&mut self, value: Self, condition: Condition) { + fn cmovnz(&mut self, value: &Self, condition: Condition) { let mut lo = (*self & u32::MAX as u64) as u32; let mut hi = (*self >> 32) as u32; - lo.cmovz((value & u32::MAX as u64) as u32, condition); - hi.cmovz((value >> 32) as u32, condition); + lo.cmovnz(&((*value & u32::MAX as u64) as u32), condition); + hi.cmovnz(&((*value >> 32) as u32), condition); *self = (lo as u64) | (hi as u64) << 32; } #[inline(always)] - fn cmovnz(&mut self, value: Self, condition: Condition) { + fn cmovz(&mut self, value: &Self, condition: Condition) { let mut lo = (*self & u32::MAX as u64) as u32; let mut hi = (*self >> 32) as u32; - lo.cmovnz((value & u32::MAX as u64) as u32, condition); - hi.cmovnz((value >> 32) as u32, condition); + lo.cmovz(&((*value & u32::MAX as u64) as u32), condition); + hi.cmovz(&((*value >> 32) as u32), condition); *self = (lo as u64) | (hi as u64) << 32; } } + +#[cfg(target_arch = "x86_64")] +impl Cmov for u64 { + #[inline(always)] + fn cmovnz(&mut self, value: &Self, condition: Condition) { + cmov!("cmovnz {1:r}, {2:r}", self, *value, condition); + } + + #[inline(always)] + fn cmovz(&mut self, value: &Self, condition: Condition) { + cmov!("cmovz {1:r}, {2:r}", self, *value, condition); + } +} diff --git a/cmov/tests/lib.rs b/cmov/tests/lib.rs index a7f7ad4a..52053a5e 100644 --- a/cmov/tests/lib.rs +++ b/cmov/tests/lib.rs @@ -6,23 +6,23 @@ mod u8 { let mut n = 0x11u8; for cond in 1..0xFF { - n.cmovz(0x22, cond); + n.cmovz(&0x22, cond); assert_eq!(n, 0x11); } - n.cmovz(0x22, 0); + n.cmovz(&0x22, 0); assert_eq!(n, 0x22); } #[test] fn cmovnz_works() { let mut n = 0x11u8; - n.cmovnz(0x22, 0); + n.cmovnz(&0x22, 0); assert_eq!(n, 0x11); for cond in 1..0xFF { let mut n = 0x11u8; - n.cmovnz(0x22, cond); + n.cmovnz(&0x22, cond); assert_eq!(n, 0x22); } } @@ -36,23 +36,23 @@ mod u16 { let mut n = 0x1111u16; for cond in 1..0xFF { - n.cmovz(0x2222, cond); + n.cmovz(&0x2222, cond); assert_eq!(n, 0x1111); } - n.cmovz(0x2222, 0); + n.cmovz(&0x2222, 0); assert_eq!(n, 0x2222); } #[test] fn cmovnz_works() { let mut n = 0x1111u16; - n.cmovnz(0x2222, 0); + n.cmovnz(&0x2222, 0); assert_eq!(n, 0x1111); for cond in 1..0xFF { let mut n = 0x1111u16; - n.cmovnz(0x2222, cond); + n.cmovnz(&0x2222, cond); assert_eq!(n, 0x2222); } } @@ -66,23 +66,23 @@ mod u32 { let mut n = 0x11111111u32; for cond in 1..0xFF { - n.cmovz(0x22222222, cond); + n.cmovz(&0x22222222, cond); assert_eq!(n, 0x11111111); } - n.cmovz(0x22222222, 0); + n.cmovz(&0x22222222, 0); assert_eq!(n, 0x22222222); } #[test] fn cmovnz_works() { let mut n = 0x11111111u32; - n.cmovnz(0x22222222, 0); + n.cmovnz(&0x22222222, 0); assert_eq!(n, 0x11111111); for cond in 1..0xFF { let mut n = 0x11111111u32; - n.cmovnz(0x22222222, cond); + n.cmovnz(&0x22222222, cond); assert_eq!(n, 0x22222222); } } @@ -96,23 +96,23 @@ mod u64 { let mut n = 0x1111_1111_1111_1111_u64; for cond in 1..0xFF { - n.cmovz(0x2222_2222_2222_2222, cond); + n.cmovz(&0x2222_2222_2222_2222, cond); assert_eq!(n, 0x1111_1111_1111_1111); } - n.cmovz(0x2222_2222_2222_2222, 0); + n.cmovz(&0x2222_2222_2222_2222, 0); assert_eq!(n, 0x2222_2222_2222_2222); } #[test] fn cmovnz_works() { let mut n = 0x1111_1111_1111_1111_u64; - n.cmovnz(0x2222_2222_2222_2222, 0); + n.cmovnz(&0x2222_2222_2222_2222, 0); assert_eq!(n, 0x1111_1111_1111_1111); for cond in 1..0xFF { let mut n = 0x1111_1111_1111_1111_u64; - n.cmovnz(0x2222_2222_2222_2222, cond); + n.cmovnz(&0x2222_2222_2222_2222, cond); assert_eq!(n, 0x2222_2222_2222_2222); } } @@ -126,23 +126,23 @@ mod u128 { let mut n = 0x1111_1111_1111_1111_2222_2222_2222_2222_u128; for cond in 1..0xFF { - n.cmovz(0x2222_2222_2222_2222_3333_3333_3333_3333, cond); + n.cmovz(&0x2222_2222_2222_2222_3333_3333_3333_3333, cond); assert_eq!(n, 0x1111_1111_1111_1111_2222_2222_2222_2222); } - n.cmovz(0x2222_2222_2222_2222_3333_3333_3333_3333, 0); + n.cmovz(&0x2222_2222_2222_2222_3333_3333_3333_3333, 0); assert_eq!(n, 0x2222_2222_2222_2222_3333_3333_3333_3333); } #[test] fn cmovnz_works() { let mut n = 0x1111_1111_1111_1111_2222_2222_2222_2222_u128; - n.cmovnz(0x2222_2222_2222_2222_3333_3333_3333_3333, 0); + n.cmovnz(&0x2222_2222_2222_2222_3333_3333_3333_3333, 0); assert_eq!(n, 0x1111_1111_1111_1111_2222_2222_2222_2222); for cond in 1..0xFF { let mut n = 0x1111_1111_1111_1111_u128; - n.cmovnz(0x2222_2222_2222_2222_3333_3333_3333_3333, cond); + n.cmovnz(&0x2222_2222_2222_2222_3333_3333_3333_3333, cond); assert_eq!(n, 0x2222_2222_2222_2222_3333_3333_3333_3333); } } From 30b2c5561613d2ef472ebe25905ed5fbb32f54e3 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Sun, 26 Mar 2023 10:43:19 -0700 Subject: [PATCH 071/116] fiat-constify/zeroize_derive: bump `syn` to v2 (#858) --- Cargo.lock | 55 ++-- fiat-constify/Cargo.toml | 2 +- fiat-constify/src/main.rs | 100 +++---- zeroize/derive/Cargo.toml | 3 +- zeroize/derive/src/lib.rs | 596 ++++++++++++++++++++------------------ 5 files changed, 380 insertions(+), 376 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8f1fc1a3..cdac0c34 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -109,15 +109,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "libc" -version = "0.2.138" +version = "0.2.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" [[package]] name = "opaque-debug" @@ -134,33 +134,33 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.23" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "serde" -version = "1.0.151" +version = "1.0.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" +checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.151" +version = "1.0.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" +checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" dependencies = [ "proc-macro2", "quote", @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.91" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" dependencies = [ "itoa", "ryu", @@ -180,27 +180,15 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.107" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" +checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2", - "quote", - "syn", - "unicode-xid", -] - [[package]] name = "typenum" version = "1.16.0" @@ -209,15 +197,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" -version = "1.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" - -[[package]] -name = "unicode-xid" -version = "0.2.4" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "version_check" @@ -250,5 +232,4 @@ dependencies = [ "proc-macro2", "quote", "syn", - "synstructure", ] diff --git a/fiat-constify/Cargo.toml b/fiat-constify/Cargo.toml index 2c2b46a3..c3af946d 100644 --- a/fiat-constify/Cargo.toml +++ b/fiat-constify/Cargo.toml @@ -18,4 +18,4 @@ rust-version = "1.56" [dependencies] proc-macro2 = "1" quote = "1" -syn = { version = "1", features = ["extra-traits", "full"] } +syn = { version = "2", features = ["extra-traits", "full"] } diff --git a/fiat-constify/src/main.rs b/fiat-constify/src/main.rs index c26a5c2c..b697190d 100644 --- a/fiat-constify/src/main.rs +++ b/fiat-constify/src/main.rs @@ -5,16 +5,16 @@ #![allow(clippy::single_match, clippy::new_without_default)] -use proc_macro2::Span; +use proc_macro2::{Literal, Span}; use quote::{quote, ToTokens}; use std::{collections::BTreeMap as Map, env, fs, ops::Deref}; use syn::{ punctuated::Punctuated, - token::{Bang, Brace, Bracket, Colon, Const, Eq, Let, Mut, Paren, Pound, RArrow, Semi}, + token::{Brace, Bracket, Colon, Const, Eq, Let, Mut, Not, Paren, Pound, RArrow, Semi}, AttrStyle, Attribute, Block, Expr, ExprAssign, ExprCall, ExprLit, ExprPath, ExprReference, - ExprRepeat, ExprTuple, FnArg, Ident, Item, ItemFn, ItemType, Lit, LitInt, Local, Pat, PatIdent, - PatTuple, PatType, Path, PathArguments, PathSegment, ReturnType, Stmt, Type, TypeArray, - TypePath, TypeReference, TypeTuple, UnOp, + ExprRepeat, ExprTuple, FnArg, Ident, Item, ItemFn, ItemType, Lit, LitInt, Local, LocalInit, + MacroDelimiter, Meta, MetaList, Pat, PatIdent, PatTuple, PatType, Path, PathArguments, + PathSegment, ReturnType, Stmt, Type, TypeArray, TypePath, TypeReference, TypeTuple, UnOp, }; fn main() -> Result<(), Box> { @@ -59,29 +59,33 @@ fn main() -> Result<(), Box> { /// Build a toplevel attribute with the given name and comma-separated values. fn build_attribute(name: &str, values: &[&str]) -> Attribute { - let span = Span::call_site(); let values = values .iter() .map(|value| build_path(value)) .collect::>(); + let path = build_path(name); + let tokens = quote! { #(#values),* }; + let delimiter = MacroDelimiter::Paren(Paren::default()); Attribute { - pound_token: Pound { spans: [span] }, - style: AttrStyle::Inner(Bang { spans: [span] }), - bracket_token: Bracket { span }, - path: build_path(name), - tokens: quote! { (#(#values),*) }, + pound_token: Pound::default(), + style: AttrStyle::Inner(Not::default()), + bracket_token: Bracket::default(), + meta: Meta::List(MetaList { + path, + delimiter, + tokens, + }), } } /// Parse a path from a double-colon-delimited string. fn build_path(path: &str) -> Path { - let span = Span::call_site(); let mut segments = Punctuated::new(); for segment in path.split("::") { segments.push(PathSegment { - ident: Ident::new(segment, span), + ident: Ident::new(segment, Span::call_site()), arguments: PathArguments::None, }); } @@ -103,10 +107,8 @@ fn get_ident_from_pat(pat: &Pat) -> Ident { /// Rewrite a fiat-crypto generated `fn` as a `const fn`, making the necessary /// transformations to the code in order for it to work in that context. fn rewrite_fn_as_const(func: &mut ItemFn, type_registry: &TypeRegistry) { - let span = Span::call_site(); - // Mark function as being `const fn`. - func.sig.constness = Some(Const { span }); + func.sig.constness = Some(Const::default()); // Transform mutable arguments into return values. let mut inputs = Punctuated::new(); @@ -142,7 +144,6 @@ fn rewrite_fn_as_const(func: &mut ItemFn, type_registry: &TypeRegistry) { /// values for outputs, removing mutable references, and adding a return /// value/tuple. fn rewrite_fn_body(statements: &[Stmt], outputs: &Outputs, registry: &TypeRegistry) -> Block { - let span = Span::call_site(); let mut stmts = Vec::new(); stmts.extend(outputs.to_let_bindings(registry).into_iter()); @@ -156,7 +157,7 @@ fn rewrite_fn_body(statements: &[Stmt], outputs: &Outputs, registry: &TypeRegist stmts.push(outputs.to_return_value()); Block { - brace_token: Brace { span }, + brace_token: Brace::default(), stmts, } } @@ -165,7 +166,7 @@ fn rewrite_fn_body(statements: &[Stmt], outputs: &Outputs, registry: &TypeRegist /// operations into value assignments. fn rewrite_fn_stmt(stmt: &mut Stmt) { match stmt { - Stmt::Semi(expr, _) => match expr { + Stmt::Expr(expr, Some(_)) => match expr { Expr::Assign(ExprAssign { left, .. }) => match *left.clone() { Expr::Unary(unary) => { // Remove deref since we're removing mutable references @@ -225,20 +226,22 @@ fn rewrite_fn_call(mut call: ExprCall) -> Local { // Overwrite call arguments with the ones that aren't mutable references call.args = args; - let span = Span::call_site(); - let pat = Pat::Tuple(PatTuple { attrs: Vec::new(), - paren_token: Paren { span }, + paren_token: Paren::default(), elems: output, }); Local { attrs: Vec::new(), - let_token: Let { span }, + let_token: Let::default(), pat, - init: Some((Eq { spans: [span] }, Box::new(Expr::Call(call)))), - semi_token: Semi { spans: [span] }, + init: Some(LocalInit { + eq_token: Eq::default(), + expr: Box::new(Expr::Call(call)), + diverge: None, + }), + semi_token: Semi::default(), } } @@ -299,28 +302,30 @@ impl Outputs { /// Generate `let mut outN: Ty = ` bindings at the start /// of the function. pub fn to_let_bindings(&self, registry: &TypeRegistry) -> Vec { - let span = Span::call_site(); - self.0 .iter() .map(|(ident, ty)| { Stmt::Local(Local { attrs: Vec::new(), - let_token: Let { span }, + let_token: Let::default(), pat: Pat::Type(PatType { attrs: Vec::new(), pat: Box::new(Pat::Ident(PatIdent { attrs: Vec::new(), by_ref: None, - mutability: Some(Mut { span }), + mutability: Some(Mut::default()), ident: ident.clone(), subpat: None, })), - colon_token: Colon { spans: [span] }, + colon_token: Colon::default(), ty: Box::new(ty.clone()), }), - init: Some((Eq { spans: [span] }, Box::new(default_for(ty, registry)))), - semi_token: Semi { spans: [span] }, + init: Some(LocalInit { + eq_token: Eq::default(), + expr: Box::new(default_for(ty, registry)), + diverge: None, + }), + semi_token: Semi::default(), }) }) .collect() @@ -328,10 +333,7 @@ impl Outputs { /// Finish annotating outputs, updating the provided `Signature`. pub fn to_return_type(&self) -> ReturnType { - let span = Span::call_site(); - let rarrow = RArrow { - spans: [span, span], - }; + let rarrow = RArrow::default(); let ret = match self.0.len() { 0 => panic!("expected at least one output"), @@ -344,7 +346,7 @@ impl Outputs { } Type::Tuple(TypeTuple { - paren_token: Paren { span }, + paren_token: Paren::default(), elems, }) } @@ -355,8 +357,6 @@ impl Outputs { /// Generate the return value for the statement as a tuple of the outputs. pub fn to_return_value(&self) -> Stmt { - let span = Span::call_site(); - let mut elems = self.0.keys().map(|ident| { let mut segments = Punctuated::new(); segments.push(PathSegment { @@ -377,31 +377,33 @@ impl Outputs { }); if elems.len() == 1 { - Stmt::Expr(elems.next().unwrap()) + Stmt::Expr(elems.next().unwrap(), None) } else { - Stmt::Expr(Expr::Tuple(ExprTuple { - attrs: Vec::new(), - paren_token: Paren { span }, - elems: elems.collect(), - })) + Stmt::Expr( + Expr::Tuple(ExprTuple { + attrs: Vec::new(), + paren_token: Paren::default(), + elems: elems.collect(), + }), + None, + ) } } } /// Get a default value for the given type. fn default_for(ty: &Type, registry: &TypeRegistry) -> Expr { - let span = Span::call_site(); let zero = Expr::Lit(ExprLit { attrs: Vec::new(), - lit: Lit::Int(LitInt::new("0", span)), + lit: Lit::Int(LitInt::from(Literal::u8_unsuffixed(0))), }); match ty { Type::Array(TypeArray { len, .. }) => Expr::Repeat(ExprRepeat { attrs: Vec::new(), - bracket_token: Bracket { span }, + bracket_token: Bracket::default(), expr: Box::new(zero), - semi_token: Semi { spans: [span] }, + semi_token: Semi::default(), len: Box::new(len.clone()), }), Type::Path(TypePath { path, .. }) => { diff --git a/zeroize/derive/Cargo.toml b/zeroize/derive/Cargo.toml index 9f8a5887..cadc4438 100644 --- a/zeroize/derive/Cargo.toml +++ b/zeroize/derive/Cargo.toml @@ -17,8 +17,7 @@ proc-macro = true [dependencies] proc-macro2 = "1" quote = "1" -syn = "1" -synstructure = "0.12.2" +syn = {version = "2", features = ["full", "extra-traits"]} [package.metadata.docs.rs] rustdoc-args = ["--document-private-items"] diff --git a/zeroize/derive/src/lib.rs b/zeroize/derive/src/lib.rs index baf69901..650dacb6 100644 --- a/zeroize/derive/src/lib.rs +++ b/zeroize/derive/src/lib.rs @@ -4,90 +4,118 @@ #![forbid(unsafe_code)] #![warn(rust_2018_idioms, trivial_casts, unused_qualifications)] -use proc_macro2::TokenStream; -use quote::quote; +use proc_macro2::{Ident, TokenStream}; +use quote::{format_ident, quote}; use syn::{ parse::{Parse, ParseStream}, + parse_quote, punctuated::Punctuated, token::Comma, - Attribute, Lit, Meta, NestedMeta, Result, WherePredicate, + Attribute, Data, DeriveInput, Expr, ExprLit, Field, Fields, GenericParam, Lit, Meta, Result, + Variant, WherePredicate, }; -use synstructure::{decl_derive, AddBounds, BindStyle, BindingInfo, VariantInfo}; - -decl_derive!( - [Zeroize, attributes(zeroize)] => - - /// Derive the `Zeroize` trait. - /// - /// Supports the following attributes: - /// - /// On the item level: - /// - `#[zeroize(drop)]`: *deprecated* use `ZeroizeOnDrop` instead - /// - `#[zeroize(bound = "T: MyTrait")]`: this replaces any trait bounds - /// inferred by zeroize-derive - /// - /// On the field level: - /// - `#[zeroize(skip)]`: skips this field or variant when calling `zeroize()` - derive_zeroize -); - -decl_derive!( - [ZeroizeOnDrop, attributes(zeroize)] => - - /// Derive the `ZeroizeOnDrop` trait. - /// - /// Supports the following attributes: - /// - /// On the field level: - /// - `#[zeroize(skip)]`: skips this field or variant when calling `zeroize()` - derive_zeroize_on_drop -); /// Name of zeroize-related attributes const ZEROIZE_ATTR: &str = "zeroize"; -/// Custom derive for `Zeroize` -fn derive_zeroize(mut s: synstructure::Structure<'_>) -> TokenStream { - let attributes = ZeroizeAttrs::parse(&s); - - if let Some(bounds) = attributes.bound { - s.add_bounds(AddBounds::None); +/// Derive the `Zeroize` trait. +/// +/// Supports the following attributes: +/// +/// On the item level: +/// - `#[zeroize(drop)]`: *deprecated* use `ZeroizeOnDrop` instead +/// - `#[zeroize(bound = "T: MyTrait")]`: this replaces any trait bounds +/// inferred by zeroize-derive +/// +/// On the field level: +/// - `#[zeroize(skip)]`: skips this field or variant when calling `zeroize()` +#[proc_macro_derive(Zeroize, attributes(zeroize))] +pub fn derive_zeroize(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + derive_zeroize_impl(syn::parse_macro_input!(input as DeriveInput)).into() +} - for bound in bounds.0 { - s.add_where_predicate(bound); +fn derive_zeroize_impl(input: DeriveInput) -> TokenStream { + let attributes = ZeroizeAttrs::parse(&input); + + let extra_bounds = match attributes.bound { + Some(bounds) => bounds.0, + None => { + let mut out: Punctuated = Default::default(); + for param in &input.generics.params { + if let GenericParam::Type(type_param) = param { + let type_name = &type_param.ident; + out.push(parse_quote! { #type_name: Zeroize }) + } + } + out } - } + }; + + let mut generics = input.generics.clone(); + generics.make_where_clause().predicates.extend(extra_bounds); + + let ty_name = &input.ident; - // NOTE: These are split into named functions to simplify testing with - // synstructure's `test_derive!` macro. - if attributes.drop { - derive_zeroize_with_drop(s) + let (impl_gen, type_gen, where_) = generics.split_for_impl(); + + let drop_impl = if attributes.drop { + quote! { + #[doc(hidden)] + impl #impl_gen Drop for #ty_name #type_gen #where_ { + fn drop(&mut self) { + self.zeroize() + } + } + } } else { - derive_zeroize_without_drop(s) + quote! {} + }; + + let zeroizers = generate_fields(&input, quote! { zeroize }); + let zeroize_impl = quote! { + impl #impl_gen ::zeroize::Zeroize for #ty_name #type_gen #where_ { + fn zeroize(&mut self) { + #zeroizers + } + } + }; + + quote! { + #zeroize_impl + #drop_impl } } -/// Custom derive for `ZeroizeOnDrop` -fn derive_zeroize_on_drop(mut s: synstructure::Structure<'_>) -> TokenStream { - let zeroizers = generate_fields(&mut s, quote! { zeroize_or_on_drop }); +/// Derive the `ZeroizeOnDrop` trait. +/// +/// Supports the following attributes: +/// +/// On the field level: +/// - `#[zeroize(skip)]`: skips this field or variant when calling `zeroize()` +#[proc_macro_derive(ZeroizeOnDrop, attributes(zeroize))] +pub fn derive_zeroize_on_drop(input: proc_macro::TokenStream) -> proc_macro::TokenStream { + derive_zeroize_on_drop_impl(syn::parse_macro_input!(input as DeriveInput)).into() +} + +fn derive_zeroize_on_drop_impl(input: DeriveInput) -> TokenStream { + let zeroizers = generate_fields(&input, quote! { zeroize_or_on_drop }); + + let (impl_gen, type_gen, where_) = input.generics.split_for_impl(); + let name = input.ident.clone(); - let drop_impl = s.add_bounds(AddBounds::None).gen_impl(quote! { - gen impl Drop for @Self { + let drop_impl = quote! { + impl #impl_gen Drop for #name #type_gen #where_ { fn drop(&mut self) { - use zeroize::__internal::AssertZeroize; - use zeroize::__internal::AssertZeroizeOnDrop; - match self { - #zeroizers - } + use ::zeroize::__internal::AssertZeroize; + use ::zeroize::__internal::AssertZeroizeOnDrop; + #zeroizers } } - }); - - let zeroize_on_drop_impl = impl_zeroize_on_drop(&s); + }; + let zeroize_on_drop_impl = impl_zeroize_on_drop(&input); quote! { #drop_impl - #zeroize_on_drop_impl } } @@ -112,40 +140,42 @@ impl Parse for Bounds { impl ZeroizeAttrs { /// Parse attributes from the incoming AST - fn parse(s: &synstructure::Structure<'_>) -> Self { + fn parse(input: &DeriveInput) -> Self { let mut result = Self::default(); - for attr in s.ast().attrs.iter() { + for attr in &input.attrs { result.parse_attr(attr, None, None); } - for v in s.variants().iter() { - // only process actual enum variants here, as we don't want to process struct attributes twice - if v.prefix.is_some() { - for attr in v.ast().attrs.iter() { - result.parse_attr(attr, Some(v), None); + + match &input.data { + syn::Data::Enum(enum_) => { + for variant in &enum_.variants { + for attr in &variant.attrs { + result.parse_attr(attr, Some(variant), None); + } + for field in &variant.fields { + for attr in &field.attrs { + result.parse_attr(attr, Some(variant), Some(field)); + } + } } } - for binding in v.bindings().iter() { - for attr in binding.ast().attrs.iter() { - result.parse_attr(attr, Some(v), Some(binding)); + syn::Data::Struct(struct_) => { + for field in &struct_.fields { + for attr in &field.attrs { + result.parse_attr(attr, None, Some(field)); + } } } + syn::Data::Union(union_) => panic!("Unsupported untagged union {:?}", union_), } result } /// Parse attribute and handle `#[zeroize(...)]` attributes - fn parse_attr( - &mut self, - attr: &Attribute, - variant: Option<&VariantInfo<'_>>, - binding: Option<&BindingInfo<'_>>, - ) { - let meta_list = match attr - .parse_meta() - .unwrap_or_else(|e| panic!("error parsing attribute: {:?} ({})", attr, e)) - { + fn parse_attr(&mut self, attr: &Attribute, variant: Option<&Variant>, binding: Option<&Field>) { + let meta_list = match &attr.meta { Meta::List(list) => list, _ => return, }; @@ -155,29 +185,23 @@ impl ZeroizeAttrs { return; } - for nested_meta in &meta_list.nested { - if let NestedMeta::Meta(meta) = nested_meta { - self.parse_meta(meta, variant, binding); - } else { - panic!("malformed #[zeroize] attribute: {:?}", nested_meta); - } + for meta in attr + .parse_args_with(Punctuated::::parse_terminated) + .unwrap_or_else(|e| panic!("error parsing attribute: {:?} ({})", attr, e)) + { + self.parse_meta(&meta, variant, binding); } } /// Parse `#[zeroize(...)]` attribute metadata (e.g. `drop`) - fn parse_meta( - &mut self, - meta: &Meta, - variant: Option<&VariantInfo<'_>>, - binding: Option<&BindingInfo<'_>>, - ) { + fn parse_meta(&mut self, meta: &Meta, variant: Option<&Variant>, binding: Option<&Field>) { if meta.path().is_ident("drop") { assert!(!self.drop, "duplicate #[zeroize] drop flags"); match (variant, binding) { (_variant, Some(_binding)) => { // structs don't have a variant prefix, and only structs have bindings outside of a variant - let item_kind = match variant.and_then(|variant| variant.prefix) { + let item_kind = match variant { Some(_) => "enum", None => "struct", }; @@ -203,7 +227,7 @@ impl ZeroizeAttrs { match (variant, binding) { (_variant, Some(_binding)) => { // structs don't have a variant prefix, and only structs have bindings outside of a variant - let item_kind = match variant.and_then(|variant| variant.prefix) { + let item_kind = match variant { Some(_) => "enum", None => "struct", }; @@ -221,7 +245,10 @@ impl ZeroizeAttrs { )), (None, None) => { if let Meta::NameValue(meta_name_value) = meta { - if let Lit::Str(lit) = &meta_name_value.lit { + if let Expr::Lit(ExprLit { + lit: Lit::Str(lit), .. + }) = &meta_name_value.value + { if lit.value().is_empty() { self.bound = Some(Bounds(Punctuated::new())); } else { @@ -253,277 +280,278 @@ impl ZeroizeAttrs { } } -fn generate_fields(s: &mut synstructure::Structure<'_>, method: TokenStream) -> TokenStream { - s.bind_with(|_| BindStyle::RefMut); +fn field_ident(n: usize, field: &Field) -> Ident { + if let Some(ref name) = field.ident { + name.clone() + } else { + format_ident!("__zeroize_field_{}", n) + } +} - s.filter_variants(|vi| { - let result = filter_skip(vi.ast().attrs, true); +fn generate_fields(input: &DeriveInput, method: TokenStream) -> TokenStream { + let input_id = &input.ident; + let fields: Vec<_> = match input.data { + Data::Enum(ref enum_) => enum_ + .variants + .iter() + .filter_map(|variant| { + if attr_skip(&variant.attrs) { + if variant.fields.iter().any(|field| attr_skip(&field.attrs)) { + panic!("duplicate #[zeroize] skip flags") + } + None + } else { + let variant_id = &variant.ident; + Some((quote! { #input_id :: #variant_id }, &variant.fields)) + } + }) + .collect(), + Data::Struct(ref struct_) => vec![(quote! { #input_id }, &struct_.fields)], + Data::Union(ref union_) => panic!("Cannot generate fields for untagged union {:?}", union_), + }; + + let arms = fields.into_iter().map(|(name, fields)| { + let method_field = fields.iter().enumerate().filter_map(|(n, field)| { + if attr_skip(&field.attrs) { + None + } else { + let name = field_ident(n, field); + Some(quote! { #name.#method() }) + } + }); + + let field_bindings = fields + .iter() + .enumerate() + .map(|(n, field)| field_ident(n, field)); + + let binding = match fields { + Fields::Named(_) => quote! { + #name { #(#field_bindings),* } + }, + Fields::Unnamed(_) => quote! { + #name ( #(#field_bindings),* ) + }, + Fields::Unit => quote! { + #name + }, + }; - // check for duplicate `#[zeroize(skip)]` attributes in nested variants - for field in vi.ast().fields { - filter_skip(&field.attrs, result); + quote! { + #[allow(unused_variables)] + #binding => { + #(#method_field);* + } } + }); - result - }) - .filter(|bi| filter_skip(&bi.ast().attrs, true)) - .each(|bi| quote! { #bi.#method(); }) + quote! { + match self { + #(#arms),* + _ => {} + } + } } -fn filter_skip(attrs: &[Attribute], start: bool) -> bool { - let mut result = start; - - for attr in attrs.iter().filter_map(|attr| attr.parse_meta().ok()) { +fn attr_skip(attrs: &[Attribute]) -> bool { + let mut result = false; + for attr in attrs.iter().map(|attr| &attr.meta) { if let Meta::List(list) = attr { if list.path.is_ident(ZEROIZE_ATTR) { - for nested in list.nested { - if let NestedMeta::Meta(Meta::Path(path)) = nested { + for meta in list + .parse_args_with(Punctuated::::parse_terminated) + .unwrap_or_else(|e| panic!("error parsing attribute: {:?} ({})", list, e)) + { + if let Meta::Path(path) = meta { if path.is_ident("skip") { - assert!(result, "duplicate #[zeroize] skip flags"); - result = false; + assert!(!result, "duplicate #[zeroize] skip flags"); + result = true; } } } } } } - result } -/// Custom derive for `Zeroize` (without `Drop`) -fn derive_zeroize_without_drop(mut s: synstructure::Structure<'_>) -> TokenStream { - let zeroizers = generate_fields(&mut s, quote! { zeroize }); - - s.bound_impl( - quote!(zeroize::Zeroize), - quote! { - fn zeroize(&mut self) { - match self { - #zeroizers - } - } - }, - ) -} - -/// Custom derive for `Zeroize` and `Drop` -fn derive_zeroize_with_drop(s: synstructure::Structure<'_>) -> TokenStream { - let drop_impl = s.gen_impl(quote! { - gen impl Drop for @Self { - fn drop(&mut self) { - self.zeroize(); - } - } - }); - - let zeroize_impl = derive_zeroize_without_drop(s); - +fn impl_zeroize_on_drop(input: &DeriveInput) -> TokenStream { + let name = input.ident.clone(); + let (impl_gen, type_gen, where_) = input.generics.split_for_impl(); quote! { - #zeroize_impl - #[doc(hidden)] - #drop_impl + impl #impl_gen ::zeroize::ZeroizeOnDrop for #name #type_gen #where_ {} } } -fn impl_zeroize_on_drop(s: &synstructure::Structure<'_>) -> TokenStream { - #[allow(unused_qualifications)] - s.bound_impl(quote!(zeroize::ZeroizeOnDrop), Option::::None) -} - #[cfg(test)] mod tests { use super::*; - use syn::parse_str; - use synstructure::{test_derive, Structure}; + + #[track_caller] + fn test_derive( + f: impl Fn(DeriveInput) -> TokenStream, + input: TokenStream, + expected_output: TokenStream, + ) { + let output = f(syn::parse2(input).unwrap()); + assert_eq!(format!("{output}"), format!("{expected_output}")); + } + + #[track_caller] + fn parse_zeroize_test(unparsed: &str) -> TokenStream { + derive_zeroize_impl(syn::parse_str(unparsed).expect("Failed to parse test input")) + } #[test] fn zeroize_without_drop() { - test_derive! { - derive_zeroize_without_drop { + test_derive( + derive_zeroize_impl, + quote! { struct Z { a: String, b: Vec, c: [u8; 3], } - } - expands to { - #[allow(non_upper_case_globals)] - #[doc(hidden)] - const _DERIVE_zeroize_Zeroize_FOR_Z: () = { - extern crate zeroize; - impl zeroize::Zeroize for Z { - fn zeroize(&mut self) { - match self { - Z { - a: ref mut __binding_0, - b: ref mut __binding_1, - c: ref mut __binding_2, - } => { - { __binding_0.zeroize(); } - { __binding_1.zeroize(); } - { __binding_2.zeroize(); } - } + }, + quote! { + impl ::zeroize::Zeroize for Z { + fn zeroize(&mut self) { + match self { + #[allow(unused_variables)] + Z { a, b, c } => { + a.zeroize(); + b.zeroize(); + c.zeroize() } + _ => {} } } - }; - } - no_build // tests the code compiles are in the `zeroize` crate - } + } + }, + ) } #[test] fn zeroize_with_drop() { - test_derive! { - derive_zeroize_with_drop { + test_derive( + derive_zeroize_impl, + quote! { + #[zeroize(drop)] struct Z { a: String, b: Vec, c: [u8; 3], } - } - expands to { - #[allow(non_upper_case_globals)] - #[doc(hidden)] - const _DERIVE_zeroize_Zeroize_FOR_Z: () = { - extern crate zeroize; - impl zeroize::Zeroize for Z { - fn zeroize(&mut self) { - match self { - Z { - a: ref mut __binding_0, - b: ref mut __binding_1, - c: ref mut __binding_2, - } => { - { __binding_0.zeroize(); } - { __binding_1.zeroize(); } - { __binding_2.zeroize(); } - } + }, + quote! { + impl ::zeroize::Zeroize for Z { + fn zeroize(&mut self) { + match self { + #[allow(unused_variables)] + Z { a, b, c } => { + a.zeroize(); + b.zeroize(); + c.zeroize() } + _ => {} } } - }; + } #[doc(hidden)] - #[allow(non_upper_case_globals)] - const _DERIVE_Drop_FOR_Z: () = { - impl Drop for Z { - fn drop(&mut self) { - self.zeroize(); - } + impl Drop for Z { + fn drop(&mut self) { + self.zeroize() } - }; - } - no_build // tests the code compiles are in the `zeroize` crate - } + } + }, + ) } #[test] fn zeroize_with_skip() { - test_derive! { - derive_zeroize_without_drop { + test_derive( + derive_zeroize_impl, + quote! { struct Z { a: String, b: Vec, #[zeroize(skip)] c: [u8; 3], } - } - expands to { - #[allow(non_upper_case_globals)] - #[doc(hidden)] - const _DERIVE_zeroize_Zeroize_FOR_Z: () = { - extern crate zeroize; - impl zeroize::Zeroize for Z { - fn zeroize(&mut self) { - match self { - Z { - a: ref mut __binding_0, - b: ref mut __binding_1, - .. - } => { - { __binding_0.zeroize(); } - { __binding_1.zeroize(); } - } + }, + quote! { + impl ::zeroize::Zeroize for Z { + fn zeroize(&mut self) { + match self { + #[allow(unused_variables)] + Z { a, b, c } => { + a.zeroize(); + b.zeroize() } + _ => {} } } - }; - } - no_build // tests the code compiles are in the `zeroize` crate - } + } + }, + ) } #[test] fn zeroize_with_bound() { - test_derive! { - derive_zeroize { + test_derive( + derive_zeroize_impl, + quote! { #[zeroize(bound = "T: MyTrait")] struct Z(T); - } - expands to { - #[allow(non_upper_case_globals)] - #[doc(hidden)] - const _DERIVE_zeroize_Zeroize_FOR_Z: () = { - extern crate zeroize; - impl zeroize::Zeroize for Z - where T: MyTrait - { - fn zeroize(&mut self) { - match self { - Z(ref mut __binding_0,) => { - { __binding_0.zeroize(); } - } + }, + quote! { + impl ::zeroize::Zeroize for Z where T: MyTrait { + fn zeroize(&mut self) { + match self { + #[allow(unused_variables)] + Z(__zeroize_field_0) => { + __zeroize_field_0.zeroize() } + _ => {} } } - }; - } - no_build // tests the code compiles are in the `zeroize` crate - } + } + }, + ) } #[test] fn zeroize_only_drop() { - test_derive! { - derive_zeroize_on_drop { + test_derive( + derive_zeroize_on_drop_impl, + quote! { struct Z { a: String, b: Vec, c: [u8; 3], } - } - expands to { - #[allow(non_upper_case_globals)] - const _DERIVE_Drop_FOR_Z: () = { - impl Drop for Z { - fn drop(&mut self) { - use zeroize::__internal::AssertZeroize; - use zeroize::__internal::AssertZeroizeOnDrop; - match self { - Z { - a: ref mut __binding_0, - b: ref mut __binding_1, - c: ref mut __binding_2, - } => { - { __binding_0.zeroize_or_on_drop(); } - { __binding_1.zeroize_or_on_drop(); } - { __binding_2.zeroize_or_on_drop(); } - } + }, + quote! { + impl Drop for Z { + fn drop(&mut self) { + use ::zeroize::__internal::AssertZeroize; + use ::zeroize::__internal::AssertZeroizeOnDrop; + match self { + #[allow(unused_variables)] + Z { a, b, c } => { + a.zeroize_or_on_drop(); + b.zeroize_or_on_drop(); + c.zeroize_or_on_drop() } + _ => {} } } - }; - #[allow(non_upper_case_globals)] + } #[doc(hidden)] - const _DERIVE_zeroize_ZeroizeOnDrop_FOR_Z: () = { - extern crate zeroize; - impl zeroize::ZeroizeOnDrop for Z {} - }; - } - no_build // tests the code compiles are in the `zeroize` crate - } + impl ::zeroize::ZeroizeOnDrop for Z {} + }, + ) } #[test] @@ -801,10 +829,4 @@ mod tests { struct Z(T); )); } - - fn parse_zeroize_test(unparsed: &str) -> TokenStream { - derive_zeroize(Structure::new( - &parse_str(unparsed).expect("Failed to parse test input"), - )) - } } From 1d5bf32d32d6717b9cd0c3e5998f9fae0a9c6160 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 26 Mar 2023 13:15:14 -0600 Subject: [PATCH 072/116] zeroize: add `cross` tests to CI (#874) Adds PPC32, which should be useful for checking that any optional ASM-based features will still work on platforms where ASM has not yet been stabilized. --- .github/workflows/cmov.yml | 2 -- .github/workflows/zeroize.yml | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/cmov.yml b/.github/workflows/cmov.yml index 9b736012..b2f67ad5 100644 --- a/.github/workflows/cmov.yml +++ b/.github/workflows/cmov.yml @@ -89,13 +89,11 @@ jobs: rust: 1.60.0 # MSRV - target: aarch64-unknown-linux-gnu rust: stable - # PPC32 - target: powerpc-unknown-linux-gnu rust: 1.60.0 # MSRV - target: powerpc-unknown-linux-gnu rust: stable - runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index 240df4e1..21ffdea1 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -92,6 +92,27 @@ jobs: - run: cargo test --target ${{ matrix.target }} - run: cargo test --target ${{ matrix.target }} --all-features + # Cross-compiled tests + cross: + strategy: + matrix: + include: + # PPC32 + - target: powerpc-unknown-linux-gnu + rust: 1.56.0 # MSRV + - target: powerpc-unknown-linux-gnu + rust: stable + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: RustCrypto/actions/cargo-cache@master + - uses: dtolnay/rust-toolchain@master + with: + toolchain: ${{ matrix.rust }} + targets: ${{ matrix.target }} + - uses: RustCrypto/actions/cross-install@master + - run: cross test --target ${{ matrix.target }} + # Feature-gated ARM64 SIMD register support (MSRV 1.59) aarch64: strategy: From e03bf4e16fe4b00056f7cb1bd3be802224925223 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 26 Mar 2023 16:43:31 -0600 Subject: [PATCH 073/116] zeroize_derive v1.4.0 (#875) --- Cargo.lock | 2 +- zeroize/Cargo.toml | 2 +- zeroize/derive/CHANGELOG.md | 11 +++++++++++ zeroize/derive/Cargo.toml | 2 +- zeroize/derive/LICENSE-MIT | 2 +- 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cdac0c34..9bb7659e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,7 +227,7 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.0-pre" +version = "1.4.0" dependencies = [ "proc-macro2", "quote", diff --git a/zeroize/Cargo.toml b/zeroize/Cargo.toml index 380a6a50..0d38204a 100644 --- a/zeroize/Cargo.toml +++ b/zeroize/Cargo.toml @@ -19,7 +19,7 @@ rust-version = "1.56" [dependencies] serde = { version = "1.0", default-features = false, optional = true } -zeroize_derive = { version = "=1.4.0-pre", path = "derive", optional = true } +zeroize_derive = { version = "1.3", path = "derive", optional = true } [features] default = ["alloc"] diff --git a/zeroize/derive/CHANGELOG.md b/zeroize/derive/CHANGELOG.md index 41913423..0cd48399 100644 --- a/zeroize/derive/CHANGELOG.md +++ b/zeroize/derive/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.4.0 (2023-03-26) +### Changed +- 2021 edition upgrade; MSRV 1.56 ([#869]) +- Bump `syn` to v2 ([#858]) + +### Removed +- `synstructure` dependency ([#858]) + +[#858]: https://github.com/RustCrypto/utils/pull/858 +[#869]: https://github.com/RustCrypto/utils/pull/869 + ## 1.3.3 (2022-11-30) ### Fixed - Deriving `ZeroizeOnDrop` on items with generics ([#787]) diff --git a/zeroize/derive/Cargo.toml b/zeroize/derive/Cargo.toml index cadc4438..8ac579c8 100644 --- a/zeroize/derive/Cargo.toml +++ b/zeroize/derive/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "zeroize_derive" description = "Custom derive support for zeroize" -version = "1.4.0-pre" +version = "1.4.0" authors = ["The RustCrypto Project Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/zeroize/derive" diff --git a/zeroize/derive/LICENSE-MIT b/zeroize/derive/LICENSE-MIT index 42816283..de3a9c5c 100644 --- a/zeroize/derive/LICENSE-MIT +++ b/zeroize/derive/LICENSE-MIT @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2019-2021 The RustCrypto Project Developers +Copyright (c) 2019-2023 The RustCrypto Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 54d5f70a79374ba9e4bc044e358d490be6596269 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 26 Mar 2023 17:26:40 -0600 Subject: [PATCH 074/116] zeroize v1.6.0 (#876) --- Cargo.lock | 2 +- zeroize/CHANGELOG.md | 12 ++++++++++++ zeroize/Cargo.toml | 2 +- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9bb7659e..88291a31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -219,7 +219,7 @@ dependencies = [ [[package]] name = "zeroize" -version = "1.6.0-pre" +version = "1.6.0" dependencies = [ "serde", "zeroize_derive", diff --git a/zeroize/CHANGELOG.md b/zeroize/CHANGELOG.md index 83f89587..12fded96 100644 --- a/zeroize/CHANGELOG.md +++ b/zeroize/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.6.0 (2023-03-26) +### Added +- Impl `Zeroize` for `core::num::Wrapping` ([#818]) +- Impl `Zeroize` for `str` and `Box` ([#842]) + +### Changed +- 2021 edition upgrade; MSRV 1.56 ([#869]) + +[#818]: https://github.com/RustCrypto/utils/pull/818 +[#842]: https://github.com/RustCrypto/utils/pull/842 +[#869]: https://github.com/RustCrypto/utils/pull/869 + ## 1.5.7 (2022-07-20) ### Added - Optional `serde` support ([#780]) diff --git a/zeroize/Cargo.toml b/zeroize/Cargo.toml index 0d38204a..d1bbf81b 100644 --- a/zeroize/Cargo.toml +++ b/zeroize/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "zeroize" -version = "1.6.0-pre" +version = "1.6.0" description = """ Securely clear secrets from memory with a simple trait built on stable Rust primitives which guarantee memory is zeroed using an From 7e45b74d76354bbaf266344b9cc011967f657017 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 27 Mar 2023 08:15:08 -0600 Subject: [PATCH 075/116] build(deps): bump proc-macro2 from 1.0.53 to 1.0.54 (#877) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.53 to 1.0.54. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.53...1.0.54) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88291a31..d16ce888 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,9 +125,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.53" +version = "1.0.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73" +checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" dependencies = [ "unicode-ident", ] From 74770c8561061483e749caf7256f0301aa8f7234 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Mon, 27 Mar 2023 09:28:35 -0700 Subject: [PATCH 076/116] Do not automatically inject bounds (#879) Fixes #878 --- zeroize/derive/src/lib.rs | 16 +++------------- zeroize/tests/zeroize_derive.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/zeroize/derive/src/lib.rs b/zeroize/derive/src/lib.rs index 650dacb6..215bd785 100644 --- a/zeroize/derive/src/lib.rs +++ b/zeroize/derive/src/lib.rs @@ -8,11 +8,10 @@ use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use syn::{ parse::{Parse, ParseStream}, - parse_quote, punctuated::Punctuated, token::Comma, - Attribute, Data, DeriveInput, Expr, ExprLit, Field, Fields, GenericParam, Lit, Meta, Result, - Variant, WherePredicate, + Attribute, Data, DeriveInput, Expr, ExprLit, Field, Fields, Lit, Meta, Result, Variant, + WherePredicate, }; /// Name of zeroize-related attributes @@ -39,16 +38,7 @@ fn derive_zeroize_impl(input: DeriveInput) -> TokenStream { let extra_bounds = match attributes.bound { Some(bounds) => bounds.0, - None => { - let mut out: Punctuated = Default::default(); - for param in &input.generics.params { - if let GenericParam::Type(type_param) = param { - let type_name = &type_param.ident; - out.push(parse_quote! { #type_name: Zeroize }) - } - } - out - } + None => Default::default(), }; let mut generics = input.generics.clone(); diff --git a/zeroize/tests/zeroize_derive.rs b/zeroize/tests/zeroize_derive.rs index 96c10c32..1277cc55 100644 --- a/zeroize/tests/zeroize_derive.rs +++ b/zeroize/tests/zeroize_derive.rs @@ -325,3 +325,29 @@ fn derive_zeroize_on_drop_generic() { #[derive(ZeroizeOnDrop)] struct Z(Vec); } + +#[test] +fn derive_zeroize_unused_param() { + #[derive(Zeroize)] + struct Z { + arr: [u32; 5], + #[zeroize(skip)] + skipped: T, + } +} + +#[test] +// Issue #878 +fn derive_zeroize_with_marker() { + #[derive(ZeroizeOnDrop, Zeroize)] + struct Test { + #[zeroize(skip)] + field: Option, + } + + trait Secret: ZeroizeOnDrop + Zeroize {} + + impl Secret for Test {} + + trait Marker {} +} From e3af7c3cb337ce8b9f4ef8b68ea72af1457c5220 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 27 Mar 2023 11:09:58 -0600 Subject: [PATCH 077/116] zeroize_derive v1.4.1 (#880) --- Cargo.lock | 2 +- zeroize/derive/CHANGELOG.md | 6 ++++++ zeroize/derive/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d16ce888..43ed2e6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,7 +227,7 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.0" +version = "1.4.1" dependencies = [ "proc-macro2", "quote", diff --git a/zeroize/derive/CHANGELOG.md b/zeroize/derive/CHANGELOG.md index 0cd48399..46c926de 100644 --- a/zeroize/derive/CHANGELOG.md +++ b/zeroize/derive/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.4.1 (2023-03-27) +### Changed +- Do not automatically inject bounds ([#879]) + +[#879]: https://github.com/RustCrypto/utils/pull/879 + ## 1.4.0 (2023-03-26) ### Changed - 2021 edition upgrade; MSRV 1.56 ([#869]) diff --git a/zeroize/derive/Cargo.toml b/zeroize/derive/Cargo.toml index 8ac579c8..303bb37c 100644 --- a/zeroize/derive/Cargo.toml +++ b/zeroize/derive/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "zeroize_derive" description = "Custom derive support for zeroize" -version = "1.4.0" +version = "1.4.1" authors = ["The RustCrypto Project Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/zeroize/derive" From 8c650ca2f1eeeddeac0eba82e0008dcfc95bdc67 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Mar 2023 07:53:42 -0600 Subject: [PATCH 078/116] build(deps): bump generic-array from 0.14.6 to 0.14.7 (#881) Bumps [generic-array](https://github.com/fizyk20/generic-array) from 0.14.6 to 0.14.7. - [Release notes](https://github.com/fizyk20/generic-array/releases) - [Changelog](https://github.com/fizyk20/generic-array/blob/master/CHANGELOG.md) - [Commits](https://github.com/fizyk20/generic-array/commits) --- updated-dependencies: - dependency-name: generic-array dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43ed2e6e..d91600d0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "generic-array" -version = "0.14.6" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", From 4b069849286b6d1bd86fea097ddb66ff3db9d6c0 Mon Sep 17 00:00:00 2001 From: Matthew Maurer Date: Thu, 30 Mar 2023 18:14:56 -0700 Subject: [PATCH 079/116] zeroize_derive: Inject where clauses; skip unused (#882) The where clauses I was previously injecting *were* load bearing, but they needed to be filtered for skipped fields. Fixes #878 --- zeroize/derive/Cargo.toml | 2 +- zeroize/derive/src/lib.rs | 50 +++++++++++++++++++++++++++++++-- zeroize/tests/zeroize_derive.rs | 9 ++++++ 3 files changed, 58 insertions(+), 3 deletions(-) diff --git a/zeroize/derive/Cargo.toml b/zeroize/derive/Cargo.toml index 303bb37c..baaacf13 100644 --- a/zeroize/derive/Cargo.toml +++ b/zeroize/derive/Cargo.toml @@ -17,7 +17,7 @@ proc-macro = true [dependencies] proc-macro2 = "1" quote = "1" -syn = {version = "2", features = ["full", "extra-traits"]} +syn = {version = "2", features = ["full", "extra-traits", "visit"]} [package.metadata.docs.rs] rustdoc-args = ["--document-private-items"] diff --git a/zeroize/derive/src/lib.rs b/zeroize/derive/src/lib.rs index 215bd785..2f31fc65 100644 --- a/zeroize/derive/src/lib.rs +++ b/zeroize/derive/src/lib.rs @@ -8,8 +8,10 @@ use proc_macro2::{Ident, TokenStream}; use quote::{format_ident, quote}; use syn::{ parse::{Parse, ParseStream}, + parse_quote, punctuated::Punctuated, token::Comma, + visit::Visit, Attribute, Data, DeriveInput, Expr, ExprLit, Field, Fields, Lit, Meta, Result, Variant, WherePredicate, }; @@ -36,12 +38,19 @@ pub fn derive_zeroize(input: proc_macro::TokenStream) -> proc_macro::TokenStream fn derive_zeroize_impl(input: DeriveInput) -> TokenStream { let attributes = ZeroizeAttrs::parse(&input); + let mut generics = input.generics.clone(); + let extra_bounds = match attributes.bound { Some(bounds) => bounds.0, - None => Default::default(), + None => attributes + .auto_params + .iter() + .map(|type_param| -> WherePredicate { + parse_quote! {#type_param: Zeroize} + }) + .collect(), }; - let mut generics = input.generics.clone(); generics.make_where_clause().predicates.extend(extra_bounds); let ty_name = &input.ident; @@ -117,6 +126,8 @@ struct ZeroizeAttrs { drop: bool, /// Custom bounds as defined by the user bound: Option, + /// Type parameters in use by fields + auto_params: Vec, } /// Parsing helper for custom bounds @@ -128,10 +139,37 @@ impl Parse for Bounds { } } +struct BoundAccumulator<'a> { + generics: &'a syn::Generics, + params: Vec, +} + +impl<'ast> Visit<'ast> for BoundAccumulator<'ast> { + fn visit_path(&mut self, path: &'ast syn::Path) { + if path.segments.len() != 1 { + return; + } + + if let Some(segment) = path.segments.first() { + for param in &self.generics.params { + if let syn::GenericParam::Type(type_param) = param { + if type_param.ident == segment.ident && !self.params.contains(&segment.ident) { + self.params.push(type_param.ident.clone()); + } + } + } + } + } +} + impl ZeroizeAttrs { /// Parse attributes from the incoming AST fn parse(input: &DeriveInput) -> Self { let mut result = Self::default(); + let mut bound_accumulator = BoundAccumulator { + generics: &input.generics, + params: Vec::new(), + }; for attr in &input.attrs { result.parse_attr(attr, None, None); @@ -147,6 +185,9 @@ impl ZeroizeAttrs { for attr in &field.attrs { result.parse_attr(attr, Some(variant), Some(field)); } + if !attr_skip(&field.attrs) { + bound_accumulator.visit_type(&field.ty); + } } } } @@ -155,11 +196,16 @@ impl ZeroizeAttrs { for attr in &field.attrs { result.parse_attr(attr, None, Some(field)); } + if !attr_skip(&field.attrs) { + bound_accumulator.visit_type(&field.ty); + } } } syn::Data::Union(union_) => panic!("Unsupported untagged union {:?}", union_), } + result.auto_params = bound_accumulator.params; + result } diff --git a/zeroize/tests/zeroize_derive.rs b/zeroize/tests/zeroize_derive.rs index 1277cc55..c561ba61 100644 --- a/zeroize/tests/zeroize_derive.rs +++ b/zeroize/tests/zeroize_derive.rs @@ -351,3 +351,12 @@ fn derive_zeroize_with_marker() { trait Marker {} } + +#[test] +// Issue #878 +fn derive_zeroize_used_param() { + #[derive(Zeroize)] + struct Z { + used: T, + } +} From 83c7093d6068700c3f2a60b4b7e581b6da508008 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 30 Mar 2023 20:07:44 -0600 Subject: [PATCH 080/116] zeroize_derive v1.4.2 (#883) --- Cargo.lock | 2 +- zeroize/derive/CHANGELOG.md | 6 ++++++ zeroize/derive/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d91600d0..70d32907 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -227,7 +227,7 @@ dependencies = [ [[package]] name = "zeroize_derive" -version = "1.4.1" +version = "1.4.2" dependencies = [ "proc-macro2", "quote", diff --git a/zeroize/derive/CHANGELOG.md b/zeroize/derive/CHANGELOG.md index 46c926de..8b950c05 100644 --- a/zeroize/derive/CHANGELOG.md +++ b/zeroize/derive/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 1.4.2 (2023-03-30) +### Changed +- Inject where clauses; skip unused ([#882]) + +[#882]: https://github.com/RustCrypto/utils/pull/882 + ## 1.4.1 (2023-03-27) ### Changed - Do not automatically inject bounds ([#879]) diff --git a/zeroize/derive/Cargo.toml b/zeroize/derive/Cargo.toml index baaacf13..07dab7fe 100644 --- a/zeroize/derive/Cargo.toml +++ b/zeroize/derive/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "zeroize_derive" description = "Custom derive support for zeroize" -version = "1.4.1" +version = "1.4.2" authors = ["The RustCrypto Project Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/zeroize/derive" From 734c63b03165ae249fd02e6ebc5a21b2a4971993 Mon Sep 17 00:00:00 2001 From: jake <77554505+brxken128@users.noreply.github.com> Date: Sat, 1 Apr 2023 18:35:54 +0100 Subject: [PATCH 081/116] cmov: implement constant-time equality comparisons (#873) --- cmov/src/aarch64.rs | 114 +++++++++------- cmov/src/lib.rs | 56 +++++++- cmov/src/portable.rs | 38 +++++- cmov/src/x86.rs | 78 +++++++++-- cmov/tests/lib.rs | 305 ++++++++++++++++++++++++++++++++++--------- 5 files changed, 475 insertions(+), 116 deletions(-) diff --git a/cmov/src/aarch64.rs b/cmov/src/aarch64.rs index 700b4b47..82920479 100644 --- a/cmov/src/aarch64.rs +++ b/cmov/src/aarch64.rs @@ -1,15 +1,15 @@ -use crate::{Cmov, Condition}; +use crate::{Cmov, CmovEq, Condition}; use core::arch::asm; macro_rules! csel { - ($cmp:expr, $csel:expr, $dst:expr, $src:expr, $condition:expr) => { + ($csel:expr, $dst:expr, $src:expr, $condition:expr) => { unsafe { asm! { - $cmp, + "cmp {0:w}, 0", $csel, in(reg) $condition, inlateout(reg) *$dst, - in(reg) $src, + in(reg) *$src, in(reg) *$dst, options(pure, nomem, nostack), }; @@ -17,74 +17,96 @@ macro_rules! csel { }; } +macro_rules! csel_eq { + ($instruction:expr, $lhs:expr, $rhs:expr, $condition:expr, $dst:expr) => { + let mut tmp = *$dst as u16; + unsafe { + asm! { + "eor {0:w}, {1:w}, {2:w}", + "cmp {0:w}, 0", + $instruction, + out(reg) _, + in(reg) *$lhs, + in(reg) *$rhs, + inlateout(reg) tmp, + in(reg) $condition as u16, + in(reg) tmp, + options(pure, nomem, nostack), + }; + }; + + *$dst = tmp as u8; + }; +} + impl Cmov for u16 { #[inline(always)] fn cmovnz(&mut self, value: &Self, condition: Condition) { - csel!( - "cmp {0:w}, 0", - "csel {1:w}, {2:w}, {3:w}, NE", - self, - *value, - condition - ); + csel!("csel {1:w}, {2:w}, {3:w}, NE", self, value, condition); } #[inline(always)] fn cmovz(&mut self, value: &Self, condition: Condition) { - csel!( - "cmp {0:w}, 0", - "csel {1:w}, {2:w}, {3:w}, EQ", - self, - *value, - condition - ); + csel!("csel {1:w}, {2:w}, {3:w}, EQ", self, value, condition); + } +} + +impl CmovEq for u16 { + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + csel_eq!("csel {3:w}, {4:w}, {5:w}, NE", self, rhs, input, output); + } + + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + csel_eq!("csel {3:w}, {4:w}, {5:w}, EQ", self, rhs, input, output); } } impl Cmov for u32 { #[inline(always)] fn cmovnz(&mut self, value: &Self, condition: Condition) { - csel!( - "cmp {0:w}, 0", - "csel {1:w}, {2:w}, {3:w}, NE", - self, - *value, - condition - ); + csel!("csel {1:w}, {2:w}, {3:w}, NE", self, value, condition); } #[inline(always)] fn cmovz(&mut self, value: &Self, condition: Condition) { - csel!( - "cmp {0:w}, 0", - "csel {1:w}, {2:w}, {3:w}, EQ", - self, - *value, - condition - ); + csel!("csel {1:w}, {2:w}, {3:w}, EQ", self, value, condition); + } +} + +impl CmovEq for u32 { + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + csel_eq!("csel {3:w}, {4:w}, {5:w}, NE", self, rhs, input, output); + } + + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + csel_eq!("csel {3:w}, {4:w}, {5:w}, EQ", self, rhs, input, output); } } impl Cmov for u64 { #[inline(always)] fn cmovnz(&mut self, value: &Self, condition: Condition) { - csel!( - "cmp {0:x}, 0", - "csel {1:x}, {2:x}, {3:x}, NE", - self, - *value, - condition - ); + csel!("csel {1:x}, {2:x}, {3:x}, NE", self, value, condition); } #[inline(always)] fn cmovz(&mut self, value: &Self, condition: Condition) { - csel!( - "cmp {0:x}, 0", - "csel {1:x}, {2:x}, {3:x}, EQ", - self, - *value, - condition - ); + csel!("csel {1:x}, {2:x}, {3:x}, EQ", self, value, condition); + } +} + +impl CmovEq for u64 { + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + csel_eq!("csel {3:w}, {4:w}, {5:w}, NE", self, rhs, input, output); + } + + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + csel_eq!("csel {3:w}, {4:w}, {5:w}, EQ", self, rhs, input, output); } } diff --git a/cmov/src/lib.rs b/cmov/src/lib.rs index 1a9d9634..d661218e 100644 --- a/cmov/src/lib.rs +++ b/cmov/src/lib.rs @@ -22,7 +22,6 @@ mod x86; pub type Condition = u8; /// Conditional move -// TODO(tarcieri): make one of `cmovz`/`cmovnz` a provided method which calls the other? pub trait Cmov { /// Move if non-zero. /// @@ -41,6 +40,25 @@ pub trait Cmov { } } +/// Conditional move with equality comparison +pub trait CmovEq { + /// Move if both inputs are equal. + /// + /// Uses a `xor` instruction to compare the two values, and + /// conditionally moves `input` to `output` when they are equal. + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition); + + /// Move if both inputs are not equal. + /// + /// Uses a `xor` instruction to compare the two values, and + /// conditionally moves `input` to `output` when they are not equal. + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + let mut tmp = 1u8; + self.cmoveq(rhs, 0u8, &mut tmp); + tmp.cmoveq(&1u8, input, output); + } +} + impl Cmov for u8 { #[inline(always)] fn cmovnz(&mut self, value: &Self, condition: Condition) { @@ -57,6 +75,18 @@ impl Cmov for u8 { } } +impl CmovEq for u8 { + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + (*self as u16).cmoveq(&(*rhs as u16), input, output); + } + + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + (*self as u16).cmovne(&(*rhs as u16), input, output); + } +} + impl Cmov for u128 { #[inline(always)] fn cmovnz(&mut self, value: &Self, condition: Condition) { @@ -80,3 +110,27 @@ impl Cmov for u128 { *self = (lo as u128) | (hi as u128) << 64; } } + +impl CmovEq for u128 { + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + let lo = (*self & u64::MAX as u128) as u64; + let hi = (*self >> 64) as u64; + + let mut tmp = 1u8; + lo.cmovne(&((*rhs & u64::MAX as u128) as u64), 0, &mut tmp); + hi.cmovne(&((*rhs >> 64) as u64), 0, &mut tmp); + tmp.cmoveq(&0, input, output); + } + + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + let lo = (*self & u64::MAX as u128) as u64; + let hi = (*self >> 64) as u64; + + let mut tmp = 1u8; + lo.cmovne(&((*rhs & u64::MAX as u128) as u64), 0, &mut tmp); + hi.cmovne(&((*rhs >> 64) as u64), 0, &mut tmp); + tmp.cmoveq(&1, input, output); + } +} diff --git a/cmov/src/portable.rs b/cmov/src/portable.rs index f793a0c7..623d4c61 100644 --- a/cmov/src/portable.rs +++ b/cmov/src/portable.rs @@ -6,7 +6,7 @@ // TODO(tarcieri): more optimized implementation for small integers -use crate::{Cmov, Condition}; +use crate::{Cmov, CmovEq, Condition}; impl Cmov for u16 { #[inline(always)] @@ -24,6 +24,18 @@ impl Cmov for u16 { } } +impl CmovEq for u16 { + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + (*self as u64).cmovne(&(*rhs as u64), input, output); + } + + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + (*self as u64).cmoveq(&(*rhs as u64), input, output); + } +} + impl Cmov for u32 { #[inline(always)] fn cmovnz(&mut self, value: &Self, condition: Condition) { @@ -40,6 +52,18 @@ impl Cmov for u32 { } } +impl CmovEq for u32 { + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + (*self as u64).cmovne(&(*rhs as u64), input, output); + } + + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + (*self as u64).cmoveq(&(*rhs as u64), input, output); + } +} + impl Cmov for u64 { #[inline(always)] fn cmovnz(&mut self, value: &Self, condition: Condition) { @@ -54,6 +78,18 @@ impl Cmov for u64 { } } +impl CmovEq for u64 { + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + output.cmovnz(&input, (self ^ rhs) as u8); + } + + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + output.cmovz(&input, (self ^ rhs) as u8); + } +} + /// Check if the given condition value is non-zero /// /// # Returns diff --git a/cmov/src/x86.rs b/cmov/src/x86.rs index 9b49ecf4..1f3d72ce 100644 --- a/cmov/src/x86.rs +++ b/cmov/src/x86.rs @@ -7,7 +7,7 @@ //! > quadword from a register or memory location to a register location. //! > The source and destination must be of the same size. -use crate::{Cmov, Condition}; +use crate::{Cmov, CmovEq, Condition}; use core::arch::asm; macro_rules! cmov { @@ -18,7 +18,7 @@ macro_rules! cmov { $instruction, in(reg_byte) $condition, inlateout(reg) *$dst, - in(reg) $src, + in(reg) *$src, options(pure, nomem, nostack), }; } @@ -28,24 +28,48 @@ macro_rules! cmov { impl Cmov for u16 { #[inline(always)] fn cmovnz(&mut self, value: &Self, condition: Condition) { - cmov!("cmovnz {1:e}, {2:e}", self, *value, condition); + cmov!("cmovnz {1:e}, {2:e}", self, value, condition); } #[inline(always)] fn cmovz(&mut self, value: &Self, condition: Condition) { - cmov!("cmovz {1:e}, {2:e}", self, *value, condition); + cmov!("cmovz {1:e}, {2:e}", self, value, condition); + } +} + +impl CmovEq for u16 { + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + output.cmovz(&input, (self ^ rhs) as u8); + } + + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + output.cmovnz(&input, (self ^ rhs) as u8); } } impl Cmov for u32 { #[inline(always)] fn cmovnz(&mut self, value: &Self, condition: Condition) { - cmov!("cmovnz {1:e}, {2:e}", self, *value, condition); + cmov!("cmovnz {1:e}, {2:e}", self, value, condition); } #[inline(always)] fn cmovz(&mut self, value: &Self, condition: Condition) { - cmov!("cmovz {1:e}, {2:e}", self, *value, condition); + cmov!("cmovz {1:e}, {2:e}", self, value, condition); + } +} + +impl CmovEq for u32 { + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + output.cmovz(&input, (self ^ rhs) as u8); + } + + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + output.cmovnz(&input, (self ^ rhs) as u8); } } @@ -74,15 +98,53 @@ impl Cmov for u64 { } } +#[cfg(target_arch = "x86")] +impl CmovEq for u64 { + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + let lo = (*self & u32::MAX as u64) as u32; + let hi = (*self >> 32) as u32; + + let mut tmp = 1u8; + lo.cmovne(&((*rhs & u32::MAX as u64) as u32), 0, &mut tmp); + hi.cmovne(&((*rhs >> 32) as u32), 0, &mut tmp); + tmp.cmoveq(&0, input, output); + } + + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + let lo = (*self & u32::MAX as u64) as u32; + let hi = (*self >> 32) as u32; + + let mut tmp = 1u8; + lo.cmovne(&((*rhs & u32::MAX as u64) as u32), 0, &mut tmp); + hi.cmovne(&((*rhs >> 32) as u32), 0, &mut tmp); + tmp.cmoveq(&1, input, output); + } +} + #[cfg(target_arch = "x86_64")] impl Cmov for u64 { #[inline(always)] fn cmovnz(&mut self, value: &Self, condition: Condition) { - cmov!("cmovnz {1:r}, {2:r}", self, *value, condition); + cmov!("cmovnz {1:r}, {2:r}", self, value, condition); } #[inline(always)] fn cmovz(&mut self, value: &Self, condition: Condition) { - cmov!("cmovz {1:r}, {2:r}", self, *value, condition); + cmov!("cmovz {1:r}, {2:r}", self, value, condition); + } +} + +#[cfg(target_arch = "x86_64")] +impl CmovEq for u64 { + #[inline(always)] + fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { + output.cmovz(&input, (self ^ rhs) as u8); + } + + #[inline(always)] + fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { + output.cmovnz(&input, (self ^ rhs) as u8); } } diff --git a/cmov/tests/lib.rs b/cmov/tests/lib.rs index 52053a5e..294b5828 100644 --- a/cmov/tests/lib.rs +++ b/cmov/tests/lib.rs @@ -1,149 +1,334 @@ mod u8 { - use cmov::Cmov; + use cmov::{Cmov, CmovEq}; + + pub const U8_A: u8 = 0x11; + pub const U8_B: u8 = 0x22; #[test] fn cmovz_works() { - let mut n = 0x11u8; + let mut n = U8_A; for cond in 1..0xFF { - n.cmovz(&0x22, cond); - assert_eq!(n, 0x11); + n.cmovz(&U8_B, cond); + assert_eq!(n, U8_A); } - n.cmovz(&0x22, 0); - assert_eq!(n, 0x22); + n.cmovz(&U8_B, 0); + assert_eq!(n, U8_B); } #[test] fn cmovnz_works() { - let mut n = 0x11u8; - n.cmovnz(&0x22, 0); - assert_eq!(n, 0x11); + let mut n = U8_A; + n.cmovnz(&U8_B, 0); + assert_eq!(n, U8_A); for cond in 1..0xFF { - let mut n = 0x11u8; - n.cmovnz(&0x22, cond); - assert_eq!(n, 0x22); + let mut n = U8_A; + n.cmovnz(&U8_B, cond); + assert_eq!(n, U8_B); } } + + #[test] + fn cmoveq_works() { + let mut o = 0u8; + + for cond in 1..0xFFu8 { + cond.cmoveq(&cond, cond, &mut o); + assert_eq!(o, cond); + cond.cmoveq(&0, 0, &mut o); + assert_eq!(o, cond); + } + + U8_A.cmoveq(&U8_A, 43u8, &mut o); + assert_eq!(o, 43u8); + U8_A.cmoveq(&U8_B, 55u8, &mut o); + assert_eq!(o, 43u8); + } + + #[test] + fn cmovne_works() { + let mut o = 0u8; + + for cond in 1..0xFFu8 { + cond.cmovne(&0, cond, &mut o); + assert_eq!(o, cond); + cond.cmovne(&cond, 0, &mut o); + assert_eq!(o, cond); + } + + U8_A.cmovne(&U8_B, 55u8, &mut o); + assert_eq!(o, 55u8); + U8_A.cmovne(&U8_A, 12u8, &mut o); + assert_eq!(o, 55u8); + } } mod u16 { - use cmov::Cmov; + use cmov::{Cmov, CmovEq}; + + pub const U16_A: u16 = 0x1111; + pub const U16_B: u16 = 0x2222; #[test] fn cmovz_works() { - let mut n = 0x1111u16; + let mut n = U16_A; for cond in 1..0xFF { - n.cmovz(&0x2222, cond); - assert_eq!(n, 0x1111); + n.cmovz(&U16_B, cond); + assert_eq!(n, U16_A); } - n.cmovz(&0x2222, 0); - assert_eq!(n, 0x2222); + n.cmovz(&U16_B, 0); + assert_eq!(n, U16_B); } #[test] fn cmovnz_works() { - let mut n = 0x1111u16; - n.cmovnz(&0x2222, 0); - assert_eq!(n, 0x1111); + let mut n = U16_A; + n.cmovnz(&U16_B, 0); + assert_eq!(n, U16_A); for cond in 1..0xFF { - let mut n = 0x1111u16; - n.cmovnz(&0x2222, cond); - assert_eq!(n, 0x2222); + let mut n = U16_A; + n.cmovnz(&U16_B, cond); + assert_eq!(n, U16_B); } } + + #[test] + fn cmoveq_works() { + let mut o = 0u8; + + for cond in 1..0xFFu16 { + cond.cmoveq(&cond, cond as u8, &mut o); + assert_eq!(o, cond as u8); + cond.cmoveq(&0, 0, &mut o); + assert_eq!(o, cond as u8); + } + + U16_A.cmoveq(&U16_A, 43u8, &mut o); + assert_eq!(o, 43u8); + U16_A.cmoveq(&U16_B, 55u8, &mut o); + assert_eq!(o, 43u8); + } + + #[test] + fn cmovne_works() { + let mut o = 0u8; + + for cond in 1..0xFFu16 { + cond.cmovne(&0, cond as u8, &mut o); + assert_eq!(o, cond as u8); + cond.cmovne(&cond, 0, &mut o); + assert_eq!(o, cond as u8); + } + + U16_A.cmovne(&U16_B, 55u8, &mut o); + assert_eq!(o, 55u8); + U16_A.cmovne(&U16_A, 12u8, &mut o); + assert_eq!(o, 55u8); + } } mod u32 { - use cmov::Cmov; + use cmov::{Cmov, CmovEq}; + + pub const U32_A: u32 = 0x1111_1111; + pub const U32_B: u32 = 0x2222_2222; #[test] fn cmovz_works() { - let mut n = 0x11111111u32; + let mut n = U32_A; for cond in 1..0xFF { - n.cmovz(&0x22222222, cond); - assert_eq!(n, 0x11111111); + n.cmovz(&U32_B, cond); + assert_eq!(n, U32_A); } - n.cmovz(&0x22222222, 0); - assert_eq!(n, 0x22222222); + n.cmovz(&U32_B, 0); + assert_eq!(n, U32_B); } #[test] fn cmovnz_works() { - let mut n = 0x11111111u32; - n.cmovnz(&0x22222222, 0); - assert_eq!(n, 0x11111111); + let mut n = U32_A; + n.cmovnz(&U32_B, 0); + assert_eq!(n, U32_A); for cond in 1..0xFF { - let mut n = 0x11111111u32; - n.cmovnz(&0x22222222, cond); - assert_eq!(n, 0x22222222); + let mut n = U32_A; + n.cmovnz(&U32_B, cond); + assert_eq!(n, U32_B); + } + } + + #[test] + fn cmoveq_works() { + let mut o = 0u8; + + for cond in 1..0xFFu32 { + cond.cmoveq(&cond, cond as u8, &mut o); + assert_eq!(o, cond as u8); + cond.cmoveq(&0, 0, &mut o); + assert_eq!(o, cond as u8); } + + U32_A.cmoveq(&U32_A, 43u8, &mut o); + assert_eq!(o, 43u8); + U32_A.cmoveq(&U32_B, 55u8, &mut o); + assert_eq!(o, 43u8); + } + + #[test] + fn cmovne_works() { + let mut o = 0u8; + + for cond in 1..0xFFu32 { + cond.cmovne(&0, cond as u8, &mut o); + assert_eq!(o, cond as u8); + cond.cmovne(&cond, 0, &mut o); + assert_eq!(o, cond as u8); + } + + U32_A.cmovne(&U32_B, 55u8, &mut o); + assert_eq!(o, 55u8); + U32_A.cmovne(&U32_A, 12u8, &mut o); + assert_eq!(o, 55u8); } } mod u64 { - use cmov::Cmov; + use cmov::{Cmov, CmovEq}; + + pub const U64_A: u64 = 0x1111_1111_1111_1111; + pub const U64_B: u64 = 0x2222_2222_2222_2222; #[test] fn cmovz_works() { - let mut n = 0x1111_1111_1111_1111_u64; + let mut n = U64_A; for cond in 1..0xFF { - n.cmovz(&0x2222_2222_2222_2222, cond); - assert_eq!(n, 0x1111_1111_1111_1111); + n.cmovz(&U64_B, cond); + assert_eq!(n, U64_A); } - n.cmovz(&0x2222_2222_2222_2222, 0); - assert_eq!(n, 0x2222_2222_2222_2222); + n.cmovz(&U64_B, 0); + assert_eq!(n, U64_B); } #[test] fn cmovnz_works() { - let mut n = 0x1111_1111_1111_1111_u64; - n.cmovnz(&0x2222_2222_2222_2222, 0); - assert_eq!(n, 0x1111_1111_1111_1111); + let mut n = U64_A; + n.cmovnz(&U64_B, 0); + assert_eq!(n, U64_A); for cond in 1..0xFF { - let mut n = 0x1111_1111_1111_1111_u64; - n.cmovnz(&0x2222_2222_2222_2222, cond); - assert_eq!(n, 0x2222_2222_2222_2222); + let mut n = U64_A; + n.cmovnz(&U64_B, cond); + assert_eq!(n, U64_B); + } + } + + #[test] + fn cmoveq_works() { + let mut o = 0u8; + + for cond in 1..0xFFu64 { + cond.cmoveq(&cond, cond as u8, &mut o); + assert_eq!(o, cond as u8); + cond.cmoveq(&0, 0, &mut o); + assert_eq!(o, cond as u8); + } + + U64_A.cmoveq(&U64_A, 43u8, &mut o); + assert_eq!(o, 43u8); + U64_A.cmoveq(&U64_B, 55u8, &mut o); + assert_eq!(o, 43u8); + } + + #[test] + fn cmovne_works() { + let mut o = 0u8; + + for cond in 1..0xFFu64 { + cond.cmovne(&0, cond as u8, &mut o); + assert_eq!(o, cond as u8); + cond.cmovne(&cond, 0, &mut o); + assert_eq!(o, cond as u8); } + + U64_A.cmovne(&U64_B, 55u8, &mut o); + assert_eq!(o, 55u8); + U64_A.cmovne(&U64_A, 12u8, &mut o); + assert_eq!(o, 55u8); } } mod u128 { - use cmov::Cmov; + use cmov::{Cmov, CmovEq}; + + pub const U128_A: u128 = 0x1111_1111_1111_1111_2222_2222_2222_2222; + pub const U128_B: u128 = 0x2222_2222_2222_2222_3333_3333_3333_3333; #[test] fn cmovz_works() { - let mut n = 0x1111_1111_1111_1111_2222_2222_2222_2222_u128; + let mut n = U128_A; for cond in 1..0xFF { - n.cmovz(&0x2222_2222_2222_2222_3333_3333_3333_3333, cond); - assert_eq!(n, 0x1111_1111_1111_1111_2222_2222_2222_2222); + n.cmovz(&U128_B, cond); + assert_eq!(n, U128_A); } - n.cmovz(&0x2222_2222_2222_2222_3333_3333_3333_3333, 0); - assert_eq!(n, 0x2222_2222_2222_2222_3333_3333_3333_3333); + n.cmovz(&U128_B, 0); + assert_eq!(n, U128_B); } #[test] fn cmovnz_works() { - let mut n = 0x1111_1111_1111_1111_2222_2222_2222_2222_u128; - n.cmovnz(&0x2222_2222_2222_2222_3333_3333_3333_3333, 0); - assert_eq!(n, 0x1111_1111_1111_1111_2222_2222_2222_2222); + let mut n = U128_A; + n.cmovnz(&U128_B, 0); + assert_eq!(n, U128_A); for cond in 1..0xFF { - let mut n = 0x1111_1111_1111_1111_u128; - n.cmovnz(&0x2222_2222_2222_2222_3333_3333_3333_3333, cond); - assert_eq!(n, 0x2222_2222_2222_2222_3333_3333_3333_3333); + let mut n = U128_A; + n.cmovnz(&U128_B, cond); + assert_eq!(n, U128_B); + } + } + + #[test] + fn cmoveq_works() { + let mut o = 0u8; + + for cond in 1..0xFFu128 { + cond.cmoveq(&cond, cond as u8, &mut o); + assert_eq!(o, cond as u8); + cond.cmoveq(&0, 0, &mut o); + assert_eq!(o, cond as u8); + } + + U128_A.cmoveq(&U128_A, 43u8, &mut o); + assert_eq!(o, 43u8); + U128_A.cmoveq(&U128_B, 55u8, &mut o); + assert_eq!(o, 43u8); + } + + #[test] + fn cmovne_works() { + let mut o = 0u8; + + for cond in 1..0xFFu128 { + cond.cmovne(&0, cond as u8, &mut o); + assert_eq!(o, cond as u8); + cond.cmovne(&cond, 0, &mut o); + assert_eq!(o, cond as u8); } + + U128_A.cmovne(&U128_B, 55u8, &mut o); + assert_eq!(o, 55u8); + U128_A.cmovne(&U128_A, 12u8, &mut o); + assert_eq!(o, 55u8); } } From 63fb20f03d11ecfaa22ab0121b9b7efedf7cc8f3 Mon Sep 17 00:00:00 2001 From: Charles Zinn Date: Sat, 1 Apr 2023 19:53:59 -0400 Subject: [PATCH 082/116] Add RawPadding trait to block-padding for padding blocks of arbitrary size (#870) --- block-padding/CHANGELOG.md | 6 +++ block-padding/Cargo.toml | 2 +- block-padding/src/lib.rs | 108 ++++++++++++++++++++++++------------- 3 files changed, 79 insertions(+), 37 deletions(-) diff --git a/block-padding/CHANGELOG.md b/block-padding/CHANGELOG.md index d2262996..8afef8b3 100644 --- a/block-padding/CHANGELOG.md +++ b/block-padding/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.3.3 (2023-04-02) +### Added +- `RawPadding` trait for padding blocks of arbitrary size ([#870]) + +[#870]: https://github.com/RustCrypto/utils/pull/870 + ## 0.3.2 (2022-03-10) ### Fixed - Potential unsoundness for incorrect `Padding` implementations ([#748]) diff --git a/block-padding/Cargo.toml b/block-padding/Cargo.toml index e8d66f02..6a049717 100644 --- a/block-padding/Cargo.toml +++ b/block-padding/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "block-padding" -version = "0.3.2" +version = "0.3.3" description = "Padding and unpadding of messages divided into blocks." authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" diff --git a/block-padding/src/lib.rs b/block-padding/src/lib.rs index 3f2fc67e..be950cc6 100644 --- a/block-padding/src/lib.rs +++ b/block-padding/src/lib.rs @@ -29,6 +29,25 @@ pub enum PadType { NoPadding, } +/// Trait for padding messages divided into blocks of arbitrary size +pub trait RawPadding { + /// Padding type + const TYPE: PadType; + + /// Pads `block` filled with data up to `pos` (i.e length of a message + /// stored in the block is equal to `pos`). + /// + /// # Panics + /// If `pos` is bigger than `block.len()`. Most padding algorithms also + /// panic if they are equal. + fn raw_pad(block: &mut [u8], pos: usize); + + /// Unpad data in the `block`. + /// + /// Returns `Err(UnpadError)` if the block contains malformed padding. + fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError>; +} + /// Block size. pub type Block = GenericArray; @@ -73,6 +92,23 @@ pub trait Padding> { } } +impl> Padding for T +where + T: RawPadding, +{ + const TYPE: PadType = T::TYPE; + + #[inline] + fn pad(block: &mut Block, pos: usize) { + T::raw_pad(block.as_mut_slice(), pos); + } + + #[inline] + fn unpad(block: &Block) -> Result<&[u8], UnpadError> { + T::raw_unpad(block.as_slice()) + } +} + /// Pad block with zeros. /// /// ``` @@ -94,12 +130,12 @@ pub trait Padding> { #[derive(Clone, Copy, Debug)] pub struct ZeroPadding; -impl> Padding for ZeroPadding { +impl RawPadding for ZeroPadding { const TYPE: PadType = PadType::Ambiguous; #[inline] - fn pad(block: &mut Block, pos: usize) { - if pos > B::USIZE { + fn raw_pad(block: &mut [u8], pos: usize) { + if pos > block.len() { panic!("`pos` is bigger than block size"); } for b in &mut block[pos..] { @@ -108,8 +144,8 @@ impl> Padding for ZeroPadding { } #[inline] - fn unpad(block: &Block) -> Result<&[u8], UnpadError> { - for i in (0..B::USIZE).rev() { + fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> { + for i in (0..block.len()).rev() { if block[i] != 0 { return Ok(&block[..i + 1]); } @@ -140,12 +176,12 @@ pub struct Pkcs7; impl Pkcs7 { #[inline] - fn unpad>(block: &Block, strict: bool) -> Result<&[u8], UnpadError> { + fn unpad(block: &[u8], strict: bool) -> Result<&[u8], UnpadError> { // TODO: use bounds to check it at compile time - if B::USIZE > 255 { + if block.len() > 255 { panic!("block size is too big for PKCS#7"); } - let bs = B::USIZE; + let bs = block.len(); let n = block[bs - 1]; if n == 0 || n as usize > bs { return Err(UnpadError); @@ -158,26 +194,26 @@ impl Pkcs7 { } } -impl> Padding for Pkcs7 { +impl RawPadding for Pkcs7 { const TYPE: PadType = PadType::Reversible; #[inline] - fn pad(block: &mut Block, pos: usize) { - // TODO: use bounds to check it at compile time - if B::USIZE > 255 { + fn raw_pad(block: &mut [u8], pos: usize) { + // TODO: use bounds to check it at compile time for Padding + if block.len() > 255 { panic!("block size is too big for PKCS#7"); } - if pos >= B::USIZE { + if pos >= block.len() { panic!("`pos` is bigger or equal to block size"); } - let n = (B::USIZE - pos) as u8; + let n = (block.len() - pos) as u8; for b in &mut block[pos..] { *b = n; } } #[inline] - fn unpad(block: &Block) -> Result<&[u8], UnpadError> { + fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> { Pkcs7::unpad(block, true) } } @@ -202,18 +238,18 @@ impl> Padding for Pkcs7 { #[derive(Clone, Copy, Debug)] pub struct Iso10126; -impl> Padding for Iso10126 { +impl RawPadding for Iso10126 { const TYPE: PadType = PadType::Reversible; #[inline] - fn pad(block: &mut Block, pos: usize) { + fn raw_pad(block: &mut [u8], pos: usize) { // Instead of generating random bytes as specified by Iso10126 we // simply use Pkcs7 padding. - Pkcs7::pad(block, pos) + Pkcs7::raw_pad(block, pos) } #[inline] - fn unpad(block: &Block) -> Result<&[u8], UnpadError> { + fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> { Pkcs7::unpad(block, false) } } @@ -237,19 +273,19 @@ impl> Padding for Iso10126 { #[derive(Clone, Copy, Debug)] pub struct AnsiX923; -impl> Padding for AnsiX923 { +impl RawPadding for AnsiX923 { const TYPE: PadType = PadType::Reversible; #[inline] - fn pad(block: &mut Block, pos: usize) { + fn raw_pad(block: &mut [u8], pos: usize) { // TODO: use bounds to check it at compile time - if B::USIZE > 255 { + if block.len() > 255 { panic!("block size is too big for PKCS#7"); } - if pos >= B::USIZE { + if pos >= block.len() { panic!("`pos` is bigger or equal to block size"); } - let bs = B::USIZE; + let bs = block.len(); for b in &mut block[pos..bs - 1] { *b = 0; } @@ -257,12 +293,12 @@ impl> Padding for AnsiX923 { } #[inline] - fn unpad(block: &Block) -> Result<&[u8], UnpadError> { + fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> { // TODO: use bounds to check it at compile time - if B::USIZE > 255 { + if block.len() > 255 { panic!("block size is too big for PKCS#7"); } - let bs = B::USIZE; + let bs = block.len(); let n = block[bs - 1] as usize; if n == 0 || n > bs { return Err(UnpadError); @@ -293,12 +329,12 @@ impl> Padding for AnsiX923 { #[derive(Clone, Copy, Debug)] pub struct Iso7816; -impl> Padding for Iso7816 { +impl RawPadding for Iso7816 { const TYPE: PadType = PadType::Reversible; #[inline] - fn pad(block: &mut Block, pos: usize) { - if pos >= B::USIZE { + fn raw_pad(block: &mut [u8], pos: usize) { + if pos >= block.len() { panic!("`pos` is bigger or equal to block size"); } block[pos] = 0x80; @@ -308,8 +344,8 @@ impl> Padding for Iso7816 { } #[inline] - fn unpad(block: &Block) -> Result<&[u8], UnpadError> { - for i in (0..B::USIZE).rev() { + fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> { + for i in (0..block.len()).rev() { match block[i] { 0x80 => return Ok(&block[..i]), 0x00 => continue, @@ -344,18 +380,18 @@ impl> Padding for Iso7816 { #[derive(Clone, Copy, Debug)] pub struct NoPadding; -impl> Padding for NoPadding { +impl RawPadding for NoPadding { const TYPE: PadType = PadType::NoPadding; #[inline] - fn pad(_block: &mut Block, pos: usize) { - if pos > B::USIZE { + fn raw_pad(block: &mut [u8], pos: usize) { + if pos > block.len() { panic!("`pos` is bigger than block size"); } } #[inline] - fn unpad(block: &Block) -> Result<&[u8], UnpadError> { + fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> { Ok(block) } } From c1e32c58ca814c0b6265725002f4d853c3272bef 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: Sun, 2 Apr 2023 02:55:36 +0300 Subject: [PATCH 083/116] Update Cargo.lock --- Cargo.lock | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 70d32907..47156007 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,7 +20,7 @@ dependencies = [ [[package]] name = "block-padding" -version = "0.3.2" +version = "0.3.3" dependencies = [ "generic-array", ] @@ -125,9 +125,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.54" +version = "1.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e472a104799c74b514a57226160104aa483546de37e839ec50e3c2e41dd87534" +checksum = "1d0dd4be24fcdcfeaa12a432d588dc59bbad6cad3510c67e74a2b6b2fc950564" dependencies = [ "unicode-ident", ] @@ -149,18 +149,18 @@ checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "serde" -version = "1.0.158" +version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9" +checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.158" +version = "1.0.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad" +checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" dependencies = [ "proc-macro2", "quote", @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" dependencies = [ "itoa", "ryu", @@ -180,9 +180,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.8" +version = "2.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9" +checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" dependencies = [ "proc-macro2", "quote", From f3dfe51805c831001ea82dcbbdfac53d35ef8b36 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Sun, 2 Apr 2023 02:21:12 +0000 Subject: [PATCH 084/116] hex-literal: remove support for comments inside literals and migrate to CTFE (#816) --- .github/workflows/hex-literal.yml | 4 +- hex-literal/CHANGELOG.md | 8 ++ hex-literal/Cargo.toml | 10 +- hex-literal/README.md | 84 ++++++++++++ hex-literal/src/comments.rs | 216 ------------------------------ hex-literal/src/lib.rs | 213 +++++++++-------------------- hex-literal/tests/comments.rs | 41 ------ 7 files changed, 163 insertions(+), 413 deletions(-) create mode 100644 hex-literal/README.md delete mode 100644 hex-literal/src/comments.rs delete mode 100644 hex-literal/tests/comments.rs diff --git a/.github/workflows/hex-literal.yml b/.github/workflows/hex-literal.yml index 133e36ef..dc77aeb2 100644 --- a/.github/workflows/hex-literal.yml +++ b/.github/workflows/hex-literal.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: rust: - - 1.45.0 # MSRV + - 1.57.0 # MSRV - stable target: - thumbv7em-none-eabi @@ -48,7 +48,7 @@ jobs: strategy: matrix: rust: - - 1.45.0 # MSRV + - 1.57.0 # MSRV - stable steps: - uses: actions/checkout@v3 diff --git a/hex-literal/CHANGELOG.md b/hex-literal/CHANGELOG.md index 1c72f15b..338be64b 100644 --- a/hex-literal/CHANGELOG.md +++ b/hex-literal/CHANGELOG.md @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## UNRELEASED +### Changed +- Disallow comments inside hex strings ([#816]) +- Migrate to 2021 edition and bump MSRV to 1.57 ([#816]) +- Use CTFE instead of proc macro ([#816]) + +[#816]: https://github.com/RustCrypto/utils/pull/816 + ## 0.3.4 (2021-11-11) ### Changed - Provide more info in `panic!` messages ([#664]) diff --git a/hex-literal/Cargo.toml b/hex-literal/Cargo.toml index e3d36833..b704b6b9 100644 --- a/hex-literal/Cargo.toml +++ b/hex-literal/Cargo.toml @@ -3,11 +3,9 @@ name = "hex-literal" version = "0.3.4" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" -description = "Procedural macro for converting hexadecimal string to byte array at compile time." +description = "Macro for converting hexadecimal string to a byte array at compile time" documentation = "https://docs.rs/hex-literal" repository = "https://github.com/RustCrypto/utils" -keywords = ["hex", "proc-macro", "literals"] -edition = "2018" - -[lib] -proc-macro = true +keywords = ["hex", "literals"] +edition = "2021" +rust-version = "1.57" diff --git a/hex-literal/README.md b/hex-literal/README.md new file mode 100644 index 00000000..72d527e4 --- /dev/null +++ b/hex-literal/README.md @@ -0,0 +1,84 @@ +# [RustCrypto]: hex-literal + +[![Crate][crate-image]][crate-link] +[![Docs][docs-image]][docs-link] +![Apache 2.0/MIT Licensed][license-image] +![MSRV][rustc-image] +[![Build Status][build-image]][build-link] + +This crate provides the `hex!` macro for converting hexadecimal string literals to a byte array at compile time. + +It accepts the following characters in the input string: + +- `'0'...'9'`, `'a'...'f'`, `'A'...'F'` — hex characters which will be used in construction of the output byte array +- `' '`, `'\r'`, `'\n'`, `'\t'` — formatting characters which will be ignored + +# Examples +```rust +use hex_literal::hex; + +// The macro can be used in const contexts +const DATA: [u8; 4] = hex!("01020304"); +assert_eq!(DATA, [1, 2, 3, 4]); + +// Both upper and lower hex values are supported +assert_eq!(hex!("a1 b2 c3 d4"), [0xA1, 0xB2, 0xC3, 0xD4]); +assert_eq!(hex!("E5 E6 90 92"), [0xE5, 0xE6, 0x90, 0x92]); +assert_eq!(hex!("0a0B 0C0d"), [10, 11, 12, 13]); + +// Multi-line literals +let bytes1 = hex!(" + 00010203 04050607 + 08090a0b 0c0d0e0f +"); +assert_eq!(bytes1, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); + +// It's possible to use several literals (results will be concatenated) +let bytes2 = hex!( + "00010203 04050607" // first half + "08090a0b" /* block comment */ "0c0d0e0f" // second half +); +assert_eq!(bytes1, bytes2); +``` + +Using an unsupported character inside literals will result in a compilation error: +```rust,compile_fail +# use hex_literal::hex; +hex!("АА"); // Cyrillic "А" +hex!("11 22"); // Japanese space +hex!("0123 // Сomments inside literals are not supported"); +``` + +## Minimum Supported Rust Version + +Rust **1.57** 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 a minor version bump. + +## License + +Licensed under either of: + +* [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) +* [MIT license](http://opensource.org/licenses/MIT) + +at your option. + +### Contribution + +Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. + +[//]: # (badges) + +[crate-image]: https://img.shields.io/crates/v/hex-literal.svg +[crate-link]: https://crates.io/crates/hex-literal +[docs-image]: https://docs.rs/hex-literal/badge.svg +[docs-link]: https://docs.rs/hex-literal/ +[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.57+-blue.svg +[build-image]: https://github.com/RustCrypto/utils/actions/workflows/hex-literal.yml/badge.svg +[build-link]: https://github.com/RustCrypto/utils/actions/workflows/hex-literal.yml + +[//]: # (general links) + +[RustCrypto]: https://github.com/RustCrypto diff --git a/hex-literal/src/comments.rs b/hex-literal/src/comments.rs deleted file mode 100644 index 6f8799d2..00000000 --- a/hex-literal/src/comments.rs +++ /dev/null @@ -1,216 +0,0 @@ -//! Provides an Iterator decorator that uses a finite state machine to exclude comments -//! from a string in linear time and constant space. - -use std::iter::Peekable; - -pub(crate) trait Exclude: Sized + Iterator { - fn exclude_comments(self) -> ExcludingComments; -} - -impl> Exclude for T { - fn exclude_comments(self) -> ExcludingComments { - ExcludingComments::new_from_iter(self) - } -} - -pub(crate) struct ExcludingComments> { - state: State, - iter: Peekable, -} - -impl> Iterator for ExcludingComments { - type Item = u8; - - fn next(&mut self) -> Option { - let next_byte = self.next_byte(); - if next_byte.is_none() { - match self.state { - State::BlockComment | State::PotentialBlockCommentEnd => { - panic!("block comment not terminated with */") - } - State::PotentialComment { .. } => panic!("encountered isolated `/`"), - _ => {} - } - } - next_byte - } -} - -/// States of the comment removal machine: -///
-///           Normal
-///            '/'                   
-///      PotentialComment
-///     '/'            '*'
-/// LineComment     BlockComment
-///    '\n'            '*'
-///   Normal      PotentialBlockCommentEnd
-///                    '/'           '_'
-///                   Normal     BlockComment
-/// 
-#[derive(Copy, Clone)] -enum State { - Normal, - PotentialComment, - LineComment, - BlockComment, - PotentialBlockCommentEnd, -} - -impl> ExcludingComments { - fn new_from_iter(iter: I) -> Self { - Self { - state: State::Normal, - iter: iter.peekable(), - } - } - - fn next_byte(&mut self) -> Option { - loop { - let next = self.iter.next()?; - self.state = match (self.state, next) { - (State::Normal, b'/') => State::PotentialComment, - (State::Normal, _) => return Some(next), - (State::PotentialComment, b'/') => State::LineComment, - (State::PotentialComment, b'*') => State::BlockComment, - (State::PotentialComment, _) => panic!("encountered isolated `/`"), - (State::LineComment, b'\n') => { - self.state = State::Normal; - return Some(b'\n'); - } - (State::LineComment, _) => continue, - (State::BlockComment, b'*') => State::PotentialBlockCommentEnd, - (State::BlockComment, _) => continue, - (State::PotentialBlockCommentEnd, b'/') => State::Normal, - (State::PotentialBlockCommentEnd, _) => State::BlockComment, - }; - } - } -} - -#[cfg(test)] -mod tests { - use std::vec::IntoIter; - - use super::*; - - /// Converts the input to an iterator of u8, excludes comments, maps back to char and collects - /// the results. - fn exclude_comments(input: &str) -> String { - let excluding_comments: ExcludingComments> = input - .to_string() - .into_bytes() - .into_iter() - .exclude_comments(); - excluding_comments.map(|b| b as char).collect() - } - - #[test] - fn empty() { - assert!(exclude_comments("").is_empty()); - } - - #[test] - fn single_char() { - assert_eq!(exclude_comments("0"), "0"); - } - - #[test] - fn two_chars() { - assert_eq!(exclude_comments("ab"), "ab"); - } - - #[test] - fn comment() { - assert_eq!(exclude_comments("ab//cd"), "ab"); - } - - #[test] - fn comments_are_ended_by_new_line() { - assert_eq!(exclude_comments("ab//comment\nde"), "ab\nde"); - } - - #[test] - fn new_lines_without_comments() { - assert_eq!(exclude_comments("ab\nde"), "ab\nde"); - } - - #[test] - #[should_panic] - fn panic_on_single_slash() { - exclude_comments("ab/cd"); - } - - #[test] - fn line_comments_on_multiple_lines() { - assert_eq!( - exclude_comments( - " -line 1 //comment 1 -line 2 // comment 2 // comment 3 -line 3 -line 4 // comment 4" - ), - " -line 1 -line 2 -line 3 -line 4 " - ); - } - - #[test] - fn block_comment() { - assert_eq!(exclude_comments("ab/*comment*/12"), "ab12"); - } - - #[test] - fn empty_block_comment() { - assert_eq!(exclude_comments("ab/**/12"), "ab12"); - } - - #[test] - fn block_comment_with_asterisk_and_slash_inside() { - assert_eq!(exclude_comments("ab/*false * asterisk and / */12"), "ab12"); - } - - #[test] - fn block_comment_within_line_comment() { - assert_eq!(exclude_comments("ab// /*comment*/12"), "ab"); - } - - #[test] - #[should_panic(expected = "block comment not terminated with */")] - fn block_comment_not_terminated() { - exclude_comments("ab /*comment"); - } - - #[test] - #[should_panic(expected = "block comment not terminated with */")] - fn block_comment_not_completely_terminated() { - exclude_comments("ab /*comment*"); - } - - #[test] - fn block_and_line_comments_on_multiple_lines() { - assert_eq!( - exclude_comments( - " -line 1 /* comment 1 */ -line /* comment 2 */2 // line comment 1 -line 3 /* some comments -over multiple lines -*/ -line 4 /* more multiline comments -* with leading -* asterisks -*/end// line comment 2" - ), - " -line 1 -line 2 -line 3 -line 4 end" - ); - } -} diff --git a/hex-literal/src/lib.rs b/hex-literal/src/lib.rs index 5399d3f3..4b31b071 100644 --- a/hex-literal/src/lib.rs +++ b/hex-literal/src/lib.rs @@ -1,169 +1,86 @@ -//! This crate provides the `hex!` macro for converting hexadecimal string literals -//! to a byte array at compile time. -//! -//! It accepts the following characters in the input string: -//! -//! - `'0'...'9'`, `'a'...'f'`, `'A'...'F'` — hex characters which will be used -//! in construction of the output byte array -//! - `' '`, `'\r'`, `'\n'`, `'\t'` — formatting characters which will be -//! ignored -//! -//! Additionally it accepts line (`//`) and block (`/* .. */`) comments. Characters -//! inside of those are ignored. -//! -//! # Examples -//! ``` -//! # #[macro_use] extern crate hex_literal; -//! // the macro can be used in const context -//! const DATA: [u8; 4] = hex!("01020304"); -//! # fn main() { -//! assert_eq!(DATA, [1, 2, 3, 4]); -//! -//! // it understands both upper and lower hex values -//! assert_eq!(hex!("a1 b2 c3 d4"), [0xA1, 0xB2, 0xC3, 0xD4]); -//! assert_eq!(hex!("E5 E6 90 92"), [0xE5, 0xE6, 0x90, 0x92]); -//! assert_eq!(hex!("0a0B 0C0d"), [10, 11, 12, 13]); -//! let bytes = hex!(" -//! 00010203 04050607 -//! 08090a0b 0c0d0e0f -//! "); -//! assert_eq!(bytes, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); -//! -//! // it's possible to use several literals (results will be concatenated) -//! let bytes2 = hex!( -//! "00010203 04050607" // first half -//! "08090a0b 0c0d0e0f" // second half -//! ); -//! assert_eq!(bytes2, bytes); -//! -//! // comments can be also included inside literals -//! assert_eq!(hex!("0a0B // 0c0d line comments"), [10, 11]); -//! assert_eq!(hex!("0a0B // line comments -//! 0c0d"), [10, 11, 12, 13]); -//! assert_eq!(hex!("0a0B /* block comments */ 0c0d"), [10, 11, 12, 13]); -//! assert_eq!(hex!("0a0B /* multi-line -//! block comments -//! */ 0c0d"), [10, 11, 12, 13]); -//! # } -//! ``` +#![doc = include_str!("../README.md")] +#![no_std] #![doc( html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" )] -mod comments; -extern crate proc_macro; - -use std::vec::IntoIter; - -use proc_macro::{Delimiter, Group, Literal, Punct, Spacing, TokenStream, TokenTree}; - -use crate::comments::{Exclude, ExcludingComments}; - -/// Strips any outer `Delimiter::None` groups from the input, -/// returning a `TokenStream` consisting of the innermost -/// non-empty-group `TokenTree`. -/// This is used to handle a proc macro being invoked -/// by a `macro_rules!` expansion. -/// See https://github.com/rust-lang/rust/issues/72545 for background -fn ignore_groups(mut input: TokenStream) -> TokenStream { - let mut tokens = input.clone().into_iter(); - loop { - if let Some(TokenTree::Group(group)) = tokens.next() { - if group.delimiter() == Delimiter::None { - input = group.stream(); - continue; - } - } - return input; +const fn next_hex_char(string: &[u8], mut pos: usize) -> Option<(u8, usize)> { + while pos < string.len() { + let raw_val = string[pos]; + pos += 1; + let val = match raw_val { + b'0'..=b'9' => raw_val - 48, + b'A'..=b'F' => raw_val - 55, + b'a'..=b'f' => raw_val - 87, + b' ' | b'\r' | b'\n' | b'\t' => continue, + 0..=127 => panic!("Encountered invalid ASCII character"), + _ => panic!("Encountered non-ASCII character"), + }; + return Some((val, pos)); } + None } -struct TokenTreeIter { - buf: ExcludingComments>, - is_punct: bool, +const fn next_byte(string: &[u8], pos: usize) -> Option<(u8, usize)> { + let (half1, pos) = match next_hex_char(string, pos) { + Some(v) => v, + None => return None, + }; + let (half2, pos) = match next_hex_char(string, pos) { + Some(v) => v, + None => panic!("Odd number of hex characters"), + }; + Some(((half1 << 4) + half2, pos)) } -impl TokenTreeIter { - /// Constructs a new `TokenTreeIter` from a given `proc_macro::Literal`. - /// - /// # Panics - /// This panics if the given `Literal` is not a string literal. - fn new(input: Literal) -> Self { - let mut buf: Vec = input.to_string().into(); - - match buf.as_slice() { - [b'"', .., b'"'] => (), - _ => panic!("expected string literal, got `{}`", input), - }; - buf.pop(); - let mut iter = buf.into_iter().exclude_comments(); - iter.next(); - Self { - buf: iter, - is_punct: false, +/// Compute length of a byte array which will be decoded from the strings. +/// +/// This function is an implementation detail and SHOULD NOT be called directly! +#[doc(hidden)] +pub const fn len(strings: &[&[u8]]) -> usize { + let mut i = 0; + let mut len = 0; + while i < strings.len() { + let mut pos = 0; + while let Some((_, new_pos)) = next_byte(strings[i], pos) { + len += 1; + pos = new_pos; } + i += 1; } + len +} - /// Parses a single hex character (a-f/A-F/0-9) as a `u8` from the `TokenTreeIter`'s - /// internal buffer, ignoring whitespace. - /// - /// # Panics - /// This panics if a non-hex, non-whitespace character is encountered. - fn next_hex_val(&mut self) -> Option { - loop { - let v = self.buf.next()?; - let n = match v { - b'0'..=b'9' => v - 48, - b'A'..=b'F' => v - 55, - b'a'..=b'f' => v - 87, - b' ' | b'\r' | b'\n' | b'\t' => continue, - 0..=127 => panic!("encountered invalid character: `{}`", v as char), - _ => panic!("encountered invalid non-ASCII character"), - }; - return Some(n); +/// Decode hex strings into a byte array of pre-computed length. +/// +/// This function is an implementation detail and SHOULD NOT be called directly! +#[doc(hidden)] +pub const fn decode(strings: &[&[u8]]) -> [u8; LEN] { + let mut i = 0; + let mut buf = [0u8; LEN]; + let mut buf_pos = 0; + while i < strings.len() { + let mut pos = 0; + while let Some((byte, new_pos)) = next_byte(strings[i], pos) { + buf[buf_pos] = byte; + buf_pos += 1; + pos = new_pos; } + i += 1; } -} - -impl Iterator for TokenTreeIter { - type Item = TokenTree; - - /// Produces hex values (as `u8` literals) parsed from the `TokenTreeIter`'s - /// internal buffer, alternating with commas to separate the elements of the - /// generated array of bytes. - /// - /// # Panics - /// This panics if the internal buffer contains an odd number of hex - /// characters. - fn next(&mut self) -> Option { - let v = if self.is_punct { - TokenTree::Punct(Punct::new(',', Spacing::Alone)) - } else { - let p1 = self.next_hex_val()?; - let p2 = match self.next_hex_val() { - Some(v) => v, - None => panic!("expected even number of hex characters"), - }; - let val = (p1 << 4) + p2; - TokenTree::Literal(Literal::u8_suffixed(val)) - }; - self.is_punct = !self.is_punct; - Some(v) + if LEN != buf_pos { + panic!("Length mismatch. Please report this bug."); } + buf } /// Macro for converting sequence of string literals containing hex-encoded data /// into an array of bytes. -#[proc_macro] -pub fn hex(input: TokenStream) -> TokenStream { - let mut out_ts = TokenStream::new(); - for tt in ignore_groups(input) { - let iter = match tt { - TokenTree::Literal(literal) => TokenTreeIter::new(literal), - unexpected => panic!("expected string literal, got `{}`", unexpected), - }; - out_ts.extend(iter); - } - TokenStream::from(TokenTree::Group(Group::new(Delimiter::Bracket, out_ts))) +#[macro_export] +macro_rules! hex { + ($($s:literal)*) => {{ + const STRINGS: &[&'static [u8]] = &[$($s.as_bytes(),)*]; + $crate::decode::<{ $crate::len(STRINGS) }>(STRINGS) + }}; } diff --git a/hex-literal/tests/comments.rs b/hex-literal/tests/comments.rs deleted file mode 100644 index 7ebb7eb7..00000000 --- a/hex-literal/tests/comments.rs +++ /dev/null @@ -1,41 +0,0 @@ -use hex_literal::hex; - -#[test] -fn single_line_comments() { - assert_eq!(hex!("dd 03 // comment"), [0xdd, 0x03]); - assert_eq!( - hex!( - "00 04 f0 // a comment here - 54 fe // another comment" - ), - [0x00, 0x04, 0xf0, 0x54, 0xfe] - ); - assert_eq!( - hex!( - "// initial comment - 01 02" - ), - [0x01, 0x02] - ); -} - -#[test] -fn block_comments() { - assert_eq!( - hex!("00 01 02 /* intervening comment */ 03 04"), - [0x00, 0x01, 0x02, 0x03, 0x04] - ); - assert_eq!(hex!("/* initial comment */ ff df dd"), [0xff, 0xdf, 0xdd]); - assert_eq!( - hex!( - "8f ff 7d /* - comment - on - several - lines - */ - d0 a3" - ), - [0x8f, 0xff, 0x7d, 0xd0, 0xa3] - ); -} From 66c6226816f92581cb2acb779da6b2f81049fbb4 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Sun, 2 Apr 2023 03:00:07 +0000 Subject: [PATCH 085/116] hex-literal: release v0.4.0 (#884) --- Cargo.lock | 8 ++++---- hex-literal/CHANGELOG.md | 2 +- hex-literal/Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 47156007..b2421ab0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15,7 +15,7 @@ version = "0.11.0-pre" dependencies = [ "crypto-common", "generic-array", - "hex-literal 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "hex-literal 0.3.4", ] [[package]] @@ -85,12 +85,12 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "hex-literal" version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" [[package]] name = "hex-literal" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" +version = "0.4.0" [[package]] name = "hybrid-array" diff --git a/hex-literal/CHANGELOG.md b/hex-literal/CHANGELOG.md index 338be64b..517eb2b9 100644 --- a/hex-literal/CHANGELOG.md +++ b/hex-literal/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## UNRELEASED +## 0.4.0 (2023-04-02) ### Changed - Disallow comments inside hex strings ([#816]) - Migrate to 2021 edition and bump MSRV to 1.57 ([#816]) diff --git a/hex-literal/Cargo.toml b/hex-literal/Cargo.toml index b704b6b9..a4062093 100644 --- a/hex-literal/Cargo.toml +++ b/hex-literal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hex-literal" -version = "0.3.4" +version = "0.4.0" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Macro for converting hexadecimal string to a byte array at compile time" From 9cba5a5ca0c575fddede2833709c2b58f1080170 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 2 Apr 2023 21:12:33 -0600 Subject: [PATCH 086/116] cmov v0.3.0 (#886) --- Cargo.lock | 2 +- cmov/CHANGELOG.md | 16 ++++++++++++++++ cmov/Cargo.toml | 2 +- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2421ab0..8489ed9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -27,7 +27,7 @@ dependencies = [ [[package]] name = "cmov" -version = "0.3.0-pre" +version = "0.3.0" [[package]] name = "collectable" diff --git a/cmov/CHANGELOG.md b/cmov/CHANGELOG.md index 9350f141..fbf92a71 100644 --- a/cmov/CHANGELOG.md +++ b/cmov/CHANGELOG.md @@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.3.0 (2023-04-02) +### Added +- `miri` support by forcing the `portable` backend ([#864]) +- Constant-time equality comparisons ([#873]) + +### Changed +- Make `Cmov::cmovz` a provided method ([#871]) + +### Fixed +- Builds on `x86` (32-bit) targets ([#863]) + +[#863]: https://github.com/RustCrypto/utils/pull/863 +[#864]: https://github.com/RustCrypto/utils/pull/864 +[#871]: https://github.com/RustCrypto/utils/pull/881 +[#873]: https://github.com/RustCrypto/utils/pull/883 + ## 0.2.0 (2023-02-26) ### Added - `Condition` alias for `u8` ([#830]) diff --git a/cmov/Cargo.toml b/cmov/Cargo.toml index a185a365..f08912c6 100644 --- a/cmov/Cargo.toml +++ b/cmov/Cargo.toml @@ -6,7 +6,7 @@ constant-time and not be rewritten as branches by the compiler. Provides wrappers for the CMOV family of instructions on x86/x86_64 and CSEL on AArch64. """ -version = "0.3.0-pre" +version = "0.3.0" authors = ["RustCrypto Developers"] license = "Apache-2.0 OR MIT" repository = "https://github.com/RustCrypto/utils/tree/master/cmov" From 13385f64b2d38bf9c0bc908e577c9f9c9b5b84d9 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Mon, 3 Apr 2023 19:01:58 +0000 Subject: [PATCH 087/116] Use minimal permissions for CI jobs (#885) --- .github/workflows/blobby.yml | 3 +++ .github/workflows/block-buffer.yml | 3 +++ .github/workflows/block-padding.yml | 3 +++ .github/workflows/cmov.yml | 3 +++ .github/workflows/cpufeatures.yml | 3 +++ .github/workflows/dbl.yml | 3 +++ .github/workflows/fiat-constify.yml | 3 +++ .github/workflows/hex-literal.yml | 3 +++ .github/workflows/hybrid-array.yml | 3 +++ .github/workflows/inout.yml | 3 +++ .github/workflows/opaque-debug.yml | 3 +++ .github/workflows/security-audit.yml | 1 + .github/workflows/workspace.yml | 3 +++ .github/workflows/zeroize.yml | 3 +++ 14 files changed, 40 insertions(+) diff --git a/.github/workflows/blobby.yml b/.github/workflows/blobby.yml index b7407895..eac18c91 100644 --- a/.github/workflows/blobby.yml +++ b/.github/workflows/blobby.yml @@ -8,6 +8,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: blobby diff --git a/.github/workflows/block-buffer.yml b/.github/workflows/block-buffer.yml index 73cfe835..b5d10e59 100644 --- a/.github/workflows/block-buffer.yml +++ b/.github/workflows/block-buffer.yml @@ -8,6 +8,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: block-buffer diff --git a/.github/workflows/block-padding.yml b/.github/workflows/block-padding.yml index 2160c150..55cd3412 100644 --- a/.github/workflows/block-padding.yml +++ b/.github/workflows/block-padding.yml @@ -8,6 +8,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: block-padding diff --git a/.github/workflows/cmov.yml b/.github/workflows/cmov.yml index b2f67ad5..7f107cfe 100644 --- a/.github/workflows/cmov.yml +++ b/.github/workflows/cmov.yml @@ -9,6 +9,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: cmov diff --git a/.github/workflows/cpufeatures.yml b/.github/workflows/cpufeatures.yml index 1161033e..936e8d41 100644 --- a/.github/workflows/cpufeatures.yml +++ b/.github/workflows/cpufeatures.yml @@ -8,6 +8,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: cpufeatures diff --git a/.github/workflows/dbl.yml b/.github/workflows/dbl.yml index c470862d..1b75b3aa 100644 --- a/.github/workflows/dbl.yml +++ b/.github/workflows/dbl.yml @@ -8,6 +8,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: dbl diff --git a/.github/workflows/fiat-constify.yml b/.github/workflows/fiat-constify.yml index 8e4cfe11..79904b24 100644 --- a/.github/workflows/fiat-constify.yml +++ b/.github/workflows/fiat-constify.yml @@ -9,6 +9,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: fiat-constify diff --git a/.github/workflows/hex-literal.yml b/.github/workflows/hex-literal.yml index dc77aeb2..12a03c08 100644 --- a/.github/workflows/hex-literal.yml +++ b/.github/workflows/hex-literal.yml @@ -8,6 +8,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: hex-literal diff --git a/.github/workflows/hybrid-array.yml b/.github/workflows/hybrid-array.yml index ae98cefb..46fe7c30 100644 --- a/.github/workflows/hybrid-array.yml +++ b/.github/workflows/hybrid-array.yml @@ -9,6 +9,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: hybrid-array diff --git a/.github/workflows/inout.yml b/.github/workflows/inout.yml index 6412ccdb..d8da0436 100644 --- a/.github/workflows/inout.yml +++ b/.github/workflows/inout.yml @@ -8,6 +8,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: inout diff --git a/.github/workflows/opaque-debug.yml b/.github/workflows/opaque-debug.yml index 12a6664d..dfb4b660 100644 --- a/.github/workflows/opaque-debug.yml +++ b/.github/workflows/opaque-debug.yml @@ -8,6 +8,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: opaque-debug diff --git a/.github/workflows/security-audit.yml b/.github/workflows/security-audit.yml index 6bc14e9e..215d0547 100644 --- a/.github/workflows/security-audit.yml +++ b/.github/workflows/security-audit.yml @@ -1,4 +1,5 @@ name: Security Audit + on: pull_request: paths: Cargo.lock diff --git a/.github/workflows/workspace.yml b/.github/workflows/workspace.yml index f8e79b03..80c32293 100644 --- a/.github/workflows/workspace.yml +++ b/.github/workflows/workspace.yml @@ -9,6 +9,9 @@ on: paths-ignore: - README.md +permissions: + contents: read + jobs: clippy: runs-on: ubuntu-latest diff --git a/.github/workflows/zeroize.yml b/.github/workflows/zeroize.yml index 21ffdea1..7f69a611 100644 --- a/.github/workflows/zeroize.yml +++ b/.github/workflows/zeroize.yml @@ -9,6 +9,9 @@ on: push: branches: master +permissions: + contents: read + defaults: run: working-directory: zeroize From b8bd42f441f8e2987ded60fbaa809e7bf9d17a8e Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 5 Apr 2023 12:08:48 +0000 Subject: [PATCH 088/116] hex-literal: enforce const evaluation (#889) --- Cargo.lock | 10 +++++----- hex-literal/CHANGELOG.md | 6 ++++++ hex-literal/Cargo.toml | 2 +- hex-literal/README.md | 29 ++++++++++++++++++++++------- hex-literal/src/lib.rs | 4 +++- 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8489ed9f..3edcd864 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -90,7 +90,7 @@ checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" [[package]] name = "hex-literal" -version = "0.4.0" +version = "0.4.1" [[package]] name = "hybrid-array" @@ -115,9 +115,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "libc" -version = "0.2.140" +version = "0.2.141" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" +checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" [[package]] name = "opaque-debug" @@ -125,9 +125,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.55" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d0dd4be24fcdcfeaa12a432d588dc59bbad6cad3510c67e74a2b6b2fc950564" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] diff --git a/hex-literal/CHANGELOG.md b/hex-literal/CHANGELOG.md index 517eb2b9..260838e6 100644 --- a/hex-literal/CHANGELOG.md +++ b/hex-literal/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.4.1 (2023-04-05) +### Changed +- Enforce const evaluation ([#889]) + +[#889]: https://github.com/RustCrypto/utils/pull/889 + ## 0.4.0 (2023-04-02) ### Changed - Disallow comments inside hex strings ([#816]) diff --git a/hex-literal/Cargo.toml b/hex-literal/Cargo.toml index a4062093..ad07ffb1 100644 --- a/hex-literal/Cargo.toml +++ b/hex-literal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hex-literal" -version = "0.4.0" +version = "0.4.1" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Macro for converting hexadecimal string to a byte array at compile time" diff --git a/hex-literal/README.md b/hex-literal/README.md index 72d527e4..eb06be5e 100644 --- a/hex-literal/README.md +++ b/hex-literal/README.md @@ -31,22 +31,37 @@ let bytes1 = hex!(" 00010203 04050607 08090a0b 0c0d0e0f "); -assert_eq!(bytes1, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); +assert_eq!( + bytes1, + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], +); -// It's possible to use several literals (results will be concatenated) +// It's possible to use several literals +// (results will be concatenated) let bytes2 = hex!( "00010203 04050607" // first half - "08090a0b" /* block comment */ "0c0d0e0f" // second half + "08090a0b 0c0d0e0f" // second half ); assert_eq!(bytes1, bytes2); ``` Using an unsupported character inside literals will result in a compilation error: ```rust,compile_fail -# use hex_literal::hex; -hex!("АА"); // Cyrillic "А" -hex!("11 22"); // Japanese space -hex!("0123 // Сomments inside literals are not supported"); +hex_literal::hex!("АА"); // Cyrillic "А" +hex_literal::hex!("11 22"); // Japanese space +``` + +Сomments inside literals are not supported: +```rust,compile_fail +hex_literal::hex!("0123 // foo"); +``` + +Each literal must contain an even number of hex characters: +```rust,compile_fail +hex_literal::hex!( + "01234" + "567" +); ``` ## Minimum Supported Rust Version diff --git a/hex-literal/src/lib.rs b/hex-literal/src/lib.rs index 4b31b071..f6c8fac7 100644 --- a/hex-literal/src/lib.rs +++ b/hex-literal/src/lib.rs @@ -81,6 +81,8 @@ pub const fn decode(strings: &[&[u8]]) -> [u8; LEN] { macro_rules! hex { ($($s:literal)*) => {{ const STRINGS: &[&'static [u8]] = &[$($s.as_bytes(),)*]; - $crate::decode::<{ $crate::len(STRINGS) }>(STRINGS) + const LEN: usize = $crate::len(STRINGS); + const RES: [u8; LEN] = $crate::decode(STRINGS); + RES }}; } From b3263983d585171a3c91c7074dab48c46f0c754b Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 9 Apr 2023 19:23:24 -0600 Subject: [PATCH 089/116] wycheproof2blb: secp224r1 support (#891) Adds support for extracting secp224r1 test vectors from Wycheproof, in order to test the `p224` crate. --- wycheproof2blb/src/ecdsa.rs | 2 +- wycheproof2blb/src/main.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/wycheproof2blb/src/ecdsa.rs b/wycheproof2blb/src/ecdsa.rs index 2e0fc706..7c01a112 100644 --- a/wycheproof2blb/src/ecdsa.rs +++ b/wycheproof2blb/src/ecdsa.rs @@ -55,7 +55,7 @@ pub fn generator(data: &[u8], algorithm: &str, _key_size: u32) -> Vec let mut infos = vec![]; for g in &suite.test_groups { assert_eq!(g.key.curve, algorithm); - assert!(matches!(g.sha.as_str(), "SHA-256" | "SHA-384")); + assert!(matches!(g.sha.as_str(), "SHA-224" | "SHA-256" | "SHA-384")); for tc in &g.tests { if tc.case.result == crate::wycheproof::CaseResult::Acceptable { // TODO: figure out what to do with test cases that pass but which have weak params diff --git a/wycheproof2blb/src/main.rs b/wycheproof2blb/src/main.rs index fc5b9996..87cac8b8 100644 --- a/wycheproof2blb/src/main.rs +++ b/wycheproof2blb/src/main.rs @@ -112,6 +112,10 @@ fn main() { file: "eddsa_test.json", generator: ed25519::generator, }, + "secp224r1" => Algorithm { + file: "ecdsa_secp224r1_sha224_test.json", + generator: ecdsa::generator, + }, "secp256r1" => Algorithm { file: "ecdsa_secp256r1_sha256_test.json", generator: ecdsa::generator, From 72505ea620ee4d557a68372b6ba44a87f7d2ab1b Mon Sep 17 00:00:00 2001 From: Roman Volosatovs Date: Wed, 19 Apr 2023 16:28:37 +0200 Subject: [PATCH 090/116] cpufeatures: support freestanding/UEFI `x86` targets (#821) This fixes compilation of dependent crates for these targets. For example, `sha2`: Before: ``` $ cargo build --target x86_64-unknown-none --no-default-features Compiling sha2 v0.10.6 (/home/rvolosatovs/src/github.com/rustcrypto/hashes/sha2) LLVM ERROR: Do not know how to split the result of this operator! error: could not compile `sha2` $ cargo build --target x86_64-unknown-uefi --no-default-features Compiling sha2 v0.10.6 (/home/rvolosatovs/src/github.com/rustcrypto/hashes/sha2) LLVM ERROR: Do not know how to split the result of this operator! error: could not compile `sha2` ``` After: ``` $ cargo build --target x86_64-unknown-none --no-default-features Compiling cpufeatures v0.2.5 (/home/rvolosatovs/src/github.com/rustcrypto/utils/cpufeatures) Compiling sha2 v0.10.6 (/home/rvolosatovs/src/github.com/rustcrypto/hashes/sha2) Finished dev [optimized + debuginfo] target(s) in 0.19s $ cargo build --target x86_64-unknown-uefi --no-default-features Compiling cpufeatures v0.2.5 (/home/rvolosatovs/src/github.com/rustcrypto/utils/cpufeatures) Compiling sha2 v0.10.6 (/home/rvolosatovs/src/github.com/rustcrypto/hashes/sha2) Finished dev [optimized + debuginfo] target(s) in 0.19s ``` Signed-off-by: Roman Volosatovs --- cpufeatures/src/x86.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/cpufeatures/src/x86.rs b/cpufeatures/src/x86.rs index a60fa0d3..3eb5ae91 100644 --- a/cpufeatures/src/x86.rs +++ b/cpufeatures/src/x86.rs @@ -14,11 +14,12 @@ macro_rules! __unless_target_features { ($($tf:tt),+ => $body:expr ) => {{ #[cfg(not(all($(target_feature=$tf,)*)))] { - #[cfg(not(target_env = "sgx"))] + #[cfg(not(any(target_env = "sgx", target_os = "none", target_os = "uefi")))] $body - // CPUID is not available on SGX targets - #[cfg(target_env = "sgx")] + // CPUID is not available on SGX. Freestanding and UEFI targets + // do not support SIMD features with default compilation flags. + #[cfg(any(target_env = "sgx", target_os = "none", target_os = "uefi"))] false } From f0c595a201421acf9070835f7a3301532bd771bf Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Thu, 20 Apr 2023 16:03:57 -0600 Subject: [PATCH 091/116] cpufeatures v0.2.7 (#892) --- cpufeatures/CHANGELOG.md | 6 ++++++ cpufeatures/Cargo.toml | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/cpufeatures/CHANGELOG.md b/cpufeatures/CHANGELOG.md index 71acc5de..aeb6894f 100644 --- a/cpufeatures/CHANGELOG.md +++ b/cpufeatures/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.7 (2023-04-20) +### Added +- Support freestanding/UEFI `x86` targets ([#821]) + +[#821]: https://github.com/RustCrypto/utils/issues/821 + ## 0.2.6 (2023-03-24) ### Added - Support dynamic feature detection on iOS and derivative platforms ([#848]) diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index 58eec221..5e085ca2 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cpufeatures" -version = "0.2.6" +version = "0.2.7" description = """ Lightweight runtime CPU feature detection for x86/x86_64 and aarch64 with no_std support and support for mobile targets including Android and iOS From 1c51db5c5a0269b3fc703b824e6f69507ead744d Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Wed, 3 May 2023 13:39:01 -0600 Subject: [PATCH 092/116] hybrid-array: use GATs for `ArraySize` (#893) It's quite annoying to have to add a generic parameter to `ArraySize`, particularly when notating it in bounds. GATs provide a solution to this problem, moving the type parameter to the associated type so bounds are simply `N: ArraySize`. --- .github/workflows/hybrid-array.yml | 4 ++-- Cargo.lock | 4 ++-- hybrid-array/Cargo.toml | 4 ++-- hybrid-array/README.md | 2 +- hybrid-array/src/lib.rs | 34 +++++++++++++++--------------- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/.github/workflows/hybrid-array.yml b/.github/workflows/hybrid-array.yml index 46fe7c30..aba9a19e 100644 --- a/.github/workflows/hybrid-array.yml +++ b/.github/workflows/hybrid-array.yml @@ -26,7 +26,7 @@ jobs: strategy: matrix: rust: - - 1.56.0 # MSRV + - 1.65.0 # MSRV - stable target: - armv7a-none-eabi @@ -50,7 +50,7 @@ jobs: strategy: matrix: toolchain: - - 1.56.0 # MSRV + - 1.65.0 # MSRV - stable runs-on: ubuntu-latest steps: diff --git a/Cargo.lock b/Cargo.lock index 3edcd864..85dfebae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,7 +35,7 @@ version = "0.0.2" [[package]] name = "cpufeatures" -version = "0.2.6" +version = "0.2.7" dependencies = [ "libc", ] @@ -94,7 +94,7 @@ version = "0.4.1" [[package]] name = "hybrid-array" -version = "0.1.0" +version = "0.2.0-pre" dependencies = [ "typenum", ] diff --git a/hybrid-array/Cargo.toml b/hybrid-array/Cargo.toml index 9ca231e9..a5729d7f 100644 --- a/hybrid-array/Cargo.toml +++ b/hybrid-array/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hybrid-array" -version = "0.1.0" # Also update html_root_url in lib.rs when bumping this +version = "0.2.0-pre" description = """ Hybrid typenum-based and const generic array types designed to provide the flexibility of typenum-based expressions while also allowing interoperability @@ -14,7 +14,7 @@ categories = ["no-std", "data-structures"] keywords = ["generic-array"] readme = "README.md" edition = "2021" -rust-version = "1.56" +rust-version = "1.65" [dependencies] typenum = "1.16" diff --git a/hybrid-array/README.md b/hybrid-array/README.md index a9db69ef..86093c1c 100644 --- a/hybrid-array/README.md +++ b/hybrid-array/README.md @@ -51,7 +51,7 @@ dual licensed as above, without any additional terms or conditions. [safety-image]: https://img.shields.io/badge/unsafe-forbidden-success.svg [safety-link]: https://github.com/rust-secure-code/safety-dance/ [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg -[rustc-image]: https://img.shields.io/badge/rustc-1.56+-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.65+-blue.svg [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index f673ebc7..41ff4a92 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -56,7 +56,7 @@ pub trait ArrayOps: /// [`ArraySize`] type: `typenum`-provided [`Unsigned`] integer. /// /// Not to be confused with [`ArrayOps::SIZE`], which is a `usize`. - type Size: ArraySize; + type Size: ArraySize; /// Returns a reference to the inner array. fn as_array_ref(&self) -> &[T; N]; @@ -106,15 +106,15 @@ pub trait ArrayOps: /// Trait which associates a [`usize`] size and `ArrayType` with a /// `typenum`-provided [`Unsigned`] integer. -pub trait ArraySize: Unsigned { +pub trait ArraySize: Unsigned { /// Array type which corresponds to this size. - type ArrayType: AsRef<[T]> + AsMut<[T]> + IntoArray + Sized; + type ArrayType: AsRef<[T]> + AsMut<[T]> + IntoArray + Sized; } /// Convert the given type into an [`Array`]. pub trait IntoArray { /// Size of the [`Array`]. - type Size: ArraySize; + type Size: ArraySize; /// Convert into the `hybrid-array` crate's [`Array`] type. fn into_hybrid_array(self) -> Array; @@ -157,8 +157,8 @@ macro_rules! impl_array_size { } } - impl ArraySize for typenum::$ty { - type ArrayType = [T; $len]; + impl ArraySize for typenum::$ty { + type ArrayType = [T; $len]; } impl IntoArray for [T; $len] { @@ -290,11 +290,11 @@ impl_array_size! { /// allowing interoperability and a transition path to const generics. #[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] #[repr(transparent)] -pub struct Array>(pub U::ArrayType); +pub struct Array(pub U::ArrayType); impl Array where - U: ArraySize, + U: ArraySize, { /// Returns a slice containing the entire array. Equivalent to `&s[..]`. #[inline] @@ -312,7 +312,7 @@ where impl AsRef<[T; N]> for Array where Self: ArrayOps, - U: ArraySize, + U: ArraySize, { #[inline] fn as_ref(&self) -> &[T; N] { @@ -323,7 +323,7 @@ where impl AsMut<[T; N]> for Array where Self: ArrayOps, - U: ArraySize, + U: ArraySize, { #[inline] fn as_mut(&mut self) -> &mut [T; N] { @@ -334,7 +334,7 @@ where impl Borrow<[T; N]> for Array where Self: ArrayOps, - U: ArraySize, + U: ArraySize, { #[inline] fn borrow(&self) -> &[T; N] { @@ -345,7 +345,7 @@ where impl BorrowMut<[T; N]> for Array where Self: ArrayOps, - U: ArraySize, + U: ArraySize, { #[inline] fn borrow_mut(&mut self) -> &mut [T; N] { @@ -356,7 +356,7 @@ where impl From<[T; N]> for Array where Self: ArrayOps, - U: ArraySize, + U: ArraySize, { #[inline] fn from(arr: [T; N]) -> Array { @@ -367,7 +367,7 @@ where impl Index for Array where [T]: Index, - U: ArraySize, + U: ArraySize, { type Output = <[T] as Index>::Output; @@ -380,7 +380,7 @@ where impl IndexMut for Array where [T]: IndexMut, - U: ArraySize, + U: ArraySize, { #[inline] fn index_mut(&mut self, index: I) -> &mut Self::Output { @@ -391,8 +391,8 @@ where impl<'a, T, U> TryFrom<&'a [T]> for Array where T: Copy, - U: ArraySize, - U::ArrayType: TryFrom<&'a [T], Error = TryFromSliceError>, + U: ArraySize, + U::ArrayType: TryFrom<&'a [T], Error = TryFromSliceError>, { type Error = TryFromSliceError; From b30adcf5fd9899e9a5f80fa625546d7c3688b0fc Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sat, 6 May 2023 08:53:38 -0600 Subject: [PATCH 093/116] hybrid-array v0.2.0-pre.0 (#894) --- Cargo.lock | 2 +- hybrid-array/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 85dfebae..48262fb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,7 +94,7 @@ version = "0.4.1" [[package]] name = "hybrid-array" -version = "0.2.0-pre" +version = "0.2.0-pre.0" dependencies = [ "typenum", ] diff --git a/hybrid-array/Cargo.toml b/hybrid-array/Cargo.toml index a5729d7f..4323fd23 100644 --- a/hybrid-array/Cargo.toml +++ b/hybrid-array/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hybrid-array" -version = "0.2.0-pre" +version = "0.2.0-pre.0" description = """ Hybrid typenum-based and const generic array types designed to provide the flexibility of typenum-based expressions while also allowing interoperability From 3ec050400090ae1561f9e250a080a8a63d039a1f Mon Sep 17 00:00:00 2001 From: Alexander Wagner Date: Thu, 11 May 2023 16:07:05 +0200 Subject: [PATCH 094/116] zeroize: Update comments on MSRV (#896) --- zeroize/src/aarch64.rs | 2 +- zeroize/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/zeroize/src/aarch64.rs b/zeroize/src/aarch64.rs index 956f6487..b26cb18c 100644 --- a/zeroize/src/aarch64.rs +++ b/zeroize/src/aarch64.rs @@ -1,7 +1,7 @@ //! [`Zeroize`] impls for ARM64 SIMD registers. //! //! Gated behind the `aarch64` feature: MSRV 1.59 -//! (the overall crate is MSRV 1.51) +//! (the overall crate is MSRV 1.56) use crate::{atomic_fence, volatile_write, Zeroize}; diff --git a/zeroize/src/lib.rs b/zeroize/src/lib.rs index 4e006578..9ca780e5 100644 --- a/zeroize/src/lib.rs +++ b/zeroize/src/lib.rs @@ -30,7 +30,7 @@ //! //! ## Minimum Supported Rust Version //! -//! Requires Rust **1.51** or newer. +//! Requires Rust **1.56** 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 From 017165f4c509ed137f0afbafac59215cb20490c7 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: Tue, 16 May 2023 13:29:11 +0300 Subject: [PATCH 095/116] Update Cargo.lock --- Cargo.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 48262fb3..542d2123 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,9 +115,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "libc" -version = "0.2.141" +version = "0.2.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" +checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" [[package]] name = "opaque-debug" @@ -125,18 +125,18 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" dependencies = [ "proc-macro2", ] @@ -149,18 +149,18 @@ checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "serde" -version = "1.0.159" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c04e8343c3daeec41f58990b9d77068df31209f2af111e059e9fe9646693065" +checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.159" +version = "1.0.163" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c614d17805b093df4b147b51339e7e44bf05ef59fba1e45d83500bcfb4d8585" +checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" dependencies = [ "proc-macro2", "quote", @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d721eca97ac802aa7777b701877c8004d950fc142651367300d21c1cc0194744" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ "itoa", "ryu", @@ -180,9 +180,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.13" +version = "2.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c9da457c5285ac1f936ebd076af6dac17a61cfe7826f2076b4d015cf47bc8ec" +checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" dependencies = [ "proc-macro2", "quote", From 26232f7fe7c994de77af82ca6ef2a475a1a90317 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 26 May 2023 06:55:21 -0600 Subject: [PATCH 096/116] build(deps): bump proc-macro2 from 1.0.57 to 1.0.59 (#902) Bumps [proc-macro2](https://github.com/dtolnay/proc-macro2) from 1.0.57 to 1.0.59. - [Release notes](https://github.com/dtolnay/proc-macro2/releases) - [Commits](https://github.com/dtolnay/proc-macro2/compare/1.0.57...1.0.59) --- updated-dependencies: - dependency-name: proc-macro2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 542d2123..bed4c89f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -125,9 +125,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.57" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4ec6d5fe0b140acb27c9a0444118cf55bfbb4e0b259739429abb4521dd67c16" +checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" dependencies = [ "unicode-ident", ] From b6cedcf47133672230e8258affd93c72229ec533 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 29 May 2023 21:04:36 -0600 Subject: [PATCH 097/116] hybrid-array: reference conversion support (#904) Adds a set of reference conversions to `Array` as well as the `ArrayOps` trait: - `&Array`: `From<&[T, N]>` + TryFrom<&[T]> - `&mut Array`: `From<&mut [T, N]>` + `TryFrom<&mut [T]>` The implementation uses an unsafe pointer cast to convert a slice into the corresponding reference newtype. Additionally it adds the following panicking inherent methods to `Array` to ease migrating code based on `GenericArray`: - `Array::ref_from_slice`: alternative to `GenericArray::from_slice` - `Array::ref_from_mut_slice`: alternative to `GenericArray::from_mut_slice` - `Array::clone_from_slice`: alternative to `GenericArray::clone_from_slice` These methods are marked with TODOs to deprecate them before a final v0.2.0 release, however for now they're not deprecate to ease a migration. --- hybrid-array/src/lib.rs | 120 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 119 insertions(+), 1 deletion(-) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index 41ff4a92..06438399 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -5,7 +5,6 @@ html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" )] -#![forbid(unsafe_code)] #![warn( clippy::cast_lossless, clippy::cast_possible_truncation, @@ -67,6 +66,12 @@ pub trait ArrayOps: /// Create array from Rust's core array type. fn from_core_array(arr: [T; N]) -> Self; + /// Create array reference from reference to Rust's core array type. + fn from_core_array_ref(arr: &[T; N]) -> &Self; + + /// Create mutable array reference from reference to Rust's core array type. + fn from_core_array_mut(arr: &mut [T; N]) -> &mut Self; + /// Create array where each array element `T` is returned by the `cb` call. fn from_fn(mut cb: F) -> Self where @@ -140,6 +145,16 @@ macro_rules! impl_array_size { Self(arr) } + fn from_core_array_ref(array_ref: &[T; $len]) -> &Self { + // SAFETY: `$ty` is a `repr(transparent)` newtype for `[T; $len]` + unsafe { &*(array_ref.as_ptr() as *const Self) } + } + + fn from_core_array_mut(array_ref: &mut [T; $len]) -> &mut Self { + // SAFETY: `$ty` is a `repr(transparent)` newtype for `[T; $len]` + unsafe { &mut *(array_ref.as_mut_ptr() as *mut Self) } + } + #[inline] fn from_slice(slice: &[T]) -> Result where @@ -307,6 +322,45 @@ where pub fn as_mut_slice(&mut self) -> &mut [T] { self.0.as_mut() } + + /// Convert the given slice into a reference to a hybrid array. + /// + /// # Panics + /// + /// Panics if the slice's length doesn't match the array type. + // TODO(tarcieri): deprecate this before the v0.2 release + // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] + #[inline] + pub fn ref_from_slice(slice: &[T]) -> &Self { + slice.try_into().expect("slice length mismatch") + } + + /// Convert the given mutable slice to a mutable reference to a hybrid array. + /// + /// # Panics + /// + /// Panics if the slice's length doesn't match the array type. + // TODO(tarcieri): deprecate this before the v0.2 release + // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] + #[inline] + pub fn ref_from_mut_slice(slice: &mut [T]) -> &mut Self { + slice.try_into().expect("slice length mismatch") + } + + /// Clone the contents of the slice as a new hybrid array. + /// + /// # Panics + /// + /// Panics if the slice's length doesn't match the array type. + // TODO(tarcieri): deprecate this before the v0.2 release + // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] + #[inline] + pub fn clone_from_slice(slice: &[T]) -> Self + where + Self: Clone, + { + Self::ref_from_slice(slice).clone() + } } impl AsRef<[T; N]> for Array @@ -364,6 +418,28 @@ where } } +impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array +where + Array: ArrayOps, + U: ArraySize, +{ + #[inline] + fn from(array_ref: &'a [T; N]) -> &'a Array { + >::from_core_array_ref(array_ref) + } +} + +impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array +where + Array: ArrayOps, + U: ArraySize, +{ + #[inline] + fn from(array_ref: &'a mut [T; N]) -> &'a mut Array { + >::from_core_array_mut(array_ref) + } +} + impl Index for Array where [T]: Index, @@ -402,5 +478,47 @@ where } } +impl<'a, T, U> TryFrom<&'a [T]> for &'a Array +where + U: ArraySize, +{ + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: &'a [T]) -> Result { + check_slice_length::(slice)?; + + // SAFETY: `Array` is a `repr(transparent)` newtype for a core + // array with length checked above. + Ok(unsafe { *(slice.as_ptr() as *const Self) }) + } +} + +impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array +where + U: ArraySize, +{ + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: &'a mut [T]) -> Result { + check_slice_length::(slice)?; + + // SAFETY: `Array` is a `repr(transparent)` newtype for a core + // array with length checked above. + Ok(unsafe { *(slice.as_ptr() as *mut Self) }) + } +} + /// Byte array type. pub type ByteArray = Array; + +/// Generate a [`TryFromSliceError`] if the slice doesn't match the given length. +fn check_slice_length(slice: &[T]) -> Result<(), TryFromSliceError> { + if slice.len() != U::USIZE { + // Hack: `TryFromSliceError` lacks a public constructor + <&[T; 1]>::try_from([].as_slice())?; + } + + Ok(()) +} From 17f5d341ff26f1d7c38979b6d5fabd6c46aa7a25 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 29 May 2023 21:31:58 -0600 Subject: [PATCH 098/116] hybrid-array: move array type definition to top of file (#906) --- hybrid-array/src/lib.rs | 428 ++++++++++++++++++++-------------------- 1 file changed, 214 insertions(+), 214 deletions(-) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index 06438399..7a0f30e1 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -33,6 +33,220 @@ use core::{ }; use typenum::Unsigned; +/// Hybrid typenum-based and const generic array type. +/// +/// Provides the flexibility of typenum-based expressions while also +/// allowing interoperability and a transition path to const generics. +#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] +#[repr(transparent)] +pub struct Array(pub U::ArrayType); + +impl Array +where + U: ArraySize, +{ + /// Returns a slice containing the entire array. Equivalent to `&s[..]`. + #[inline] + pub fn as_slice(&self) -> &[T] { + self.0.as_ref() + } + + /// Returns a mutable slice containing the entire array. Equivalent to `&mut s[..]`. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [T] { + self.0.as_mut() + } + + /// Convert the given slice into a reference to a hybrid array. + /// + /// # Panics + /// + /// Panics if the slice's length doesn't match the array type. + // TODO(tarcieri): deprecate this before the v0.2 release + // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] + #[inline] + pub fn ref_from_slice(slice: &[T]) -> &Self { + slice.try_into().expect("slice length mismatch") + } + + /// Convert the given mutable slice to a mutable reference to a hybrid array. + /// + /// # Panics + /// + /// Panics if the slice's length doesn't match the array type. + // TODO(tarcieri): deprecate this before the v0.2 release + // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] + #[inline] + pub fn ref_from_mut_slice(slice: &mut [T]) -> &mut Self { + slice.try_into().expect("slice length mismatch") + } + + /// Clone the contents of the slice as a new hybrid array. + /// + /// # Panics + /// + /// Panics if the slice's length doesn't match the array type. + // TODO(tarcieri): deprecate this before the v0.2 release + // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] + #[inline] + pub fn clone_from_slice(slice: &[T]) -> Self + where + Self: Clone, + { + Self::ref_from_slice(slice).clone() + } +} + +impl AsRef<[T; N]> for Array +where + Self: ArrayOps, + U: ArraySize, +{ + #[inline] + fn as_ref(&self) -> &[T; N] { + self.as_array_ref() + } +} + +impl AsMut<[T; N]> for Array +where + Self: ArrayOps, + U: ArraySize, +{ + #[inline] + fn as_mut(&mut self) -> &mut [T; N] { + self.as_array_mut() + } +} + +impl Borrow<[T; N]> for Array +where + Self: ArrayOps, + U: ArraySize, +{ + #[inline] + fn borrow(&self) -> &[T; N] { + self.as_array_ref() + } +} + +impl BorrowMut<[T; N]> for Array +where + Self: ArrayOps, + U: ArraySize, +{ + #[inline] + fn borrow_mut(&mut self) -> &mut [T; N] { + self.as_array_mut() + } +} + +impl From<[T; N]> for Array +where + Self: ArrayOps, + U: ArraySize, +{ + #[inline] + fn from(arr: [T; N]) -> Array { + Self::from_core_array(arr) + } +} + +impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array +where + Array: ArrayOps, + U: ArraySize, +{ + #[inline] + fn from(array_ref: &'a [T; N]) -> &'a Array { + >::from_core_array_ref(array_ref) + } +} + +impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array +where + Array: ArrayOps, + U: ArraySize, +{ + #[inline] + fn from(array_ref: &'a mut [T; N]) -> &'a mut Array { + >::from_core_array_mut(array_ref) + } +} + +impl Index for Array +where + [T]: Index, + U: ArraySize, +{ + type Output = <[T] as Index>::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + Index::index(self.as_slice(), index) + } +} + +impl IndexMut for Array +where + [T]: IndexMut, + U: ArraySize, +{ + #[inline] + fn index_mut(&mut self, index: I) -> &mut Self::Output { + IndexMut::index_mut(self.as_mut_slice(), index) + } +} + +impl<'a, T, U> TryFrom<&'a [T]> for Array +where + T: Copy, + U: ArraySize, + U::ArrayType: TryFrom<&'a [T], Error = TryFromSliceError>, +{ + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: &'a [T]) -> Result, TryFromSliceError> { + U::ArrayType::try_from(slice).map(Self) + } +} + +impl<'a, T, U> TryFrom<&'a [T]> for &'a Array +where + U: ArraySize, +{ + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: &'a [T]) -> Result { + check_slice_length::(slice)?; + + // SAFETY: `Array` is a `repr(transparent)` newtype for a core + // array with length checked above. + Ok(unsafe { *(slice.as_ptr() as *const Self) }) + } +} + +impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array +where + U: ArraySize, +{ + type Error = TryFromSliceError; + + #[inline] + fn try_from(slice: &'a mut [T]) -> Result { + check_slice_length::(slice)?; + + // SAFETY: `Array` is a `repr(transparent)` newtype for a core + // array with length checked above. + Ok(unsafe { *(slice.as_ptr() as *mut Self) }) + } +} + +/// Byte array type. +pub type ByteArray = Array; + /// Array operations which are const generic over a given array size. pub trait ArrayOps: AsRef<[T; N]> @@ -299,220 +513,6 @@ impl_array_size! { 8192 => U8192 } -/// Hybrid typenum-based and const generic array type. -/// -/// Provides the flexibility of typenum-based expressions while also -/// allowing interoperability and a transition path to const generics. -#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)] -#[repr(transparent)] -pub struct Array(pub U::ArrayType); - -impl Array -where - U: ArraySize, -{ - /// Returns a slice containing the entire array. Equivalent to `&s[..]`. - #[inline] - pub fn as_slice(&self) -> &[T] { - self.0.as_ref() - } - - /// Returns a mutable slice containing the entire array. Equivalent to `&mut s[..]`. - #[inline] - pub fn as_mut_slice(&mut self) -> &mut [T] { - self.0.as_mut() - } - - /// Convert the given slice into a reference to a hybrid array. - /// - /// # Panics - /// - /// Panics if the slice's length doesn't match the array type. - // TODO(tarcieri): deprecate this before the v0.2 release - // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] - #[inline] - pub fn ref_from_slice(slice: &[T]) -> &Self { - slice.try_into().expect("slice length mismatch") - } - - /// Convert the given mutable slice to a mutable reference to a hybrid array. - /// - /// # Panics - /// - /// Panics if the slice's length doesn't match the array type. - // TODO(tarcieri): deprecate this before the v0.2 release - // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] - #[inline] - pub fn ref_from_mut_slice(slice: &mut [T]) -> &mut Self { - slice.try_into().expect("slice length mismatch") - } - - /// Clone the contents of the slice as a new hybrid array. - /// - /// # Panics - /// - /// Panics if the slice's length doesn't match the array type. - // TODO(tarcieri): deprecate this before the v0.2 release - // #[deprecated(since = "0.2.0", note = "use TryFrom instead")] - #[inline] - pub fn clone_from_slice(slice: &[T]) -> Self - where - Self: Clone, - { - Self::ref_from_slice(slice).clone() - } -} - -impl AsRef<[T; N]> for Array -where - Self: ArrayOps, - U: ArraySize, -{ - #[inline] - fn as_ref(&self) -> &[T; N] { - self.as_array_ref() - } -} - -impl AsMut<[T; N]> for Array -where - Self: ArrayOps, - U: ArraySize, -{ - #[inline] - fn as_mut(&mut self) -> &mut [T; N] { - self.as_array_mut() - } -} - -impl Borrow<[T; N]> for Array -where - Self: ArrayOps, - U: ArraySize, -{ - #[inline] - fn borrow(&self) -> &[T; N] { - self.as_array_ref() - } -} - -impl BorrowMut<[T; N]> for Array -where - Self: ArrayOps, - U: ArraySize, -{ - #[inline] - fn borrow_mut(&mut self) -> &mut [T; N] { - self.as_array_mut() - } -} - -impl From<[T; N]> for Array -where - Self: ArrayOps, - U: ArraySize, -{ - #[inline] - fn from(arr: [T; N]) -> Array { - Self::from_core_array(arr) - } -} - -impl<'a, T, U, const N: usize> From<&'a [T; N]> for &'a Array -where - Array: ArrayOps, - U: ArraySize, -{ - #[inline] - fn from(array_ref: &'a [T; N]) -> &'a Array { - >::from_core_array_ref(array_ref) - } -} - -impl<'a, T, U, const N: usize> From<&'a mut [T; N]> for &'a mut Array -where - Array: ArrayOps, - U: ArraySize, -{ - #[inline] - fn from(array_ref: &'a mut [T; N]) -> &'a mut Array { - >::from_core_array_mut(array_ref) - } -} - -impl Index for Array -where - [T]: Index, - U: ArraySize, -{ - type Output = <[T] as Index>::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - Index::index(self.as_slice(), index) - } -} - -impl IndexMut for Array -where - [T]: IndexMut, - U: ArraySize, -{ - #[inline] - fn index_mut(&mut self, index: I) -> &mut Self::Output { - IndexMut::index_mut(self.as_mut_slice(), index) - } -} - -impl<'a, T, U> TryFrom<&'a [T]> for Array -where - T: Copy, - U: ArraySize, - U::ArrayType: TryFrom<&'a [T], Error = TryFromSliceError>, -{ - type Error = TryFromSliceError; - - #[inline] - fn try_from(slice: &'a [T]) -> Result, TryFromSliceError> { - U::ArrayType::try_from(slice).map(Self) - } -} - -impl<'a, T, U> TryFrom<&'a [T]> for &'a Array -where - U: ArraySize, -{ - type Error = TryFromSliceError; - - #[inline] - fn try_from(slice: &'a [T]) -> Result { - check_slice_length::(slice)?; - - // SAFETY: `Array` is a `repr(transparent)` newtype for a core - // array with length checked above. - Ok(unsafe { *(slice.as_ptr() as *const Self) }) - } -} - -impl<'a, T, U> TryFrom<&'a mut [T]> for &'a mut Array -where - U: ArraySize, -{ - type Error = TryFromSliceError; - - #[inline] - fn try_from(slice: &'a mut [T]) -> Result { - check_slice_length::(slice)?; - - // SAFETY: `Array` is a `repr(transparent)` newtype for a core - // array with length checked above. - Ok(unsafe { *(slice.as_ptr() as *mut Self) }) - } -} - -/// Byte array type. -pub type ByteArray = Array; - /// Generate a [`TryFromSliceError`] if the slice doesn't match the given length. fn check_slice_length(slice: &[T]) -> Result<(), TryFromSliceError> { if slice.len() != U::USIZE { From 391b9921d6dc8cb44be6574fe9b794f21b81f319 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Mon, 29 May 2023 21:43:57 -0600 Subject: [PATCH 099/116] hybrid-array: impl `Default` for `Array` (#905) --- hybrid-array/src/lib.rs | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index 7a0f30e1..abdc9d15 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -244,6 +244,16 @@ where } } +/// Generate a [`TryFromSliceError`] if the slice doesn't match the given length. +fn check_slice_length(slice: &[T]) -> Result<(), TryFromSliceError> { + if slice.len() != U::USIZE { + // Hack: `TryFromSliceError` lacks a public constructor + <&[T; 1]>::try_from([].as_slice())?; + } + + Ok(()) +} + /// Byte array type. pub type ByteArray = Array; @@ -398,6 +408,15 @@ macro_rules! impl_array_size { } } + impl Default for Array + where + T: Default + { + fn default() -> Self { + Self([(); $len].map(|_| T::default())) + } + } + impl IntoIterator for Array { type Item = T; type IntoIter = IntoIter; @@ -512,13 +531,3 @@ impl_array_size! { 4096 => U4096, 8192 => U8192 } - -/// Generate a [`TryFromSliceError`] if the slice doesn't match the given length. -fn check_slice_length(slice: &[T]) -> Result<(), TryFromSliceError> { - if slice.len() != U::USIZE { - // Hack: `TryFromSliceError` lacks a public constructor - <&[T; 1]>::try_from([].as_slice())?; - } - - Ok(()) -} From ee1c0e35932cf7eb005adcc1b88b861de394e5d0 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 09:23:02 -0600 Subject: [PATCH 100/116] hybrid-array: add sealed::ArrayExt trait (#907) Adds an extension trait with a blanket impl for all core arrays, and adds it to the bounds for `ArraySize::ArrayType`. It currently provides a `from_fn` constructor which is now leveraged by a now-generic `Default` impl which bounds on `ArraySize`. This reduces the bounds needed in generic code to just `ArraySize`, even to leverage the `Default` impl, and should also permit some additional array constructors. --- hybrid-array/src/lib.rs | 55 ++++++++++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 17 deletions(-) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index abdc9d15..c2c34732 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -141,6 +141,16 @@ where } } +impl Default for Array +where + T: Default, + U: ArraySize, +{ + fn default() -> Self { + Self(sealed::ArrayExt::from_fn(|_| Default::default())) + } +} + impl From<[T; N]> for Array where Self: ArrayOps, @@ -297,16 +307,11 @@ pub trait ArrayOps: fn from_core_array_mut(arr: &mut [T; N]) -> &mut Self; /// Create array where each array element `T` is returned by the `cb` call. - fn from_fn(mut cb: F) -> Self + fn from_fn(cb: F) -> Self where F: FnMut(usize) -> T, { - let mut idx = 0; - Self::from_core_array([(); N].map(|_| { - let res = cb(idx); - idx = idx.saturating_add(1); // TODO(tarcieri): better overflow handling? - res - })) + Self::from_core_array(sealed::ArrayExt::from_fn(cb)) } /// Create array from a slice. @@ -337,7 +342,7 @@ pub trait ArrayOps: /// `typenum`-provided [`Unsigned`] integer. pub trait ArraySize: Unsigned { /// Array type which corresponds to this size. - type ArrayType: AsRef<[T]> + AsMut<[T]> + IntoArray + Sized; + type ArrayType: AsRef<[T]> + AsMut<[T]> + IntoArray + sealed::ArrayExt; } /// Convert the given type into an [`Array`]. @@ -349,6 +354,31 @@ pub trait IntoArray { fn into_hybrid_array(self) -> Array; } +/// Sealed traits. +mod sealed { + /// Extension trait with helper functions for core arrays. + pub trait ArrayExt: Sized { + fn from_fn(cb: F) -> Self + where + F: FnMut(usize) -> T; + } + + impl ArrayExt for [T; N] { + fn from_fn(mut cb: F) -> Self + where + F: FnMut(usize) -> T, + { + let mut idx = 0; + + [(); N].map(|_| { + let res = cb(idx); + idx = idx.saturating_add(1); // TODO(tarcieri): better overflow handling? + res + }) + } + } +} + macro_rules! impl_array_size { ($($len:expr => $ty:ident),+) => { $( @@ -408,15 +438,6 @@ macro_rules! impl_array_size { } } - impl Default for Array - where - T: Default - { - fn default() -> Self { - Self([(); $len].map(|_| T::default())) - } - } - impl IntoIterator for Array { type Item = T; type IntoIter = IntoIter; From 6813b81a6a9aa573055c2e477a84563a918f9e91 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 10:00:46 -0600 Subject: [PATCH 101/116] hybrid-array: add `Deref`/`DerefMut` impls for `Array` (#908) Derefs to the inner core array type. Also adds bounds for `Deref`/`DerefMut` to `ArrayOps`, with a `Target` of `[T; N]`. --- hybrid-array/src/lib.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index c2c34732..36e439fb 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -28,7 +28,7 @@ pub use typenum; use core::{ array::{IntoIter, TryFromSliceError}, borrow::{Borrow, BorrowMut}, - ops::{Index, IndexMut, Range}, + ops::{Deref, DerefMut, Index, IndexMut, Range}, slice::{Iter, IterMut}, }; use typenum::Unsigned; @@ -151,6 +151,26 @@ where } } +impl Deref for Array +where + U: ArraySize, +{ + type Target = U::ArrayType; + + fn deref(&self) -> &U::ArrayType { + &self.0 + } +} + +impl DerefMut for Array +where + U: ArraySize, +{ + fn deref_mut(&mut self) -> &mut U::ArrayType { + &mut self.0 + } +} + impl From<[T; N]> for Array where Self: ArrayOps, @@ -273,6 +293,8 @@ pub trait ArrayOps: + AsMut<[T; N]> + Borrow<[T; N]> + BorrowMut<[T; N]> + + Deref + + DerefMut + From<[T; N]> + Index + Index> From 3fd603275f5d3ed495b70546746de0778f9453f4 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 15:16:44 -0600 Subject: [PATCH 102/116] hybrid-array: test `TryFrom<&[u8]>` for `&Array` impl (#909) --- hybrid-array/src/lib.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index 36e439fb..491a1e2a 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -408,10 +408,12 @@ macro_rules! impl_array_size { const SIZE: usize = $len; type Size = typenum::$ty; + #[inline] fn as_array_ref(&self) -> &[T; $len] { &self.0 } + #[inline] fn as_array_mut(&mut self) -> &mut [T; $len] { &mut self.0 } @@ -421,11 +423,13 @@ macro_rules! impl_array_size { Self(arr) } + #[inline] fn from_core_array_ref(array_ref: &[T; $len]) -> &Self { // SAFETY: `$ty` is a `repr(transparent)` newtype for `[T; $len]` unsafe { &*(array_ref.as_ptr() as *const Self) } } + #[inline] fn from_core_array_mut(array_ref: &mut [T; $len]) -> &mut Self { // SAFETY: `$ty` is a `repr(transparent)` newtype for `[T; $len]` unsafe { &mut *(array_ref.as_mut_ptr() as *mut Self) } @@ -574,3 +578,19 @@ impl_array_size! { 4096 => U4096, 8192 => U8192 } + +#[cfg(test)] +mod tests { + use super::ByteArray; + use typenum::{U0, U3, U6}; + + #[test] + fn tryfrom_slice_for_array_ref() { + let slice: &[u8] = &[1, 2, 3, 4, 5, 6]; + assert!(ByteArray::::try_from(slice).is_err()); + assert!(ByteArray::::try_from(slice).is_err()); + + let array_ref = ByteArray::::try_from(slice).unwrap(); + assert_eq!(&*array_ref, slice); + } +} From df502cdda7156fbd9b92c714d976ed7e01ba6feb Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 15:39:49 -0600 Subject: [PATCH 103/116] hybrid-array: leverage `ArrayExt` to factor more methods onto `Array` (#910) Changes `ArrayOps` to contain only operations that need to know the exact size (as a const generic) of an associated array. --- hybrid-array/src/lib.rs | 81 ++++++++++++++++++++++------------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index 491a1e2a..d8c01911 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -45,6 +45,34 @@ impl Array where U: ArraySize, { + /// Create array where each array element `T` is returned by the `cb` call. + pub fn from_fn(cb: F) -> Self + where + F: FnMut(usize) -> T, + { + Self(sealed::ArrayExt::from_fn(cb)) + } + + /// Create array from a slice. + pub fn from_slice(slice: &[T]) -> Result + where + T: Copy, + { + sealed::ArrayExt::from_slice(slice).map(Self) + } + + /// Returns an iterator over the array. + #[inline] + fn iter(&self) -> Iter<'_, T> { + self.as_ref().iter() + } + + /// Returns an iterator that allows modifying each value. + #[inline] + fn iter_mut(&mut self) -> IterMut<'_, T> { + self.as_mut().iter_mut() + } + /// Returns a slice containing the entire array. Equivalent to `&s[..]`. #[inline] pub fn as_slice(&self) -> &[T] { @@ -232,13 +260,12 @@ impl<'a, T, U> TryFrom<&'a [T]> for Array where T: Copy, U: ArraySize, - U::ArrayType: TryFrom<&'a [T], Error = TryFromSliceError>, { type Error = TryFromSliceError; #[inline] fn try_from(slice: &'a [T]) -> Result, TryFromSliceError> { - U::ArrayType::try_from(slice).map(Self) + sealed::ArrayExt::from_slice(slice).map(Self) } } @@ -328,31 +355,6 @@ pub trait ArrayOps: /// Create mutable array reference from reference to Rust's core array type. fn from_core_array_mut(arr: &mut [T; N]) -> &mut Self; - /// Create array where each array element `T` is returned by the `cb` call. - fn from_fn(cb: F) -> Self - where - F: FnMut(usize) -> T, - { - Self::from_core_array(sealed::ArrayExt::from_fn(cb)) - } - - /// Create array from a slice. - fn from_slice(slice: &[T]) -> Result - where - T: Copy; - - /// Returns an iterator over the array. - #[inline] - fn iter(&self) -> Iter<'_, T> { - self.as_ref().iter() - } - - /// Returns an iterator that allows modifying each value. - #[inline] - fn iter_mut(&mut self) -> IterMut<'_, T> { - self.as_mut().iter_mut() - } - /// Returns an array of the same size as `self`, with function `f` applied to each element /// in order. fn map(self, f: F) -> [U; N] @@ -378,11 +380,17 @@ pub trait IntoArray { /// Sealed traits. mod sealed { + use core::array::TryFromSliceError; + /// Extension trait with helper functions for core arrays. pub trait ArrayExt: Sized { fn from_fn(cb: F) -> Self where F: FnMut(usize) -> T; + + fn from_slice(slice: &[T]) -> Result + where + T: Copy; } impl ArrayExt for [T; N] { @@ -398,6 +406,13 @@ mod sealed { res }) } + + fn from_slice(slice: &[T]) -> Result + where + T: Copy, + { + slice.try_into() + } } } @@ -425,24 +440,16 @@ macro_rules! impl_array_size { #[inline] fn from_core_array_ref(array_ref: &[T; $len]) -> &Self { - // SAFETY: `$ty` is a `repr(transparent)` newtype for `[T; $len]` + // SAFETY: `Self` is a `repr(transparent)` newtype for `[T; $len]` unsafe { &*(array_ref.as_ptr() as *const Self) } } #[inline] fn from_core_array_mut(array_ref: &mut [T; $len]) -> &mut Self { - // SAFETY: `$ty` is a `repr(transparent)` newtype for `[T; $len]` + // SAFETY: `Self` is a `repr(transparent)` newtype for `[T; $len]` unsafe { &mut *(array_ref.as_mut_ptr() as *mut Self) } } - #[inline] - fn from_slice(slice: &[T]) -> Result - where - T: Copy - { - slice.try_into().map(Self) - } - #[inline] fn map(self, f: F) -> [U; $len] where From 0fa48b78cd8aaa1119add63fdc55e5617ad6ab11 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 16:11:08 -0600 Subject: [PATCH 104/116] hybrid-array: unseal `ArrayExt` (#911) It's leaked through `ArraySize::ArrayType` bounds, and it may potentially be useful to have in the public API. --- hybrid-array/src/lib.rs | 84 ++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 43 deletions(-) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index d8c01911..ef70b364 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -50,7 +50,7 @@ where where F: FnMut(usize) -> T, { - Self(sealed::ArrayExt::from_fn(cb)) + Self(ArrayExt::from_fn(cb)) } /// Create array from a slice. @@ -58,7 +58,7 @@ where where T: Copy, { - sealed::ArrayExt::from_slice(slice).map(Self) + ArrayExt::from_slice(slice).map(Self) } /// Returns an iterator over the array. @@ -175,7 +175,7 @@ where U: ArraySize, { fn default() -> Self { - Self(sealed::ArrayExt::from_fn(|_| Default::default())) + Self(ArrayExt::from_fn(|_| Default::default())) } } @@ -265,7 +265,7 @@ where #[inline] fn try_from(slice: &'a [T]) -> Result, TryFromSliceError> { - sealed::ArrayExt::from_slice(slice).map(Self) + ArrayExt::from_slice(slice).map(Self) } } @@ -362,11 +362,47 @@ pub trait ArrayOps: F: FnMut(T) -> U; } +/// Extension trait with helper functions for core arrays. +pub trait ArrayExt: Sized { + /// Create array using the given callback function for each element. + fn from_fn(cb: F) -> Self + where + F: FnMut(usize) -> T; + + /// Create array from a slice, returning [`TryFromSliceError`] if the slice + /// length does not match the array length. + fn from_slice(slice: &[T]) -> Result + where + T: Copy; +} + +impl ArrayExt for [T; N] { + fn from_fn(mut cb: F) -> Self + where + F: FnMut(usize) -> T, + { + let mut idx = 0; + + [(); N].map(|_| { + let res = cb(idx); + idx = idx.saturating_add(1); // TODO(tarcieri): better overflow handling? + res + }) + } + + fn from_slice(slice: &[T]) -> Result + where + T: Copy, + { + slice.try_into() + } +} + /// Trait which associates a [`usize`] size and `ArrayType` with a /// `typenum`-provided [`Unsigned`] integer. pub trait ArraySize: Unsigned { /// Array type which corresponds to this size. - type ArrayType: AsRef<[T]> + AsMut<[T]> + IntoArray + sealed::ArrayExt; + type ArrayType: AsRef<[T]> + AsMut<[T]> + IntoArray + ArrayExt; } /// Convert the given type into an [`Array`]. @@ -378,44 +414,6 @@ pub trait IntoArray { fn into_hybrid_array(self) -> Array; } -/// Sealed traits. -mod sealed { - use core::array::TryFromSliceError; - - /// Extension trait with helper functions for core arrays. - pub trait ArrayExt: Sized { - fn from_fn(cb: F) -> Self - where - F: FnMut(usize) -> T; - - fn from_slice(slice: &[T]) -> Result - where - T: Copy; - } - - impl ArrayExt for [T; N] { - fn from_fn(mut cb: F) -> Self - where - F: FnMut(usize) -> T, - { - let mut idx = 0; - - [(); N].map(|_| { - let res = cb(idx); - idx = idx.saturating_add(1); // TODO(tarcieri): better overflow handling? - res - }) - } - - fn from_slice(slice: &[T]) -> Result - where - T: Copy, - { - slice.try_into() - } - } -} - macro_rules! impl_array_size { ($($len:expr => $ty:ident),+) => { $( From 1c599fd6c86a2721bf7bc6a57bf35e192328e134 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 17:20:53 -0600 Subject: [PATCH 105/116] hybrid-array v0.2.0-pre.1 (#912) --- Cargo.lock | 2 +- hybrid-array/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bed4c89f..2b562c93 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,7 +94,7 @@ version = "0.4.1" [[package]] name = "hybrid-array" -version = "0.2.0-pre.0" +version = "0.2.0-pre.1" dependencies = [ "typenum", ] diff --git a/hybrid-array/Cargo.toml b/hybrid-array/Cargo.toml index 4323fd23..459fff2e 100644 --- a/hybrid-array/Cargo.toml +++ b/hybrid-array/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hybrid-array" -version = "0.2.0-pre.0" +version = "0.2.0-pre.1" description = """ Hybrid typenum-based and const generic array types designed to provide the flexibility of typenum-based expressions while also allowing interoperability From 14b1e130a84e1a15967b6d17b9daec265794ed68 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 18:02:02 -0600 Subject: [PATCH 106/116] hybrid-array: change `Deref::Target` to `[T]` (#913) This makes porting existing `generic-array` code easier, and also means deref coercion will allow `&Array` to deref to `&[T]`, making it usable anywhere a slice is. --- hybrid-array/src/lib.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index ef70b364..8c08cca0 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -183,10 +183,11 @@ impl Deref for Array where U: ArraySize, { - type Target = U::ArrayType; + type Target = [T]; - fn deref(&self) -> &U::ArrayType { - &self.0 + #[inline] + fn deref(&self) -> &[T] { + self.0.as_ref() } } @@ -194,8 +195,9 @@ impl DerefMut for Array where U: ArraySize, { - fn deref_mut(&mut self) -> &mut U::ArrayType { - &mut self.0 + #[inline] + fn deref_mut(&mut self) -> &mut [T] { + self.0.as_mut() } } @@ -320,8 +322,6 @@ pub trait ArrayOps: + AsMut<[T; N]> + Borrow<[T; N]> + BorrowMut<[T; N]> - + Deref - + DerefMut + From<[T; N]> + Index + Index> From 04a440a25d438e64962e0d621592ce8a885ba912 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 18:45:00 -0600 Subject: [PATCH 107/116] hybrid-array: make `ArraySize` an `unsafe trait` (#914) It's used when checking the lengths of slices match an array size prior to using a pointer cast to convert types. If someone were to make their own `typenum::Unsigned` type and impl `ArraySize` for it with an `ArrayType` whose size does not match `Unsigned::USIZE`, that would be UB. Really `ArraySize` is not intended for downstream crates to impl anyway, but making it an `unsafe trait` at least captures the UB potential. Additionally this adds more debug checks to `check_slice_length` to ensure that if there is a length mismatch, it's at least caught in debug builds. --- hybrid-array/src/lib.rs | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index 8c08cca0..38da7bf8 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -304,10 +304,16 @@ where } /// Generate a [`TryFromSliceError`] if the slice doesn't match the given length. -fn check_slice_length(slice: &[T]) -> Result<(), TryFromSliceError> { +#[cfg_attr(debug_assertions, allow(clippy::panic_in_result_fn))] +fn check_slice_length(slice: &[T]) -> Result<(), TryFromSliceError> { + debug_assert_eq!(Array::<(), U>::default().len(), U::USIZE); + if slice.len() != U::USIZE { // Hack: `TryFromSliceError` lacks a public constructor <&[T; 1]>::try_from([].as_slice())?; + + #[cfg(debug_assertions)] + unreachable!(); } Ok(()) @@ -400,7 +406,17 @@ impl ArrayExt for [T; N] { /// Trait which associates a [`usize`] size and `ArrayType` with a /// `typenum`-provided [`Unsigned`] integer. -pub trait ArraySize: Unsigned { +/// +/// # Safety +/// +/// `ArrayType` MUST be an array with a number of elements exactly equal to +/// [`Unsigned::USIZE`]. +/// +/// Failure to so will cause undefined behavior. +/// +/// NOTE: do not implement this trait yourself. It is implemented for types in +/// [`typenum::consts`]. +pub unsafe trait ArraySize: Unsigned { /// Array type which corresponds to this size. type ArrayType: AsRef<[T]> + AsMut<[T]> + IntoArray + ArrayExt; } @@ -457,7 +473,7 @@ macro_rules! impl_array_size { } } - impl ArraySize for typenum::$ty { + unsafe impl ArraySize for typenum::$ty { type ArrayType = [T; $len]; } @@ -587,7 +603,7 @@ impl_array_size! { #[cfg(test)] mod tests { use super::ByteArray; - use typenum::{U0, U3, U6}; + use typenum::{U0, U3, U6, U7}; #[test] fn tryfrom_slice_for_array_ref() { @@ -597,5 +613,7 @@ mod tests { let array_ref = ByteArray::::try_from(slice).unwrap(); assert_eq!(&*array_ref, slice); + + assert!(ByteArray::::try_from(slice).is_err()); } } From fc8d750adcd5a3beeb9a562c16c37145ddaff0cc Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 18:56:56 -0600 Subject: [PATCH 108/116] hybrid-array: re-export `typenum::consts` (#915) --- hybrid-array/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index 38da7bf8..86e2c9f5 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -24,6 +24,7 @@ )] pub use typenum; +pub use typenum::consts; use core::{ array::{IntoIter, TryFromSliceError}, From f117cc1977972f288786a8b64c07e6028a8c1b84 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 20:05:45 -0600 Subject: [PATCH 109/116] hybrid-array: rename `ArrayOps` methods (#916) Renames the following methods of the `ArrayOps` trait: - `as_array_ref` -> `as_core_array` - `as_array_mut` -> `as_mut_core_array` - `from_core_array_ref` -> `ref_from_core_array` - `from_core_array_mut` -> `ref_from_mut_core_array` - `map` -> `map_to_core_array` --- hybrid-array/src/lib.rs | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/hybrid-array/src/lib.rs b/hybrid-array/src/lib.rs index 86e2c9f5..e7004e26 100644 --- a/hybrid-array/src/lib.rs +++ b/hybrid-array/src/lib.rs @@ -133,7 +133,7 @@ where { #[inline] fn as_ref(&self) -> &[T; N] { - self.as_array_ref() + self.as_core_array() } } @@ -144,7 +144,7 @@ where { #[inline] fn as_mut(&mut self) -> &mut [T; N] { - self.as_array_mut() + self.as_mut_core_array() } } @@ -155,7 +155,7 @@ where { #[inline] fn borrow(&self) -> &[T; N] { - self.as_array_ref() + self.as_core_array() } } @@ -166,7 +166,7 @@ where { #[inline] fn borrow_mut(&mut self) -> &mut [T; N] { - self.as_array_mut() + self.as_mut_core_array() } } @@ -220,7 +220,7 @@ where { #[inline] fn from(array_ref: &'a [T; N]) -> &'a Array { - >::from_core_array_ref(array_ref) + >::ref_from_core_array(array_ref) } } @@ -231,7 +231,7 @@ where { #[inline] fn from(array_ref: &'a mut [T; N]) -> &'a mut Array { - >::from_core_array_mut(array_ref) + >::ref_from_mut_core_array(array_ref) } } @@ -348,23 +348,23 @@ pub trait ArrayOps: type Size: ArraySize; /// Returns a reference to the inner array. - fn as_array_ref(&self) -> &[T; N]; + fn as_core_array(&self) -> &[T; N]; /// Returns a mutable reference to the inner array. - fn as_array_mut(&mut self) -> &mut [T; N]; + fn as_mut_core_array(&mut self) -> &mut [T; N]; /// Create array from Rust's core array type. fn from_core_array(arr: [T; N]) -> Self; /// Create array reference from reference to Rust's core array type. - fn from_core_array_ref(arr: &[T; N]) -> &Self; + fn ref_from_core_array(arr: &[T; N]) -> &Self; /// Create mutable array reference from reference to Rust's core array type. - fn from_core_array_mut(arr: &mut [T; N]) -> &mut Self; + fn ref_from_mut_core_array(arr: &mut [T; N]) -> &mut Self; /// Returns an array of the same size as `self`, with function `f` applied to each element /// in order. - fn map(self, f: F) -> [U; N] + fn map_to_core_array(self, f: F) -> [U; N] where F: FnMut(T) -> U; } @@ -439,12 +439,12 @@ macro_rules! impl_array_size { type Size = typenum::$ty; #[inline] - fn as_array_ref(&self) -> &[T; $len] { + fn as_core_array(&self) -> &[T; $len] { &self.0 } #[inline] - fn as_array_mut(&mut self) -> &mut [T; $len] { + fn as_mut_core_array(&mut self) -> &mut [T; $len] { &mut self.0 } @@ -454,19 +454,19 @@ macro_rules! impl_array_size { } #[inline] - fn from_core_array_ref(array_ref: &[T; $len]) -> &Self { + fn ref_from_core_array(array_ref: &[T; $len]) -> &Self { // SAFETY: `Self` is a `repr(transparent)` newtype for `[T; $len]` unsafe { &*(array_ref.as_ptr() as *const Self) } } #[inline] - fn from_core_array_mut(array_ref: &mut [T; $len]) -> &mut Self { + fn ref_from_mut_core_array(array_ref: &mut [T; $len]) -> &mut Self { // SAFETY: `Self` is a `repr(transparent)` newtype for `[T; $len]` unsafe { &mut *(array_ref.as_mut_ptr() as *mut Self) } } #[inline] - fn map(self, f: F) -> [U; $len] + fn map_to_core_array(self, f: F) -> [U; $len] where F: FnMut(T) -> U { From e4dff327bd84281628ff6b1a2ce0f66a6ad29fc0 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 20:21:34 -0600 Subject: [PATCH 110/116] hybrid-array v0.2.0-pre.2 (#917) --- Cargo.lock | 2 +- hybrid-array/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2b562c93..f2e0b7ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,7 +94,7 @@ version = "0.4.1" [[package]] name = "hybrid-array" -version = "0.2.0-pre.1" +version = "0.2.0-pre.2" dependencies = [ "typenum", ] diff --git a/hybrid-array/Cargo.toml b/hybrid-array/Cargo.toml index 459fff2e..93159f28 100644 --- a/hybrid-array/Cargo.toml +++ b/hybrid-array/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "hybrid-array" -version = "0.2.0-pre.1" +version = "0.2.0-pre.2" description = """ Hybrid typenum-based and const generic array types designed to provide the flexibility of typenum-based expressions while also allowing interoperability From 052cbe10c57a5237bce6e29ea3a4ac2cc2f8bfe8 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: Thu, 8 Jun 2023 23:37:27 +0300 Subject: [PATCH 111/116] Fix hex-literal's MSRV badge --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 856d52d0..0e07239c 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ This repository contains various utility crates used in the RustCrypto project. | [`collectable`] | [![crates.io](https://img.shields.io/crates/v/collectable.svg)](https://crates.io/crates/collectable) | [![Documentation](https://docs.rs/collectable/badge.svg)](https://docs.rs/collectable) | ![MSRV 1.41][msrv-1.41] | Fallible, `no_std`-friendly collection traits | | [`cpufeatures`] | [![crates.io](https://img.shields.io/crates/v/cpufeatures.svg)](https://crates.io/crates/cpufeatures) | [![Documentation](https://docs.rs/cpufeatures/badge.svg)](https://docs.rs/cpufeatures) | ![MSRV 1.40][msrv-1.40] | Lightweight and efficient alternative to the `is_x86_feature_detected!` macro | | [`dbl`] | [![crates.io](https://img.shields.io/crates/v/dbl.svg)](https://crates.io/crates/dbl) | [![Documentation](https://docs.rs/dbl/badge.svg)](https://docs.rs/dbl) | ![MSRV 1.41][msrv-1.41] | Double operation in Galois Field (GF) | -| [`hex-literal`] | [![crates.io](https://img.shields.io/crates/v/hex-literal.svg)](https://crates.io/crates/hex-literal) | [![Documentation](https://docs.rs/hex-literal/badge.svg)](https://docs.rs/hex-literal) | ![MSRV 1.45][msrv-1.45] | Procedural macro for converting hexadecimal string to byte array at compile time | +| [`hex-literal`] | [![crates.io](https://img.shields.io/crates/v/hex-literal.svg)](https://crates.io/crates/hex-literal) | [![Documentation](https://docs.rs/hex-literal/badge.svg)](https://docs.rs/hex-literal) | ![MSRV 1.57][msrv-1.57] | Procedural macro for converting hexadecimal string to byte array at compile time | | [`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 | @@ -50,6 +50,7 @@ Unless you explicitly state otherwise, any contribution intentionally submitted [msrv-1.45]: https://img.shields.io/badge/rustc-1.45.0+-blue.svg [msrv-1.51]: https://img.shields.io/badge/rustc-1.51.0+-blue.svg [msrv-1.56]: https://img.shields.io/badge/rustc-1.56.0+-blue.svg +[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 [//]: # (crates) From 6ad2abf2b41feef6f8adf9fdaee5fb9c9b1e3849 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, 9 Jun 2023 07:58:39 +0300 Subject: [PATCH 112/116] Update Cargo.lock --- Cargo.lock | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f2e0b7ea..ee662a1b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,9 +115,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "libc" -version = "0.2.144" +version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" [[package]] name = "opaque-debug" @@ -125,18 +125,18 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" dependencies = [ "proc-macro2", ] @@ -149,18 +149,18 @@ checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "serde" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.163" +version = "1.0.164" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" dependencies = [ "proc-macro2", "quote", @@ -180,9 +180,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" dependencies = [ "proc-macro2", "quote", @@ -197,9 +197,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "version_check" From 95219acbd028bbd3966fb94bbd78a999141a3e8d Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Thu, 15 Jun 2023 22:01:33 +0300 Subject: [PATCH 113/116] cpufeatures: check OS register support (#919) --- Cargo.lock | 2 +- cpufeatures/CHANGELOG.md | 6 ++ cpufeatures/Cargo.toml | 2 +- cpufeatures/src/x86.rs | 119 ++++++++++++++++++++++++--------------- 4 files changed, 83 insertions(+), 46 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee662a1b..6f6b616e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,7 +35,7 @@ version = "0.0.2" [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.8" dependencies = [ "libc", ] diff --git a/cpufeatures/CHANGELOG.md b/cpufeatures/CHANGELOG.md index aeb6894f..a0533ef4 100644 --- a/cpufeatures/CHANGELOG.md +++ b/cpufeatures/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.8 (2023-06-15) +### Fixed +- Check OS register support on x86 targets ([#919]) + +[#919]: https://github.com/RustCrypto/utils/issues/919 + ## 0.2.7 (2023-04-20) ### Added - Support freestanding/UEFI `x86` targets ([#821]) diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index 5e085ca2..cad6fac5 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cpufeatures" -version = "0.2.7" +version = "0.2.8" description = """ Lightweight runtime CPU feature detection for x86/x86_64 and aarch64 with no_std support and support for mobile targets including Android and iOS diff --git a/cpufeatures/src/x86.rs b/cpufeatures/src/x86.rs index 3eb5ae91..2199f277 100644 --- a/cpufeatures/src/x86.rs +++ b/cpufeatures/src/x86.rs @@ -3,23 +3,23 @@ //! Portable, `no_std`-friendly implementation that relies on the x86 `CPUID` //! instruction for feature detection. -// Evaluate the given `$body` expression any of the supplied target features -// are not enabled. Otherwise returns true. -// -// The `$body` expression is not evaluated on SGX targets, and returns false -// on these targets unless *all* supplied target features are enabled. +/// Evaluate the given `$body` expression any of the supplied target features +/// are not enabled. Otherwise returns true. +/// +/// The `$body` expression is not evaluated on SGX targets, and returns false +/// on these targets unless *all* supplied target features are enabled. #[macro_export] #[doc(hidden)] macro_rules! __unless_target_features { ($($tf:tt),+ => $body:expr ) => {{ #[cfg(not(all($(target_feature=$tf,)*)))] { - #[cfg(not(any(target_env = "sgx", target_os = "none", target_os = "uefi")))] + #[cfg(not(any(target_env = "sgx", target_os = "", target_os = "uefi")))] $body // CPUID is not available on SGX. Freestanding and UEFI targets // do not support SIMD features with default compilation flags. - #[cfg(any(target_env = "sgx", target_os = "none", target_os = "uefi"))] + #[cfg(any(target_env = "sgx", target_os = "", target_os = "uefi"))] false } @@ -28,7 +28,7 @@ macro_rules! __unless_target_features { }}; } -// Use CPUID to detect the presence of all supplied target features. +/// Use CPUID to detect the presence of all supplied target features. #[macro_export] #[doc(hidden)] macro_rules! __detect_target_features { @@ -61,54 +61,85 @@ macro_rules! __detect_target_features { }}; } +/// Check that OS supports required SIMD registers +#[macro_export] +#[doc(hidden)] +macro_rules! __xgetbv { + ($cr:expr, $mask:expr) => {{ + #[cfg(target_arch = "x86")] + use core::arch::x86 as arch; + #[cfg(target_arch = "x86_64")] + use core::arch::x86_64 as arch; + + // Check bits 26 and 27 + let xmask = 0b11 << 26; + let xsave = $cr[0].ecx & xmask == xmask; + if xsave { + let xcr0 = unsafe { arch::_xgetbv(arch::_XCR_XFEATURE_ENABLED_MASK) }; + (xcr0 & $mask) == $mask + } else { + false + } + }}; +} + macro_rules! __expand_check_macro { - ($(($name:tt $(, $i:expr, $reg:ident, $offset:expr)*)),* $(,)?) => { + ($(($name:tt, $reg_cap:tt $(, $i:expr, $reg:ident, $offset:expr)*)),* $(,)?) => { #[macro_export] #[doc(hidden)] macro_rules! check { $( - ($cr:expr, $name) => { - true + ($cr:expr, $name) => {{ + // Register bits are listed here: + // https://wiki.osdev.org/CPU_Registers_x86#Extended_Control_Registers + let reg_cap = match $reg_cap { + // Bit 1 + "xmm" => $crate::__xgetbv!($cr, 0b10), + // Bits 1 and 2 + "ymm" => $crate::__xgetbv!($cr, 0b110), + // Bits 1, 2, 5, 6, and 7 + "zmm" => $crate::__xgetbv!($cr, 0b1110_0110), + _ => true, + }; + reg_cap $( & ($cr[$i].$reg & (1 << $offset) != 0) )* - }; + }}; )* } }; } -// Note that according to the [Intel manual][0] AVX2 and FMA require -// that we check availability of AVX before using them. -// -// [0]: https://www.intel.com/content/dam/develop/external/us/en/documents/36945 __expand_check_macro! { - ("mmx", 0, edx, 23), - ("sse", 0, edx, 25), - ("sse2", 0, edx, 26), - ("sse3", 0, ecx, 0), - ("pclmulqdq", 0, ecx, 1), - ("ssse3", 0, ecx, 9), - ("fma", 0, ecx, 28, 0, ecx, 12), - ("sse4.1", 0, ecx, 19), - ("sse4.2", 0, ecx, 20), - ("popcnt", 0, ecx, 23), - ("aes", 0, ecx, 25), - ("avx", 0, ecx, 28), - ("rdrand", 0, ecx, 30), - ("sgx", 1, ebx, 2), - ("bmi1", 1, ebx, 3), - ("avx2", 0, ecx, 28, 1, ebx, 5), - ("bmi2", 1, ebx, 8), - ("avx512f", 1, ebx, 16), - ("avx512dq", 1, ebx, 17), - ("rdseed", 1, ebx, 18), - ("adx", 1, ebx, 19), - ("avx512ifma", 1, ebx, 21), - ("avx512pf", 1, ebx, 26), - ("avx512er", 1, ebx, 27), - ("avx512cd", 1, ebx, 28), - ("sha", 1, ebx, 29), - ("avx512bw", 1, ebx, 30), - ("avx512vl", 1, ebx, 31), + ("sse3", "xmm", 0, ecx, 0), + ("pclmulqdq", "xmm", 0, ecx, 1), + ("ssse3", "xmm", 0, ecx, 9), + ("fma", "xmm", 0, ecx, 12, 0, ecx, 28), + ("sse4.1", "xmm", 0, ecx, 19), + ("sse4.2", "xmm", 0, ecx, 20), + ("popcnt", "", 0, ecx, 23), + ("aes", "xmm", 0, ecx, 25), + ("avx", "xmm", 0, ecx, 28), + ("rdrand", "", 0, ecx, 30), + + ("mmx", "", 0, edx, 23), + ("sse", "xmm", 0, edx, 25), + ("sse2", "xmm", 0, edx, 26), + + ("sgx", "", 1, ebx, 2), + ("bmi1", "", 1, ebx, 3), + ("bmi2", "", 1, ebx, 8), + ("avx2", "ymm", 1, ebx, 5, 0, ecx, 28), + ("avx512f", "zmm", 1, ebx, 16), + ("avx512dq", "zmm", 1, ebx, 17), + ("rdseed", "", 1, ebx, 18), + ("adx", "", 1, ebx, 19), + ("avx512ifma", "zmm", 1, ebx, 21), + ("avx512pf", "zmm", 1, ebx, 26), + ("avx512er", "zmm", 1, ebx, 27), + ("avx512cd", "zmm", 1, ebx, 28), + ("sha", "xmm", 1, ebx, 29), + ("avx512bw", "zmm", 1, ebx, 30), + ("avx512vl", "zmm", 1, ebx, 31), } From adbf3871d6a08bfe419906e59eec79795b5b8f52 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: Mon, 26 Jun 2023 14:02:14 +0300 Subject: [PATCH 114/116] Update Cargo.lock --- Cargo.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f6b616e..24c438d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -115,9 +115,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "libc" -version = "0.2.146" +version = "0.2.147" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" [[package]] name = "opaque-debug" @@ -125,9 +125,9 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.60" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" dependencies = [ "unicode-ident", ] @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" dependencies = [ "itoa", "ryu", @@ -180,9 +180,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.18" +version = "2.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" dependencies = [ "proc-macro2", "quote", From 721520334eee6b8465a2c8eb1e73074453c9f11a Mon Sep 17 00:00:00 2001 From: jake <77554505+brxken128@users.noreply.github.com> Date: Wed, 5 Jul 2023 11:24:50 +0100 Subject: [PATCH 115/116] cpufeatures: add support for `avx512vbmi(2)` (#926) --- cpufeatures/src/x86.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cpufeatures/src/x86.rs b/cpufeatures/src/x86.rs index 2199f277..958eff3e 100644 --- a/cpufeatures/src/x86.rs +++ b/cpufeatures/src/x86.rs @@ -142,4 +142,6 @@ __expand_check_macro! { ("sha", "xmm", 1, ebx, 29), ("avx512bw", "zmm", 1, ebx, 30), ("avx512vl", "zmm", 1, ebx, 31), + ("avx512vbmi", "zmm", 1, ecx, 1), + ("avx512vbmi2", "zmm", 1, ecx, 6), } From 0726c7d827cfe38e67894e0650158b0e2e72f658 Mon Sep 17 00:00:00 2001 From: Artyom Pavlov Date: Wed, 5 Jul 2023 13:45:38 +0300 Subject: [PATCH 116/116] cpufeatures: release v0.2.9 (#927) --- Cargo.lock | 34 +++++++++++++++++----------------- cpufeatures/CHANGELOG.md | 6 ++++++ cpufeatures/Cargo.toml | 2 +- 3 files changed, 24 insertions(+), 18 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 24c438d8..9f5ac9a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,7 +35,7 @@ version = "0.0.2" [[package]] name = "cpufeatures" -version = "0.2.8" +version = "0.2.9" dependencies = [ "libc", ] @@ -109,9 +109,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "62b02a5381cc465bd3041d84623d0fa3b66738b52b8e2fc3bab8ad63ab032f4a" [[package]] name = "libc" @@ -134,33 +134,33 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "fe232bdf6be8c8de797b22184ee71118d63780ea42ac85b61d1baa6d3b782ae9" [[package]] name = "serde" -version = "1.0.164" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +checksum = "d01b7404f9d441d3ad40e6a636a7782c377d2abdbe4fa2440e2edcc2f4f10db8" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.164" +version = "1.0.166" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +checksum = "5dd83d6dde2b6b2d466e14d9d1acce8816dedee94f735eac6395808b3483c6d6" dependencies = [ "proc-macro2", "quote", @@ -169,9 +169,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.99" +version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3" +checksum = "0f1e14e89be7aa4c4b78bdbdc9eb5bf8517829a600ae8eaa39a6e1d960b5185c" dependencies = [ "itoa", "ryu", @@ -180,9 +180,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.22" +version = "2.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +checksum = "59fb7d6d8281a51045d62b8eb3a7d1ce347b76f312af50cd3dc0af39c87c1737" dependencies = [ "proc-macro2", "quote", @@ -197,9 +197,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" +checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" [[package]] name = "version_check" diff --git a/cpufeatures/CHANGELOG.md b/cpufeatures/CHANGELOG.md index a0533ef4..c62941d0 100644 --- a/cpufeatures/CHANGELOG.md +++ b/cpufeatures/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 0.2.9 (2023-07-05) +### Added +- Support for `avx512vbmi` and `avx512vbmi2` target features ([#926]) + +[#926]: https://github.com/RustCrypto/utils/pull/926 + ## 0.2.8 (2023-06-15) ### Fixed - Check OS register support on x86 targets ([#919]) diff --git a/cpufeatures/Cargo.toml b/cpufeatures/Cargo.toml index cad6fac5..20ff471d 100644 --- a/cpufeatures/Cargo.toml +++ b/cpufeatures/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "cpufeatures" -version = "0.2.8" +version = "0.2.9" description = """ Lightweight runtime CPU feature detection for x86/x86_64 and aarch64 with no_std support and support for mobile targets including Android and iOS