From 9a65db3f26abd298e7fc58b0caa04fffbef9b237 Mon Sep 17 00:00:00 2001 From: Tony Arcieri Date: Tue, 30 May 2023 09:29:02 -0600 Subject: [PATCH] [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 e761daa9..fca4878f 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 c7568454..52c1985b 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 63fca3de..11ff47d9 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 ba35578f..21008623 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 f4d3993d..ed5d2dca 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`].