├── .gitignore ├── .typos.toml ├── ctutils ├── src │ ├── traits.rs │ ├── traits │ │ ├── ct_gt.rs │ │ ├── ct_lt.rs │ │ └── ct_eq.rs │ └── lib.rs ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-MIT └── README.md ├── .github ├── dependabot.yml └── workflows │ ├── aarch64-dit.yml │ ├── security-audit.yml │ ├── digest-io.yml │ ├── blobby.yml │ ├── workspace.yml │ ├── dbl.yml │ ├── block-padding.yml │ ├── block-buffer.yml │ ├── inout.yml │ ├── hex-literal.yml │ ├── opaque-debug.yml │ ├── ctutils.yml │ ├── cmov.yml │ ├── cpufeatures.yml │ └── zeroize.yml ├── opaque-debug ├── Cargo.toml ├── CHANGELOG.md ├── LICENSE-MIT ├── tests │ └── mod.rs ├── README.md └── src │ └── lib.rs ├── digest-io ├── CHANGELOG.md ├── src │ ├── lib.rs │ ├── io_wrapper.rs │ ├── writer.rs │ └── reader.rs ├── Cargo.toml ├── LICENSE-MIT └── README.md ├── cpufeatures ├── tests │ ├── aarch64.rs │ ├── x86.rs │ └── loongarch64.rs ├── src │ ├── miri.rs │ ├── lib.rs │ └── loongarch64.rs ├── LICENSE-MIT └── Cargo.toml ├── blobby ├── Cargo.toml ├── tests │ └── mod.rs ├── LICENSE-MIT ├── src │ ├── lib.rs │ └── bin │ │ ├── decode.rs │ │ └── encode.rs └── CHANGELOG.md ├── collectable ├── Cargo.toml ├── CHANGELOG.md ├── LICENSE-MIT └── src │ └── lib.rs ├── hex-literal ├── Cargo.toml ├── LICENSE-MIT ├── tests │ └── basic.rs ├── CHANGELOG.md ├── src │ └── lib.rs └── README.md ├── aarch64-dit ├── CHANGELOG.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE-MIT └── README.md ├── Cargo.toml ├── wycheproof2blb ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE-MIT └── src │ ├── aes_siv.rs │ ├── ed25519.rs │ ├── hkdf.rs │ ├── mac.rs │ ├── ecdsa.rs │ ├── aead.rs │ └── wycheproof.rs ├── block-padding ├── Cargo.toml ├── LICENSE-MIT ├── README.md └── CHANGELOG.md ├── block-buffer ├── Cargo.toml ├── LICENSE-MIT ├── README.md ├── CHANGELOG.md └── src │ └── sealed.rs ├── inout ├── src │ ├── lib.rs │ └── errors.rs ├── Cargo.toml ├── tests │ └── split-inout.rs ├── LICENSE-MIT ├── README.md └── CHANGELOG.md ├── dbl ├── Cargo.toml ├── CHANGELOG.md ├── LICENSE-MIT └── README.md ├── cmov ├── Cargo.toml ├── LICENSE-MIT ├── CHANGELOG.md ├── src │ ├── portable.rs │ └── aarch64.rs └── README.md ├── SECURITY.md ├── zeroize_derive ├── Cargo.toml ├── LICENSE-MIT ├── README.md └── CHANGELOG.md ├── zeroize ├── src │ ├── aarch64.rs │ ├── x86.rs │ └── barrier.rs ├── LICENSE-MIT ├── Cargo.toml ├── tests │ └── alloc.rs └── README.md └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | **/Cargo.lock 3 | **/*proptest-regressions 4 | -------------------------------------------------------------------------------- /.typos.toml: -------------------------------------------------------------------------------- 1 | [files] 2 | extend-exclude = [ 3 | ".git/" 4 | ] 5 | -------------------------------------------------------------------------------- /ctutils/src/traits.rs: -------------------------------------------------------------------------------- 1 | //! Trait definitions. 2 | //! 3 | //! These are each in their own module so we can also define tests for the core types they're impl'd 4 | //! on in the same module. 5 | 6 | pub(crate) mod ct_eq; 7 | pub(crate) mod ct_gt; 8 | pub(crate) mod ct_lt; 9 | pub(crate) mod ct_select; 10 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | open-pull-requests-limit: 10 8 | - package-ecosystem: github-actions 9 | directory: "/" 10 | schedule: 11 | interval: weekly 12 | open-pull-requests-limit: 10 13 | -------------------------------------------------------------------------------- /ctutils/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.1.0 (2025-12-19) 8 | - Initial release 9 | -------------------------------------------------------------------------------- /opaque-debug/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "opaque-debug" 3 | version = "0.4.0-pre" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/opaque-debug" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "MIT OR Apache-2.0" 11 | description = "Macro for opaque Debug trait implementation" 12 | -------------------------------------------------------------------------------- /digest-io/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.1.0 (UNRELEASED) 8 | - Initial release ([#1172]) 9 | 10 | [#1172]: https://github.com/RustCrypto/utils/pull/1172 11 | -------------------------------------------------------------------------------- /cpufeatures/tests/aarch64.rs: -------------------------------------------------------------------------------- 1 | //! ARM64 tests 2 | 3 | #![cfg(target_arch = "aarch64")] 4 | 5 | cpufeatures::new!(armcaps, "aes", "sha2", "sha3", "sm4"); 6 | 7 | #[test] 8 | fn init() { 9 | let token: armcaps::InitToken = armcaps::init(); 10 | assert_eq!(token.get(), armcaps::get()); 11 | } 12 | 13 | #[test] 14 | fn init_get() { 15 | let (token, val) = armcaps::init_get(); 16 | assert_eq!(val, token.get()); 17 | } 18 | -------------------------------------------------------------------------------- /cpufeatures/tests/x86.rs: -------------------------------------------------------------------------------- 1 | //! x86/x86_64 tests 2 | 3 | #![cfg(any(target_arch = "x86", target_arch = "x86_64"))] 4 | 5 | cpufeatures::new!(cpuid, "aes", "sha"); 6 | 7 | #[test] 8 | fn init() { 9 | let token: cpuid::InitToken = cpuid::init(); 10 | assert_eq!(token.get(), cpuid::get()); 11 | } 12 | 13 | #[test] 14 | fn init_get() { 15 | let (token, val) = cpuid::init_get(); 16 | assert_eq!(val, token.get()); 17 | } 18 | -------------------------------------------------------------------------------- /blobby/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "blobby" 3 | version = "0.4.0" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/blobby" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "MIT OR Apache-2.0" 11 | categories = ["no-std"] 12 | description = "Iterator over simple binary blob storage" 13 | 14 | [features] 15 | alloc = [] 16 | -------------------------------------------------------------------------------- /collectable/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "collectable" 3 | version = "0.1.0" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/collectable" 8 | repository = "https://github.com/RustCrypto/utils" 9 | license = "Apache-2.0 OR MIT" 10 | keywords = ["arrayvec", "heapless"] 11 | categories = ["data-structures", "no-std"] 12 | description = "Fallible, no_std-friendly collection traits" 13 | 14 | [features] 15 | alloc = [] 16 | -------------------------------------------------------------------------------- /hex-literal/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "hex-literal" 3 | version = "1.1.0" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/hex-literal" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "MIT OR Apache-2.0" 11 | keywords = ["hex", "literals"] 12 | categories = ["no-std"] 13 | description = "A macro for converting hexadecimal string literals to a byte array at compile time" 14 | -------------------------------------------------------------------------------- /cpufeatures/src/miri.rs: -------------------------------------------------------------------------------- 1 | //! Minimal miri support. 2 | //! 3 | //! Miri is an interpreter, and though it tries to emulate the target CPU 4 | //! it does not support any target features. 5 | 6 | #[macro_export] 7 | #[doc(hidden)] 8 | macro_rules! __unless_target_features { 9 | ($($tf:tt),+ => $body:expr ) => { 10 | false 11 | }; 12 | } 13 | 14 | #[macro_export] 15 | #[doc(hidden)] 16 | macro_rules! __detect_target_features { 17 | ($($tf:tt),+) => { 18 | false 19 | }; 20 | } 21 | -------------------------------------------------------------------------------- /aarch64-dit/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.2.0 (unreleased) 8 | ### Changed 9 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 10 | 11 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 12 | 13 | ## 0.1.0 (2024-09-06) 14 | - Initial release 15 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | resolver = "3" 3 | members = [ 4 | "blobby", 5 | "block-buffer", 6 | "block-padding", 7 | "collectable", 8 | "cmov", 9 | "ctutils", 10 | "cpufeatures", 11 | "dbl", 12 | "digest-io", 13 | "hex-literal", 14 | "inout", 15 | "opaque-debug", 16 | "wycheproof2blb", 17 | "zeroize", 18 | "zeroize_derive" 19 | ] 20 | exclude = ["aarch64-dit"] 21 | 22 | [profile.dev] 23 | opt-level = 2 24 | 25 | [patch.crates-io] 26 | cmov = { path = "cmov" } 27 | -------------------------------------------------------------------------------- /wycheproof2blb/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.2.0 (unreleased) 8 | ### Changed 9 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 10 | 11 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 12 | 13 | ## 0.1.0 (2021-12-07) 14 | - Initial release 15 | -------------------------------------------------------------------------------- /digest-io/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | #![cfg_attr(docsrs, feature(doc_cfg))] 3 | #![forbid(unsafe_code)] 4 | #![doc( 5 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", 6 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" 7 | )] 8 | #![warn(missing_debug_implementations)] 9 | 10 | mod io_wrapper; 11 | mod reader; 12 | mod writer; 13 | 14 | pub use io_wrapper::IoWrapper; 15 | pub use reader::HashReader; 16 | pub use writer::HashWriter; 17 | -------------------------------------------------------------------------------- /block-padding/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "block-padding" 3 | version = "0.4.2" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/block-padding" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "MIT OR Apache-2.0" 11 | keywords = ["padding", "pkcs7", "ansix923", "iso7816"] 12 | categories = ["cryptography", "no-std"] 13 | description = "Padding and unpadding of messages divided into blocks." 14 | 15 | [dependencies] 16 | hybrid-array = "0.4.3" 17 | -------------------------------------------------------------------------------- /aarch64-dit/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 4 4 | 5 | [[package]] 6 | name = "aarch64-dit" 7 | version = "0.2.0-pre" 8 | dependencies = [ 9 | "cpufeatures", 10 | ] 11 | 12 | [[package]] 13 | name = "cpufeatures" 14 | version = "0.3.0-pre" 15 | dependencies = [ 16 | "libc", 17 | ] 18 | 19 | [[package]] 20 | name = "libc" 21 | version = "0.2.169" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" 24 | -------------------------------------------------------------------------------- /digest-io/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "digest-io" 3 | version = "0.1.0" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/digest-io" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "MIT OR Apache-2.0" 11 | keywords = ["crypto", "digest", "wrappers"] 12 | categories = ["cryptography"] 13 | description = "std::io-compatibility wrappers for traits defined in the digest crate" 14 | 15 | [dependencies] 16 | digest = "0.11.0-rc.3" 17 | 18 | [dev-dependencies] 19 | sha2 = "0.11.0-pre.5" 20 | sha3 = "0.11.0-pre.5" 21 | -------------------------------------------------------------------------------- /wycheproof2blb/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wycheproof2blb" 3 | version = "0.2.0-pre" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | repository = "https://github.com/RustCrypto/utils" 8 | license = "MIT OR Apache-2.0" 9 | keywords = ["test", "Wycheproof"] 10 | categories = ["cryptography", "no-std"] 11 | description = "A utility for converting Wycheproof test vectors to the blobby format" 12 | 13 | [dependencies] 14 | blobby = { version = "0.4.0-pre", path = "../blobby", features = ["alloc"] } 15 | hex = "0.4" 16 | serde = { version = "1.0.184", features = ["derive"] } 17 | serde_json = "1" 18 | -------------------------------------------------------------------------------- /block-buffer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "block-buffer" 3 | version = "0.11.0" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/block-buffer" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "MIT OR Apache-2.0" 11 | keywords = ["block", "buffer"] 12 | categories = ["cryptography", "no-std"] 13 | description = "Buffer types for block processing of data" 14 | 15 | [dependencies] 16 | hybrid-array = "0.4" 17 | zeroize = { version = "1.4", optional = true, default-features = false } 18 | 19 | [dev-dependencies] 20 | hex-literal = "1" 21 | -------------------------------------------------------------------------------- /opaque-debug/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.4.0 (unreleased) 8 | ### Changed 9 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 10 | 11 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 12 | 13 | ## 0.3.1 (2024-03-01) 14 | ### Added 15 | - Support for generic parameters ([#1053]) 16 | 17 | [#1053]: https://github.com/RustCrypto/utils/pull/1053 18 | 19 | ## 0.3.0 (2020-06-11) 20 | -------------------------------------------------------------------------------- /cpufeatures/tests/loongarch64.rs: -------------------------------------------------------------------------------- 1 | //! LoongArch64 tests 2 | 3 | #![cfg(target_arch = "loongarch64")] 4 | 5 | cpufeatures::new!( 6 | lacaps, 7 | "32s", 8 | "f", 9 | "d", 10 | "frecipe", 11 | "div32", 12 | "lsx", 13 | "lasx", 14 | "lam-bh", 15 | "lamcas", 16 | "ld-seq-sa", 17 | "scq", 18 | "lbt", 19 | "lvz", 20 | "ual" 21 | ); 22 | 23 | #[test] 24 | fn init() { 25 | let token: lacaps::InitToken = lacaps::init(); 26 | assert_eq!(token.get(), lacaps::get()); 27 | } 28 | 29 | #[test] 30 | fn init_get() { 31 | let (token, val) = lacaps::init_get(); 32 | assert_eq!(val, token.get()); 33 | } 34 | -------------------------------------------------------------------------------- /inout/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Collection of custom reference types for code generic over in-place and 2 | //! buffer-to-buffer modes of operation. 3 | 4 | #![no_std] 5 | #![doc( 6 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg", 7 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/8f1a9894/logo.svg" 8 | )] 9 | #![cfg_attr(docsrs, feature(doc_cfg))] 10 | #![warn(missing_docs)] 11 | 12 | #[cfg(feature = "block-padding")] 13 | pub use block_padding; 14 | 15 | mod errors; 16 | mod inout; 17 | mod inout_buf; 18 | mod reserved; 19 | 20 | pub use crate::{errors::*, inout::*, inout_buf::*, reserved::*}; 21 | -------------------------------------------------------------------------------- /dbl/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "dbl" 3 | version = "0.5.0" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/dbl" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "MIT OR Apache-2.0" 11 | keywords = ["crypto", "dbl", "gf", "galois"] 12 | categories = ["cryptography", "no-std"] 13 | description = """ 14 | Double operation in Galois Field `GF(2^128)` using the lexicographically first 15 | polynomial among the irreducible degree `n` polynomials having a minimum number of coefficients. 16 | """ 17 | 18 | [dependencies] 19 | hybrid-array = "0.4" 20 | -------------------------------------------------------------------------------- /cmov/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cmov" 3 | version = "0.4.1" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/cmov" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "Apache-2.0 OR MIT" 11 | keywords = ["crypto", "intrinsics"] 12 | categories = ["cryptography", "hardware-support", "no-std"] 13 | description = """ 14 | Conditional move CPU intrinsics which are guaranteed to execute in 15 | constant-time and not be rewritten as branches by the compiler. 16 | Provides wrappers for the CMOV family of instructions on x86/x86_64 17 | and CSEL on AArch64. 18 | """ 19 | -------------------------------------------------------------------------------- /inout/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "inout" 3 | version = "0.2.1" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/inout" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "MIT OR Apache-2.0" 11 | keywords = ["custom-reference"] 12 | categories = ["no-std"] 13 | description = "Custom reference types for code generic over in-place and buffer-to-buffer modes of operation." 14 | 15 | [dependencies] 16 | hybrid-array = "0.4" 17 | block-padding = { version = "0.4", path = "../block-padding", optional = true } 18 | 19 | [package.metadata.docs.rs] 20 | all-features = true 21 | -------------------------------------------------------------------------------- /aarch64-dit/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "aarch64-dit" 3 | version = "0.2.0-pre" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/aarch64-dit" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "Apache-2.0 OR MIT" 11 | keywords = ["crypto", "intrinsics"] 12 | categories = ["cryptography", "hardware-support", "no-std"] 13 | description = "Wrappers for enabling/disabling the Data Independent Timing (DIT) feature on AArch64 CPUs" 14 | 15 | [dependencies] 16 | cpufeatures = { version = "0.3.0-pre", path = "../cpufeatures" } 17 | 18 | [package.metadata.docs.rs] 19 | default-target = "aarch64-unknown-linux-gnu" 20 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Security updates are applied only to the most recent release. 6 | 7 | ## Reporting a Vulnerability 8 | 9 | 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. 10 | 11 | Please disclose it at [security advisory](https://github.com/RustCrypto/utils/security/advisories/new). 12 | 13 | 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. 14 | -------------------------------------------------------------------------------- /zeroize_derive/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "zeroize_derive" 3 | version = "1.5.0" 4 | authors = ["The RustCrypto Project Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/zeroize_derive" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "Apache-2.0 OR MIT" 11 | keywords = ["memory", "memset", "secure", "volatile", "zero"] 12 | categories = ["cryptography", "memory-management", "no-std", "os"] 13 | description = "Custom derive support for zeroize" 14 | 15 | [lib] 16 | proc-macro = true 17 | 18 | [dependencies] 19 | proc-macro2 = "1" 20 | quote = "1" 21 | syn = { version = "2", features = ["full", "extra-traits", "visit"] } 22 | 23 | [package.metadata.docs.rs] 24 | rustdoc-args = ["--document-private-items"] 25 | -------------------------------------------------------------------------------- /dbl/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.5.0 (2025-09-02) 8 | ### Changed 9 | - Bump `hybrid-array` to v0.4 ([#1208]) 10 | 11 | [#1208]: https://github.com/RustCrypto/utils/pull/1208 12 | 13 | ## 0.4.0 (2025-08-06) 14 | ### Changed 15 | - Migrated from `generic-array` to `hybrid-array` ([#944]) 16 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 17 | - Seal the `Dbl` trait ([#1198]) 18 | 19 | [#944]: https://github.com/RustCrypto/utils/pull/944 20 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 21 | [#1198]: https://github.com/RustCrypto/utils/pull/1198 22 | -------------------------------------------------------------------------------- /collectable/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.1.0 (unreleased) 8 | ### Changed 9 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 10 | 11 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 12 | 13 | ## 0.0.2 (2020-05-24) 14 | ### Added 15 | - `TryPush` trait ([#45]) 16 | 17 | ### Changed 18 | - Borrow iterators rather than consume them ([#44], [#46]) 19 | 20 | [#46]: https://github.com/RustCrypto/utils/pull/46 21 | [#45]: https://github.com/RustCrypto/utils/pull/45 22 | [#44]: https://github.com/RustCrypto/utils/pull/44 23 | 24 | ## 0.0.1 (2020-05-24) 25 | - Initial release 26 | -------------------------------------------------------------------------------- /digest-io/src/io_wrapper.rs: -------------------------------------------------------------------------------- 1 | use digest::{Update, XofReader}; 2 | use std::io; 3 | 4 | /// Wrapper which allows to update state of an [`Update`] implementor by writing into it 5 | /// and to read data from a [`XofReader`] implementor. 6 | #[derive(Debug)] 7 | pub struct IoWrapper(pub T); 8 | 9 | impl io::Write for IoWrapper { 10 | #[inline] 11 | fn write(&mut self, buf: &[u8]) -> io::Result { 12 | Update::update(&mut self.0, buf); 13 | Ok(buf.len()) 14 | } 15 | 16 | #[inline] 17 | fn flush(&mut self) -> io::Result<()> { 18 | Ok(()) 19 | } 20 | } 21 | 22 | impl io::Read for IoWrapper { 23 | #[inline] 24 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 25 | XofReader::read(&mut self.0, buf); 26 | Ok(buf.len()) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /zeroize/src/aarch64.rs: -------------------------------------------------------------------------------- 1 | //! [`Zeroize`] impls for ARM64 SIMD registers. 2 | 3 | use crate::{Zeroize, optimization_barrier, volatile_write}; 4 | 5 | use core::arch::aarch64::*; 6 | 7 | macro_rules! impl_zeroize_for_simd_register { 8 | ($($type:ty),* $(,)?) => { 9 | $( 10 | impl Zeroize for $type { 11 | #[inline] 12 | fn zeroize(&mut self) { 13 | volatile_write(self, unsafe { core::mem::zeroed() }); 14 | optimization_barrier(self); 15 | } 16 | } 17 | )+ 18 | }; 19 | } 20 | 21 | // TODO(tarcieri): other NEON register types? 22 | impl_zeroize_for_simd_register! { 23 | uint8x8_t, 24 | uint8x16_t, 25 | uint16x4_t, 26 | uint16x8_t, 27 | uint32x2_t, 28 | uint32x4_t, 29 | uint64x1_t, 30 | uint64x2_t, 31 | } 32 | -------------------------------------------------------------------------------- /blobby/tests/mod.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "alloc")] 2 | 3 | const ITEMS_LEN: usize = 10; 4 | const DEDUP_LEN: usize = 3; 5 | const TEST_BLOBS: &[&[u8]; ITEMS_LEN] = &[ 6 | b"1", 7 | b"12", 8 | b"1", 9 | b"1", 10 | b"123", 11 | &[42; 100_000], 12 | &[42; 100_000], 13 | &[13; 7_000], 14 | &[13; 7_000], 15 | &[13; 5_000], 16 | ]; 17 | 18 | #[test] 19 | fn blobby_rondtrip_test() -> Result<(), blobby::Error> { 20 | let (blobby_data, dedup_len) = blobby::encode_blobs(TEST_BLOBS); 21 | assert_eq!(dedup_len, DEDUP_LEN); 22 | assert_eq!(blobby_data.len(), 112_025); 23 | 24 | let decoded_blobs = blobby::parse_into_array::(&blobby_data)?; 25 | assert_eq!(decoded_blobs, TEST_BLOBS[..]); 26 | 27 | let decoded_blobs = blobby::parse_into_vec(&blobby_data)?; 28 | assert_eq!(decoded_blobs, TEST_BLOBS[..]); 29 | 30 | Ok(()) 31 | } 32 | -------------------------------------------------------------------------------- /zeroize/src/x86.rs: -------------------------------------------------------------------------------- 1 | //! [`Zeroize`] impls for x86 SIMD registers 2 | 3 | use crate::{Zeroize, optimization_barrier, volatile_write}; 4 | 5 | #[cfg(target_arch = "x86")] 6 | use core::arch::x86::*; 7 | 8 | #[cfg(target_arch = "x86_64")] 9 | use core::arch::x86_64::*; 10 | 11 | macro_rules! impl_zeroize_for_simd_register { 12 | ($($type:ty),* $(,)?) => { 13 | $( 14 | impl Zeroize for $type { 15 | #[inline] 16 | fn zeroize(&mut self) { 17 | volatile_write(self, unsafe { core::mem::zeroed() }); 18 | optimization_barrier(self); 19 | } 20 | } 21 | )* 22 | }; 23 | } 24 | 25 | impl_zeroize_for_simd_register!(__m128, __m128d, __m128i, __m256, __m256d, __m256i); 26 | 27 | // NOTE: MSRV 1.72 28 | #[cfg(feature = "simd")] 29 | impl_zeroize_for_simd_register!(__m512, __m512d, __m512i); 30 | -------------------------------------------------------------------------------- /ctutils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "ctutils" 3 | description = """ 4 | Constant-time utility library with selection and equality testing support targeting cryptographic 5 | applications. Supports `const fn` where appropriate. Built on the `cmov` crate which provides 6 | architecture-specific predication intrinsics. Heavily inspired by the `subtle` crate. 7 | """ 8 | version = "0.1.0" 9 | authors = ["RustCrypto Developers"] 10 | license = "Apache-2.0 OR MIT" 11 | homepage = "https://github.com/RustCrypto/utils/tree/master/ctselect" 12 | repository = "https://github.com/RustCrypto/utils" 13 | categories = ["cryptography", "no-std"] 14 | keywords = ["crypto", "intrinsics"] 15 | readme = "README.md" 16 | edition = "2024" 17 | rust-version = "1.85" 18 | 19 | [dependencies] 20 | cmov = "0.4" 21 | 22 | # optional dependencies 23 | subtle = { version = "2", optional = true, default-features = false } 24 | 25 | [package.metadata.docs.rs] 26 | all-features = true 27 | -------------------------------------------------------------------------------- /inout/tests/split-inout.rs: -------------------------------------------------------------------------------- 1 | use hybrid_array::{ 2 | Array, 3 | sizes::{U2, U4, U8}, 4 | }; 5 | use inout::{InOut, InOutBuf}; 6 | 7 | #[test] 8 | fn test_split() { 9 | let mut buf = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]; 10 | let inout: InOutBuf<'_, '_, u8> = buf.as_mut_slice().into(); 11 | 12 | let expected: Vec<&[u8]> = vec![ 13 | &[1, 2], 14 | &[3, 4], 15 | &[5, 6], 16 | &[7, 8], 17 | &[9, 10], 18 | &[11, 12], 19 | &[13, 14], 20 | &[15, 16], 21 | ]; 22 | let mut expected = expected.into_iter(); 23 | 24 | let (blocks, _tail) = inout.into_chunks::(); 25 | for block in blocks.into_iter() { 26 | type SubBlock = Array; 27 | 28 | let subblocks = Array::, U4>::from(block); 29 | 30 | for subblock in subblocks { 31 | assert_eq!(Some(subblock.get_in().as_slice()), expected.next()); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /.github/workflows/aarch64-dit.yml: -------------------------------------------------------------------------------- 1 | name: aarch64-dit 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "aarch64-dit/**" 7 | - "Cargo.*" 8 | push: 9 | branches: master 10 | 11 | permissions: 12 | contents: read 13 | 14 | defaults: 15 | run: 16 | working-directory: aarch64-dit 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | 22 | # Cancels CI jobs when new commits are pushed to a PR branch 23 | concurrency: 24 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 25 | cancel-in-progress: true 26 | 27 | jobs: 28 | macos: 29 | strategy: 30 | matrix: 31 | toolchain: 32 | - 1.85.0 # MSRV 33 | - stable 34 | runs-on: macos-latest 35 | steps: 36 | - uses: actions/checkout@v6 37 | - uses: RustCrypto/actions/cargo-cache@master 38 | - uses: dtolnay/rust-toolchain@master 39 | with: 40 | toolchain: ${{ matrix.toolchain }} 41 | targets: aarch64-apple-darwin 42 | - run: cargo test 43 | -------------------------------------------------------------------------------- /.github/workflows/security-audit.yml: -------------------------------------------------------------------------------- 1 | name: Security Audit 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - .github/workflows/security-audit.yml 7 | - Cargo.lock 8 | push: 9 | branches: master 10 | paths: 11 | - .github/workflows/security-audit.yml 12 | - Cargo.lock 13 | schedule: 14 | - cron: "0 0 * * *" 15 | 16 | permissions: # added using https://github.com/step-security/secure-repo 17 | contents: read 18 | 19 | jobs: 20 | security_audit: 21 | permissions: 22 | checks: write # for actions-rs/audit-check to create check 23 | contents: read # for actions/checkout to fetch code 24 | issues: write # for actions-rs/audit-check to create issues 25 | name: Security Audit 26 | runs-on: ubuntu-latest 27 | steps: 28 | - uses: actions/checkout@v6 29 | - name: Cache cargo bin 30 | uses: actions/cache@v5 31 | with: 32 | path: ~/.cargo/bin 33 | key: ${{ runner.os }}-cargo-audit-v0.22.0 34 | - uses: rustsec/audit-check@v2 35 | with: 36 | token: ${{ secrets.GITHUB_TOKEN }} 37 | -------------------------------------------------------------------------------- /ctutils/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /dbl/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /blobby/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /cmov/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /collectable/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /digest-io/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /zeroize/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /aarch64-dit/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2024-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /block-buffer/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /block-padding/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /cpufeatures/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2020-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /opaque-debug/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /wycheproof2blb/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2021-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /zeroize_derive/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019-2025 The RustCrypto Project Developers 2 | 3 | Permission is hereby granted, free of charge, to any 4 | person obtaining a copy of this software and associated 5 | documentation files (the "Software"), to deal in the 6 | Software without restriction, including without 7 | limitation the rights to use, copy, modify, merge, 8 | publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software 10 | is furnished to do so, subject to the following 11 | conditions: 12 | 13 | The above copyright notice and this permission notice 14 | shall be included in all copies or substantial portions 15 | of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 | DEALINGS IN THE SOFTWARE. 26 | -------------------------------------------------------------------------------- /inout/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2022-2025 The RustCrypto Project Developers 2 | Copyright (c) 2022 Artyom Pavlov 3 | 4 | Permission is hereby granted, free of charge, to any 5 | person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the 7 | Software without restriction, including without 8 | limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software 11 | is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice 15 | shall be included in all copies or substantial portions 16 | of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 19 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 20 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 21 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 22 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 25 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /cpufeatures/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cpufeatures" 3 | version = "0.3.0-pre" 4 | authors = ["RustCrypto Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/cpufeatures" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "MIT OR Apache-2.0" 11 | keywords = ["cpuid", "target-feature"] 12 | categories = ["hardware-support", "no-std"] 13 | description = """ 14 | Lightweight runtime CPU feature detection for aarch64, loongarch64, and x86/x86_64 targets, 15 | with no_std support and support for mobile targets including Android and iOS 16 | """ 17 | 18 | [target.'cfg(all(target_arch = "aarch64", target_vendor = "apple"))'.dependencies] 19 | libc = { version = "0.2.155", default-features = false } 20 | 21 | [target.'cfg(all(target_arch = "aarch64", target_os = "linux"))'.dependencies] 22 | libc = { version = "0.2.155", default-features = false } 23 | 24 | [target.'cfg(all(target_arch = "loongarch64", target_os = "linux"))'.dependencies] 25 | libc = { version = "0.2.155", default-features = false } 26 | 27 | [target.'cfg(all(target_arch = "aarch64", target_os = "android"))'.dependencies] 28 | libc = { version = "0.2.155", default-features = false } 29 | -------------------------------------------------------------------------------- /hex-literal/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2018-2025 The RustCrypto Project Developers 2 | Copyright (c) 2018 Artyom Pavlov 3 | 4 | Permission is hereby granted, free of charge, to any 5 | person obtaining a copy of this software and associated 6 | documentation files (the "Software"), to deal in the 7 | Software without restriction, including without 8 | limitation the rights to use, copy, modify, merge, 9 | publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software 11 | is furnished to do so, subject to the following 12 | conditions: 13 | 14 | The above copyright notice and this permission notice 15 | shall be included in all copies or substantial portions 16 | of the Software. 17 | 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF 19 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 20 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A 21 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT 22 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 23 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 24 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 25 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 26 | DEALINGS IN THE SOFTWARE. 27 | -------------------------------------------------------------------------------- /blobby/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc = include_str!("../README.md")] 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", 5 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" 6 | )] 7 | #![cfg_attr(docsrs, feature(doc_cfg))] 8 | #![deny(unsafe_code)] 9 | 10 | #[cfg(feature = "alloc")] 11 | extern crate alloc; 12 | 13 | pub(crate) mod decode; 14 | #[cfg(feature = "alloc")] 15 | pub use decode::parse_into_vec; 16 | pub use decode::{Header, parse_into_array}; 17 | 18 | #[cfg(feature = "alloc")] 19 | mod encode; 20 | #[cfg(feature = "alloc")] 21 | pub use encode::encode_blobs; 22 | 23 | /// Error type used by `blobby` functions 24 | #[derive(Debug, Eq, PartialEq, Copy, Clone)] 25 | pub enum Error { 26 | /// Decoded VLQ number is too big 27 | InvalidVlq, 28 | /// Invalid de-duplicated blob index 29 | InvalidIndex, 30 | /// Unexpected end of data 31 | UnexpectedEnd, 32 | /// Not enough elements for `BlobNIterator` 33 | NotEnoughElements, 34 | /// Bad array length was provided to [`parse_as_array`] 35 | BadArrayLen, 36 | } 37 | 38 | const NEXT_MASK: u8 = 0b1000_0000; 39 | const VAL_MASK: u8 = 0b0111_1111; 40 | -------------------------------------------------------------------------------- /.github/workflows/digest-io.yml: -------------------------------------------------------------------------------- 1 | name: digest-io 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "digest-io/**" 7 | - "Cargo.*" 8 | push: 9 | branches: master 10 | 11 | permissions: 12 | contents: read 13 | 14 | defaults: 15 | run: 16 | working-directory: digest-io 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | 22 | # Cancels CI jobs when new commits are pushed to a PR branch 23 | concurrency: 24 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 25 | cancel-in-progress: true 26 | 27 | jobs: 28 | minimal-versions: 29 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 30 | with: 31 | working-directory: ${{ github.workflow }} 32 | 33 | test: 34 | runs-on: ubuntu-latest 35 | strategy: 36 | matrix: 37 | rust: 38 | - 1.85.0 # MSRV 39 | - stable 40 | steps: 41 | - uses: actions/checkout@v6 42 | - uses: RustCrypto/actions/cargo-cache@master 43 | - uses: dtolnay/rust-toolchain@master 44 | with: 45 | toolchain: ${{ matrix.rust }} 46 | - run: cargo test --no-default-features 47 | - run: cargo test 48 | - run: cargo test --all-features 49 | -------------------------------------------------------------------------------- /opaque-debug/tests/mod.rs: -------------------------------------------------------------------------------- 1 | #![allow(dead_code)] 2 | 3 | struct Foo { 4 | secret: u64, 5 | } 6 | 7 | opaque_debug::implement!(Foo); 8 | 9 | struct FooGeneric { 10 | secret: u64, 11 | generic: T, 12 | } 13 | 14 | opaque_debug::implement!(FooGeneric); 15 | 16 | struct FooManyGenerics { 17 | secret: u64, 18 | generic1: T, 19 | generic2: U, 20 | generic3: V, 21 | } 22 | 23 | opaque_debug::implement!(FooManyGenerics); 24 | 25 | #[test] 26 | fn debug_formatting() { 27 | let s = format!("{:?}", Foo { secret: 42 }); 28 | assert_eq!(s, "Foo { ... }"); 29 | } 30 | 31 | #[test] 32 | fn debug_formatting_generic() { 33 | let s = format!( 34 | "{:?}", 35 | FooGeneric::<()> { 36 | secret: 42, 37 | generic: () 38 | } 39 | ); 40 | assert_eq!(s, "FooGeneric<()> { ... }"); 41 | } 42 | 43 | #[test] 44 | fn debug_formatting_many_generics() { 45 | let s = format!( 46 | "{:?}", 47 | FooManyGenerics::<(), u8, &str> { 48 | secret: 42, 49 | generic1: (), 50 | generic2: 0u8, 51 | generic3: "hello", 52 | } 53 | ); 54 | assert_eq!(s, "FooManyGenerics<(), u8, &str> { ... }"); 55 | } 56 | -------------------------------------------------------------------------------- /zeroize/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "zeroize" 3 | version = "1.9.0-pre" 4 | authors = ["The RustCrypto Project Developers"] 5 | edition = "2024" 6 | rust-version = "1.85" 7 | documentation = "https://docs.rs/zeroize" 8 | readme = "README.md" 9 | repository = "https://github.com/RustCrypto/utils" 10 | license = "Apache-2.0 OR MIT" 11 | keywords = ["memory", "memset", "secure", "volatile", "zero"] 12 | categories = ["cryptography", "memory-management", "no-std", "os"] 13 | description = """ 14 | Securely clear secrets from memory with a simple trait built on 15 | stable Rust primitives which guarantee memory is zeroed using an 16 | operation will not be 'optimized away' by the compiler. 17 | Uses a portable pure Rust implementation that works everywhere, 18 | even WASM! 19 | """ 20 | 21 | [dependencies] 22 | serde = { version = "1.0", default-features = false, optional = true } 23 | zeroize_derive = { version = "1.4", path = "../zeroize_derive", optional = true } 24 | 25 | [features] 26 | default = ["alloc"] 27 | alloc = [] 28 | std = ["alloc"] 29 | 30 | aarch64 = [] # NOTE: vestigial no-op feature; AArch64 support is always enabled now 31 | derive = ["zeroize_derive"] 32 | simd = [] # NOTE: MSRV 1.72 33 | 34 | [package.metadata.docs.rs] 35 | all-features = true 36 | -------------------------------------------------------------------------------- /.github/workflows/blobby.yml: -------------------------------------------------------------------------------- 1 | name: blobby 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "blobby/**" 7 | - "Cargo.*" 8 | push: 9 | branches: master 10 | 11 | permissions: 12 | contents: read 13 | 14 | defaults: 15 | run: 16 | working-directory: blobby 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | 22 | # Cancels CI jobs when new commits are pushed to a PR branch 23 | concurrency: 24 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 25 | cancel-in-progress: true 26 | 27 | jobs: 28 | test: 29 | runs-on: ubuntu-latest 30 | strategy: 31 | matrix: 32 | rust: 33 | - 1.85.0 # MSRV 34 | - stable 35 | steps: 36 | - uses: actions/checkout@v6 37 | - uses: RustCrypto/actions/cargo-cache@master 38 | - uses: dtolnay/rust-toolchain@master 39 | with: 40 | toolchain: ${{ matrix.rust }} 41 | # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates 42 | - run: rm ../Cargo.toml 43 | - run: cargo test 44 | 45 | minimal-versions: 46 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 47 | with: 48 | working-directory: ${{ github.workflow }} 49 | -------------------------------------------------------------------------------- /.github/workflows/workspace.yml: -------------------------------------------------------------------------------- 1 | name: Workspace 2 | 3 | on: 4 | pull_request: 5 | paths-ignore: 6 | - README.md 7 | push: 8 | branches: master 9 | paths-ignore: 10 | - README.md 11 | 12 | permissions: 13 | contents: read 14 | 15 | # Cancels CI jobs when new commits are pushed to a PR branch 16 | concurrency: 17 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 18 | cancel-in-progress: true 19 | 20 | jobs: 21 | clippy: 22 | runs-on: ubuntu-latest 23 | steps: 24 | - uses: actions/checkout@v6 25 | - uses: RustCrypto/actions/cargo-cache@master 26 | - uses: dtolnay/rust-toolchain@master 27 | with: 28 | toolchain: 1.92.0 # Pinned to prevent breakages 29 | components: clippy 30 | - run: cargo clippy --workspace --all-features --lib --bins --tests -- -D warnings 31 | 32 | rustfmt: 33 | runs-on: ubuntu-latest 34 | steps: 35 | - uses: actions/checkout@v6 36 | - uses: dtolnay/rust-toolchain@master 37 | with: 38 | toolchain: stable 39 | components: rustfmt 40 | - run: cargo fmt --all -- --check 41 | 42 | typos: 43 | runs-on: ubuntu-latest 44 | steps: 45 | - uses: actions/checkout@v6 46 | - uses: crate-ci/typos@v1 47 | -------------------------------------------------------------------------------- /blobby/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.4.0 (2025-10-08) 8 | ### Changed 9 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 10 | - Replaced iterators with `const fn` parsing ([#1187]) 11 | - Format of the file. File header now contains total number of stored blobs. ([#1207]) 12 | 13 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 14 | [#1187]: https://github.com/RustCrypto/utils/pull/1187 15 | [#1207]: https://github.com/RustCrypto/utils/pull/1207 16 | 17 | ## 0.3.1 (2021-12-07) 18 | ### Added 19 | - `encode_blobs` function ([#280]) 20 | 21 | [#280]: https://github.com/RustCrypto/utils/pull/280 22 | 23 | ## 0.3.0 (2020-07-01) 24 | ### Changed 25 | - New storage format with de-duplication capability ([#64]) 26 | 27 | [#64]: https://github.com/RustCrypto/utils/pull/64 28 | 29 | ## 0.2.0 (2020-06-13) 30 | ### Added 31 | - `Blob5Iterator` 32 | 33 | ### Changed 34 | - Bumped MSRV to 1.34. 35 | - Removed `byteorder` from non-dev dependencies. 36 | 37 | ## 0.1.2 (2019-01-28) 38 | 39 | ## 0.1.1 (2018-09-26) 40 | 41 | ## 0.1.0 (2018-09-26) 42 | - Initial release 43 | -------------------------------------------------------------------------------- /zeroize_derive/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: `zeroize_derive` 2 | 3 | [![Crate][crate-image]][crate-link] 4 | ![Apache 2.0 Licensed/MIT][license-image] 5 | ![MSRV][rustc-image] 6 | [![Build Status][build-image]][build-link] 7 | 8 | Custom derive support for [zeroize]: a crate for securely zeroing memory 9 | while avoiding compiler optimizations. 10 | 11 | This crate isn't intended to be used directly. 12 | See [zeroize] crate for documentation. 13 | 14 | ## License 15 | 16 | Licensed under either of: 17 | 18 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 19 | * [MIT license](http://opensource.org/licenses/MIT) 20 | 21 | at your option. 22 | 23 | ### Contribution 24 | 25 | Unless you explicitly state otherwise, any contribution intentionally submitted 26 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 27 | dual licensed as above, without any additional terms or conditions. 28 | 29 | [//]: # (badges) 30 | 31 | [crate-image]: https://img.shields.io/crates/v/zeroize_derive.svg 32 | [crate-link]: https://crates.io/crates/zeroize_derive 33 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 34 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 35 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/zeroize.yml/badge.svg?branch=master 36 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/zeroize.yml?query=branch:master 37 | 38 | [//]: # (general links) 39 | 40 | [RustCrypto]: https://github.com/RustCrypto 41 | [zeroize]: https://github.com/RustCrypto/utils/tree/master/zeroize 42 | -------------------------------------------------------------------------------- /ctutils/src/traits/ct_gt.rs: -------------------------------------------------------------------------------- 1 | use crate::Choice; 2 | use core::cmp; 3 | 4 | /// Constant time greater than. 5 | pub trait CtGt { 6 | /// Compute whether `self > other` in constant time. 7 | fn ct_gt(&self, other: &Self) -> Choice; 8 | } 9 | 10 | // Impl `CtGt` using overflowing subtraction 11 | macro_rules! impl_unsigned_ct_gt { 12 | ( $($uint:ty),+ ) => { 13 | $( 14 | impl CtGt for $uint { 15 | #[inline] 16 | fn ct_gt(&self, other: &Self) -> Choice { 17 | let (_, overflow) = other.overflowing_sub(*self); 18 | Choice::new(overflow.into()) 19 | } 20 | } 21 | )+ 22 | }; 23 | } 24 | 25 | impl_unsigned_ct_gt!(u8, u16, u32, u64, u128); 26 | 27 | impl CtGt for cmp::Ordering { 28 | #[inline] 29 | fn ct_gt(&self, other: &Self) -> Choice { 30 | // No impl of `CtGt` for `i8`, so use `u8` 31 | let a = (*self as i8) + 1; 32 | let b = (*other as i8) + 1; 33 | (a as u8).ct_gt(&(b as u8)) 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::CtGt; 40 | use core::cmp::Ordering; 41 | 42 | #[test] 43 | fn ct_gt() { 44 | let a = 42u64; 45 | let b = 43u64; 46 | assert!(!a.ct_gt(&a).to_bool()); 47 | assert!(!a.ct_gt(&b).to_bool()); 48 | assert!(b.ct_gt(&a).to_bool()); 49 | } 50 | 51 | #[test] 52 | fn ordering() { 53 | assert!(!Ordering::Equal.ct_gt(&Ordering::Equal).to_bool()); 54 | assert!(!Ordering::Less.ct_gt(&Ordering::Greater).to_bool()); 55 | assert!(Ordering::Greater.ct_gt(&Ordering::Less).to_bool()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /ctutils/src/traits/ct_lt.rs: -------------------------------------------------------------------------------- 1 | use crate::Choice; 2 | use core::cmp; 3 | 4 | /// Constant time less than. 5 | pub trait CtLt { 6 | /// Compute whether `self < other` in constant time. 7 | fn ct_lt(&self, other: &Self) -> Choice; 8 | } 9 | 10 | // Impl `CtLt` using overflowing subtraction 11 | macro_rules! impl_unsigned_ct_lt { 12 | ( $($uint:ty),+ ) => { 13 | $( 14 | impl CtLt for $uint { 15 | #[inline] 16 | fn ct_lt(&self, other: &Self) -> Choice { 17 | let (_, overflow) = self.overflowing_sub(*other); 18 | Choice::new(overflow.into()) 19 | } 20 | } 21 | )+ 22 | }; 23 | } 24 | 25 | impl_unsigned_ct_lt!(u8, u16, u32, u64, u128); 26 | 27 | impl CtLt for cmp::Ordering { 28 | #[inline] 29 | fn ct_lt(&self, other: &Self) -> Choice { 30 | // No impl of `CtLt` for `i8`, so use `u8` 31 | let a = (*self as i8) + 1; 32 | let b = (*other as i8) + 1; 33 | (a as u8).ct_lt(&(b as u8)) 34 | } 35 | } 36 | 37 | #[cfg(test)] 38 | mod tests { 39 | use super::CtLt; 40 | use core::cmp::Ordering; 41 | 42 | #[test] 43 | fn ct_lt() { 44 | let a = 42u64; 45 | let b = 43u64; 46 | assert!(!a.ct_lt(&a).to_bool()); 47 | assert!(a.ct_lt(&b).to_bool()); 48 | assert!(!b.ct_lt(&a).to_bool()); 49 | } 50 | 51 | #[test] 52 | fn ordering() { 53 | assert!(!Ordering::Equal.ct_lt(&Ordering::Equal).to_bool()); 54 | assert!(Ordering::Less.ct_lt(&Ordering::Greater).to_bool()); 55 | assert!(!Ordering::Greater.ct_lt(&Ordering::Less).to_bool()); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /opaque-debug/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: Opaque Debug 2 | 3 | [![crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache2/MIT licensed][license-image] 7 | ![Rust Version][rustc-image] 8 | [![Project Chat][chat-image]][chat-link] 9 | 10 | Macro for opaque Debug trait implementation. 11 | 12 | ## License 13 | 14 | Licensed under either of: 15 | 16 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 17 | * [MIT license](http://opensource.org/licenses/MIT) 18 | 19 | at your option. 20 | 21 | ### Contribution 22 | 23 | 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. 24 | 25 | [//]: # (badges) 26 | 27 | [crate-image]: https://img.shields.io/crates/v/opaque-debug.svg 28 | [crate-link]: https://crates.io/crates/opaque-debug 29 | [docs-image]: https://docs.rs/opaque-debug/badge.svg 30 | [docs-link]: https://docs.rs/opaque-debug/ 31 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 32 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 33 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 34 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils 35 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/opaque-debug.yml/badge.svg?branch=master 36 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/opaque-debug.yml?query=branch:master 37 | 38 | [//]: # (general links) 39 | 40 | [RustCrypto]: https://github.com/rustcrypto 41 | -------------------------------------------------------------------------------- /inout/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: In/Out Ref Types 2 | 3 | [![crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache2/MIT licensed][license-image] 7 | ![Rust Version][rustc-image] 8 | [![Project Chat][chat-image]][chat-link] 9 | 10 | Custom reference types for code generic over in-place and buffer-to-buffer modes of operation. 11 | 12 | ## License 13 | 14 | Licensed under either of: 15 | 16 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 17 | * [MIT license](http://opensource.org/licenses/MIT) 18 | 19 | at your option. 20 | 21 | ### Contribution 22 | 23 | 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. 24 | 25 | [//]: # (badges) 26 | 27 | [crate-image]: https://img.shields.io/crates/v/inout.svg 28 | [crate-link]: https://crates.io/crates/inout 29 | [docs-image]: https://docs.rs/inout/badge.svg 30 | [docs-link]: https://docs.rs/inout/ 31 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 32 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 33 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 34 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils 35 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/inout.yml/badge.svg?branch=master 36 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/inout.yml?query=branch:master 37 | 38 | [//]: # (general links) 39 | 40 | [RustCrypto]: https://github.com/rustcrypto 41 | -------------------------------------------------------------------------------- /block-buffer/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: Block Buffer 2 | 3 | [![crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache2/MIT licensed][license-image] 7 | ![Rust Version][rustc-image] 8 | [![Project Chat][chat-image]][chat-link] 9 | 10 | Buffer type for block processing of data with minimized amount of unreachable panics. 11 | 12 | ## License 13 | 14 | Licensed under either of: 15 | 16 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 17 | * [MIT license](http://opensource.org/licenses/MIT) 18 | 19 | at your option. 20 | 21 | ### Contribution 22 | 23 | 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. 24 | 25 | [//]: # (badges) 26 | 27 | [crate-image]: https://img.shields.io/crates/v/block-buffer.svg 28 | [crate-link]: https://crates.io/crates/block-buffer 29 | [docs-image]: https://docs.rs/block-buffer/badge.svg 30 | [docs-link]: https://docs.rs/block-buffer/ 31 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 32 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 33 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 34 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils 35 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/block-buffer.yml/badge.svg?branch=master 36 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/block-buffer.yml?query=branch:master 37 | 38 | [//]: # (general links) 39 | 40 | [RustCrypto]: https://github.com/rustcrypto 41 | -------------------------------------------------------------------------------- /.github/workflows/dbl.yml: -------------------------------------------------------------------------------- 1 | name: dbl 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/dbl.yml" 7 | - "dbl/**" 8 | - "Cargo.*" 9 | push: 10 | branches: master 11 | 12 | permissions: 13 | contents: read 14 | 15 | defaults: 16 | run: 17 | working-directory: dbl 18 | 19 | env: 20 | CARGO_INCREMENTAL: 0 21 | RUSTFLAGS: "-Dwarnings" 22 | 23 | # Cancels CI jobs when new commits are pushed to a PR branch 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | build: 30 | runs-on: ubuntu-latest 31 | strategy: 32 | matrix: 33 | rust: 34 | - 1.85.0 # MSRV 35 | - stable 36 | target: 37 | - thumbv7em-none-eabi 38 | - wasm32-unknown-unknown 39 | steps: 40 | - uses: actions/checkout@v6 41 | - uses: RustCrypto/actions/cargo-cache@master 42 | - uses: dtolnay/rust-toolchain@master 43 | with: 44 | toolchain: ${{ matrix.rust }} 45 | targets: ${{ matrix.target }} 46 | - run: cargo build --target ${{ matrix.target }} 47 | 48 | minimal-versions: 49 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 50 | with: 51 | working-directory: ${{ github.workflow }} 52 | 53 | test: 54 | runs-on: ubuntu-latest 55 | strategy: 56 | matrix: 57 | rust: 58 | - 1.85.0 # MSRV 59 | - stable 60 | steps: 61 | - uses: actions/checkout@v6 62 | - uses: RustCrypto/actions/cargo-cache@master 63 | - uses: dtolnay/rust-toolchain@master 64 | with: 65 | toolchain: ${{ matrix.rust }} 66 | - run: cargo test 67 | -------------------------------------------------------------------------------- /.github/workflows/block-padding.yml: -------------------------------------------------------------------------------- 1 | name: block-padding 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "block-padding/**" 7 | - "Cargo.*" 8 | push: 9 | branches: master 10 | 11 | permissions: 12 | contents: read 13 | 14 | defaults: 15 | run: 16 | working-directory: block-padding 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | 22 | # Cancels CI jobs when new commits are pushed to a PR branch 23 | concurrency: 24 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 25 | cancel-in-progress: true 26 | 27 | jobs: 28 | build: 29 | runs-on: ubuntu-latest 30 | strategy: 31 | matrix: 32 | rust: 33 | - 1.85.0 # MSRV 34 | - stable 35 | target: 36 | - thumbv7em-none-eabi 37 | - wasm32-unknown-unknown 38 | steps: 39 | - uses: actions/checkout@v6 40 | - uses: RustCrypto/actions/cargo-cache@master 41 | - uses: dtolnay/rust-toolchain@master 42 | with: 43 | toolchain: ${{ matrix.rust }} 44 | targets: ${{ matrix.target }} 45 | - run: cargo build --target ${{ matrix.target }} 46 | 47 | minimal-versions: 48 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 49 | with: 50 | working-directory: ${{ github.workflow }} 51 | 52 | test: 53 | runs-on: ubuntu-latest 54 | strategy: 55 | matrix: 56 | rust: 57 | - 1.85.0 # MSRV 58 | - stable 59 | steps: 60 | - uses: actions/checkout@v6 61 | - uses: RustCrypto/actions/cargo-cache@master 62 | - uses: dtolnay/rust-toolchain@master 63 | with: 64 | toolchain: ${{ matrix.rust }} 65 | - run: cargo test 66 | -------------------------------------------------------------------------------- /inout/src/errors.rs: -------------------------------------------------------------------------------- 1 | use core::fmt; 2 | 3 | /// The error returned when slice can not be converted into array. 4 | #[derive(Copy, Clone, Debug)] 5 | pub struct IntoArrayError; 6 | 7 | impl fmt::Display for IntoArrayError { 8 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { 9 | f.write_str("Failed to convert into array.") 10 | } 11 | } 12 | 13 | impl core::error::Error for IntoArrayError {} 14 | 15 | /// The error returned when input and output slices have different length 16 | /// and thus can not be converted to `InOutBuf`. 17 | #[derive(Copy, Clone, Debug)] 18 | pub struct NotEqualError; 19 | 20 | impl fmt::Display for NotEqualError { 21 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { 22 | f.write_str("Length of input slices is not equal to each other") 23 | } 24 | } 25 | 26 | impl core::error::Error for NotEqualError {} 27 | 28 | /// Padding error. Usually emitted when size of output buffer is insufficient. 29 | #[cfg(feature = "block-padding")] 30 | #[derive(Clone, Copy, Debug)] 31 | pub struct PadError; 32 | 33 | #[cfg(feature = "block-padding")] 34 | impl fmt::Display for PadError { 35 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { 36 | f.write_str("Padding error") 37 | } 38 | } 39 | 40 | #[cfg(feature = "block-padding")] 41 | impl core::error::Error for PadError {} 42 | 43 | /// Output buffer is smaller than input buffer. 44 | #[derive(Clone, Copy, Debug)] 45 | pub struct OutIsTooSmallError; 46 | 47 | impl fmt::Display for OutIsTooSmallError { 48 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { 49 | f.write_str("Output buffer is smaller than input") 50 | } 51 | } 52 | 53 | impl core::error::Error for OutIsTooSmallError {} 54 | -------------------------------------------------------------------------------- /.github/workflows/block-buffer.yml: -------------------------------------------------------------------------------- 1 | name: block-buffer 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "block-buffer/**" 7 | - "Cargo.*" 8 | push: 9 | branches: master 10 | 11 | permissions: 12 | contents: read 13 | 14 | defaults: 15 | run: 16 | working-directory: block-buffer 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | 22 | # Cancels CI jobs when new commits are pushed to a PR branch 23 | concurrency: 24 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 25 | cancel-in-progress: true 26 | 27 | jobs: 28 | build: 29 | runs-on: ubuntu-latest 30 | strategy: 31 | matrix: 32 | rust: 33 | - 1.85.0 # MSRV 34 | - stable 35 | target: 36 | - thumbv7em-none-eabi 37 | - wasm32-unknown-unknown 38 | steps: 39 | - uses: actions/checkout@v6 40 | - uses: RustCrypto/actions/cargo-cache@master 41 | - uses: dtolnay/rust-toolchain@master 42 | with: 43 | toolchain: ${{ matrix.rust }} 44 | targets: ${{ matrix.target }} 45 | - run: cargo build --target ${{ matrix.target }} 46 | 47 | minimal-versions: 48 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 49 | with: 50 | working-directory: ${{ github.workflow }} 51 | 52 | test: 53 | runs-on: ubuntu-latest 54 | strategy: 55 | matrix: 56 | rust: 57 | - 1.85.0 # MSRV 58 | - stable 59 | steps: 60 | - uses: actions/checkout@v6 61 | - uses: RustCrypto/actions/cargo-cache@master 62 | - uses: dtolnay/rust-toolchain@master 63 | with: 64 | toolchain: ${{ matrix.rust }} 65 | - run: cargo test 66 | - run: cargo test --all-features 67 | -------------------------------------------------------------------------------- /block-padding/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: Block Padding 2 | 3 | [![crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache2/MIT licensed][license-image] 7 | ![Rust Version][rustc-image] 8 | [![Project Chat][chat-image]][chat-link] 9 | 10 | Padding and unpadding of messages divided into blocks. 11 | 12 | This crate provides the `Padding` trait with padding and unpadding methods. 13 | Additionally, several common padding schemes are available out of the box. 14 | 15 | ## License 16 | 17 | Licensed under either of: 18 | 19 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 20 | * [MIT license](http://opensource.org/licenses/MIT) 21 | 22 | at your option. 23 | 24 | ### Contribution 25 | 26 | 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. 27 | 28 | [//]: # (badges) 29 | 30 | [crate-image]: https://img.shields.io/crates/v/block-padding.svg 31 | [crate-link]: https://crates.io/crates/block-padding 32 | [docs-image]: https://docs.rs/block-padding/badge.svg 33 | [docs-link]: https://docs.rs/block-padding/ 34 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 35 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 36 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 37 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils 38 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/block-padding.yml/badge.svg?branch=master 39 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/block-padding.yml?query=branch:master 40 | 41 | [//]: # (general links) 42 | 43 | [RustCrypto]: https://github.com/rustcrypto 44 | -------------------------------------------------------------------------------- /wycheproof2blb/src/aes_siv.rs: -------------------------------------------------------------------------------- 1 | use crate::TestInfo; 2 | use crate::wycheproof; 3 | use crate::wycheproof::{case_result, description, hex_string}; 4 | use serde::Deserialize; 5 | 6 | #[derive(Debug, Deserialize)] 7 | struct TestSuite { 8 | #[serde(flatten)] 9 | pub suite: wycheproof::Suite, 10 | #[serde(rename = "testGroups")] 11 | pub test_groups: Vec, 12 | } 13 | 14 | #[derive(Debug, Deserialize)] 15 | struct TestGroup { 16 | #[allow(dead_code)] 17 | #[serde(flatten)] 18 | pub group: wycheproof::Group, 19 | #[serde(rename = "keySize")] 20 | pub key_size: u32, 21 | pub tests: Vec, 22 | } 23 | 24 | #[derive(Debug, Deserialize)] 25 | struct TestCase { 26 | #[serde(flatten)] 27 | pub case: wycheproof::Case, 28 | #[serde(with = "hex_string")] 29 | pub key: Vec, 30 | #[serde(with = "hex_string")] 31 | pub aad: Vec, 32 | #[serde(with = "hex_string")] 33 | pub msg: Vec, 34 | #[serde(with = "hex_string")] 35 | pub ct: Vec, 36 | } 37 | 38 | pub fn generator(data: &[u8], algorithm: &str, key_size: u32) -> Vec { 39 | let suite: TestSuite = serde_json::from_slice(data).unwrap(); 40 | assert_eq!(algorithm, suite.suite.algorithm); 41 | 42 | let mut infos = vec![]; 43 | for g in &suite.test_groups { 44 | if key_size != 0 && g.key_size != key_size { 45 | continue; 46 | } 47 | for tc in &g.tests { 48 | infos.push(TestInfo { 49 | data: vec![ 50 | tc.key.clone(), 51 | tc.aad.clone(), 52 | tc.msg.clone(), 53 | tc.ct.clone(), 54 | vec![case_result(&tc.case)], 55 | ], 56 | desc: description(&suite.suite, &tc.case), 57 | }); 58 | } 59 | } 60 | infos 61 | } 62 | -------------------------------------------------------------------------------- /.github/workflows/inout.yml: -------------------------------------------------------------------------------- 1 | name: inout 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "inout/**" 7 | - "Cargo.*" 8 | push: 9 | branches: master 10 | 11 | permissions: 12 | contents: read 13 | 14 | defaults: 15 | run: 16 | working-directory: inout 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | 22 | # Cancels CI jobs when new commits are pushed to a PR branch 23 | concurrency: 24 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 25 | cancel-in-progress: true 26 | 27 | jobs: 28 | build: 29 | runs-on: ubuntu-latest 30 | strategy: 31 | matrix: 32 | rust: 33 | - 1.85.0 # MSRV 34 | - stable 35 | target: 36 | - thumbv7em-none-eabi 37 | - wasm32-unknown-unknown 38 | steps: 39 | - uses: actions/checkout@v6 40 | - uses: RustCrypto/actions/cargo-cache@master 41 | - uses: dtolnay/rust-toolchain@master 42 | with: 43 | toolchain: ${{ matrix.rust }} 44 | targets: ${{ matrix.target }} 45 | - run: cargo build --target ${{ matrix.target }} 46 | - run: cargo build --features block-padding --target ${{ matrix.target }} 47 | 48 | minimal-versions: 49 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 50 | with: 51 | working-directory: ${{ github.workflow }} 52 | 53 | test: 54 | runs-on: ubuntu-latest 55 | strategy: 56 | matrix: 57 | rust: 58 | - 1.85.0 # MSRV 59 | - stable 60 | steps: 61 | - uses: actions/checkout@v6 62 | - uses: RustCrypto/actions/cargo-cache@master 63 | - uses: dtolnay/rust-toolchain@master 64 | with: 65 | toolchain: ${{ matrix.rust }} 66 | - run: cargo test 67 | - run: cargo test --features block-padding 68 | - run: cargo test --all-features 69 | -------------------------------------------------------------------------------- /blobby/src/bin/decode.rs: -------------------------------------------------------------------------------- 1 | //! Encoding utility 2 | use std::error::Error; 3 | 4 | #[cfg(not(feature = "alloc"))] 5 | fn main() -> Result<(), Box> { 6 | Err("The decode binary should be compiled with enabled `alloc` feature!".into()) 7 | } 8 | 9 | #[cfg(feature = "alloc")] 10 | fn main() -> Result<(), Box> { 11 | use std::io::{self, BufRead, BufReader, BufWriter, Write}; 12 | use std::{env, fs::File}; 13 | 14 | fn encode_hex(data: &[u8]) -> String { 15 | let mut res = String::with_capacity(2 * data.len()); 16 | for &byte in data { 17 | res.push_str(&format!("{byte:02X}")); 18 | } 19 | res 20 | } 21 | 22 | fn decode(mut reader: R, mut writer: W) -> io::Result { 23 | let mut data = Vec::new(); 24 | reader.read_to_end(&mut data)?; 25 | let res = blobby::parse_into_vec(&data).map_err(|e| { 26 | io::Error::new( 27 | io::ErrorKind::InvalidData, 28 | format!("invalid blobby data: {e:?}"), 29 | ) 30 | })?; 31 | let len = res.len(); 32 | for blob in res { 33 | writer.write_all(encode_hex(blob).as_bytes())?; 34 | writer.write_all(b"\n")?; 35 | } 36 | Ok(len) 37 | } 38 | 39 | let args: Vec = env::args().skip(1).collect(); 40 | 41 | if args.is_empty() { 42 | println!( 43 | "Blobby decoding utility.\n\ 44 | Usage: decode " 45 | ); 46 | return Ok(()); 47 | } 48 | 49 | let in_path = args[0].as_str(); 50 | let out_path = args[1].as_str(); 51 | let in_file = BufReader::new(File::open(in_path)?); 52 | let out_file = BufWriter::new(File::create(out_path)?); 53 | 54 | let n = decode(in_file, out_file)?; 55 | println!("Processed {n} record(s)"); 56 | 57 | Ok(()) 58 | } 59 | -------------------------------------------------------------------------------- /wycheproof2blb/src/ed25519.rs: -------------------------------------------------------------------------------- 1 | use crate::TestInfo; 2 | use crate::wycheproof; 3 | use crate::wycheproof::{case_result, description, hex_string}; 4 | use serde::Deserialize; 5 | 6 | #[derive(Debug, Deserialize)] 7 | struct TestSuite { 8 | #[serde(flatten)] 9 | pub suite: wycheproof::Suite, 10 | #[serde(rename = "testGroups")] 11 | pub test_groups: Vec, 12 | } 13 | 14 | #[derive(Debug, Deserialize)] 15 | struct TestGroup { 16 | #[allow(dead_code)] 17 | #[serde(flatten)] 18 | pub group: wycheproof::Group, 19 | #[allow(dead_code)] 20 | #[serde(rename = "keyDer")] 21 | pub key_der: String, 22 | #[allow(dead_code)] 23 | #[serde(rename = "keyPem")] 24 | pub key_pem: String, 25 | pub key: TestKey, 26 | pub tests: Vec, 27 | } 28 | 29 | #[derive(Debug, Deserialize)] 30 | struct TestKey { 31 | #[serde(with = "hex_string")] 32 | sk: Vec, 33 | #[serde(with = "hex_string")] 34 | pk: Vec, 35 | } 36 | 37 | #[derive(Debug, Deserialize)] 38 | struct TestCase { 39 | #[serde(flatten)] 40 | pub case: wycheproof::Case, 41 | #[serde(with = "hex_string")] 42 | pub msg: Vec, 43 | #[serde(with = "hex_string")] 44 | pub sig: Vec, 45 | } 46 | 47 | pub fn generator(data: &[u8], algorithm: &str, _key_size: u32) -> Vec { 48 | let suite: TestSuite = serde_json::from_slice(data).unwrap(); 49 | assert_eq!(algorithm, suite.suite.algorithm); 50 | 51 | let mut infos = vec![]; 52 | for g in &suite.test_groups { 53 | for tc in &g.tests { 54 | infos.push(TestInfo { 55 | data: vec![ 56 | g.key.sk.clone(), 57 | g.key.pk.clone(), 58 | tc.msg.clone(), 59 | tc.sig.clone(), 60 | vec![case_result(&tc.case)], 61 | ], 62 | desc: description(&suite.suite, &tc.case), 63 | }); 64 | } 65 | } 66 | infos 67 | } 68 | -------------------------------------------------------------------------------- /.github/workflows/hex-literal.yml: -------------------------------------------------------------------------------- 1 | name: hex-literal 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "hex-literal/**" 7 | - "Cargo.*" 8 | push: 9 | branches: master 10 | 11 | permissions: 12 | contents: read 13 | 14 | defaults: 15 | run: 16 | working-directory: hex-literal 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | 22 | # Cancels CI jobs when new commits are pushed to a PR branch 23 | concurrency: 24 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 25 | cancel-in-progress: true 26 | 27 | jobs: 28 | build: 29 | runs-on: ubuntu-latest 30 | strategy: 31 | matrix: 32 | rust: 33 | - 1.85.0 # MSRV 34 | - stable 35 | target: 36 | - thumbv7em-none-eabi 37 | - wasm32-unknown-unknown 38 | steps: 39 | - uses: actions/checkout@v6 40 | - uses: RustCrypto/actions/cargo-cache@master 41 | - uses: dtolnay/rust-toolchain@master 42 | with: 43 | toolchain: ${{ matrix.rust }} 44 | targets: ${{ matrix.target }} 45 | # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates 46 | - run: rm ../Cargo.toml 47 | - run: cargo build --target ${{ matrix.target }} 48 | 49 | minimal-versions: 50 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 51 | with: 52 | working-directory: ${{ github.workflow }} 53 | 54 | test: 55 | runs-on: ubuntu-latest 56 | strategy: 57 | matrix: 58 | rust: 59 | - 1.85.0 # MSRV 60 | - stable 61 | steps: 62 | - uses: actions/checkout@v6 63 | - uses: RustCrypto/actions/cargo-cache@master 64 | - uses: dtolnay/rust-toolchain@master 65 | with: 66 | toolchain: ${{ matrix.rust }} 67 | # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates 68 | - run: rm ../Cargo.toml 69 | - run: cargo test 70 | -------------------------------------------------------------------------------- /.github/workflows/opaque-debug.yml: -------------------------------------------------------------------------------- 1 | name: opaque-debug 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "opaque-debug/**" 7 | - "Cargo.*" 8 | push: 9 | branches: master 10 | 11 | permissions: 12 | contents: read 13 | 14 | defaults: 15 | run: 16 | working-directory: opaque-debug 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | 22 | # Cancels CI jobs when new commits are pushed to a PR branch 23 | concurrency: 24 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 25 | cancel-in-progress: true 26 | 27 | jobs: 28 | build: 29 | runs-on: ubuntu-latest 30 | strategy: 31 | matrix: 32 | rust: 33 | - 1.85.0 # MSRV 34 | - stable 35 | target: 36 | - thumbv7em-none-eabi 37 | - wasm32-unknown-unknown 38 | steps: 39 | - uses: actions/checkout@v6 40 | - uses: RustCrypto/actions/cargo-cache@master 41 | - uses: dtolnay/rust-toolchain@master 42 | with: 43 | toolchain: ${{ matrix.rust }} 44 | targets: ${{ matrix.target }} 45 | # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates 46 | - run: rm ../Cargo.toml 47 | - run: cargo build --target ${{ matrix.target }} 48 | 49 | minimal-versions: 50 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 51 | with: 52 | working-directory: ${{ github.workflow }} 53 | 54 | test: 55 | runs-on: ubuntu-latest 56 | strategy: 57 | matrix: 58 | rust: 59 | - 1.85.0 # MSRV 60 | - stable 61 | steps: 62 | - uses: actions/checkout@v6 63 | - uses: RustCrypto/actions/cargo-cache@master 64 | - uses: dtolnay/rust-toolchain@master 65 | with: 66 | toolchain: ${{ matrix.rust }} 67 | # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates 68 | - run: rm ../Cargo.toml 69 | - run: cargo test 70 | -------------------------------------------------------------------------------- /zeroize/tests/alloc.rs: -------------------------------------------------------------------------------- 1 | use std::alloc::{GlobalAlloc, Layout, System}; 2 | 3 | use zeroize::Zeroize; 4 | 5 | // Allocator that ensures that deallocated data is zeroized. 6 | struct ProxyAllocator; 7 | 8 | unsafe impl GlobalAlloc for ProxyAllocator { 9 | unsafe fn alloc(&self, layout: Layout) -> *mut u8 { 10 | unsafe { System.alloc(layout) } 11 | } 12 | 13 | unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { 14 | if layout.size() == 160 { 15 | for i in 0..layout.size() { 16 | let b = unsafe { core::ptr::read(ptr.add(i)) }; 17 | if b != 0 { 18 | panic!() 19 | } 20 | } 21 | } 22 | 23 | unsafe { System.dealloc(ptr, layout) } 24 | } 25 | } 26 | 27 | #[global_allocator] 28 | static PROXY_ALLOCATOR: ProxyAllocator = ProxyAllocator; 29 | 30 | struct SecretBox(Box); 31 | 32 | impl SecretBox { 33 | fn new(val: S) -> Self { 34 | Self(Box::new(val)) 35 | } 36 | } 37 | 38 | impl Drop for SecretBox { 39 | fn drop(&mut self) { 40 | self.0.as_mut().zeroize() 41 | } 42 | } 43 | 44 | #[test] 45 | fn secret_box_alloc_test() { 46 | let b1 = SecretBox::new([u128::MAX; 10]); 47 | core::hint::black_box(&b1); 48 | let b2 = SecretBox::new([u8::MAX; 160]); 49 | core::hint::black_box(&b2); 50 | } 51 | 52 | struct ObserveSecretBox(Box); 53 | 54 | impl ObserveSecretBox { 55 | fn new(val: S) -> Self { 56 | Self(Box::new(val)) 57 | } 58 | } 59 | 60 | impl Drop for ObserveSecretBox { 61 | fn drop(&mut self) { 62 | *self.0 = Default::default(); 63 | zeroize::optimization_barrier(&self); 64 | } 65 | } 66 | 67 | #[test] 68 | fn observe_secret_box_alloc_test() { 69 | let b1 = ObserveSecretBox::new([u128::MAX; 10]); 70 | core::hint::black_box(&b1); 71 | let b2 = SecretBox::new([u8::MAX; 160]); 72 | core::hint::black_box(&b2); 73 | } 74 | -------------------------------------------------------------------------------- /hex-literal/tests/basic.rs: -------------------------------------------------------------------------------- 1 | use hex_literal::hex; 2 | 3 | #[test] 4 | fn single_literal() { 5 | assert_eq!(hex!("ff e4"), [0xff, 0xe4]); 6 | } 7 | 8 | #[test] 9 | fn empty() { 10 | let nothing: [u8; 0] = hex!(); 11 | let empty_literals: [u8; 0] = hex!("" "" ""); 12 | let expected: [u8; 0] = []; 13 | assert_eq!(nothing, expected); 14 | assert_eq!(empty_literals, expected); 15 | } 16 | 17 | #[test] 18 | fn upper_case() { 19 | assert_eq!(hex!("AE DF 04 B2"), [0xae, 0xdf, 0x04, 0xb2]); 20 | assert_eq!(hex!("FF BE 8C 00 01"), [0xff, 0xbe, 0x8c, 0x00, 0x01]); 21 | } 22 | 23 | #[test] 24 | fn mixed_case() { 25 | assert_eq!(hex!("bF dd E4 Cd"), [0xbf, 0xdd, 0xe4, 0xcd]); 26 | } 27 | 28 | #[test] 29 | fn multiple_literals() { 30 | assert_eq!( 31 | hex!( 32 | "01 dd f7 7f" 33 | "ee f0 d8" 34 | ), 35 | [0x01, 0xdd, 0xf7, 0x7f, 0xee, 0xf0, 0xd8] 36 | ); 37 | assert_eq!( 38 | hex!( 39 | "ff" 40 | "e8 d0" 41 | "" 42 | "01 1f" 43 | "ab" 44 | ), 45 | [0xff, 0xe8, 0xd0, 0x01, 0x1f, 0xab] 46 | ); 47 | } 48 | 49 | #[test] 50 | fn no_spacing() { 51 | assert_eq!(hex!("abf0d8bb0f14"), [0xab, 0xf0, 0xd8, 0xbb, 0x0f, 0x14]); 52 | assert_eq!( 53 | hex!("09FFd890cbcCd1d08F"), 54 | [0x09, 0xff, 0xd8, 0x90, 0xcb, 0xcc, 0xd1, 0xd0, 0x8f] 55 | ); 56 | } 57 | 58 | #[test] 59 | fn allows_various_spacing() { 60 | // newlines 61 | assert_eq!( 62 | hex!( 63 | "f 64 | f 65 | d 66 | 0 67 | e 68 | 69 | 8 70 | " 71 | ), 72 | [0xff, 0xd0, 0xe8] 73 | ); 74 | // tabs 75 | assert_eq!(hex!("9f d 1 f07 3 01 "), [0x9f, 0xd1, 0xf0, 0x73, 0x01]); 76 | // spaces 77 | assert_eq!(hex!(" e e d0 9 1 f f "), [0xee, 0xd0, 0x91, 0xff]); 78 | } 79 | 80 | #[test] 81 | fn can_use_const() { 82 | const _: [u8; 4] = hex!("ff d3 01 7f"); 83 | } 84 | -------------------------------------------------------------------------------- /inout/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.2.1 (2025-10-06) 8 | ### Changed 9 | - Migrate to fixed `Padding::pad_detached` from `block-padding` v0.4.1 ([#1227]) 10 | 11 | [#1227]: https://github.com/RustCrypto/utils/pull/1227 12 | 13 | ## 0.2.0 (2025-10-06) [YANKED] 14 | ### Changed 15 | - Migrated from `generic-array` to `hybrid-array` ([#944]) 16 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 17 | 18 | ### Added 19 | - `InOut::into_out` and `InOutBufReserved::into_out` methods ([#1132]) 20 | - `InOutBufReserved::split_reserved` method ([#1133]) 21 | - `InOut::into_out_with_copied_in` and `InOutBuf::into_out_with_copied_in` methods ([#1169]) 22 | 23 | [#944]: https://github.com/RustCrypto/utils/pull/944 24 | [#1132]: https://github.com/RustCrypto/utils/pull/1132 25 | [#1133]: https://github.com/RustCrypto/utils/pull/1133 26 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 27 | [#1169]: https://github.com/RustCrypto/utils/pull/1169 28 | 29 | ## 0.1.4 (2025-02-21) 30 | ### Fixed 31 | - Return output length from `InOutBufReserved::get_out_len` instead of input length ([#1150]) 32 | 33 | [#1150]: https://github.com/RustCrypto/utils/pull/1150 34 | 35 | ## 0.1.3 (2022-03-31) 36 | ### Fixed 37 | - MIRI error in `From` impl for `InOutBuf` ([#755]) 38 | 39 | [#755]: https://github.com/RustCrypto/utils/pull/755 40 | 41 | ## 0.1.2 (2022-02-10) 42 | ### Changed 43 | - Use borrow instead of consuming in `InOutBufReserved::get_*_len()` methods ([#734]) 44 | 45 | [#734]: https://github.com/RustCrypto/utils/pull/734 46 | 47 | ## 0.1.1 (2022-02-10) 48 | ### Fixed 49 | - Fix doc build on docs.rs by optionally enabling the `doc_cfg` feature ([#733]) 50 | 51 | [#733]: https://github.com/RustCrypto/utils/pull/733 52 | 53 | ## 0.1.0 (2022-02-10) 54 | - Initial release ([#675]) 55 | 56 | [#675]: https://github.com/RustCrypto/utils/pull/675 57 | -------------------------------------------------------------------------------- /dbl/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: Double operation in `GF(2^n)` 2 | 3 | [![crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache2/MIT licensed][license-image] 7 | ![Rust Version][rustc-image] 8 | [![Project Chat][chat-image]][chat-link] 9 | 10 | Double operation (a.k.a. "multiply-by-x") in Galois Field `GF(2^n)` using 11 | the lexicographically first polynomial among the irreducible degree `n` polynomials 12 | having a minimum number of coefficients. 13 | 14 | ## Minimum Supported Rust Version (MSRV) Policy 15 | 16 | MSRV increases are not considered breaking changes and can happen in patch 17 | releases. 18 | 19 | The crate MSRV accounts for all supported targets and crate feature 20 | combinations, excluding explicitly unstable features. 21 | 22 | ## License 23 | 24 | Licensed under either of: 25 | 26 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 27 | * [MIT license](http://opensource.org/licenses/MIT) 28 | 29 | at your option. 30 | 31 | ### Contribution 32 | 33 | 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. 34 | 35 | [//]: # (badges) 36 | 37 | [crate-image]: https://img.shields.io/crates/v/dbl.svg 38 | [crate-link]: https://crates.io/crates/dbl 39 | [docs-image]: https://docs.rs/dbl/badge.svg 40 | [docs-link]: https://docs.rs/dbl/ 41 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 42 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 43 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 44 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils 45 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/dbl.yml/badge.svg?branch=master 46 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/dbl.yml?query=branch:master 47 | 48 | [//]: # (general links) 49 | 50 | [RustCrypto]: https://github.com/rustcrypto 51 | -------------------------------------------------------------------------------- /.github/workflows/ctutils.yml: -------------------------------------------------------------------------------- 1 | name: ctutils 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/ctutils.yml" 7 | - "ctutils/**" 8 | - "Cargo.*" 9 | push: 10 | branches: master 11 | 12 | permissions: 13 | contents: read 14 | 15 | defaults: 16 | run: 17 | working-directory: ctutils 18 | 19 | env: 20 | CARGO_INCREMENTAL: 0 21 | RUSTFLAGS: "-Dwarnings" 22 | 23 | # Cancels CI jobs when new commits are pushed to a PR branch 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | build: 30 | runs-on: ubuntu-latest 31 | strategy: 32 | matrix: 33 | rust: 34 | - 1.85.0 # MSRV 35 | - stable 36 | target: 37 | - thumbv7em-none-eabi 38 | - wasm32-unknown-unknown 39 | steps: 40 | - uses: actions/checkout@v6 41 | - uses: RustCrypto/actions/cargo-cache@master 42 | - uses: dtolnay/rust-toolchain@master 43 | with: 44 | toolchain: ${{ matrix.rust }} 45 | targets: ${{ matrix.target }} 46 | - run: cargo build --target ${{ matrix.target }} 47 | 48 | minimal-versions: 49 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 50 | with: 51 | working-directory: ${{ github.workflow }} 52 | 53 | test: 54 | runs-on: ubuntu-latest 55 | strategy: 56 | matrix: 57 | rust: 58 | - 1.85.0 # MSRV 59 | - stable 60 | steps: 61 | - uses: actions/checkout@v6 62 | - uses: RustCrypto/actions/cargo-cache@master 63 | - uses: dtolnay/rust-toolchain@master 64 | with: 65 | toolchain: ${{ matrix.rust }} 66 | - run: cargo test 67 | - run: cargo test --all-features 68 | - run: cargo test --all-features --release 69 | 70 | # Test using `cargo careful` 71 | test-careful: 72 | runs-on: ubuntu-latest 73 | steps: 74 | - uses: actions/checkout@v6 75 | - uses: dtolnay/rust-toolchain@nightly 76 | - run: cargo install cargo-careful 77 | - run: cargo careful test --all-features 78 | -------------------------------------------------------------------------------- /aarch64-dit/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: AArch64 Data-Independent Timing (DIT) 2 | 3 | [![Crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache 2.0/MIT Licensed][license-image] 7 | ![MSRV][msrv-image] 8 | 9 | Wrappers for enabling/disabling the [Data-Independent Timing] feature of modern AArch64 CPUs which 10 | can be used to help ensure that instructions take a constant amount of time regardless of input 11 | data, thus preventing potential information leaks via timing sidechannels. 12 | 13 | [Documentation][docs-link] 14 | 15 | ## Minimum Supported Rust Version 16 | 17 | Rust **1.85** or newer. 18 | 19 | In the future, we reserve the right to change MSRV (i.e. MSRV is out-of-scope for this crate's 20 | SemVer guarantees), however when we do it will be accompanied by a minor version bump. 21 | 22 | ## License 23 | 24 | Licensed under either of: 25 | 26 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 27 | * [MIT license](http://opensource.org/licenses/MIT) 28 | 29 | at your option. 30 | 31 | ### Contribution 32 | 33 | Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the 34 | work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any 35 | additional terms or conditions. 36 | 37 | [//]: # (badges) 38 | 39 | [crate-image]: https://img.shields.io/crates/v/aarch64-dit.svg 40 | [crate-link]: https://crates.io/crates/aarch64-dit 41 | [docs-image]: https://docs.rs/aarch64-dit/badge.svg 42 | [docs-link]: https://docs.rs/aarch64-dit/ 43 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 44 | [msrv-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 45 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/aarch64-dit.yml/badge.svg?branch=master 46 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/aarch64-dit.yml?query=branch:master 47 | 48 | [//]: # (links) 49 | 50 | [RustCrypto]: https://github.com/RustCrypto 51 | [Data-Independent Timing]: https://developer.arm.com/documentation/ddi0595/2021-06/AArch64-Registers/DIT--Data-Independent-Timing 52 | -------------------------------------------------------------------------------- /wycheproof2blb/src/hkdf.rs: -------------------------------------------------------------------------------- 1 | use crate::TestInfo; 2 | use crate::wycheproof; 3 | use crate::wycheproof::{description, hex_string}; 4 | use serde::Deserialize; 5 | 6 | #[derive(Debug, Deserialize)] 7 | struct TestSuite { 8 | #[serde(flatten)] 9 | pub suite: wycheproof::Suite, 10 | #[serde(rename = "testGroups")] 11 | pub test_groups: Vec, 12 | } 13 | 14 | #[derive(Debug, Deserialize)] 15 | struct TestGroup { 16 | #[allow(dead_code)] 17 | #[serde(flatten)] 18 | pub group: wycheproof::Group, 19 | #[allow(dead_code)] 20 | #[serde(rename = "keySize")] 21 | pub key_size: u32, 22 | pub tests: Vec, 23 | } 24 | 25 | #[derive(Debug, Deserialize)] 26 | struct TestCase { 27 | #[serde(flatten)] 28 | pub case: wycheproof::Case, 29 | #[serde(with = "hex_string")] 30 | pub ikm: Vec, 31 | #[serde(with = "hex_string")] 32 | pub salt: Vec, 33 | #[serde(with = "hex_string")] 34 | pub info: Vec, 35 | pub size: usize, 36 | #[serde(with = "hex_string")] 37 | pub okm: Vec, 38 | } 39 | 40 | pub fn generator(data: &[u8], algorithm: &str, _key_size: u32) -> Vec { 41 | let suite: TestSuite = serde_json::from_slice(data).unwrap(); 42 | assert_eq!(algorithm, suite.suite.algorithm); 43 | 44 | let mut infos = vec![]; 45 | for g in &suite.test_groups { 46 | for tc in &g.tests { 47 | if tc.case.result != crate::wycheproof::CaseResult::Valid { 48 | continue; 49 | } 50 | if tc.okm.len() != tc.size { 51 | eprintln!( 52 | "Skipping case {} with size={} != okm.len()={}", 53 | tc.case.case_id, 54 | tc.size, 55 | tc.okm.len() 56 | ); 57 | } 58 | infos.push(TestInfo { 59 | data: vec![ 60 | tc.ikm.clone(), 61 | tc.salt.clone(), 62 | tc.info.clone(), 63 | tc.okm.clone(), 64 | ], 65 | desc: description(&suite.suite, &tc.case), 66 | }); 67 | } 68 | } 69 | infos 70 | } 71 | -------------------------------------------------------------------------------- /wycheproof2blb/src/mac.rs: -------------------------------------------------------------------------------- 1 | use crate::TestInfo; 2 | use crate::wycheproof; 3 | use crate::wycheproof::{CaseResult, description, hex_string}; 4 | use serde::Deserialize; 5 | 6 | #[derive(Debug, Deserialize)] 7 | pub struct TestSuite { 8 | #[serde(flatten)] 9 | pub suite: wycheproof::Suite, 10 | #[serde(rename = "testGroups")] 11 | pub test_groups: Vec, 12 | } 13 | 14 | #[derive(Debug, Deserialize)] 15 | pub struct TestGroup { 16 | #[serde(flatten)] 17 | pub group: wycheproof::Group, 18 | #[serde(rename = "keySize")] 19 | pub key_size: u32, 20 | #[serde(rename = "tagSize")] 21 | pub tag_size: u32, 22 | pub tests: Vec, 23 | } 24 | 25 | #[derive(Debug, Deserialize)] 26 | pub struct TestCase { 27 | #[serde(flatten)] 28 | pub case: wycheproof::Case, 29 | #[serde(with = "hex_string")] 30 | pub key: Vec, 31 | #[serde(with = "hex_string")] 32 | pub msg: Vec, 33 | #[serde(with = "hex_string")] 34 | pub tag: Vec, 35 | } 36 | 37 | pub fn generator(data: &[u8], algorithm: &str, key_size: u32) -> Vec { 38 | let suite: TestSuite = serde_json::from_slice(data).unwrap(); 39 | assert_eq!(algorithm, suite.suite.algorithm); 40 | 41 | let mut infos = vec![]; 42 | for g in &suite.test_groups { 43 | for tc in &g.tests { 44 | if key_size != 0 && g.key_size != key_size { 45 | continue; 46 | } 47 | if tc.case.result != CaseResult::Valid { 48 | // TODO: adapt HMAC tests for invalid cases 49 | continue; 50 | } 51 | assert_eq!(tc.key.len() * 8, g.key_size as usize); 52 | assert_eq!(g.tag_size % 8, 0); 53 | infos.push(TestInfo { 54 | data: vec![ 55 | tc.key.clone(), 56 | tc.msg.clone(), 57 | // `tc.tag` holds the MAC output truncated to `(g.tag_size / 8)` bytes 58 | // (when this is smaller than MAC output size) 59 | tc.tag.clone(), 60 | ], 61 | desc: description(&suite.suite, &tc.case), 62 | }); 63 | } 64 | } 65 | infos 66 | } 67 | -------------------------------------------------------------------------------- /cmov/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.4.1 (2025-12-19) 8 | ### Changed 9 | - Use `black_box` in portable impl ([#1255]) 10 | 11 | [#1255]: https://github.com/RustCrypto/utils/pull/1255 12 | 13 | ## 0.4.0 (2025-09-10) 14 | ### Changed 15 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 16 | 17 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 18 | 19 | ## 0.3.1 (2023-10-14) 20 | ### Added 21 | - `CmovEq` impl for slices ([#954]) 22 | 23 | ### Changed 24 | - Use `#[inline]` instead of `#[inline(always)]` ([#924]) 25 | - `CmovEq` now invokes XOR within the ASM block ([#925]) 26 | 27 | [#924]: https://github.com/RustCrypto/utils/pull/924 28 | [#925]: https://github.com/RustCrypto/utils/pull/925 29 | [#954]: https://github.com/RustCrypto/utils/pull/954 30 | 31 | ## 0.3.0 (2023-04-02) 32 | ### Added 33 | - `miri` support by forcing the `portable` backend ([#864]) 34 | - Constant-time equality comparisons ([#873]) 35 | 36 | ### Changed 37 | - Make `Cmov::cmovz` a provided method ([#871]) 38 | 39 | ### Fixed 40 | - Builds on `x86` (32-bit) targets ([#863]) 41 | 42 | [#863]: https://github.com/RustCrypto/utils/pull/863 43 | [#864]: https://github.com/RustCrypto/utils/pull/864 44 | [#871]: https://github.com/RustCrypto/utils/pull/871 45 | [#873]: https://github.com/RustCrypto/utils/pull/873 46 | 47 | ## 0.2.0 (2023-02-26) 48 | ### Added 49 | - `Condition` alias for `u8` ([#830]) 50 | 51 | ### Changed 52 | - Redesigned trait-based API ([#830]) 53 | - Built around a `Cmov` trait 54 | - Trait is impl'd for `u8`, `u16`, `u32`, `u64`, `u128` 55 | - Accepts a `Condition` (i.e. `u8`) as a predicate 56 | - MSRV 1.60 ([#839]) 57 | 58 | [#830]: https://github.com/RustCrypto/utils/pull/830 59 | [#839]: https://github.com/RustCrypto/utils/pull/839 60 | 61 | ## 0.1.1 (2022-03-02) 62 | ### Added 63 | - `cmovz`/`cmovnz`-alike support for AArch64 targets ([#744]) 64 | 65 | [#744]: https://github.com/RustCrypto/utils/pull/744 66 | 67 | ## 0.1.0 (2022-02-27) 68 | - Initial release 69 | -------------------------------------------------------------------------------- /hex-literal/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 1.1.0 (2025-10-29) 8 | ### Added 9 | - Colon-delimited literals support ([#1244]) 10 | 11 | [#1244]: https://github.com/RustCrypto/utils/pull/1244 12 | 13 | ## 1.0.0 (2025-02-22) 14 | ### Changed 15 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 16 | - Relax MSRV policy and allow MSRV bumps in patch releases 17 | 18 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 19 | 20 | ## 0.4.1 (2023-04-05) 21 | ### Changed 22 | - Enforce const evaluation ([#889]) 23 | 24 | [#889]: https://github.com/RustCrypto/utils/pull/889 25 | 26 | ## 0.4.0 (2023-04-02) 27 | ### Changed 28 | - Disallow comments inside hex strings ([#816]) 29 | - Migrate to 2021 edition and bump MSRV to 1.57 ([#816]) 30 | - Use CTFE instead of proc macro ([#816]) 31 | 32 | [#816]: https://github.com/RustCrypto/utils/pull/816 33 | 34 | ## 0.3.4 (2021-11-11) 35 | ### Changed 36 | - Provide more info in `panic!` messages ([#664]) 37 | - Minor changes in the comments filtration code ([#666]) 38 | 39 | ### Added 40 | - New tests for the `hex!()` macro and internal documentation ([#664]) 41 | 42 | ### Fixed 43 | - Make `hex!()` error when forward slash encountered as last byte ([#665]) 44 | 45 | [#664]: https://github.com/RustCrypto/utils/pull/664 46 | [#665]: https://github.com/RustCrypto/utils/pull/665 47 | [#666]: https://github.com/RustCrypto/utils/pull/666 48 | 49 | ## 0.3.3 (2021-07-17) 50 | ### Added 51 | - Accept sequence of string literals ([#519]) 52 | 53 | [#519]: https://github.com/RustCrypto/utils/pull/519 54 | 55 | ## 0.3.2 (2021-07-02) 56 | ### Added 57 | - Allow line (`//`) and block (`/* */`) comments ([#512]) 58 | 59 | [#512]: https://github.com/RustCrypto/utils/pull/512 60 | 61 | ## 0.3.1 (2020-08-01) 62 | ### Added 63 | - Documentation for the `hex!` macro ([#73]) 64 | 65 | [#73]: https://github.com/RustCrypto/utils/pull/73 66 | 67 | ## 0.3.0 (2020-07-16) 68 | ### Changed 69 | - MSRV bump to 1.45 ([#53]) 70 | 71 | [#53]: https://github.com/RustCrypto/utils/pull/53 72 | -------------------------------------------------------------------------------- /wycheproof2blb/src/ecdsa.rs: -------------------------------------------------------------------------------- 1 | use crate::TestInfo; 2 | use crate::wycheproof; 3 | use crate::wycheproof::{case_result, description, hex_string}; 4 | use serde::Deserialize; 5 | 6 | #[derive(Debug, Deserialize)] 7 | struct TestSuite { 8 | #[serde(flatten)] 9 | pub suite: wycheproof::Suite, 10 | #[serde(rename = "testGroups")] 11 | pub test_groups: Vec, 12 | } 13 | 14 | #[derive(Debug, Deserialize)] 15 | struct TestGroup { 16 | #[allow(dead_code)] 17 | #[serde(flatten)] 18 | pub group: wycheproof::Group, 19 | #[allow(dead_code)] 20 | #[serde(rename = "keyDer")] 21 | pub key_der: String, 22 | #[allow(dead_code)] 23 | #[serde(rename = "keyPem")] 24 | pub key_pem: String, 25 | pub sha: String, 26 | pub key: TestKey, 27 | pub tests: Vec, 28 | } 29 | 30 | #[derive(Debug, Deserialize)] 31 | struct TestKey { 32 | curve: String, 33 | #[allow(dead_code)] 34 | #[serde(rename = "type")] 35 | key_type: String, 36 | #[serde(with = "hex_string")] 37 | wx: Vec, 38 | #[serde(with = "hex_string")] 39 | wy: Vec, 40 | } 41 | 42 | #[derive(Debug, Deserialize)] 43 | struct TestCase { 44 | #[serde(flatten)] 45 | pub case: wycheproof::Case, 46 | #[serde(with = "hex_string")] 47 | pub msg: Vec, 48 | #[serde(with = "hex_string")] 49 | pub sig: Vec, 50 | } 51 | 52 | pub fn generator(data: &[u8], algorithm: &str, _key_size: u32) -> Vec { 53 | let suite: TestSuite = serde_json::from_slice(data).unwrap(); 54 | 55 | let mut infos = vec![]; 56 | for g in &suite.test_groups { 57 | assert!(algorithm.starts_with(&g.key.curve)); 58 | assert!(matches!( 59 | g.sha.as_str(), 60 | "SHA-224" | "SHA-256" | "SHA-384" | "SHA-512" 61 | )); 62 | for tc in &g.tests { 63 | if tc.case.result == crate::wycheproof::CaseResult::Acceptable { 64 | // TODO: figure out what to do with test cases that pass but which have weak params 65 | continue; 66 | } 67 | infos.push(TestInfo { 68 | data: vec![ 69 | g.key.wx.clone(), 70 | g.key.wy.clone(), 71 | tc.msg.clone(), 72 | tc.sig.clone(), 73 | vec![case_result(&tc.case)], 74 | ], 75 | desc: description(&suite.suite, &tc.case), 76 | }); 77 | } 78 | } 79 | infos 80 | } 81 | -------------------------------------------------------------------------------- /blobby/src/bin/encode.rs: -------------------------------------------------------------------------------- 1 | //! Encoding utility 2 | use std::error::Error; 3 | 4 | #[cfg(not(feature = "alloc"))] 5 | fn main() -> Result<(), Box> { 6 | Err("The encode binary should be compiled with enabled `alloc` feature!".into()) 7 | } 8 | 9 | #[cfg(feature = "alloc")] 10 | fn main() -> Result<(), Box> { 11 | use blobby::encode_blobs; 12 | use std::io::{self, BufRead, BufReader, BufWriter, Write}; 13 | use std::{env, fs::File}; 14 | 15 | fn decode_hex_char(b: u8) -> io::Result { 16 | let res = match b { 17 | b'0'..=b'9' => b - b'0', 18 | b'a'..=b'f' => b - b'a' + 10, 19 | b'A'..=b'F' => b - b'A' + 10, 20 | _ => { 21 | let msg = "Invalid hex string: invalid byte {b}"; 22 | return Err(io::Error::new(io::ErrorKind::InvalidData, msg)); 23 | } 24 | }; 25 | Ok(res) 26 | } 27 | 28 | fn decode_hex(data: &str) -> io::Result> { 29 | if data.len() % 2 != 0 { 30 | let msg = "Invalid hex string: length is not even"; 31 | return Err(io::Error::new(io::ErrorKind::InvalidData, msg)); 32 | } 33 | data.as_bytes() 34 | .chunks_exact(2) 35 | .map(|chunk| { 36 | let a = decode_hex_char(chunk[0])?; 37 | let b = decode_hex_char(chunk[1])?; 38 | Ok((a << 4) | b) 39 | }) 40 | .collect() 41 | } 42 | 43 | fn encode(reader: impl BufRead, mut writer: impl Write) -> io::Result { 44 | let mut blobs = Vec::new(); 45 | for line in reader.lines() { 46 | let blob = decode_hex(&line?)?; 47 | blobs.push(blob); 48 | } 49 | let (data, idx_len) = encode_blobs(&blobs); 50 | println!("Index len: {idx_len:?}"); 51 | writer.write_all(&data)?; 52 | Ok(blobs.len()) 53 | } 54 | 55 | let args: Vec = env::args().skip(1).collect(); 56 | 57 | if args.is_empty() { 58 | println!( 59 | "Blobby encoding utility.\n\ 60 | Usage: encode " 61 | ); 62 | return Ok(()); 63 | } 64 | 65 | let in_path = args[0].as_str(); 66 | let out_path = args[1].as_str(); 67 | let in_file = BufReader::new(File::open(in_path)?); 68 | let out_file = BufWriter::new(File::create(out_path)?); 69 | 70 | let n = encode(in_file, out_file)?; 71 | println!("Processed {n} record(s)"); 72 | 73 | Ok(()) 74 | } 75 | -------------------------------------------------------------------------------- /zeroize_derive/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 1.5.0 (unreleased) 8 | ### Changed 9 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 10 | 11 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 12 | 13 | ## 1.4.2 (2023-03-30) 14 | ### Changed 15 | - Inject where clauses; skip unused ([#882]) 16 | 17 | [#882]: https://github.com/RustCrypto/utils/pull/882 18 | 19 | ## 1.4.1 (2023-03-27) 20 | ### Changed 21 | - Do not automatically inject bounds ([#879]) 22 | 23 | [#879]: https://github.com/RustCrypto/utils/pull/879 24 | 25 | ## 1.4.0 (2023-03-26) 26 | ### Changed 27 | - 2021 edition upgrade; MSRV 1.56 ([#869]) 28 | - Bump `syn` to v2 ([#858]) 29 | 30 | ### Removed 31 | - `synstructure` dependency ([#858]) 32 | 33 | [#858]: https://github.com/RustCrypto/utils/pull/858 34 | [#869]: https://github.com/RustCrypto/utils/pull/869 35 | 36 | ## 1.3.3 (2022-11-30) 37 | ### Fixed 38 | - Deriving `ZeroizeOnDrop` on items with generics ([#787]) 39 | 40 | [#787]: https://github.com/RustCrypto/utils/pull/787 41 | 42 | ## 1.3.2 (2022-02-18) 43 | ### Fixed 44 | - Min versions build ([#732]) 45 | 46 | [#732]: https://github.com/RustCrypto/utils/pull/732 47 | 48 | ## 1.3.1 (2021-01-14) [YANKED] 49 | ### Removed 50 | - `ZeroizeOnDrop` implementation for `#[zeroize(drop)]` ([#715]) 51 | 52 | [#715]: https://github.com/RustCrypto/utils/pull/715 53 | 54 | ## 1.3.0 (2021-01-14) [YANKED] 55 | ### Added 56 | - `#[zeroize(bound = "T: MyTrait")]` ([#663]) 57 | - Custom derive for `ZeroizeOnDrop` ([#699], [#700]) 58 | 59 | [#663]: https://github.com/RustCrypto/utils/pull/663 60 | [#699]: https://github.com/RustCrypto/utils/pull/699 61 | [#700]: https://github.com/RustCrypto/utils/pull/700 62 | 63 | ## 1.2.2 (2021-11-04) [YANKED] 64 | ### Added 65 | - `#[zeroize(skip)]` attribute ([#654]) 66 | 67 | [#654]: https://github.com/RustCrypto/utils/pull/654 68 | 69 | ## 1.2.1 (2021-11-04) 70 | ### Changed 71 | - Moved to `RustCrypto/utils` repository 72 | 73 | ## 1.2.0 (2021-09-21) [YANKED] 74 | ### Changed 75 | - Bump MSRV to 1.51+ 76 | - Reject `#[zeroize(drop)]` on struct/enum fields, enum variants 77 | 78 | ## 1.1.1 (2021-10-09) [YANKED] 79 | ### Changed 80 | - Backport 1.2.0 `#[zeroize(drop)]` fixes but with a 1.47+ MSRV. 81 | 82 | ## 1.1.0 (2021-04-19) 83 | ### Changed 84 | - Bump MSRV to 1.47+ 85 | 86 | ## 1.0.1 (2019-09-15) 87 | ### Added 88 | - Add docs for the `Zeroize` proc macro 89 | 90 | ## 1.0.0 (2019-10-13) 91 | 92 | - Initial 1.0 release 93 | -------------------------------------------------------------------------------- /block-buffer/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.11.0 (2025-11-07) 8 | ### Added 9 | - `ReadBuffer` type ([#823]) 10 | - Optional implementation of the `Zeroize` trait ([#963]) 11 | - Generic `serialize` and `deserialize` methods ([#1200]) 12 | - `ReadBuffer::{read_cached, write_block, reset}` methods ([#1201]) 13 | 14 | ### Changed 15 | - Block sizes must be bigger than 0 and smaller than 256. 16 | This is enforced using compile-time monomorphization errors. ([#1115]) 17 | - Size of `EagerBuffer` is equal to buffer size, while previously it was equal 18 | to buffer size plus one byte ([#823]) 19 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 20 | 21 | ### Removed 22 | - `EagerBuffer::set_data` method. Use the `ReadBuffer` type instead. ([#823]) 23 | 24 | [#823]: https://github.com/RustCrypto/utils/pull/823 25 | [#963]: https://github.com/RustCrypto/utils/pull/963 26 | [#1115]: https://github.com/RustCrypto/utils/pull/1115 27 | [#1115]: https://github.com/RustCrypto/utils/pull/1116 28 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 29 | [#1200]: https://github.com/RustCrypto/utils/pull/1200 30 | [#1201]: https://github.com/RustCrypto/utils/pull/1201 31 | 32 | ## 0.10.3 (2022-09-04) 33 | ### Added 34 | - `try_new` method ([#799]) 35 | 36 | [#799]: https://github.com/RustCrypto/utils/pull/799 37 | 38 | ## 0.10.2 (2021-02-08) 39 | ### Fixed 40 | - Eliminate unreachable panic in `LazyBuffer::digest_blocks` ([#731]) 41 | 42 | [#731]: https://github.com/RustCrypto/utils/pull/731 43 | 44 | ## 0.10.1 (2021-02-05) 45 | ### Fixed 46 | - Use `as_mut_ptr` to get a pointer for mutation in the `set_data` method ([#728]) 47 | 48 | [#728]: https://github.com/RustCrypto/utils/pull/728 49 | 50 | ## 0.10.0 (2020-12-07) [YANKED] 51 | ### Changed 52 | - Significant reduction of number of unreachable panics. ([#671]) 53 | - Added buffer kind type parameter to `BlockBuffer`, respective marker types, and type aliases. ([#671]) 54 | - Various `BlockBuffer` method changes. ([#671]) 55 | 56 | ### Removed 57 | - `pad_with` method and dependency on `block-padding`. ([#671]) 58 | 59 | [#671]: https://github.com/RustCrypto/utils/pull/671 60 | 61 | ## 0.10.0 (2020-12-08) 62 | ### Changed 63 | - Rename `input_block(s)` methods to `digest_block(s)`. ([#113]) 64 | - Upgrade the `block-padding` dependency to v0.3. ([#113]) 65 | 66 | ### Added 67 | - `par_xor_data`, `xor_data`, and `set_data` methods. ([#113]) 68 | 69 | ### Removed 70 | - The `input_lazy` method. ([#113]) 71 | 72 | [#113]: https://github.com/RustCrypto/utils/pull/113 73 | -------------------------------------------------------------------------------- /block-padding/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | All notable changes to this project will be documented in this file. 3 | 4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), 5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 6 | 7 | ## 0.4.2 (2025-11-26) 8 | ### Changed 9 | - Added `'static` bound to `Padding` trait ([#1248]) 10 | 11 | [#1248]: https://github.com/RustCrypto/utils/pull/1248 12 | 13 | ## 0.4.1 (2025-10-06) [YANKED] 14 | ### Added 15 | - `PaddedData` enum ([#1227]) 16 | 17 | ### Changed 18 | - `Padding::pad_detached` method returns `PaddedData` ([#1227]) 19 | 20 | ### Fixed 21 | - `Padding::pad_detached` method for `NoPadding` and `ZeroPadding` ([#1227]) 22 | 23 | [#1227]: https://github.com/RustCrypto/utils/pull/1227 24 | 25 | ## 0.4.0 (2025-10-06) [YANKED] 26 | ### Added 27 | - `Padding::pad_detached` method ([#1225]) 28 | 29 | ### Changed 30 | - Migrated from `generic-array` to `hybrid-array` ([#944]) 31 | - Edition changed to 2024 and MSRV bumped to 1.85 ([#1149]) 32 | - Merged `RawPadding` and `Padding` traits ([#1217]) 33 | - Renamed `UnpadError` to `Error` ([#1225]) 34 | 35 | ### Removed 36 | - `Block` type alias ([#1217]) 37 | - `PadType` enum and associated type on the `Padding` trait ([#1225]) 38 | 39 | [#944]: https://github.com/RustCrypto/utils/pull/944 40 | [#1149]: https://github.com/RustCrypto/utils/pull/1149 41 | [#1217]: https://github.com/RustCrypto/utils/pull/1217 42 | [#1225]: https://github.com/RustCrypto/utils/pull/1225 43 | 44 | ## 0.3.3 (2023-04-02) 45 | ### Added 46 | - `RawPadding` trait for padding blocks of arbitrary size ([#870]) 47 | 48 | [#870]: https://github.com/RustCrypto/utils/pull/870 49 | 50 | ## 0.3.2 (2022-03-10) 51 | ### Fixed 52 | - Potential unsoundness for incorrect `Padding` implementations ([#748]) 53 | 54 | [#748]: https://github.com/RustCrypto/utils/pull/748 55 | 56 | ## 0.3.1 (2022-02-10) [YANKED] 57 | ### Fixed 58 | - Fix doc build on docs.rs by optionally enabling the `doc_cfg` feature ([#733]) 59 | 60 | [#733]: https://github.com/RustCrypto/utils/pull/733 61 | 62 | ## 0.3.0 (2022-02-10) [YANKED] 63 | ### Added 64 | - `Iso10126` padding algorithm ([#643]) 65 | - `PadType` enum, `Padding::TYPE` associated constant, and `Padding::unpad_blocks` method ([#675]) 66 | 67 | ### Changed 68 | - The `Padding` trait methods now work with blocks instead of byte slices. ([#113]) 69 | - Bump MSRV to 1.56 and edition to 2021 ([#675]) 70 | 71 | [#113]: https://github.com/RustCrypto/utils/pull/113 72 | [#643]: https://github.com/RustCrypto/utils/pull/643 73 | [#675]: https://github.com/RustCrypto/utils/pull/675 74 | 75 | ## 0.2.1 (2020-08-14) 76 | ### Added 77 | - `Copy`, `Clone`, and `Debug` trait implementations for padding types. ([#78]) 78 | 79 | [#78]: https://github.com/RustCrypto/utils/pull/78 80 | 81 | ## 0.2.0 (2020-07-10) 82 | -------------------------------------------------------------------------------- /ctutils/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: Constant-Time Utilities 2 | 3 | [![Crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache 2.0/MIT Licensed][license-image] 7 | ![MSRV][msrv-image] 8 | 9 | Constant-time utility library with selection and equality testing support targeting cryptographic 10 | applications. Supports `const fn` where appropriate. Built on the [`cmov`] crate which provides 11 | architecture-specific predication intrinsics. Heavily inspired by the [`subtle`] crate. 12 | 13 | ## About 14 | 15 | This crate contains constant-time equivalents of the `bool` and `Option` types (`Choice` and 16 | `CtOption`), along with traits that can be used in combination with them. 17 | 18 | The `CtOption` type notably provides eagerly evaluated combinator methods (as opposed to the lazily 19 | evaluated combinators on `Option`) which make it possible to write constant-time code using 20 | an idiomatic Rust style. 21 | 22 | This is an experimental next-generation constant-time library inspired by `subtle`, but for now we 23 | recommend you continue to stick with `subtle`. We may attempt to get some of the changes in this 24 | library incorporated into `subtle` for a potential v3.0. 25 | 26 | ## ⚠️ Security Warning 27 | 28 | The implementation contained in this crate has never been independently audited! 29 | 30 | USE AT YOUR OWN RISK! 31 | 32 | ## Minimum Supported Rust Version (MSRV) Policy 33 | 34 | MSRV increases are not considered breaking changes and can happen in patch releases. 35 | 36 | The crate MSRV accounts for all supported targets and crate feature combinations. 37 | 38 | ## License 39 | 40 | Licensed under either of: 41 | 42 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 43 | * [MIT license](http://opensource.org/licenses/MIT) 44 | 45 | at your option. 46 | 47 | ### Contribution 48 | 49 | Unless you explicitly state otherwise, any contribution intentionally submitted 50 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 51 | dual licensed as above, without any additional terms or conditions. 52 | 53 | [//]: # (badges) 54 | 55 | [crate-image]: https://img.shields.io/crates/v/ctutils.svg 56 | [crate-link]: https://crates.io/crates/ctutils 57 | [docs-image]: https://docs.rs/ctutils/badge.svg 58 | [docs-link]: https://docs.rs/ctutils/ 59 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 60 | [msrv-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 61 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/ctutils.yml/badge.svg?branch=master 62 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/ctutils.yml?query=branch:master 63 | 64 | [//]: # (links) 65 | 66 | [RustCrypto]: https://github.com/RustCrypto 67 | [`cmov`]: https://docs.rs/cmov 68 | [`subtle`]: https://docs.rs/subtle 69 | -------------------------------------------------------------------------------- /opaque-debug/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Macro for opaque [`Debug`] trait implementation. 2 | //! 3 | //! In many cases it's convenient to have `Debug` implementation for all crate types, 4 | //! e.g. to allow deriving of `Debug` in user-defined structs. But at the same time, using 5 | //! the default derive macro can be a security hazard since it cause leaking of sensitive 6 | //! information, for example, through uncareful logging. 7 | //! 8 | //! This crate introduces the [`implement!`] macro which creates an opaque [`Debug`] 9 | //! implementation, which does not expose any internal type data. 10 | //! 11 | //! # Examples 12 | //! ``` 13 | //! pub struct CryptoStuff { 14 | //! key: [u8; 16], 15 | //! } 16 | //! 17 | //! opaque_debug::implement!(CryptoStuff); 18 | //! 19 | //! let val = CryptoStuff { key: [42; 16] }; 20 | //! assert_eq!(format!("{:?}", val), "CryptoStuff { ... }") 21 | //! ``` 22 | //! 23 | //! The macro also support generic parameters: 24 | //! ``` 25 | //! pub struct GenericCryptoStuff { 26 | //! key: K, 27 | //! } 28 | //! 29 | //! opaque_debug::implement!(GenericCryptoStuff); 30 | //! 31 | //! let val = GenericCryptoStuff { key: [42u8; 16] }; 32 | //! assert_eq!(format!("{:?}", val), "GenericCryptoStuff<[u8; 16]> { ... }") 33 | //! ``` 34 | #![no_std] 35 | #![doc( 36 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", 37 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" 38 | )] 39 | 40 | #[doc(hidden)] 41 | pub extern crate core as __core; 42 | 43 | #[macro_export] 44 | #[doc(hidden)] 45 | macro_rules! format_params { 46 | ($single:ident) => { 47 | "{}" 48 | }; 49 | ($first:ident, $($rest:ident),+) => { 50 | concat!("{}", ", ", $crate::format_params!($($rest),+)) 51 | }; 52 | } 53 | 54 | /// Macro for implementing an opaque `Debug` implementation. 55 | #[macro_export] 56 | macro_rules! implement { 57 | ($struct:ident <$($params:ident),+>) => { 58 | impl <$($params),+> $crate::__core::fmt::Debug for $struct <$($params),+> { 59 | fn fmt( 60 | &self, 61 | f: &mut $crate::__core::fmt::Formatter, 62 | ) -> Result<(), $crate::__core::fmt::Error> { 63 | write!( 64 | f, 65 | concat!(stringify!($struct), "<", $crate::format_params!($($params),+), "> {{ ... }}"), 66 | $($crate::__core::any::type_name::<$params>()),+ 67 | ) 68 | } 69 | } 70 | }; 71 | ($struct:ty) => { 72 | impl $crate::__core::fmt::Debug for $struct { 73 | fn fmt( 74 | &self, 75 | f: &mut $crate::__core::fmt::Formatter, 76 | ) -> Result<(), $crate::__core::fmt::Error> { 77 | write!(f, concat!(stringify!($struct), " {{ ... }}")) 78 | } 79 | } 80 | }; 81 | } 82 | -------------------------------------------------------------------------------- /wycheproof2blb/src/aead.rs: -------------------------------------------------------------------------------- 1 | use crate::TestInfo; 2 | use crate::wycheproof; 3 | use crate::wycheproof::{case_result, description, hex_string}; 4 | use serde::Deserialize; 5 | 6 | #[derive(Debug, Deserialize)] 7 | pub struct TestSuite { 8 | #[serde(flatten)] 9 | pub suite: wycheproof::Suite, 10 | #[serde(rename = "testGroups")] 11 | pub test_groups: Vec, 12 | } 13 | 14 | #[derive(Debug, Deserialize)] 15 | pub struct TestGroup { 16 | #[serde(flatten)] 17 | pub group: wycheproof::Group, 18 | #[serde(rename = "ivSize")] 19 | pub iv_size: u32, 20 | #[serde(rename = "keySize")] 21 | pub key_size: u32, 22 | #[serde(rename = "tagSize")] 23 | pub tag_size: u32, 24 | pub tests: Vec, 25 | } 26 | 27 | #[derive(Debug, Deserialize)] 28 | pub struct TestCase { 29 | #[serde(flatten)] 30 | pub case: wycheproof::Case, 31 | #[serde(with = "hex_string")] 32 | pub aad: Vec, 33 | #[serde(with = "hex_string")] 34 | pub ct: Vec, 35 | #[serde(with = "hex_string")] 36 | pub iv: Vec, 37 | #[serde(with = "hex_string")] 38 | pub key: Vec, 39 | #[serde(with = "hex_string")] 40 | pub msg: Vec, 41 | #[serde(with = "hex_string")] 42 | pub tag: Vec, 43 | } 44 | 45 | pub fn aes_gcm_generator(data: &[u8], algorithm: &str, key_size: u32) -> Vec { 46 | generator(data, algorithm, key_size, 12 * 8) 47 | } 48 | 49 | pub fn chacha20_poly1305(data: &[u8], algorithm: &str, _key_size: u32) -> Vec { 50 | generator(data, algorithm, 256, 12 * 8) 51 | } 52 | 53 | pub fn xchacha20_poly1305(data: &[u8], algorithm: &str, _key_size: u32) -> Vec { 54 | generator(data, algorithm, 256, 24 * 8) 55 | } 56 | 57 | fn generator(data: &[u8], algorithm: &str, key_size: u32, iv_size: u32) -> Vec { 58 | let suite: TestSuite = serde_json::from_slice(data).unwrap(); 59 | assert_eq!(algorithm, suite.suite.algorithm); 60 | 61 | let mut infos = vec![]; 62 | for g in &suite.test_groups { 63 | for tc in &g.tests { 64 | if key_size != 0 && g.key_size != key_size { 65 | continue; 66 | } 67 | if g.iv_size != iv_size { 68 | println!(" skipping tests for iv_size={}", g.iv_size); 69 | continue; 70 | } 71 | let mut combined_ct = Vec::new(); 72 | combined_ct.extend_from_slice(&tc.ct); 73 | combined_ct.extend_from_slice(&tc.tag); 74 | 75 | infos.push(TestInfo { 76 | data: vec![ 77 | tc.key.clone(), 78 | tc.iv.clone(), 79 | tc.aad.clone(), 80 | tc.msg.clone(), 81 | combined_ct, 82 | vec![case_result(&tc.case)], 83 | ], 84 | desc: description(&suite.suite, &tc.case), 85 | }); 86 | } 87 | } 88 | infos 89 | } 90 | -------------------------------------------------------------------------------- /hex-literal/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc = include_str!("../README.md")] 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", 5 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" 6 | )] 7 | 8 | const fn next_hex_char(string: &[u8], mut pos: usize) -> Option<(u8, usize)> { 9 | while pos < string.len() { 10 | let raw_val = string[pos]; 11 | pos += 1; 12 | let val = match raw_val { 13 | b'0'..=b'9' => raw_val - 48, 14 | b'A'..=b'F' => raw_val - 55, 15 | b'a'..=b'f' => raw_val - 87, 16 | b' ' | b':' | b'\r' | b'\n' | b'\t' => continue, 17 | 0..=127 => panic!("Encountered invalid ASCII character"), 18 | _ => panic!("Encountered non-ASCII character"), 19 | }; 20 | return Some((val, pos)); 21 | } 22 | None 23 | } 24 | 25 | const fn next_byte(string: &[u8], pos: usize) -> Option<(u8, usize)> { 26 | let (half1, pos) = match next_hex_char(string, pos) { 27 | Some(v) => v, 28 | None => return None, 29 | }; 30 | let (half2, pos) = match next_hex_char(string, pos) { 31 | Some(v) => v, 32 | None => panic!("Odd number of hex characters"), 33 | }; 34 | Some(((half1 << 4) + half2, pos)) 35 | } 36 | 37 | /// Compute length of a byte array which will be decoded from the strings. 38 | /// 39 | /// This function is an implementation detail and SHOULD NOT be called directly! 40 | #[doc(hidden)] 41 | pub const fn len(strings: &[&[u8]]) -> usize { 42 | let mut i = 0; 43 | let mut len = 0; 44 | while i < strings.len() { 45 | let mut pos = 0; 46 | while let Some((_, new_pos)) = next_byte(strings[i], pos) { 47 | len += 1; 48 | pos = new_pos; 49 | } 50 | i += 1; 51 | } 52 | len 53 | } 54 | 55 | /// Decode hex strings into a byte array of pre-computed length. 56 | /// 57 | /// This function is an implementation detail and SHOULD NOT be called directly! 58 | #[doc(hidden)] 59 | pub const fn decode(strings: &[&[u8]]) -> Option<[u8; LEN]> { 60 | let mut string_pos = 0; 61 | let mut buf = [0u8; LEN]; 62 | let mut buf_pos = 0; 63 | while string_pos < strings.len() { 64 | let mut pos = 0; 65 | let string = &strings[string_pos]; 66 | string_pos += 1; 67 | 68 | while let Some((byte, new_pos)) = next_byte(string, pos) { 69 | buf[buf_pos] = byte; 70 | buf_pos += 1; 71 | pos = new_pos; 72 | } 73 | } 74 | if LEN == buf_pos { Some(buf) } else { None } 75 | } 76 | 77 | /// Converts a sequence of hexadecimal string literals to a byte array at compile time. 78 | /// 79 | /// See the crate-level docs for more information. 80 | #[macro_export] 81 | macro_rules! hex { 82 | ($($s:literal)*) => {{ 83 | const STRINGS: &[&'static [u8]] = &[$($s.as_bytes(),)*]; 84 | const { 85 | $crate::decode::<{ $crate::len(STRINGS) }>(STRINGS) 86 | .expect("Output array length should be correct") 87 | } 88 | }}; 89 | } 90 | -------------------------------------------------------------------------------- /zeroize/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: zeroize 2 | 3 | [![Crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | ![Apache 2.0/MIT Licensed][license-image] 6 | ![MSRV][rustc-image] 7 | [![Build Status][build-image]][build-link] 8 | 9 | Securely zero memory (a.k.a. [zeroize]) while avoiding compiler optimizations. 10 | 11 | This crate implements a portable approach to securely zeroing memory using 12 | techniques which guarantee they won't be "optimized away" by the compiler. 13 | 14 | The [`Zeroize` trait] is the crate's primary API. 15 | 16 | [Documentation] 17 | 18 | ## About 19 | 20 | [Zeroing memory securely is hard] - compilers optimize for performance, and 21 | in doing so they love to "optimize away" unnecessary zeroing calls. There are 22 | many documented "tricks" to attempt to avoid these optimizations and ensure 23 | that a zeroing routine is performed reliably. 24 | 25 | This crate isn't about tricks: it uses [core::ptr::write_volatile] 26 | and [core::sync::atomic] memory fences to provide easy-to-use, portable 27 | zeroing behavior which works on all of Rust's core number types and slices 28 | thereof, implemented in pure Rust with no usage of FFI or assembly. 29 | 30 | - No insecure fallbacks! 31 | - No dependencies! 32 | - No FFI or inline assembly! **WASM friendly** (and tested)! 33 | - `#![no_std]` i.e. **embedded-friendly**! 34 | - No functionality besides securely zeroing memory! 35 | - (Optional) Custom derive support for zeroing complex structures 36 | 37 | ## License 38 | 39 | Licensed under either of: 40 | 41 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 42 | * [MIT license](http://opensource.org/licenses/MIT) 43 | 44 | at your option. 45 | 46 | ### Contribution 47 | 48 | Unless you explicitly state otherwise, any contribution intentionally submitted 49 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 50 | dual licensed as above, without any additional terms or conditions. 51 | 52 | [//]: # (badges) 53 | 54 | [crate-image]: https://img.shields.io/crates/v/zeroize.svg 55 | [crate-link]: https://crates.io/crates/zeroize 56 | [docs-image]: https://docs.rs/zeroize/badge.svg 57 | [docs-link]: https://docs.rs/zeroize/ 58 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 59 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 60 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/zeroize.yml/badge.svg?branch=master 61 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/zeroize.yml?query=branch:master 62 | 63 | [//]: # (general links) 64 | 65 | [RustCrypto]: https://github.com/RustCrypto 66 | [zeroize]: https://en.wikipedia.org/wiki/Zeroisation 67 | [`Zeroize` trait]: https://docs.rs/zeroize/latest/zeroize/trait.Zeroize.html 68 | [Documentation]: https://docs.rs/zeroize/ 69 | [Zeroing memory securely is hard]: http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html 70 | [core::ptr::write_volatile]: https://doc.rust-lang.org/core/ptr/fn.write_volatile.html 71 | [core::sync::atomic]: https://doc.rust-lang.org/stable/core/sync/atomic/index.html 72 | [good cryptographic hygiene]: https://github.com/veorq/cryptocoding#clean-memory-of-secret-data 73 | -------------------------------------------------------------------------------- /block-buffer/src/sealed.rs: -------------------------------------------------------------------------------- 1 | use hybrid_array::sizes::{U0, U1}; 2 | 3 | use super::{Array, ArraySize}; 4 | use core::{mem::MaybeUninit, ptr}; 5 | 6 | type Block = MaybeUninit>; 7 | 8 | /// Sealed trait for buffer kinds. 9 | pub trait Sealed { 10 | #[cfg(not(feature = "zeroize"))] 11 | type Pos: Default + Clone; 12 | #[cfg(feature = "zeroize")] 13 | type Pos: Default + Clone + zeroize::Zeroize; 14 | 15 | type Overhead: ArraySize; 16 | 17 | const NAME: &'static str; 18 | 19 | fn get_pos(buf: &Block, pos: &Self::Pos) -> usize; 20 | 21 | fn set_pos(buf: &mut Block, pos: &mut Self::Pos, val: usize); 22 | 23 | /// Invariant guaranteed by a buffer kind, i.e. with correct 24 | /// buffer code this function always returns true. 25 | fn invariant(pos: usize, block_size: usize) -> bool; 26 | 27 | /// Split input data into slice of blocks and tail. 28 | fn split_blocks(data: &[u8]) -> (&[Array], &[u8]); 29 | } 30 | 31 | impl Sealed for super::Eager { 32 | type Pos = (); 33 | type Overhead = U0; 34 | const NAME: &'static str = "BlockBuffer"; 35 | 36 | fn get_pos(buf: &Block, _pos: &Self::Pos) -> usize { 37 | // SAFETY: last byte in `buf` for eager hashes is always properly initialized 38 | let pos = unsafe { 39 | let buf_ptr = buf.as_ptr().cast::(); 40 | let last_byte_ptr = buf_ptr.add(N::USIZE - 1); 41 | ptr::read(last_byte_ptr) 42 | }; 43 | pos as usize 44 | } 45 | 46 | fn set_pos(buf: &mut Block, _pos: &mut Self::Pos, val: usize) { 47 | debug_assert!(val <= u8::MAX as usize); 48 | // SAFETY: we write to the last byte of `buf` which is always safe 49 | unsafe { 50 | let buf_ptr = buf.as_mut_ptr().cast::(); 51 | let last_byte_ptr = buf_ptr.add(N::USIZE - 1); 52 | ptr::write(last_byte_ptr, val as u8); 53 | } 54 | } 55 | 56 | #[inline(always)] 57 | fn invariant(pos: usize, block_size: usize) -> bool { 58 | pos < block_size 59 | } 60 | 61 | #[inline(always)] 62 | fn split_blocks(data: &[u8]) -> (&[Array], &[u8]) { 63 | Array::slice_as_chunks(data) 64 | } 65 | } 66 | 67 | impl Sealed for super::Lazy { 68 | type Pos = u8; 69 | type Overhead = U1; 70 | const NAME: &'static str = "BlockBuffer"; 71 | 72 | fn get_pos(_buf_val: &Block, pos: &Self::Pos) -> usize { 73 | *pos as usize 74 | } 75 | 76 | fn set_pos(_: &mut Block, pos: &mut Self::Pos, val: usize) { 77 | debug_assert!(val <= u8::MAX as usize); 78 | *pos = val as u8; 79 | } 80 | 81 | #[inline(always)] 82 | fn invariant(pos: usize, block_size: usize) -> bool { 83 | pos <= block_size 84 | } 85 | 86 | #[inline(always)] 87 | fn split_blocks(data: &[u8]) -> (&[Array], &[u8]) { 88 | let (blocks, tail) = Array::slice_as_chunks(data); 89 | if data.is_empty() || !tail.is_empty() { 90 | (blocks, tail) 91 | } else { 92 | let (tail, blocks) = blocks.split_last().expect("`blocks` can not be empty"); 93 | (blocks, tail) 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /hex-literal/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: hex-literal 2 | 3 | [![Crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | ![Apache 2.0/MIT Licensed][license-image] 6 | ![MSRV][rustc-image] 7 | [![Build Status][build-image]][build-link] 8 | 9 | This crate provides the `hex!` macro for converting a sequence of hexadecimal string literals to a byte array at compile time. 10 | 11 | The macro accepts the following characters in input string literals: 12 | 13 | - `'0'...'9'`, `'a'...'f'`, `'A'...'F'` — hex characters which will be used in construction of the output byte array 14 | - `' '`, `:`, `'\r'`, `'\n'`, `'\t'` — formatting characters which will be ignored 15 | 16 | # Examples 17 | ```rust 18 | use hex_literal::hex; 19 | 20 | // The macro can be used in const contexts 21 | const DATA: [u8; 4] = hex!("01020304"); 22 | assert_eq!(DATA, [1, 2, 3, 4]); 23 | 24 | // Both upper and lower hex values are supported 25 | assert_eq!(hex!("a1 b2 c3 d4"), [0xA1, 0xB2, 0xC3, 0xD4]); 26 | assert_eq!(hex!("E5 E6 90 92"), [0xE5, 0xE6, 0x90, 0x92]); 27 | assert_eq!(hex!("0a0B 0C0d"), [10, 11, 12, 13]); 28 | 29 | // Colon-delimited literals 30 | assert_eq!(hex!("0A:0B:0C:0D"), [10, 11, 12, 13]); 31 | 32 | // Multi-line literals 33 | let bytes1 = hex!(" 34 | 00010203 04050607 35 | 08090a0b 0c0d0e0f 36 | "); 37 | assert_eq!( 38 | bytes1, 39 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 40 | ); 41 | 42 | // It's possible to use several literals 43 | // (results will be concatenated) 44 | let bytes2 = hex!( 45 | "00010203 04050607" // first half 46 | "08090a0b 0c0d0e0f" // second half 47 | ); 48 | assert_eq!(bytes1, bytes2); 49 | ``` 50 | 51 | Using an unsupported character inside literals will result in a compilation error: 52 | ```rust,compile_fail 53 | hex_literal::hex!("АА"); // Cyrillic "А" 54 | hex_literal::hex!("11 22"); // Japanese space 55 | ``` 56 | 57 | Сomments inside literals are not supported: 58 | ```rust,compile_fail 59 | hex_literal::hex!("0123 // foo"); 60 | ``` 61 | 62 | Each literal must contain an even number of hex characters: 63 | ```rust,compile_fail 64 | hex_literal::hex!( 65 | "01234" 66 | "567" 67 | ); 68 | ``` 69 | 70 | ## License 71 | 72 | Licensed under either of: 73 | 74 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 75 | * [MIT license](http://opensource.org/licenses/MIT) 76 | 77 | at your option. 78 | 79 | ### Contribution 80 | 81 | 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. 82 | 83 | [//]: # (badges) 84 | 85 | [crate-image]: https://img.shields.io/crates/v/hex-literal.svg 86 | [crate-link]: https://crates.io/crates/hex-literal 87 | [docs-image]: https://docs.rs/hex-literal/badge.svg 88 | [docs-link]: https://docs.rs/hex-literal/ 89 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 90 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 91 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/hex-literal.yml/badge.svg?branch=master 92 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/hex-literal.yml?query=branch:master 93 | 94 | [//]: # (general links) 95 | 96 | [RustCrypto]: https://github.com/RustCrypto 97 | -------------------------------------------------------------------------------- /cpufeatures/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc = include_str!("../README.md")] 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", 5 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" 6 | )] 7 | 8 | #[cfg(not(miri))] 9 | #[cfg(target_arch = "aarch64")] 10 | #[doc(hidden)] 11 | pub mod aarch64; 12 | 13 | #[cfg(not(miri))] 14 | #[cfg(target_arch = "loongarch64")] 15 | #[doc(hidden)] 16 | pub mod loongarch64; 17 | 18 | #[cfg(not(miri))] 19 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 20 | mod x86; 21 | 22 | #[cfg(miri)] 23 | mod miri; 24 | 25 | #[cfg(not(any( 26 | target_arch = "aarch64", 27 | target_arch = "loongarch64", 28 | target_arch = "x86", 29 | target_arch = "x86_64" 30 | )))] 31 | compile_error!("This crate works only on `aarch64`, `loongarch64`, `x86`, and `x86-64` targets."); 32 | 33 | /// Create module with CPU feature detection code. 34 | #[macro_export] 35 | macro_rules! new { 36 | ($mod_name:ident, $($tf:tt),+ $(,)?) => { 37 | mod $mod_name { 38 | use core::sync::atomic::{AtomicU8, Ordering::Relaxed}; 39 | 40 | const UNINIT: u8 = u8::max_value(); 41 | static STORAGE: AtomicU8 = AtomicU8::new(UNINIT); 42 | 43 | /// Initialization token 44 | #[derive(Copy, Clone, Debug)] 45 | pub struct InitToken(()); 46 | 47 | impl InitToken { 48 | /// Get initialized value 49 | #[inline(always)] 50 | pub fn get(&self) -> bool { 51 | $crate::__unless_target_features! { 52 | $($tf),+ => { 53 | STORAGE.load(Relaxed) == 1 54 | } 55 | } 56 | } 57 | } 58 | 59 | /// Get stored value and initialization token, 60 | /// initializing underlying storage if needed. 61 | #[inline] 62 | pub fn init_get() -> (InitToken, bool) { 63 | let res = $crate::__unless_target_features! { 64 | $($tf),+ => { 65 | #[cold] 66 | fn init_inner() -> bool { 67 | let res = $crate::__detect_target_features!($($tf),+); 68 | STORAGE.store(res as u8, Relaxed); 69 | res 70 | } 71 | 72 | // Relaxed ordering is fine, as we only have a single atomic variable. 73 | let val = STORAGE.load(Relaxed); 74 | 75 | if val == UNINIT { 76 | init_inner() 77 | } else { 78 | val == 1 79 | } 80 | } 81 | }; 82 | 83 | (InitToken(()), res) 84 | } 85 | 86 | /// Initialize underlying storage if needed and get initialization token. 87 | #[inline] 88 | pub fn init() -> InitToken { 89 | init_get().0 90 | } 91 | 92 | /// Initialize underlying storage if needed and get stored value. 93 | #[inline] 94 | pub fn get() -> bool { 95 | init_get().1 96 | } 97 | } 98 | }; 99 | } 100 | -------------------------------------------------------------------------------- /cmov/src/portable.rs: -------------------------------------------------------------------------------- 1 | //! Portable "best effort" implementation of `Cmov`. 2 | //! 3 | //! This implementation is based on portable bitwise arithmetic but cannot 4 | //! guarantee that the resulting generated assembly is free of branch 5 | //! instructions. 6 | 7 | // TODO(tarcieri): more optimized implementation for small integers 8 | 9 | use crate::{Cmov, CmovEq, Condition}; 10 | use core::{hint::black_box, mem::size_of}; 11 | 12 | impl Cmov for u16 { 13 | #[inline] 14 | fn cmovnz(&mut self, value: &Self, condition: Condition) { 15 | let mut tmp = *self as u64; 16 | tmp.cmovnz(&(*value as u64), condition); 17 | *self = tmp as u16; 18 | } 19 | 20 | #[inline] 21 | fn cmovz(&mut self, value: &Self, condition: Condition) { 22 | let mut tmp = *self as u64; 23 | tmp.cmovz(&(*value as u64), condition); 24 | *self = tmp as u16; 25 | } 26 | } 27 | 28 | impl CmovEq for u16 { 29 | #[inline] 30 | fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { 31 | (*self as u64).cmovne(&(*rhs as u64), input, output); 32 | } 33 | 34 | #[inline] 35 | fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { 36 | (*self as u64).cmoveq(&(*rhs as u64), input, output); 37 | } 38 | } 39 | 40 | impl Cmov for u32 { 41 | #[inline] 42 | fn cmovnz(&mut self, value: &Self, condition: Condition) { 43 | let mut tmp = *self as u64; 44 | tmp.cmovnz(&(*value as u64), condition); 45 | *self = tmp as u32; 46 | } 47 | 48 | #[inline] 49 | fn cmovz(&mut self, value: &Self, condition: Condition) { 50 | let mut tmp = *self as u64; 51 | tmp.cmovz(&(*value as u64), condition); 52 | *self = tmp as u32; 53 | } 54 | } 55 | 56 | impl CmovEq for u32 { 57 | #[inline] 58 | fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { 59 | (*self as u64).cmovne(&(*rhs as u64), input, output); 60 | } 61 | 62 | #[inline] 63 | fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { 64 | (*self as u64).cmoveq(&(*rhs as u64), input, output); 65 | } 66 | } 67 | 68 | impl Cmov for u64 { 69 | #[inline] 70 | fn cmovnz(&mut self, value: &Self, condition: Condition) { 71 | let mask = is_non_zero(condition).wrapping_sub(1); 72 | *self = (*self & mask) | (*value & !mask); 73 | } 74 | 75 | #[inline] 76 | fn cmovz(&mut self, value: &Self, condition: Condition) { 77 | let mask = (1 ^ is_non_zero(condition)).wrapping_sub(1); 78 | *self = (*self & mask) | (*value & !mask); 79 | } 80 | } 81 | 82 | impl CmovEq for u64 { 83 | #[inline] 84 | fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { 85 | output.cmovnz(&input, (self ^ rhs) as u8); 86 | } 87 | 88 | #[inline] 89 | fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { 90 | output.cmovz(&input, (self ^ rhs) as u8); 91 | } 92 | } 93 | 94 | /// Check if the given condition value is non-zero 95 | /// 96 | /// # Returns 97 | /// - `condition` is zero: `0` 98 | /// - `condition` is non-zero: `1` 99 | #[inline] 100 | fn is_non_zero(condition: Condition) -> u64 { 101 | const SHIFT_BITS: usize = size_of::() - 1; 102 | let condition = condition as u64; 103 | black_box(((condition | (!condition).wrapping_add(1)) >> SHIFT_BITS) & 1) 104 | } 105 | -------------------------------------------------------------------------------- /cmov/src/aarch64.rs: -------------------------------------------------------------------------------- 1 | use crate::{Cmov, CmovEq, Condition}; 2 | use core::arch::asm; 3 | 4 | macro_rules! csel { 5 | ($csel:expr, $dst:expr, $src:expr, $condition:expr) => { 6 | unsafe { 7 | asm! { 8 | "cmp {0:w}, 0", 9 | $csel, 10 | in(reg) $condition, 11 | inlateout(reg) *$dst, 12 | in(reg) *$src, 13 | in(reg) *$dst, 14 | options(pure, nomem, nostack), 15 | }; 16 | } 17 | }; 18 | } 19 | 20 | macro_rules! csel_eq { 21 | ($instruction:expr, $lhs:expr, $rhs:expr, $condition:expr, $dst:expr) => { 22 | let mut tmp = *$dst as u16; 23 | unsafe { 24 | asm! { 25 | "eor {0:w}, {1:w}, {2:w}", 26 | "cmp {0:w}, 0", 27 | $instruction, 28 | out(reg) _, 29 | in(reg) *$lhs, 30 | in(reg) *$rhs, 31 | inlateout(reg) tmp, 32 | in(reg) $condition as u16, 33 | in(reg) tmp, 34 | options(pure, nomem, nostack), 35 | }; 36 | }; 37 | 38 | *$dst = tmp as u8; 39 | }; 40 | } 41 | 42 | impl Cmov for u16 { 43 | #[inline] 44 | fn cmovnz(&mut self, value: &Self, condition: Condition) { 45 | csel!("csel {1:w}, {2:w}, {3:w}, NE", self, value, condition); 46 | } 47 | 48 | #[inline] 49 | fn cmovz(&mut self, value: &Self, condition: Condition) { 50 | csel!("csel {1:w}, {2:w}, {3:w}, EQ", self, value, condition); 51 | } 52 | } 53 | 54 | impl CmovEq for u16 { 55 | #[inline] 56 | fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { 57 | csel_eq!("csel {3:w}, {4:w}, {5:w}, NE", self, rhs, input, output); 58 | } 59 | 60 | #[inline] 61 | fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { 62 | csel_eq!("csel {3:w}, {4:w}, {5:w}, EQ", self, rhs, input, output); 63 | } 64 | } 65 | 66 | impl Cmov for u32 { 67 | #[inline] 68 | fn cmovnz(&mut self, value: &Self, condition: Condition) { 69 | csel!("csel {1:w}, {2:w}, {3:w}, NE", self, value, condition); 70 | } 71 | 72 | #[inline] 73 | fn cmovz(&mut self, value: &Self, condition: Condition) { 74 | csel!("csel {1:w}, {2:w}, {3:w}, EQ", self, value, condition); 75 | } 76 | } 77 | 78 | impl CmovEq for u32 { 79 | #[inline] 80 | fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { 81 | csel_eq!("csel {3:w}, {4:w}, {5:w}, NE", self, rhs, input, output); 82 | } 83 | 84 | #[inline] 85 | fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { 86 | csel_eq!("csel {3:w}, {4:w}, {5:w}, EQ", self, rhs, input, output); 87 | } 88 | } 89 | 90 | impl Cmov for u64 { 91 | #[inline] 92 | fn cmovnz(&mut self, value: &Self, condition: Condition) { 93 | csel!("csel {1:x}, {2:x}, {3:x}, NE", self, value, condition); 94 | } 95 | 96 | #[inline] 97 | fn cmovz(&mut self, value: &Self, condition: Condition) { 98 | csel!("csel {1:x}, {2:x}, {3:x}, EQ", self, value, condition); 99 | } 100 | } 101 | 102 | impl CmovEq for u64 { 103 | #[inline] 104 | fn cmovne(&self, rhs: &Self, input: Condition, output: &mut Condition) { 105 | csel_eq!("csel {3:w}, {4:w}, {5:w}, NE", self, rhs, input, output); 106 | } 107 | 108 | #[inline] 109 | fn cmoveq(&self, rhs: &Self, input: Condition, output: &mut Condition) { 110 | csel_eq!("csel {3:w}, {4:w}, {5:w}, EQ", self, rhs, input, output); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /zeroize/src/barrier.rs: -------------------------------------------------------------------------------- 1 | /// Observe the referenced data and prevent the compiler from removing previous writes to it. 2 | /// 3 | /// This function acts like [`core::hint::black_box`] but takes a reference and 4 | /// does not return the passed value. 5 | /// 6 | /// It's implemented using the [`core::arch::asm!`] macro on target arches where `asm!` is stable, 7 | /// i.e. `aarch64`, `arm`, `arm64ec`, `loongarch64`, `riscv32`, `riscv64`, `s390x`, `x86`, and 8 | /// `x86_64`. 9 | /// 10 | /// On all other targets it's implemented using [`core::hint::black_box`] and custom `black_box` 11 | /// implemented using `#[inline(never)]` and `read_volatile`. 12 | /// 13 | /// # Examples 14 | /// ``` 15 | /// use core::num::NonZeroU32; 16 | /// use zeroize::{ZeroizeOnDrop, zeroize_flat_type}; 17 | /// 18 | /// # type ThirdPartyType = u32; 19 | /// 20 | /// struct DataToZeroize { 21 | /// buf: [u8; 32], 22 | /// // `ThirdPartyType` can be a type with private fields 23 | /// // defined in a third-party crate and which does not implement 24 | /// // `Zeroize` or zeroization on drop. 25 | /// data: ThirdPartyType, 26 | /// pos: NonZeroU32, 27 | /// } 28 | /// 29 | /// struct SomeMoreFlatData(u64); 30 | /// 31 | /// impl Drop for DataToZeroize { 32 | /// fn drop(&mut self) { 33 | /// self.buf = [0u8; 32]; 34 | /// self.data = ThirdPartyType::default(); 35 | /// self.pos = NonZeroU32::new(32).unwrap(); 36 | /// zeroize::optimization_barrier(self); 37 | /// } 38 | /// } 39 | /// 40 | /// impl zeroize::ZeroizeOnDrop for DataToZeroize {} 41 | /// 42 | /// let mut data = DataToZeroize { 43 | /// buf: [3u8; 32], 44 | /// data: ThirdPartyType::default(), 45 | /// pos: NonZeroU32::new(32).unwrap(), 46 | /// }; 47 | /// 48 | /// // data gets zeroized when dropped 49 | /// ``` 50 | /// 51 | /// Note that erasure of `ThirdPartyType` demonstrated above can be fragile if it contains 52 | /// `MaybeUninit` or `union` data. It also does not perform erasure of types like `Box` or `Vec`. 53 | pub fn optimization_barrier(val: &T) { 54 | #[cfg(all( 55 | not(miri), 56 | any( 57 | target_arch = "aarch64", 58 | target_arch = "arm", 59 | target_arch = "arm64ec", 60 | target_arch = "loongarch64", 61 | target_arch = "riscv32", 62 | target_arch = "riscv64", 63 | target_arch = "s390x", 64 | target_arch = "x86", 65 | target_arch = "x86_64", 66 | ) 67 | ))] 68 | unsafe { 69 | core::arch::asm!( 70 | "# {}", 71 | in(reg) val as *const T as *const (), 72 | options(readonly, preserves_flags, nostack), 73 | ); 74 | } 75 | #[cfg(not(all( 76 | not(miri), 77 | any( 78 | target_arch = "aarch64", 79 | target_arch = "arm", 80 | target_arch = "arm64ec", 81 | target_arch = "loongarch64", 82 | target_arch = "riscv32", 83 | target_arch = "riscv64", 84 | target_arch = "s390x", 85 | target_arch = "x86", 86 | target_arch = "x86_64", 87 | ) 88 | )))] 89 | { 90 | /// Custom version of `core::hint::black_box` implemented using 91 | /// `#[inline(never)]` and `read_volatile`. 92 | #[inline(never)] 93 | fn custom_black_box(p: *const u8) { 94 | let _ = unsafe { core::ptr::read_volatile(p) }; 95 | } 96 | 97 | core::hint::black_box(val); 98 | if size_of_val(val) > 0 { 99 | custom_black_box(val as *const T as *const u8); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /.github/workflows/cmov.yml: -------------------------------------------------------------------------------- 1 | name: cmov 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/cmov.yml" 7 | - "cmov/**" 8 | - "Cargo.*" 9 | push: 10 | branches: master 11 | 12 | permissions: 13 | contents: read 14 | 15 | defaults: 16 | run: 17 | working-directory: cmov 18 | 19 | env: 20 | CARGO_INCREMENTAL: 0 21 | RUSTFLAGS: "-Dwarnings" 22 | 23 | # Cancels CI jobs when new commits are pushed to a PR branch 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | minimal-versions: 30 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 31 | with: 32 | working-directory: ${{ github.workflow }} 33 | 34 | build: 35 | runs-on: ubuntu-latest 36 | strategy: 37 | matrix: 38 | rust: 39 | - 1.85.0 # MSRV 40 | - stable 41 | target: 42 | - thumbv7em-none-eabi 43 | - wasm32-unknown-unknown 44 | steps: 45 | - uses: actions/checkout@v6 46 | - uses: RustCrypto/actions/cargo-cache@master 47 | - uses: dtolnay/rust-toolchain@master 48 | with: 49 | toolchain: ${{ matrix.rust }} 50 | targets: ${{ matrix.target }} 51 | - uses: RustCrypto/actions/cargo-hack-install@master 52 | - run: cargo build --target ${{ matrix.target }} 53 | 54 | test: 55 | strategy: 56 | matrix: 57 | include: 58 | # 32-bit Linux 59 | - target: i686-unknown-linux-gnu 60 | platform: ubuntu-latest 61 | rust: 1.85.0 # MSRV 62 | deps: sudo apt update && sudo apt install gcc-multilib 63 | 64 | # 64-bit Linux 65 | - target: x86_64-unknown-linux-gnu 66 | platform: ubuntu-latest 67 | rust: 1.85.0 # MSRV 68 | 69 | # 64-bit Windows 70 | - target: x86_64-pc-windows-msvc 71 | platform: windows-latest 72 | rust: 1.85.0 # MSRV 73 | 74 | # 64-bit macOS 75 | - target: x86_64-apple-darwin 76 | platform: macos-latest 77 | rust: 1.85.0 # MSRV 78 | 79 | runs-on: ${{ matrix.platform }} 80 | steps: 81 | - uses: actions/checkout@v6 82 | - uses: RustCrypto/actions/cargo-cache@master 83 | - uses: dtolnay/rust-toolchain@master 84 | with: 85 | toolchain: ${{ matrix.rust }} 86 | targets: ${{ matrix.target }} 87 | - run: ${{ matrix.deps }} 88 | - run: cargo test --target ${{ matrix.target }} 89 | 90 | # Test using `cargo careful` 91 | test-careful: 92 | runs-on: ubuntu-latest 93 | steps: 94 | - uses: actions/checkout@v6 95 | - uses: dtolnay/rust-toolchain@nightly 96 | - run: cargo install cargo-careful 97 | - run: cargo careful test --all-features 98 | 99 | # Cross-compiled tests 100 | test-cross: 101 | strategy: 102 | matrix: 103 | include: 104 | # ARM64 105 | - target: aarch64-unknown-linux-gnu 106 | rust: 1.85.0 # MSRV 107 | - target: aarch64-unknown-linux-gnu 108 | rust: stable 109 | # PPC32 110 | - target: powerpc-unknown-linux-gnu 111 | rust: 1.85.0 # MSRV 112 | - target: powerpc-unknown-linux-gnu 113 | rust: stable 114 | runs-on: ubuntu-latest 115 | steps: 116 | - uses: actions/checkout@v6 117 | - uses: RustCrypto/actions/cargo-cache@master 118 | - uses: dtolnay/rust-toolchain@master 119 | with: 120 | toolchain: ${{ matrix.rust }} 121 | targets: ${{ matrix.target }} 122 | - uses: RustCrypto/actions/cross-install@master 123 | - run: cross test --target ${{ matrix.target }} 124 | -------------------------------------------------------------------------------- /digest-io/src/writer.rs: -------------------------------------------------------------------------------- 1 | use digest::{Digest, FixedOutputReset, Output, Reset}; 2 | use std::io; 3 | 4 | /// Abstraction over a writer which hashes the data being written. 5 | #[derive(Debug)] 6 | pub struct HashWriter { 7 | writer: W, 8 | hasher: D, 9 | } 10 | 11 | impl HashWriter { 12 | /// Construct a new `HashWriter` given an existing `writer` by value. 13 | pub fn new(writer: W) -> Self { 14 | Self::new_from_parts(D::new(), writer) 15 | } 16 | 17 | /// Construct a new `HashWriter` given an existing `hasher` and `writer` by value. 18 | pub fn new_from_parts(hasher: D, writer: W) -> Self { 19 | HashWriter { writer, hasher } 20 | } 21 | 22 | /// Replace the writer with another writer 23 | pub fn replace_writer(&mut self, writer: W) { 24 | self.writer = writer; 25 | } 26 | 27 | /// Gets a reference to the underlying hasher 28 | pub fn get_hasher(&self) -> &D { 29 | &self.hasher 30 | } 31 | 32 | /// Gets a reference to the underlying writer 33 | pub fn get_writer(&self) -> &W { 34 | &self.writer 35 | } 36 | 37 | /// Gets a mutable reference to the underlying hasher 38 | /// Updates to the digest are not written to the underlying writer 39 | pub fn get_hasher_mut(&mut self) -> &mut D { 40 | &mut self.hasher 41 | } 42 | 43 | /// Gets a mutable reference to the underlying writer 44 | /// Direct writes to the underlying writer are not hashed 45 | pub fn get_writer_mut(&mut self) -> &mut W { 46 | &mut self.writer 47 | } 48 | 49 | /// Consume the HashWriter and return its hasher 50 | pub fn into_hasher(self) -> D { 51 | self.hasher 52 | } 53 | 54 | /// Consume the HashWriter and return its internal writer 55 | pub fn into_inner_writer(self) -> W { 56 | self.writer 57 | } 58 | 59 | /// Consume the HashWriter and return its hasher and internal writer 60 | pub fn into_parts(self) -> (D, W) { 61 | (self.hasher, self.writer) 62 | } 63 | 64 | /// Retrieve result and consume HashWriter instance. 65 | pub fn finalize(self) -> Output { 66 | self.hasher.finalize() 67 | } 68 | 69 | /// Write result into provided array and consume the HashWriter instance. 70 | pub fn finalize_into(self, out: &mut Output) { 71 | self.hasher.finalize_into(out) 72 | } 73 | 74 | /// Get output size of the hasher 75 | pub fn output_size() -> usize { 76 | ::output_size() 77 | } 78 | } 79 | 80 | impl Clone for HashWriter { 81 | fn clone(&self) -> HashWriter { 82 | HashWriter { 83 | writer: self.writer.clone(), 84 | hasher: self.hasher.clone(), 85 | } 86 | } 87 | } 88 | 89 | impl io::Write for HashWriter { 90 | fn write(&mut self, buf: &[u8]) -> io::Result { 91 | let bytes = self.writer.write(buf)?; 92 | 93 | if bytes > 0 { 94 | self.hasher.update(&buf[0..bytes]); 95 | } 96 | 97 | Ok(bytes) 98 | } 99 | 100 | fn flush(&mut self) -> io::Result<()> { 101 | self.writer.flush() 102 | } 103 | } 104 | 105 | impl HashWriter { 106 | /// Retrieve result and reset hasher instance. 107 | pub fn finalize_reset(&mut self) -> Output { 108 | Digest::finalize_reset(&mut self.hasher) 109 | } 110 | 111 | /// Write result into provided array and reset the hasher instance. 112 | pub fn finalize_into_reset(&mut self, out: &mut Output) { 113 | Digest::finalize_into_reset(&mut self.hasher, out) 114 | } 115 | } 116 | 117 | impl Reset for HashWriter { 118 | fn reset(&mut self) { 119 | Digest::reset(&mut self.hasher) 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /cmov/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: CMOV (Conditional Move) 2 | 3 | [![Crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache 2.0/MIT Licensed][license-image] 7 | ![MSRV][msrv-image] 8 | 9 | Conditional move CPU intrinsics which are guaranteed to execute in 10 | constant-time and not be rewritten as branches by the compiler. 11 | 12 | Provides wrappers for the [CMOV family] of instructions on x86/x86_64 and 13 | the [CSEL] instruction on AArch64 CPUs, along with a portable fallback 14 | implementation for other CPU architectures. 15 | 16 | [Documentation][docs-link] 17 | 18 | ## About 19 | 20 | Conditional move intrinsics provide [predication] which allows selection 21 | of one or more values without using branch instructions, thus making the 22 | selection constant-time with respect to the values, and not subject to CPU 23 | execution features which might introduce timing or other microarchitectural 24 | sidechannels introduced by branch prediction or other speculative execution 25 | features. 26 | 27 | Intel has confirmed that all extant CPUs implement the CMOV family of 28 | instructions in constant-time, and that this property will hold for future 29 | Intel CPUs as well. 30 | 31 | This crate provides wrappers for the CMOV/CSEL instructions implemented using 32 | inline assembly as stabilized in Rust 1.59. This means the implementation 33 | is a black box that will not be rewritten by e.g. LLVM's architecture-specific 34 | lowerings, such as the [x86-cmov-conversion] pass. 35 | 36 | ## Supported target architectures 37 | 38 | This crate provides guaranteed constant-time operation using inline assembly 39 | on the following CPU architectures: 40 | 41 | - [x] `x86` (`CMOVZ`, `CMOVNZ`) 42 | - [x] `x86_64` (`CMOVZ`, `CMOVNZ`) 43 | - [x] `aarch64` (`CSEL`) 44 | 45 | On other target architectures, a "best effort" portable fallback implementation 46 | based on bitwise arithmetic is used instead. However, we cannot guarantee that 47 | this implementation generates branch-free code. 48 | 49 | It's possible to extend constant-time guarantees to other CPU architectures. 50 | Please open an issue with your desired CPU architecture if this interests you. 51 | 52 | ## Minimum Supported Rust Version (MSRV) Policy 53 | 54 | MSRV increases are not considered breaking changes and can happen in patch 55 | releases. 56 | 57 | The crate MSRV accounts for all supported targets and crate feature 58 | combinations, excluding explicitly unstable features. 59 | 60 | ## License 61 | 62 | Licensed under either of: 63 | 64 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 65 | * [MIT license](http://opensource.org/licenses/MIT) 66 | 67 | at your option. 68 | 69 | ### Contribution 70 | 71 | Unless you explicitly state otherwise, any contribution intentionally submitted 72 | for inclusion in the work by you, as defined in the Apache-2.0 license, shall be 73 | dual licensed as above, without any additional terms or conditions. 74 | 75 | [//]: # (badges) 76 | 77 | [crate-image]: https://img.shields.io/crates/v/cmov.svg 78 | [crate-link]: https://crates.io/crates/cmov 79 | [docs-image]: https://docs.rs/cmov/badge.svg 80 | [docs-link]: https://docs.rs/cmov/ 81 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 82 | [msrv-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 83 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/cmov.yml/badge.svg?branch=master 84 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/cmov.yml?query=branch:master 85 | 86 | [//]: # (links) 87 | 88 | [RustCrypto]: https://github.com/RustCrypto 89 | [CMOV family]: https://www.jaist.ac.jp/iscenter-new/mpc/altix/altixdata/opt/intel/vtune/doc/users_guide/mergedProjects/analyzer_ec/mergedProjects/reference_olh/mergedProjects/instructions/instruct32_hh/vc35.htm 90 | [CSEL]: https://developer.arm.com/documentation/dui0802/b/CSEL 91 | [predication]: https://en.wikipedia.org/wiki/Predication_(computer_architecture) 92 | [x86-cmov-conversion]: https://dsprenkels.com/cmov-conversion.html 93 | -------------------------------------------------------------------------------- /ctutils/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![doc = include_str!("../README.md")] 3 | #![doc( 4 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg", 5 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo.svg" 6 | )] 7 | #![deny(unsafe_code)] 8 | #![warn( 9 | clippy::mod_module_files, 10 | missing_docs, 11 | missing_debug_implementations, 12 | missing_copy_implementations, 13 | rust_2018_idioms, 14 | trivial_casts, 15 | trivial_numeric_casts, 16 | unused_qualifications 17 | )] 18 | #![cfg_attr(not(test), warn(clippy::unwrap_used))] 19 | 20 | //! # API Design 21 | //! 22 | //! ## [`Choice`]: constant-time analogue for [`bool`] 23 | //! Values of this type are one of either [`Choice::FALSE`] or [`Choice::TRUE`]. 24 | //! 25 | //! To achieve constant-time operation, `Choice` is ultimately used in combination with special 26 | //! CPU-specific constant-time predication instructions implemented by the [`cmov`] crate 27 | //! (with a portable "best effort" fallback that cannot provide guarantees). 28 | //! 29 | //! It additionally uses various methods to hint to the compiler that it should avoid inserting 30 | //! branches based on its value where it otherwise would if `bool` were used instead, but cannot 31 | //! provide guarantees in this regard. 32 | //! 33 | //! ## [`CtOption`]: constant-time analogue for [`Option`] 34 | //! The core `Option` type is typically great for representing the conditional absence or presence 35 | //! of a value, and provides a number of handy combinators for operating on them. 36 | //! 37 | //! However, it has a rather fundamental flaw when constant-time is desirable: its combinators are 38 | //! lazily evaluated. To ensure constant-time operation, all combinators must be eagerly evaluated 39 | //! so they aren't conditionally executed based on the value's presence. 40 | //! 41 | //! `CtOption` instead carries a `Choice` along with a value, which makes it possible to do 42 | //! something it isn't with `Option`: evaluate combinators eagerly instead of lazily, running the 43 | //! same functions regardless of the value's effective presence or absence. 44 | //! 45 | //! ## [`CtEq`]: constant-time analogue for [`PartialEq`]/[`Eq`] 46 | //! Equality testing often short circuits for performance reasons, but when comparing values in 47 | //! constant-time such short-circuiting is forbidden. 48 | //! 49 | //! The `CtEq` trait is a replacement for these scenarios. It's impl'd for several core types 50 | //! including unsigned and signed integers as well as slices and arrays. It returns a `Choice` 51 | //! as opposed to a `bool`], following the standard practice in this crate. 52 | //! 53 | //! *NOTE: for `subtle` users, this is the equivalent of the `ConstantTimeEq` trait* 54 | //! 55 | //! ## [`CtSelect`]: constant-time [predication] 56 | //! Predication in computer architecture describes methods for conditionally modifying state 57 | //! using non-branch instructions which perform conditional modifications based on a *predicate* 58 | //! or boolean value, in the design of this library a `Choice`. 59 | //! 60 | //! The `CtSelect` trait provides methods for performing conditional moves, either conditionally 61 | //! modifying a value in-place, or selecting from two different inputs and returning a new one. 62 | //! 63 | //! *NOTE: for `subtle` users, this is the equivalent of the `ConditionallySelectable` trait* 64 | //! 65 | //! [predication]: https://en.wikipedia.org/wiki/Predication_(computer_architecture) 66 | //! 67 | //! # [`subtle`] interop 68 | //! 69 | //! When the `subtle` feature of this crate is enabled, bidirectional [`From`] impls are available 70 | //! for the following types: 71 | //! 72 | //! - [`Choice`] <=> [`subtle::Choice`] 73 | //! - [`CtOption`] <=> [`subtle::CtOption`] 74 | //! 75 | //! This makes it possible to use `ctutils` in a codebase where other dependencies are using 76 | //! `subtle`. 77 | 78 | mod choice; 79 | mod ct_option; 80 | mod traits; 81 | 82 | pub use choice::Choice; 83 | pub use ct_option::CtOption; 84 | pub use traits::{ct_eq::CtEq, ct_gt::CtGt, ct_lt::CtLt, ct_select::CtSelect}; 85 | -------------------------------------------------------------------------------- /digest-io/src/reader.rs: -------------------------------------------------------------------------------- 1 | use digest::{Digest, FixedOutputReset, Output, Reset}; 2 | use std::io; 3 | 4 | /// Abstraction over a reader which hashes the data being read 5 | #[derive(Debug)] 6 | pub struct HashReader { 7 | reader: R, 8 | hasher: D, 9 | } 10 | 11 | impl HashReader { 12 | /// Construct a new `HashReader` given an existing `reader` by value. 13 | pub fn new(reader: R) -> Self { 14 | Self::new_from_parts(D::new(), reader) 15 | } 16 | 17 | /// Construct a new `HashReader` given an existing `hasher` and `reader` by value. 18 | pub fn new_from_parts(hasher: D, reader: R) -> Self { 19 | HashReader { reader, hasher } 20 | } 21 | 22 | /// Replace the reader with another reader 23 | pub fn replace_reader(&mut self, reader: R) { 24 | self.reader = reader; 25 | } 26 | 27 | /// Gets a reference to the underlying hasher 28 | pub fn get_hasher(&self) -> &D { 29 | &self.hasher 30 | } 31 | 32 | /// Gets a reference to the underlying reader 33 | pub fn get_reader(&self) -> &R { 34 | &self.reader 35 | } 36 | 37 | /// Gets a mutable reference to the underlying hasher 38 | pub fn get_hasher_mut(&mut self) -> &mut D { 39 | &mut self.hasher 40 | } 41 | 42 | /// Gets a mutable reference to the underlying reader 43 | /// Direct reads from the underlying reader are not hashed 44 | pub fn get_reader_mut(&mut self) -> &mut R { 45 | &mut self.reader 46 | } 47 | 48 | /// Consume the HashReader and return its hasher 49 | pub fn into_hasher(self) -> D { 50 | self.hasher 51 | } 52 | 53 | /// Consume the HashReader and return its internal reader 54 | pub fn into_inner_reader(self) -> R { 55 | self.reader 56 | } 57 | 58 | /// Consume the HashReader and return its hasher and internal reader 59 | pub fn into_parts(self) -> (D, R) { 60 | (self.hasher, self.reader) 61 | } 62 | 63 | /// Retrieve result and consume HashReader instance. 64 | pub fn finalize(self) -> Output { 65 | self.hasher.finalize() 66 | } 67 | 68 | /// Write result into provided array and consume the HashReader instance. 69 | pub fn finalize_into(self, out: &mut Output) { 70 | self.hasher.finalize_into(out) 71 | } 72 | 73 | /// Get output size of the hasher 74 | pub fn output_size() -> usize { 75 | ::output_size() 76 | } 77 | } 78 | 79 | impl Clone for HashReader { 80 | fn clone(&self) -> HashReader { 81 | HashReader { 82 | reader: self.reader.clone(), 83 | hasher: self.hasher.clone(), 84 | } 85 | } 86 | } 87 | 88 | impl io::Read for HashReader { 89 | fn read(&mut self, buf: &mut [u8]) -> io::Result { 90 | let bytes = self.reader.read(buf)?; 91 | 92 | if bytes > 0 { 93 | self.hasher.update(&buf[0..bytes]); 94 | } 95 | 96 | Ok(bytes) 97 | } 98 | } 99 | 100 | impl HashReader { 101 | /// Retrieve result and reset hasher instance. 102 | pub fn finalize_reset(&mut self) -> Output { 103 | Digest::finalize_reset(&mut self.hasher) 104 | } 105 | 106 | /// Rrite result into provided array and reset the hasher instance. 107 | pub fn finalize_into_reset(&mut self, out: &mut Output) { 108 | Digest::finalize_into_reset(&mut self.hasher, out) 109 | } 110 | } 111 | 112 | impl Reset for HashReader { 113 | fn reset(&mut self) { 114 | Digest::reset(&mut self.hasher) 115 | } 116 | } 117 | 118 | impl HashReader { 119 | /// Read and hash all bytes remaining in the reader, discarding the data 120 | /// Based on implementation in b2sum crate, MIT License Copyright (c) 2017 John Downey 121 | pub fn hash_to_end(&mut self) { 122 | loop { 123 | let count = { 124 | let data = self.reader.fill_buf().unwrap(); 125 | if data.is_empty() { 126 | break; 127 | } 128 | 129 | self.hasher.update(data); 130 | data.len() 131 | }; 132 | 133 | self.reader.consume(count); 134 | } 135 | } 136 | } 137 | -------------------------------------------------------------------------------- /.github/workflows/cpufeatures.yml: -------------------------------------------------------------------------------- 1 | name: cpufeatures 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - "cpufeatures/**" 7 | - "Cargo.*" 8 | push: 9 | branches: master 10 | 11 | permissions: 12 | contents: read 13 | 14 | defaults: 15 | run: 16 | working-directory: cpufeatures 17 | 18 | env: 19 | CARGO_INCREMENTAL: 0 20 | RUSTFLAGS: "-Dwarnings" 21 | 22 | # Cancels CI jobs when new commits are pushed to a PR branch 23 | concurrency: 24 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 25 | cancel-in-progress: true 26 | 27 | jobs: 28 | minimal-versions: 29 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 30 | with: 31 | working-directory: ${{ github.workflow }} 32 | 33 | # Linux tests 34 | linux: 35 | strategy: 36 | matrix: 37 | include: 38 | # 32-bit Linux/x86 39 | - target: i686-unknown-linux-gnu 40 | rust: 1.85.0 # MSRV 41 | deps: sudo apt update && sudo apt install gcc-multilib 42 | - target: i686-unknown-linux-gnu 43 | rust: stable 44 | deps: sudo apt update && sudo apt install gcc-multilib 45 | 46 | # 64-bit Linux/x86_64 47 | - target: x86_64-unknown-linux-gnu 48 | rust: 1.85.0 # MSRV 49 | - target: x86_64-unknown-linux-gnu 50 | rust: stable 51 | runs-on: ubuntu-latest 52 | steps: 53 | - uses: actions/checkout@v6 54 | - uses: RustCrypto/actions/cargo-cache@master 55 | - uses: dtolnay/rust-toolchain@master 56 | with: 57 | toolchain: ${{ matrix.rust }} 58 | targets: ${{ matrix.target }} 59 | # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates 60 | - run: rm ../Cargo.toml 61 | - run: ${{ matrix.deps }} 62 | - run: cargo test --target ${{ matrix.target }} 63 | 64 | # macOS tests 65 | macos: 66 | strategy: 67 | matrix: 68 | toolchain: 69 | - 1.85.0 # MSRV 70 | - stable 71 | runs-on: macos-latest 72 | steps: 73 | - uses: actions/checkout@v6 74 | - uses: RustCrypto/actions/cargo-cache@master 75 | - uses: dtolnay/rust-toolchain@master 76 | with: 77 | toolchain: ${{ matrix.toolchain }} 78 | targets: x86_64-apple-darwin 79 | # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates 80 | - run: rm ../Cargo.toml 81 | - run: cargo test 82 | 83 | # Windows tests 84 | windows: 85 | strategy: 86 | matrix: 87 | include: 88 | # 64-bit Windows (GNU) 89 | - target: x86_64-pc-windows-gnu 90 | toolchain: 1.85.0 # MSRV 91 | - target: x86_64-pc-windows-gnu 92 | toolchain: stable 93 | runs-on: windows-latest 94 | steps: 95 | - uses: actions/checkout@v6 96 | - uses: RustCrypto/actions/cargo-cache@master 97 | - uses: dtolnay/rust-toolchain@master 98 | with: 99 | toolchain: ${{ matrix.toolchain }} 100 | targets: ${{ matrix.target }} 101 | # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates 102 | - run: rm ../Cargo.toml 103 | - run: cargo test --target ${{ matrix.target }} 104 | 105 | # Cross-compiled tests 106 | cross: 107 | strategy: 108 | matrix: 109 | include: 110 | # ARM64 111 | - target: aarch64-unknown-linux-gnu 112 | rust: 1.85.0 # MSRV 113 | - target: aarch64-unknown-linux-gnu 114 | rust: stable 115 | runs-on: ubuntu-latest 116 | steps: 117 | - uses: actions/checkout@v6 118 | - uses: RustCrypto/actions/cargo-cache@master 119 | - uses: dtolnay/rust-toolchain@master 120 | with: 121 | toolchain: ${{ matrix.rust }} 122 | targets: ${{ matrix.target }} 123 | - uses: RustCrypto/actions/cross-install@master 124 | # Isolate this crate from workspace which is otherwise MSRV 1.56 due to 2021 edition crates 125 | - run: rm ../Cargo.toml 126 | - run: cross test --target ${{ matrix.target }} 127 | 128 | # Build-only tests 129 | build-only: 130 | runs-on: ubuntu-latest 131 | steps: 132 | - uses: actions/checkout@v6 133 | - uses: RustCrypto/actions/cargo-cache@master 134 | - uses: dtolnay/rust-toolchain@master 135 | with: 136 | toolchain: stable 137 | - run: rustup target add loongarch64-unknown-linux-gnu 138 | - run: cargo build --target loongarch64-unknown-linux-gnu 139 | -------------------------------------------------------------------------------- /digest-io/README.md: -------------------------------------------------------------------------------- 1 | # [RustCrypto]: `std::io`-compatibility wrappers for `digest` 2 | 3 | [![crate][crate-image]][crate-link] 4 | [![Docs][docs-image]][docs-link] 5 | [![Build Status][build-image]][build-link] 6 | ![Apache2/MIT licensed][license-image] 7 | ![Rust Version][rustc-image] 8 | [![Project Chat][chat-image]][chat-link] 9 | 10 | Wrappers for compatibility between `std::io` and `digest` traits. 11 | 12 | ## Examples 13 | 14 | Updating hash function by writing data into it: 15 | 16 | ```rust 17 | use digest_io::IoWrapper; 18 | use sha2::{Digest, Sha256}; 19 | use std::{fs::File, io}; 20 | 21 | fn main() -> io::Result<()> { 22 | // Wrap SHA-256 hash function 23 | let mut hasher = IoWrapper(Sha256::new()); 24 | 25 | // Write contents of the file to the wrapped hasher 26 | let mut f = File::open("Cargo.toml")?; 27 | io::copy(&mut f, &mut hasher)?; 28 | 29 | // Get the resulting hash of the file data 30 | let hash = hasher.0.finalize(); 31 | 32 | println!("{hash:?}"); 33 | Ok(()) 34 | } 35 | ``` 36 | 37 | Reading data from a XOF reader: 38 | 39 | ```rust 40 | use digest_io::IoWrapper; 41 | use sha3::{Shake128, digest::ExtendableOutput}; 42 | use std::{fs::File, io}; 43 | 44 | fn read_array(r: &mut impl io::Read) -> io::Result<[u8; 64]> { 45 | let mut buf = [0u8; 64]; 46 | r.read_exact(&mut buf)?; 47 | Ok(buf) 48 | } 49 | 50 | fn main() -> io::Result<()> { 51 | // Create XOF reader 52 | let mut hasher = IoWrapper(Shake128::default()); 53 | let mut f = File::open("Cargo.toml")?; 54 | io::copy(&mut f, &mut hasher)?; 55 | let reader = hasher.0.finalize_xof(); 56 | 57 | // Wrap the reader and read data from it 58 | let mut reader = IoWrapper(reader); 59 | let buf = read_array(&mut reader)?; 60 | println!("{buf:?}"); 61 | 62 | Ok(()) 63 | } 64 | ``` 65 | 66 | Simultaneously reading and hashing file data: 67 | ```rust 68 | use digest_io::HashReader; 69 | use sha2::Sha256; 70 | use std::{ 71 | fs::File, 72 | io::{self, Read}, 73 | }; 74 | 75 | fn main() -> io::Result<()> { 76 | // Create new hashing reader 77 | let f = File::open("Cargo.toml")?; 78 | let mut reader = HashReader::::new(f); 79 | 80 | // Read all data from the file 81 | let mut buf = Vec::new(); 82 | reader.read_to_end(&mut buf)?; 83 | 84 | // Get the resulting hash over read data 85 | let hash = reader.finalize(); 86 | println!("Data: {buf:?}"); 87 | println!("Hash: {hash:?}"); 88 | Ok(()) 89 | } 90 | ``` 91 | 92 | Simultaneously hashing data and writing it to file: 93 | ```rust 94 | use digest_io::HashWriter; 95 | use sha2::{Digest, Sha256}; 96 | use std::{ 97 | fs::File, 98 | io::{self, Write}, 99 | }; 100 | 101 | fn main() -> io::Result<()> { 102 | // Create new hashing reader 103 | let f = File::create("out.txt")?; 104 | let mut writer = HashWriter::::new(f); 105 | 106 | // Write data to the file 107 | let data = b"Hello world!"; 108 | writer.write_all(data)?; 109 | 110 | // Get the resulting hash over written data 111 | let hash = writer.finalize(); 112 | println!("{hash:?}"); 113 | assert_eq!(hash, Sha256::digest(data)); 114 | std::fs::remove_file("out.txt")?; 115 | Ok(()) 116 | } 117 | ``` 118 | 119 | 120 | ## License 121 | 122 | Licensed under either of: 123 | 124 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 125 | * [MIT license](http://opensource.org/licenses/MIT) 126 | 127 | at your option. 128 | 129 | ### Contribution 130 | 131 | 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. 132 | 133 | [//]: # (badges) 134 | 135 | [crate-image]: https://img.shields.io/crates/v/digest-io.svg 136 | [crate-link]: https://crates.io/crates/digest-io 137 | [docs-image]: https://docs.rs/digest-io/badge.svg 138 | [docs-link]: https://docs.rs/digest-io/ 139 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 140 | [rustc-image]: https://img.shields.io/badge/rustc-1.85+-blue.svg 141 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 142 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils 143 | [build-image]: https://github.com/RustCrypto/utils/actions/workflows/digest-io.yml/badge.svg?branch=master 144 | [build-link]: https://github.com/RustCrypto/utils/actions/workflows/digest-io.yml?query=branch:master 145 | 146 | [//]: # (general links) 147 | 148 | [RustCrypto]: https://github.com/rustcrypto 149 | -------------------------------------------------------------------------------- /wycheproof2blb/src/wycheproof.rs: -------------------------------------------------------------------------------- 1 | //! Helpers for retrieving Wycheproof test vectors. 2 | 3 | use serde::Deserialize; 4 | 5 | /// `Suite` represents the common elements of the top level object in a Wycheproof json 6 | /// file. Implementations should embed (using `#[serde(flatten)]`) `Suite` in a struct 7 | /// that strongly types the `testGroups` field. 8 | #[derive(Debug, Deserialize)] 9 | pub struct Suite { 10 | pub algorithm: String, 11 | #[serde(rename = "generatorVersion")] 12 | pub generator_version: String, 13 | #[serde(rename = "numberOfTests")] 14 | pub number_of_tests: i32, 15 | pub notes: std::collections::HashMap, 16 | } 17 | 18 | /// `Group` represents the common elements of a testGroups object in a Wycheproof suite. 19 | /// Implementations should embed (using `#[serde(flatten)]`) Group in a struct that 20 | /// strongly types its list of cases. 21 | #[derive(Debug, Deserialize)] 22 | pub struct Group { 23 | #[serde(rename = "type")] 24 | pub group_type: String, 25 | } 26 | 27 | /// `Result` represents the possible result values for a Wycheproof test case. 28 | #[derive(Debug, PartialEq, Eq)] 29 | pub enum CaseResult { 30 | /// Test case is valid, the crypto operation should succeed. 31 | Valid, 32 | /// Test case is invalid; the crypto operation should fail. 33 | Invalid, 34 | /// Test case is valid, but uses weak parameters; the crypto operation might succeed 35 | /// or fail depending on how strict the library is. 36 | Acceptable, 37 | } 38 | 39 | impl std::fmt::Display for CaseResult { 40 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 41 | write!( 42 | f, 43 | "{}", 44 | match self { 45 | CaseResult::Valid => "valid", 46 | CaseResult::Invalid => "invalid", 47 | CaseResult::Acceptable => "acceptable", 48 | } 49 | ) 50 | } 51 | } 52 | 53 | /// `Case` represents the common elements of a tests object in a Wycheproof group. 54 | /// Implementations should embed (using `#[serde(flatten)]`) `Case` in a struct that 55 | /// contains fields specific to the test type. 56 | #[derive(Debug, Deserialize)] 57 | pub struct Case { 58 | #[serde(rename = "tcId")] 59 | pub case_id: i32, 60 | pub comment: String, 61 | #[serde(with = "case_result")] 62 | pub result: CaseResult, 63 | #[serde(default)] 64 | pub flags: Vec, 65 | } 66 | 67 | pub mod hex_string { 68 | //! Manual JSON deserialization implementation for hex strings. 69 | use serde::Deserialize; 70 | pub fn deserialize<'de, D: serde::Deserializer<'de>>( 71 | deserializer: D, 72 | ) -> Result, D::Error> { 73 | let s = String::deserialize(deserializer)?; 74 | ::hex::decode(&s).map_err(|_e| { 75 | serde::de::Error::invalid_value(serde::de::Unexpected::Str(&s), &"hex data expected") 76 | }) 77 | } 78 | } 79 | 80 | pub mod case_result { 81 | //! Manual JSON deserialization for a `result` enum. 82 | use serde::Deserialize; 83 | pub fn deserialize<'de, D: serde::Deserializer<'de>>( 84 | deserializer: D, 85 | ) -> Result { 86 | let s = String::deserialize(deserializer)?; 87 | match s.as_ref() { 88 | "valid" => Ok(super::CaseResult::Valid), 89 | "invalid" => Ok(super::CaseResult::Invalid), 90 | "acceptable" => Ok(super::CaseResult::Acceptable), 91 | _ => Err(serde::de::Error::invalid_value( 92 | serde::de::Unexpected::Str(&s), 93 | &"unexpected result value", 94 | )), 95 | } 96 | } 97 | } 98 | 99 | /// Convert a `result` enum to a byte. 100 | pub fn case_result(case: &Case) -> u8 { 101 | match case.result { 102 | CaseResult::Invalid => 0u8, 103 | CaseResult::Valid => 1u8, 104 | _ => panic!("Unexpected case result {}", case.result), 105 | } 106 | } 107 | 108 | /// Retrieve Wycheproof test vectors from the given filename in a Wycheproof repo. 109 | pub fn data(wycheproof_dir: &str, filename: &str) -> Vec { 110 | let path = std::path::Path::new(&wycheproof_dir) 111 | .join("testvectors") 112 | .join(filename); 113 | std::fs::read(&path) 114 | .unwrap_or_else(|_| panic!("Test vector file {filename} not found at {path:?}")) 115 | } 116 | 117 | /// Build a description for a test case in a suite 118 | pub fn description(suite: &Suite, case: &Case) -> String { 119 | format!( 120 | "{} case {} [{}] {}", 121 | suite.algorithm, case.case_id, case.result, case.comment 122 | ) 123 | } 124 | -------------------------------------------------------------------------------- /ctutils/src/traits/ct_eq.rs: -------------------------------------------------------------------------------- 1 | use crate::Choice; 2 | use cmov::CmovEq; 3 | use core::cmp; 4 | 5 | /// Constant-time equality: like `(Partial)Eq` with [`Choice`] instead of [`bool`]. 6 | /// 7 | /// Impl'd for: [`u8`], [`u16`], [`u32`], [`u64`], [`u128`], [`usize`], [`cmp::Ordering`], 8 | /// [`Choice`], and arrays/slices of any type which also impls [`CtEq`]. 9 | pub trait CtEq 10 | where 11 | Rhs: ?Sized, 12 | { 13 | /// Equality 14 | fn ct_eq(&self, other: &Rhs) -> Choice; 15 | 16 | /// Inequality 17 | fn ct_ne(&self, other: &Rhs) -> Choice { 18 | !self.ct_eq(other) 19 | } 20 | } 21 | 22 | // Impl `CtEq` using the `cmov::CmovEq` trait 23 | macro_rules! impl_unsigned_ct_eq_with_cmov { 24 | ( $($uint:ty),+ ) => { 25 | $( 26 | impl CtEq for $uint { 27 | #[inline] 28 | fn ct_eq(&self, other: &Self) -> Choice { 29 | let mut ret = 0; 30 | self.cmoveq(other, 1, &mut ret); 31 | Choice::new(ret) 32 | } 33 | } 34 | )+ 35 | }; 36 | } 37 | 38 | // Impl `CtEq` by first casting to unsigned then using the unsigned `CtEq` impls 39 | // TODO(tarcieri): add signed integer support to `cmov` 40 | macro_rules! impl_signed_ct_eq_with_cmov { 41 | ( $($int:ty => $uint:ty),+ ) => { 42 | $( 43 | impl CtEq for $int { 44 | #[inline] 45 | fn ct_eq(&self, other: &Self) -> Choice { 46 | (*self as $uint).ct_eq(&(*other as $uint)) 47 | } 48 | } 49 | )+ 50 | }; 51 | } 52 | 53 | impl_unsigned_ct_eq_with_cmov!(u8, u16, u32, u64, u128); 54 | impl_signed_ct_eq_with_cmov!(i8 => u8, i16 => u16, i32 => u32, i64 => u64, i128 => u128); 55 | 56 | #[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))] 57 | impl CtEq for usize { 58 | #[cfg(target_pointer_width = "32")] 59 | fn ct_eq(&self, other: &Self) -> Choice { 60 | (*self as u32).ct_eq(&(*other as u32)) 61 | } 62 | 63 | #[cfg(target_pointer_width = "64")] 64 | fn ct_eq(&self, other: &Self) -> Choice { 65 | (*self as u64).ct_eq(&(*other as u64)) 66 | } 67 | } 68 | 69 | impl CtEq for cmp::Ordering { 70 | #[inline] 71 | fn ct_eq(&self, other: &Self) -> Choice { 72 | // `Ordering` is `repr(i8)`, which has a `CtEq` impl 73 | (*self as i8).ct_eq(&(*other as i8)) 74 | } 75 | } 76 | 77 | impl CtEq for [T] { 78 | #[inline] 79 | fn ct_eq(&self, other: &[T]) -> Choice { 80 | let mut ret = self.len().ct_eq(&other.len()); 81 | for (a, b) in self.iter().zip(other.iter()) { 82 | ret &= a.ct_eq(b); 83 | } 84 | ret 85 | } 86 | } 87 | 88 | impl CtEq for [T; N] { 89 | #[inline] 90 | fn ct_eq(&self, other: &[T; N]) -> Choice { 91 | self.as_slice().ct_eq(other.as_slice()) 92 | } 93 | } 94 | 95 | #[cfg(test)] 96 | mod tests { 97 | use super::CtEq; 98 | use core::cmp::Ordering; 99 | 100 | macro_rules! truth_table { 101 | ($a:expr, $b:expr, $c:expr) => { 102 | assert!($a.ct_eq(&$b).to_bool()); 103 | assert!(!$a.ct_eq(&$c).to_bool()); 104 | assert!(!$b.ct_eq(&$c).to_bool()); 105 | 106 | assert!(!$a.ct_ne(&$b).to_bool()); 107 | assert!($a.ct_ne(&$c).to_bool()); 108 | assert!($b.ct_ne(&$c).to_bool()); 109 | }; 110 | } 111 | 112 | macro_rules! ct_eq_test { 113 | ($ty:ty, $name:ident) => { 114 | #[test] 115 | fn $name() { 116 | let a: $ty = 42; 117 | let b: $ty = 42; 118 | let c: $ty = 1; 119 | truth_table!(a, b, c); 120 | } 121 | }; 122 | } 123 | 124 | ct_eq_test!(u8, u8_ct_eq); 125 | ct_eq_test!(u16, u16_ct_eq); 126 | ct_eq_test!(u32, u32_ct_eq); 127 | ct_eq_test!(u64, u64_ct_eq); 128 | ct_eq_test!(u128, u128_ct_eq); 129 | ct_eq_test!(usize, usize_ct_eq); 130 | 131 | #[test] 132 | fn array_ct_eq() { 133 | let a = [1u64, 2, 3]; 134 | let b = [1u64, 2, 3]; 135 | let c = [1u64, 2, 4]; 136 | truth_table!(a, b, c); 137 | } 138 | 139 | #[test] 140 | fn ordering_ct_eq() { 141 | let a = Ordering::Greater; 142 | let b = Ordering::Greater; 143 | let c = Ordering::Less; 144 | truth_table!(a, b, c); 145 | } 146 | 147 | #[test] 148 | fn slice_ct_eq() { 149 | let a: &[u64] = &[1, 2, 3]; 150 | let b: &[u64] = &[1, 2, 3]; 151 | let c: &[u64] = &[1, 2, 4]; 152 | truth_table!(a, b, c); 153 | 154 | // Length mismatches 155 | assert!(a.ct_ne(&[]).to_bool()); 156 | assert!(a.ct_ne(&[1, 2]).to_bool()); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /collectable/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides a set of traits that can be used to abstract over 2 | //! various collection types. In particular, it supports traits for fallible 3 | //! operations (such as [`TryExtend`]) which are useful for supporting 4 | //! fixed-capacity containers, such as `heapless::Vec` or `tinyvec::Array`. 5 | 6 | #![no_std] 7 | #![doc( 8 | html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg", 9 | html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg" 10 | )] 11 | 12 | #[cfg(feature = "alloc")] 13 | extern crate alloc; 14 | 15 | /// Collection types implement all of the traits in this crate. 16 | pub trait Collection: 17 | AsRef<[T]> + AsMut<[T]> + Default + Length + Truncate + TryExtend + TryPush 18 | { 19 | } 20 | 21 | /// Obtain the length of a collection. 22 | pub trait Length { 23 | /// Get the length of this collection. 24 | fn len(&self) -> usize; 25 | 26 | /// Is the collection empty? 27 | fn is_empty(&self) -> bool { 28 | self.len() == 0 29 | } 30 | } 31 | 32 | /// Truncate the collection to the provided length. 33 | pub trait Truncate { 34 | /// Truncate this buffer to the given number of elements. 35 | /// 36 | /// If `len` is bigger than the current number of elements (or the total 37 | /// capacity of the buffer) no changes are made to the contents. 38 | fn truncate(&mut self, len: usize); 39 | } 40 | 41 | /// Fallible equivalent of [`core::iter::Extend`] - extends a collection 42 | /// with the contents of an iterator, but with the option to return an error 43 | /// in the event the container's capacity has been exceeded. 44 | /// 45 | /// [`core::iter::Extend`]: https://doc.rust-lang.org/core/iter/trait.Extend.html 46 | pub trait TryExtend { 47 | /// Error type. 48 | type Error; 49 | 50 | /// Try to extend the collection from the given iterator. 51 | fn try_extend(&mut self, iter: T) -> Result<(), Self::Error> 52 | where 53 | T: IntoIterator; 54 | 55 | /// Try to extend the collection from the given slice. 56 | fn try_extend_from_slice(&mut self, slice: &[A]) -> Result<(), Self::Error> 57 | where 58 | A: Clone, 59 | { 60 | self.try_extend(slice.iter().cloned()) 61 | } 62 | } 63 | 64 | /// Try to build a collection type from an [`Iterator`]. 65 | /// 66 | /// Fallible in the event the capacity of the underlying container type is 67 | /// exceeded. 68 | pub trait TryFromIterator: Sized { 69 | /// Error type. 70 | type Error; 71 | 72 | /// Try to create a new collection from the given iterator, potentially 73 | /// returning an error if the underlying collection's capacity is exceeded. 74 | fn try_from_iter(iter: T) -> Result 75 | where 76 | T: IntoIterator; 77 | } 78 | 79 | impl> TryFromIterator for C { 80 | type Error = >::Error; 81 | 82 | fn try_from_iter(iter: T) -> Result 83 | where 84 | T: IntoIterator, 85 | { 86 | let mut collection = Self::default(); 87 | collection.try_extend(iter)?; 88 | Ok(collection) 89 | } 90 | } 91 | 92 | /// Try to push an element onto a collection 93 | pub trait TryPush { 94 | /// Try to push an element onto a collection. 95 | /// 96 | /// Returns the original element if it's full. 97 | fn try_push(&mut self, item: T) -> Result<(), T>; 98 | } 99 | 100 | /// [`TryCollect`] is an extension to [`Iterator`] which allows for performing 101 | /// a fallible collection into a collection type. 102 | pub trait TryCollect { 103 | fn try_collect(&mut self) -> Result 104 | where 105 | B: TryFromIterator; 106 | } 107 | 108 | impl TryCollect for T 109 | where 110 | T: Iterator, 111 | { 112 | fn try_collect(&mut self) -> Result 113 | where 114 | B: TryFromIterator, 115 | { 116 | B::try_from_iter(self) 117 | } 118 | } 119 | 120 | #[cfg(feature = "alloc")] 121 | mod vec_impls { 122 | use super::{Length, Truncate, TryExtend}; 123 | use alloc::vec::Vec; 124 | use core::convert::Infallible; 125 | 126 | impl Length for Vec { 127 | fn len(&self) -> usize { 128 | Vec::len(self) 129 | } 130 | } 131 | 132 | impl Truncate for Vec { 133 | fn truncate(&mut self, len: usize) { 134 | Vec::truncate(self, len); 135 | } 136 | } 137 | 138 | impl TryExtend for Vec { 139 | type Error = Infallible; 140 | 141 | fn try_extend>(&mut self, iter: T) -> Result<(), Infallible> { 142 | Vec::extend(self, iter); 143 | Ok(()) 144 | } 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /.github/workflows/zeroize.yml: -------------------------------------------------------------------------------- 1 | name: zeroize 2 | 3 | on: 4 | pull_request: 5 | paths: 6 | - ".github/workflows/zeroize.yml" 7 | - "zeroize/**" 8 | - "Cargo.*" 9 | push: 10 | branches: master 11 | 12 | permissions: 13 | contents: read 14 | 15 | defaults: 16 | run: 17 | working-directory: zeroize 18 | 19 | env: 20 | CARGO_INCREMENTAL: 0 21 | RUSTFLAGS: "-Dwarnings" 22 | 23 | # Cancels CI jobs when new commits are pushed to a PR branch 24 | concurrency: 25 | group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} 26 | cancel-in-progress: true 27 | 28 | jobs: 29 | build: 30 | runs-on: ubuntu-latest 31 | strategy: 32 | matrix: 33 | rust: 34 | - 1.85.0 # MSRV 35 | - stable 36 | target: 37 | - armv7a-none-eabi 38 | - thumbv7em-none-eabi 39 | - wasm32-unknown-unknown 40 | steps: 41 | - uses: actions/checkout@v6 42 | - uses: RustCrypto/actions/cargo-cache@master 43 | - uses: dtolnay/rust-toolchain@master 44 | with: 45 | toolchain: ${{ matrix.rust }} 46 | targets: ${{ matrix.target }} 47 | - run: cargo build --no-default-features --target ${{ matrix.target }} 48 | 49 | minimal-versions: 50 | uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master 51 | with: 52 | working-directory: ${{ github.workflow }} 53 | 54 | test: 55 | strategy: 56 | matrix: 57 | include: 58 | # 32-bit Linux 59 | - target: i686-unknown-linux-gnu 60 | platform: ubuntu-latest 61 | rust: 1.85.0 # MSRV 62 | deps: sudo apt update && sudo apt install gcc-multilib 63 | - target: i686-unknown-linux-gnu 64 | platform: ubuntu-latest 65 | rust: stable 66 | deps: sudo apt update && sudo apt install gcc-multilib 67 | 68 | # 64-bit Linux 69 | - target: x86_64-unknown-linux-gnu 70 | platform: ubuntu-latest 71 | rust: 1.85.0 # MSRV 72 | - target: x86_64-unknown-linux-gnu 73 | platform: ubuntu-latest 74 | rust: stable 75 | 76 | # 64-bit macOS x86_64 77 | - target: x86_64-apple-darwin 78 | platform: macos-latest 79 | rust: 1.85.0 # MSRV 80 | - target: x86_64-apple-darwin 81 | platform: macos-latest 82 | rust: stable 83 | 84 | # 64-bit Windows 85 | - target: x86_64-pc-windows-msvc 86 | platform: windows-latest 87 | rust: 1.85.0 # MSRV 88 | - target: x86_64-pc-windows-msvc 89 | platform: windows-latest 90 | rust: stable 91 | runs-on: ${{ matrix.platform }} 92 | steps: 93 | - uses: actions/checkout@v6 94 | - uses: RustCrypto/actions/cargo-cache@master 95 | - uses: dtolnay/rust-toolchain@master 96 | with: 97 | toolchain: ${{ matrix.rust }} 98 | targets: ${{ matrix.target }} 99 | - run: ${{ matrix.deps }} 100 | - run: cargo test --target ${{ matrix.target }} 101 | 102 | # Cross-compiled tests 103 | cross: 104 | strategy: 105 | matrix: 106 | include: 107 | # AArch64 108 | - target: aarch64-unknown-linux-gnu 109 | rust: 1.85.0 110 | - target: aarch64-unknown-linux-gnu 111 | rust: stable 112 | 113 | # PPC32 114 | - target: powerpc-unknown-linux-gnu 115 | rust: 1.85.0 # MSRV 116 | - target: powerpc-unknown-linux-gnu 117 | rust: stable 118 | runs-on: ubuntu-latest 119 | steps: 120 | - uses: actions/checkout@v6 121 | - uses: RustCrypto/actions/cargo-cache@master 122 | - uses: dtolnay/rust-toolchain@master 123 | with: 124 | toolchain: ${{ matrix.rust }} 125 | targets: ${{ matrix.target }} 126 | - uses: RustCrypto/actions/cross-install@master 127 | - run: cross test --target ${{ matrix.target }} 128 | - run: cross test --target ${{ matrix.target }} --all-features 129 | 130 | # Tests for x86-64 `simd` support 131 | x86: 132 | strategy: 133 | matrix: 134 | include: 135 | - target: x86_64-unknown-linux-gnu 136 | rust: 1.85.0 137 | - target: x86_64-unknown-linux-gnu 138 | rust: stable 139 | runs-on: ubuntu-latest 140 | steps: 141 | - uses: actions/checkout@v6 142 | - uses: RustCrypto/actions/cargo-cache@master 143 | - uses: dtolnay/rust-toolchain@master 144 | with: 145 | toolchain: ${{ matrix.rust }} 146 | targets: ${{ matrix.target }} 147 | - uses: RustCrypto/actions/cross-install@master 148 | - run: cargo test --target ${{ matrix.target }} --features simd 149 | - run: cargo test --target ${{ matrix.target }} --all-features 150 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RustCrypto: Utilities 2 | 3 | [![Project Chat][chat-image]][chat-link] 4 | [![dependency status][deps-image]][deps-link] 5 | ![Apache2/MIT licensed][license-image] 6 | 7 | This repository contains various utility crates used in the RustCrypto project. 8 | 9 | ## Crates 10 | 11 | | Name | crates.io | Docs | Description | 12 | |------|:---------:|:----:|-------------| 13 | | [`blobby`] | [![crates.io](https://img.shields.io/crates/v/blobby.svg)](https://crates.io/crates/blobby) | [![Documentation](https://docs.rs/blobby/badge.svg)](https://docs.rs/blobby) | Decoder of the simple de-duplicated binary blob storage format | 14 | | [`block-buffer`] | [![crates.io](https://img.shields.io/crates/v/block-buffer.svg)](https://crates.io/crates/block-buffer) | [![Documentation](https://docs.rs/block-buffer/badge.svg)](https://docs.rs/block-buffer) | Fixed size buffer for block processing of data | 15 | | [`block‑padding`] | [![crates.io](https://img.shields.io/crates/v/block-padding.svg)](https://crates.io/crates/block-padding) | [![Documentation](https://docs.rs/block-padding/badge.svg)](https://docs.rs/block-padding) | Padding and unpadding of messages divided into blocks | 16 | | [`cmov`] | [![crates.io](https://img.shields.io/crates/v/cmov.svg)](https://crates.io/crates/cmov) | [![Documentation](https://docs.rs/cmov/badge.svg)](https://docs.rs/cmov) | Conditional move intrinsics | 17 | | [`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) | Fallible, `no_std`-friendly collection traits | 18 | | [`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) | Lightweight and efficient alternative to the `is_x86_feature_detected!` macro | 19 | | [`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) | Double operation in Galois Field (GF) | 20 | | [`digest-io`] | [![crates.io](https://img.shields.io/crates/v/digest-io.svg)](https://crates.io/crates/digest-io) | [![Documentation](https://docs.rs/digest-io/badge.svg)](https://docs.rs/digest-io) | `std::io`-compatibility wrappers for traits defined in the `digest` crate | 21 | | [`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) | A macro for converting hexadecimal strings to a byte array at compile time | 22 | | [`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) | Custom reference types for code generic over in-place and buffer-to-buffer modes of operation. | 23 | | [`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) | Macro for opaque `Debug` trait implementation | 24 | | [`wycheproof2blb`] | | | | Utility for converting [Wycheproof] test vectors to the blobby format | 25 | | [`zeroize`] | [![crates.io](https://img.shields.io/crates/v/zeroize.svg)](https://crates.io/crates/zeroize) | [![Documentation](https://docs.rs/zeroize/badge.svg)](https://docs.rs/zeroize) | Securely zero memory while avoiding compiler optimizations | 26 | 27 | ## License 28 | 29 | All crates licensed under either of 30 | 31 | * [Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0) 32 | * [MIT license](http://opensource.org/licenses/MIT) 33 | 34 | at your option. 35 | 36 | ### Contribution 37 | 38 | 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. 39 | 40 | [//]: # (badges) 41 | 42 | [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg 43 | [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260052-utils 44 | [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg 45 | [deps-image]: https://deps.rs/repo/github/RustCrypto/utils/status.svg 46 | [deps-link]: https://deps.rs/repo/github/RustCrypto/utils 47 | 48 | [//]: # (crates) 49 | 50 | [`blobby`]: ./blobby 51 | [`block-buffer`]: ./block-buffer 52 | [`block‑padding`]: ./block-padding 53 | [`cmov`]: ./cmov 54 | [`collectable`]: ./collectable 55 | [`cpufeatures`]: ./cpufeatures 56 | [`dbl`]: ./dbl 57 | [`digest-io`]: ./digest-io 58 | [`hex-literal`]: ./hex-literal 59 | [`inout`]: ./inout 60 | [`opaque-debug`]: ./opaque-debug 61 | [`wycheproof2blb`]: ./wycheproof2blb 62 | [`zeroize`]: ./zeroize 63 | 64 | [//]: # (misc) 65 | 66 | [Wycheproof]: https://github.com/google/wycheproof 67 | -------------------------------------------------------------------------------- /cpufeatures/src/loongarch64.rs: -------------------------------------------------------------------------------- 1 | //! LoongArch64 CPU feature detection support. 2 | //! 3 | //! This implementation relies on OS-specific APIs for feature detection. 4 | 5 | // Evaluate the given `$body` expression any of the supplied target features 6 | // are not enabled. Otherwise returns true. 7 | #[macro_export] 8 | #[doc(hidden)] 9 | macro_rules! __unless_target_features { 10 | ($($tf:tt),+ => $body:expr ) => { 11 | { 12 | #[cfg(not(all($(target_feature=$tf,)*)))] 13 | $body 14 | 15 | #[cfg(all($(target_feature=$tf,)*))] 16 | true 17 | } 18 | }; 19 | } 20 | 21 | // Linux runtime detection of target CPU features using `getauxval`. 22 | #[cfg(target_os = "linux")] 23 | #[macro_export] 24 | #[doc(hidden)] 25 | macro_rules! __detect_target_features { 26 | ($($tf:tt),+) => {{ 27 | let cpucfg1: usize; 28 | let cpucfg2: usize; 29 | let cpucfg3: usize; 30 | unsafe { 31 | std::arch::asm!( 32 | "cpucfg {}, {}", 33 | "cpucfg {}, {}", 34 | "cpucfg {}, {}", 35 | out(reg) cpucfg1, in(reg) 1, 36 | out(reg) cpucfg2, in(reg) 2, 37 | out(reg) cpucfg3, in(reg) 3, 38 | options(pure, nomem, preserves_flags, nostack) 39 | ); 40 | } 41 | let hwcaps = $crate::loongarch64::getauxval_hwcap(); 42 | $($crate::check!(cpucfg1, cpucfg2, cpucfg3, hwcaps, $tf) & )+ true 43 | }}; 44 | } 45 | 46 | /// Linux helper function for calling `getauxval` to get `AT_HWCAP`. 47 | #[cfg(target_os = "linux")] 48 | pub fn getauxval_hwcap() -> u64 { 49 | unsafe { libc::getauxval(libc::AT_HWCAP) } 50 | } 51 | 52 | #[macro_export] 53 | #[doc(hidden)] 54 | macro_rules! check { 55 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "32s") => { 56 | (($cpucfg1 & 1) != 0 || ($cpucfg1 & 2) != 0) 57 | }; 58 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "f") => { 59 | (($cpucfg2 & 2) != 0 && ($hwcaps & $crate::loongarch64::hwcaps::FPU) != 0) 60 | }; 61 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "d") => { 62 | (($cpucfg2 & 4) != 0 && ($hwcaps & $crate::loongarch64::hwcaps::FPU) != 0) 63 | }; 64 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "frecipe") => { 65 | (($cpucfg2 & (1 << 25)) != 0) 66 | }; 67 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "div32") => { 68 | (($cpucfg2 & (1 << 26)) != 0) 69 | }; 70 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "lsx") => { 71 | (($hwcaps & $crate::loongarch64::hwcaps::LSX) != 0) 72 | }; 73 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "lasx") => { 74 | (($hwcaps & $crate::loongarch64::hwcaps::LASX) != 0) 75 | }; 76 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "lam-bh") => { 77 | (($cpucfg2 & (1 << 27)) != 0) 78 | }; 79 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "lamcas") => { 80 | (($cpucfg2 & (1 << 28)) != 0) 81 | }; 82 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "ld-seq-sa") => { 83 | (($cpucfg3 & (1 << 23)) != 0) 84 | }; 85 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "scq") => { 86 | (($cpucfg2 & (1 << 30)) != 0) 87 | }; 88 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "lbt") => { 89 | (($hwcaps & $crate::loongarch64::hwcaps::LBT_X86) != 0 90 | && ($hwcaps & $crate::loongarch64::hwcaps::LBT_ARM) != 0 91 | && ($hwcaps & $crate::loongarch64::hwcaps::LBT_MIPS) != 0) 92 | }; 93 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "lvz") => { 94 | (($hwcaps & $crate::loongarch64::hwcaps::LVZ) != 0) 95 | }; 96 | ($cpucfg1:expr, $cpucfg2:expr, $cpucfg3:expr, $hwcaps:expr, "ual") => { 97 | (($hwcaps & $crate::loongarch64::hwcaps::UAL) != 0) 98 | }; 99 | } 100 | 101 | /// Linux hardware capabilities mapped to target features. 102 | /// 103 | /// Note that LLVM target features are coarser grained than what Linux supports 104 | /// and imply more capabilities under each feature. This module attempts to 105 | /// provide that mapping accordingly. 106 | #[cfg(target_os = "linux")] 107 | pub mod hwcaps { 108 | use libc::c_ulong; 109 | 110 | pub const UAL: c_ulong = libc::HWCAP_LOONGARCH_UAL; 111 | pub const FPU: c_ulong = libc::HWCAP_LOONGARCH_FPU; 112 | pub const LSX: c_ulong = libc::HWCAP_LOONGARCH_LSX; 113 | pub const LASX: c_ulong = libc::HWCAP_LOONGARCH_LASX; 114 | pub const LVZ: c_ulong = libc::HWCAP_LOONGARCH_LVZ; 115 | pub const LBT_X86: c_ulong = libc::HWCAP_LOONGARCH_LBT_X86; 116 | pub const LBT_ARM: c_ulong = libc::HWCAP_LOONGARCH_LBT_ARM; 117 | pub const LBT_MIPS: c_ulong = libc::HWCAP_LOONGARCH_LBT_MIPS; 118 | } 119 | 120 | // On other targets, runtime CPU feature detection is unavailable 121 | #[cfg(not(target_os = "linux"))] 122 | #[macro_export] 123 | #[doc(hidden)] 124 | macro_rules! __detect_target_features { 125 | ($($tf:tt),+) => { 126 | false 127 | }; 128 | } 129 | --------------------------------------------------------------------------------