From 9a65db3f26abd298e7fc58b0caa04fffbef9b237 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 09:29:02 -0600 Subject: [PATCH 1/2] [WIP] crypto-common: migrate to `hybrid-array`; MSRV 1.65 Replaces `generic-array` with `hybrid-array`, which is built on a combination of `typenum` and const generics, providing a degree of interoperability between the two systems. `hybrid-array` is designed to be a largely drop-in replacement, and the number of changes required to switch are relatively minimal aside from some idiosyncracies. --- .github/workflows/crypto-common.yml | 4 +- Cargo.lock | 12 +++++- crypto-common/Cargo.toml | 3 +- crypto-common/README.md | 6 +-- crypto-common/src/lib.rs | 58 ++++++++++++----------------- 5 files changed, 39 insertions(+), 44 deletions(-) diff --git a/.github/workflows/crypto-common.yml b/.github/workflows/crypto-common.yml index e761daa9b..fca4878f0 100644 --- a/.github/workflows/crypto-common.yml +++ b/.github/workflows/crypto-common.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: rust: - - 1.56.0 # MSRV + - 1.65.0 # MSRV - stable target: - thumbv7em-none-eabi @@ -46,7 +46,7 @@ jobs: strategy: matrix: rust: - - 1.56.0 # MSRV + - 1.65.0 # MSRV - stable steps: - uses: actions/checkout@v3 diff --git a/Cargo.lock b/Cargo.lock index c75684544..52c1985b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -291,9 +291,8 @@ dependencies = [ name = "crypto-common" version = "0.2.0-pre" dependencies = [ - "generic-array", + "hybrid-array", "rand_core 0.6.4", - "typenum", ] [[package]] @@ -609,6 +608,15 @@ dependencies = [ "zeroize", ] +[[package]] +name = "hybrid-array" +version = "0.2.0-pre.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b16010d3e71f5288f3fe2a9c6c8410dc94d71753c6b4b8f9f6c67a46cd46ef5" +dependencies = [ + "typenum", +] + [[package]] name = "inout" version = "0.1.3" diff --git a/crypto-common/Cargo.toml b/crypto-common/Cargo.toml index 63fca3de6..11ff47d9a 100644 --- a/crypto-common/Cargo.toml +++ b/crypto-common/Cargo.toml @@ -13,8 +13,7 @@ keywords = ["crypto", "traits"] categories = ["cryptography", "no-std"] [dependencies] -generic-array = { version = "0.14.6", features = ["more_lengths"] } -typenum = "1.14" # earlier versions of typenum don't satisfy the 'static bound on U* types +hybrid-array = "=0.2.0-pre.4" # optional dependencies rand_core = { version = "0.6.4", optional = true } diff --git a/crypto-common/README.md b/crypto-common/README.md index ba35578f8..21008623a 100644 --- a/crypto-common/README.md +++ b/crypto-common/README.md @@ -2,10 +2,10 @@ [![crate][crate-image]][crate-link] [![Docs][docs-image]][docs-link] +[![Build Status][build-image]][build-link] ![Apache2/MIT licensed][license-image] ![Rust Version][rustc-image] [![Project Chat][chat-image]][chat-link] -[![Build Status][build-image]][build-link] Common traits used by cryptographic algorithms. Users should generally use higher-level trait crates instead of this one. @@ -14,7 +14,7 @@ higher-level trait crates instead of this one. ## Minimum Supported Rust Version -Rust **1.56** or higher. +Rust **1.65** or higher. Minimum supported Rust version can be changed in the future, but it will be done with a minor version bump. @@ -46,7 +46,7 @@ dual licensed as above, without any additional terms or conditions. [docs-image]: https://docs.rs/crypto-common/badge.svg [docs-link]: https://docs.rs/crypto-common/ [license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg -[rustc-image]: https://img.shields.io/badge/rustc-1.56+-blue.svg +[rustc-image]: https://img.shields.io/badge/rustc-1.65+-blue.svg [chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg [chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/260041-hashes [build-image]: https://github.com/RustCrypto/traits/workflows/crypto-common/badge.svg?branch=master&event=push diff --git a/crypto-common/src/lib.rs b/crypto-common/src/lib.rs index f4d3993da..ed5d2dca6 100644 --- a/crypto-common/src/lib.rs +++ b/crypto-common/src/lib.rs @@ -15,28 +15,28 @@ extern crate std; #[cfg(feature = "rand_core")] pub use rand_core; -pub use generic_array; -pub use generic_array::typenum; +pub use hybrid_array as array; +pub use hybrid_array::typenum; use core::fmt; -use generic_array::{typenum::Unsigned, ArrayLength, GenericArray}; +use hybrid_array::{typenum::Unsigned, Array, ArraySize, ByteArray}; #[cfg(feature = "rand_core")] use rand_core::CryptoRngCore; /// Block on which [`BlockSizeUser`] implementors operate. -pub type Block = GenericArray::BlockSize>; +pub type Block = ByteArray<::BlockSize>; /// Parallel blocks on which [`ParBlocksSizeUser`] implementors operate. -pub type ParBlocks = GenericArray, ::ParBlocksSize>; +pub type ParBlocks = Array, ::ParBlocksSize>; /// Output array of [`OutputSizeUser`] implementors. -pub type Output = GenericArray::OutputSize>; +pub type Output = ByteArray<::OutputSize>; /// Key used by [`KeySizeUser`] implementors. -pub type Key = GenericArray::KeySize>; +pub type Key = ByteArray<::KeySize>; /// Initialization vector (nonce) used by [`IvSizeUser`] implementors. -pub type Iv = GenericArray::IvSize>; +pub type Iv = ByteArray<::IvSize>; /// Types which process data in blocks. pub trait BlockSizeUser { @@ -59,12 +59,12 @@ impl BlockSizeUser for &mut T { } /// Trait implemented for supported block sizes, i.e. for types from `U1` to `U255`. -pub trait BlockSizes: ArrayLength + sealed::BlockSizes + 'static {} +pub trait BlockSizes: ArraySize + sealed::BlockSizes + 'static {} -impl + sealed::BlockSizes> BlockSizes for T {} +impl BlockSizes for T {} mod sealed { - use generic_array::typenum::{Gr, IsGreater, IsLess, Le, NonZero, Unsigned, U1, U256}; + use crate::typenum::{Gr, IsGreater, IsLess, Le, NonZero, Unsigned, U1, U256}; pub trait BlockSizes {} @@ -80,13 +80,13 @@ mod sealed { /// Types which can process blocks in parallel. pub trait ParBlocksSizeUser: BlockSizeUser { /// Number of blocks which can be processed in parallel. - type ParBlocksSize: ArrayLength>; + type ParBlocksSize: ArraySize; } /// Types which return data with the given size. pub trait OutputSizeUser { /// Size of the output in bytes. - type OutputSize: ArrayLength + 'static; + type OutputSize: ArraySize + 'static; /// Return output size in bytes. #[inline(always)] @@ -100,7 +100,7 @@ pub trait OutputSizeUser { /// Generally it's used indirectly via [`KeyInit`] or [`KeyIvInit`]. pub trait KeySizeUser { /// Key size in bytes. - type KeySize: ArrayLength + 'static; + type KeySize: ArraySize + 'static; /// Return key size in bytes. #[inline(always)] @@ -114,7 +114,7 @@ pub trait KeySizeUser { /// Generally it's used indirectly via [`KeyIvInit`] or [`InnerIvInit`]. pub trait IvSizeUser { /// Initialization vector size in bytes. - type IvSize: ArrayLength + 'static; + type IvSize: ArraySize + 'static; /// Return IV size in bytes. #[inline(always)] @@ -151,11 +151,9 @@ pub trait KeyInit: KeySizeUser + Sized { /// Create new value from variable size key. #[inline] fn new_from_slice(key: &[u8]) -> Result { - if key.len() != Self::KeySize::to_usize() { - Err(InvalidLength) - } else { - Ok(Self::new(Key::::from_slice(key))) - } + <&Key>::try_from(key) + .map(Self::new) + .map_err(|_| InvalidLength) } /// Generate random key using the provided [`CryptoRngCore`]. @@ -177,16 +175,9 @@ pub trait KeyIvInit: KeySizeUser + IvSizeUser + Sized { /// Create new value from variable length key and nonce. #[inline] fn new_from_slices(key: &[u8], iv: &[u8]) -> Result { - let key_len = Self::KeySize::USIZE; - let iv_len = Self::IvSize::USIZE; - if key.len() != key_len || iv.len() != iv_len { - Err(InvalidLength) - } else { - Ok(Self::new( - Key::::from_slice(key), - Iv::::from_slice(iv), - )) - } + let key = <&Key>::try_from(key).map_err(|_| InvalidLength)?; + let iv = <&Iv>::try_from(iv).map_err(|_| InvalidLength)?; + Ok(Self::new(key, iv)) } /// Generate random key using the provided [`CryptoRngCore`]. @@ -237,11 +228,8 @@ pub trait InnerIvInit: InnerUser + IvSizeUser + Sized { /// Initialize value using `inner` and `iv` slice. #[inline] fn inner_iv_slice_init(inner: Self::Inner, iv: &[u8]) -> Result { - if iv.len() != Self::IvSize::to_usize() { - Err(InvalidLength) - } else { - Ok(Self::inner_iv_init(inner, Iv::::from_slice(iv))) - } + let iv = <&Iv>::try_from(iv).map_err(|_| InvalidLength)?; + Ok(Self::inner_iv_init(inner, iv)) } /// Generate random IV using the provided [`CryptoRngCore`]. From cc8cc8914c873825d6c78f5dbe9e32325b7023f8 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Sun, 8 Oct 2023 11:08:33 -0600 Subject: [PATCH 2/2] [WIP] cipher: migrate to hybrid array --- Cargo.lock | 45 +++++++++++++++++---------------------- Cargo.toml | 5 +++++ cipher/Cargo.toml | 4 ++-- cipher/src/block.rs | 15 +++++++------ cipher/src/lib.rs | 2 +- cipher/src/stream_core.rs | 34 ++++++++++++++--------------- 6 files changed, 53 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 52c1985b6..b489264c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -140,17 +140,16 @@ version = "0.11.0-pre" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b6a33d658e9ef24ba0c4566d3d023d7978ca2ea3efb65e4eacd4586695892b" dependencies = [ - "crypto-common 0.2.0-pre (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-common 0.2.0-pre", "generic-array", ] [[package]] name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +version = "0.4.0-pre" +source = "git+https://github.com/RustCrypto/utils.git?branch=migrate-to-hybrid-array#f887f5ee6fdd5c097a75c136ab024684cc5777b4" dependencies = [ - "generic-array", + "hybrid-array", ] [[package]] @@ -209,8 +208,8 @@ name = "cipher" version = "0.4.4" dependencies = [ "blobby", - "crypto-common 0.1.6", - "inout", + "crypto-common 0.2.0-pre", + "inout 0.2.0-pre", "zeroize", ] @@ -221,7 +220,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common 0.1.6", - "inout", + "inout 0.1.3", "zeroize", ] @@ -295,17 +294,6 @@ dependencies = [ "rand_core 0.6.4", ] -[[package]] -name = "crypto-common" -version = "0.2.0-pre" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6faaa83e7700e0832cbbf84854d4c356270526907d9b14fab927fc7a9b5befb8" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "typenum", -] - [[package]] name = "crypto-mac" version = "0.11.0" @@ -383,7 +371,7 @@ dependencies = [ "blobby", "block-buffer 0.11.0-pre", "const-oid 0.9.5", - "crypto-common 0.2.0-pre (registry+https://github.com/rust-lang/crates.io-index)", + "crypto-common 0.2.0-pre", "subtle", ] @@ -611,8 +599,7 @@ dependencies = [ [[package]] name = "hybrid-array" version = "0.2.0-pre.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b16010d3e71f5288f3fe2a9c6c8410dc94d71753c6b4b8f9f6c67a46cd46ef5" +source = "git+https://github.com/RustCrypto/utils.git?branch=migrate-to-hybrid-array#f887f5ee6fdd5c097a75c136ab024684cc5777b4" dependencies = [ "typenum", ] @@ -623,10 +610,18 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "block-padding", "generic-array", ] +[[package]] +name = "inout" +version = "0.2.0-pre" +source = "git+https://github.com/RustCrypto/utils.git?branch=migrate-to-hybrid-array#f887f5ee6fdd5c097a75c136ab024684cc5777b4" +dependencies = [ + "block-padding", + "hybrid-array", +] + [[package]] name = "jobserver" version = "0.1.26" @@ -1007,9 +1002,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicode-ident" diff --git a/Cargo.toml b/Cargo.toml index e7b7482b6..32572481a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,3 +16,8 @@ exclude = [ "crypto", "elliptic-curve" ] + +[patch.crates-io] +crypto-common = { path = "crypto-common" } +hybrid-array = { git = "https://github.com/RustCrypto/utils.git", branch = "migrate-to-hybrid-array" } +inout = { git = "https://github.com/RustCrypto/utils.git", branch = "migrate-to-hybrid-array" } diff --git a/cipher/Cargo.toml b/cipher/Cargo.toml index c36b31cc5..d439f09c7 100644 --- a/cipher/Cargo.toml +++ b/cipher/Cargo.toml @@ -13,8 +13,8 @@ keywords = ["crypto", "block-cipher", "stream-cipher", "trait"] categories = ["cryptography", "no-std"] [dependencies] -crypto-common = "0.1.6" -inout = "0.1" +crypto-common = "=0.2.0-pre" +inout = "=0.2.0-pre" # optional dependencies blobby = { version = "0.3", optional = true } diff --git a/cipher/src/block.rs b/cipher/src/block.rs index 0742ced14..7b8c99cf9 100644 --- a/cipher/src/block.rs +++ b/cipher/src/block.rs @@ -13,6 +13,7 @@ use crate::{ParBlocks, ParBlocksSizeUser}; #[cfg(all(feature = "block-padding", feature = "alloc"))] use alloc::{vec, vec::Vec}; +use crypto_common::BlockSizes; #[cfg(feature = "block-padding")] use inout::{ block_padding::{Padding, UnpadError}, @@ -20,7 +21,7 @@ use inout::{ }; use inout::{InOut, InOutBuf, NotEqualError}; -pub use crypto_common::{generic_array::ArrayLength, typenum::Unsigned, Block, BlockSizeUser}; +pub use crypto_common::{array::ArraySize, typenum::Unsigned, Block, BlockSizeUser}; /// Marker trait for block ciphers. pub trait BlockCipher: BlockSizeUser {} @@ -593,15 +594,15 @@ impl BlockDecrypt for &Alg { } /// Closure used in methods which operate over separate blocks. -struct BlockCtx<'inp, 'out, BS: ArrayLength> { +struct BlockCtx<'inp, 'out, BS: BlockSizes> { block: InOut<'inp, 'out, Block>, } -impl<'inp, 'out, BS: ArrayLength> BlockSizeUser for BlockCtx<'inp, 'out, BS> { +impl<'inp, 'out, BS: BlockSizes> BlockSizeUser for BlockCtx<'inp, 'out, BS> { type BlockSize = BS; } -impl<'inp, 'out, BS: ArrayLength> BlockClosure for BlockCtx<'inp, 'out, BS> { +impl<'inp, 'out, BS: BlockSizes> BlockClosure for BlockCtx<'inp, 'out, BS> { #[inline(always)] fn call>(self, backend: &mut B) { backend.proc_block(self.block); @@ -609,15 +610,15 @@ impl<'inp, 'out, BS: ArrayLength> BlockClosure for BlockCtx<'inp, 'out, BS> } /// Closure used in methods which operate over slice of blocks. -struct BlocksCtx<'inp, 'out, BS: ArrayLength> { +struct BlocksCtx<'inp, 'out, BS: BlockSizes> { blocks: InOutBuf<'inp, 'out, Block>, } -impl<'inp, 'out, BS: ArrayLength> BlockSizeUser for BlocksCtx<'inp, 'out, BS> { +impl<'inp, 'out, BS: BlockSizes> BlockSizeUser for BlocksCtx<'inp, 'out, BS> { type BlockSize = BS; } -impl<'inp, 'out, BS: ArrayLength> BlockClosure for BlocksCtx<'inp, 'out, BS> { +impl<'inp, 'out, BS: BlockSizes> BlockClosure for BlocksCtx<'inp, 'out, BS> { #[inline(always)] fn call>(self, backend: &mut B) { if B::ParBlocksSize::USIZE > 1 { diff --git a/cipher/src/lib.rs b/cipher/src/lib.rs index 87813d940..a8af951b8 100644 --- a/cipher/src/lib.rs +++ b/cipher/src/lib.rs @@ -48,7 +48,7 @@ mod stream_wrapper; pub use crate::{block::*, errors::*, stream::*, stream_core::*, stream_wrapper::*}; pub use crypto_common::{ - generic_array, + array, typenum::{self, consts}, AlgorithmName, Block, InnerIvInit, InvalidLength, Iv, IvSizeUser, Key, KeyInit, KeyIvInit, KeySizeUser, ParBlocks, ParBlocksSizeUser, diff --git a/cipher/src/stream_core.rs b/cipher/src/stream_core.rs index 1e4b302ea..5a9232dbe 100644 --- a/cipher/src/stream_core.rs +++ b/cipher/src/stream_core.rs @@ -1,8 +1,8 @@ use crate::{ParBlocks, ParBlocksSizeUser, StreamCipherError}; use crypto_common::{ - generic_array::{ArrayLength, GenericArray}, + array::{Array, ArraySize}, typenum::Unsigned, - Block, BlockSizeUser, + Block, BlockSizeUser, BlockSizes, }; use inout::{InOut, InOutBuf}; @@ -195,7 +195,7 @@ impl_counter! { u32 u64 u128 } /// In case if `N` is less or equal to 1, buffer of arrays has length /// of zero and tail is equal to `self`. #[inline] -fn into_chunks>(buf: &mut [T]) -> (&mut [GenericArray], &mut [T]) { +fn into_chunks(buf: &mut [T]) -> (&mut [Array], &mut [T]) { use core::slice; if N::USIZE <= 1 { return (&mut [], buf); @@ -205,32 +205,32 @@ fn into_chunks>(buf: &mut [T]) -> (&mut [GenericArray let tail_len = buf.len() - tail_pos; unsafe { let ptr = buf.as_mut_ptr(); - let chunks = slice::from_raw_parts_mut(ptr as *mut GenericArray, chunks_len); + let chunks = slice::from_raw_parts_mut(ptr as *mut Array, chunks_len); let tail = slice::from_raw_parts_mut(ptr.add(tail_pos), tail_len); (chunks, tail) } } -struct WriteBlockCtx<'a, BS: ArrayLength> { +struct WriteBlockCtx<'a, BS: BlockSizes> { block: &'a mut Block, } -impl<'a, BS: ArrayLength> BlockSizeUser for WriteBlockCtx<'a, BS> { +impl<'a, BS: BlockSizes> BlockSizeUser for WriteBlockCtx<'a, BS> { type BlockSize = BS; } -impl<'a, BS: ArrayLength> StreamClosure for WriteBlockCtx<'a, BS> { +impl<'a, BS: BlockSizes> StreamClosure for WriteBlockCtx<'a, BS> { #[inline(always)] fn call>(self, backend: &mut B) { backend.gen_ks_block(self.block); } } -struct WriteBlocksCtx<'a, BS: ArrayLength> { +struct WriteBlocksCtx<'a, BS: BlockSizes> { blocks: &'a mut [Block], } -impl<'a, BS: ArrayLength> BlockSizeUser for WriteBlocksCtx<'a, BS> { +impl<'a, BS: BlockSizes> BlockSizeUser for WriteBlocksCtx<'a, BS> { type BlockSize = BS; } -impl<'a, BS: ArrayLength> StreamClosure for WriteBlocksCtx<'a, BS> { +impl<'a, BS: BlockSizes> StreamClosure for WriteBlocksCtx<'a, BS> { #[inline(always)] fn call>(self, backend: &mut B) { if B::ParBlocksSize::USIZE > 1 { @@ -247,15 +247,15 @@ impl<'a, BS: ArrayLength> StreamClosure for WriteBlocksCtx<'a, BS> { } } -struct ApplyBlockCtx<'inp, 'out, BS: ArrayLength> { +struct ApplyBlockCtx<'inp, 'out, BS: BlockSizes> { block: InOut<'inp, 'out, Block>, } -impl<'inp, 'out, BS: ArrayLength> BlockSizeUser for ApplyBlockCtx<'inp, 'out, BS> { +impl<'inp, 'out, BS: BlockSizes> BlockSizeUser for ApplyBlockCtx<'inp, 'out, BS> { type BlockSize = BS; } -impl<'inp, 'out, BS: ArrayLength> StreamClosure for ApplyBlockCtx<'inp, 'out, BS> { +impl<'inp, 'out, BS: BlockSizes> StreamClosure for ApplyBlockCtx<'inp, 'out, BS> { #[inline(always)] fn call>(mut self, backend: &mut B) { let mut t = Default::default(); @@ -264,15 +264,15 @@ impl<'inp, 'out, BS: ArrayLength> StreamClosure for ApplyBlockCtx<'inp, 'out } } -struct ApplyBlocksCtx<'inp, 'out, BS: ArrayLength> { +struct ApplyBlocksCtx<'inp, 'out, BS: BlockSizes> { blocks: InOutBuf<'inp, 'out, Block>, } -impl<'inp, 'out, BS: ArrayLength> BlockSizeUser for ApplyBlocksCtx<'inp, 'out, BS> { +impl<'inp, 'out, BS: BlockSizes> BlockSizeUser for ApplyBlocksCtx<'inp, 'out, BS> { type BlockSize = BS; } -impl<'inp, 'out, BS: ArrayLength> StreamClosure for ApplyBlocksCtx<'inp, 'out, BS> { +impl<'inp, 'out, BS: BlockSizes> StreamClosure for ApplyBlocksCtx<'inp, 'out, BS> { #[inline(always)] #[allow(clippy::needless_range_loop)] fn call>(self, backend: &mut B) { @@ -284,7 +284,7 @@ impl<'inp, 'out, BS: ArrayLength> StreamClosure for ApplyBlocksCtx<'inp, 'ou chunk.xor_in2out(&tmp); } let n = tail.len(); - let mut buf = GenericArray::<_, B::ParBlocksSize>::default(); + let mut buf = Array::<_, B::ParBlocksSize>::default(); let ks = &mut buf[..n]; backend.gen_tail_blocks(ks); for i in 0..n {