diff --git a/aws-lc-rs/src/aead/chacha20_poly1305_openssh.rs b/aws-lc-rs/src/aead/chacha20_poly1305_openssh.rs index 0968ef4cef8..0aaa51a302e 100644 --- a/aws-lc-rs/src/aead/chacha20_poly1305_openssh.rs +++ b/aws-lc-rs/src/aead/chacha20_poly1305_openssh.rs @@ -208,7 +208,7 @@ mod tests { }; use crate::aead::Nonce; use crate::cipher::chacha::ChaCha20Key; - use crate::endian::LittleEndian; + use crate::endian::{BigEndian, FromArray, LittleEndian}; use crate::test; #[test] @@ -229,13 +229,16 @@ mod tests { } { - let x = LittleEndian::from(45u32); - let y = LittleEndian::from(897); - let z = LittleEndian::from(4567); - let iv = Nonce::from(&[x, y, z]); + let iv = Nonce::from(&LittleEndian::::from_array(&[45u32, 897, 4567])); let poly1305_key = derive_poly1305_key(&chacha_key, iv); assert_eq!(&expected_poly1305_key, &poly1305_key.key_and_nonce); } + + { + let iv = Nonce::from(&BigEndian::::from_array(&[45u32, 897, 4567])); + let poly1305_key = derive_poly1305_key(&chacha_key, iv); + assert_ne!(&expected_poly1305_key, &poly1305_key.key_and_nonce); + } } #[test] diff --git a/aws-lc-rs/src/aead/nonce.rs b/aws-lc-rs/src/aead/nonce.rs index ae0cd08a251..57ea3b38782 100644 --- a/aws-lc-rs/src/aead/nonce.rs +++ b/aws-lc-rs/src/aead/nonce.rs @@ -3,7 +3,7 @@ // Modifications copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 OR ISC -use crate::endian::{ArrayEncoding, BigEndian, Encoding, LittleEndian}; +use crate::endian::{ArrayEncoding, BigEndian, Encoding, FromArray, LittleEndian}; use crate::error; use crate::iv::FixedLength; @@ -55,11 +55,7 @@ impl From<&[u8; NONCE_LEN]> for Nonce { impl From<&[u32; NONCE_LEN / 4]> for Nonce { #[inline] fn from(values: &[u32; NONCE_LEN / 4]) -> Self { - let mut nonce = [LittleEndian::ZERO; NONCE_LEN / 4]; - for i in 0..(NONCE_LEN / 4) { - nonce[i] = LittleEndian::from(values[i]); - } - Nonce::from(&nonce) + Nonce::from(&LittleEndian::::from_array(values)) } } diff --git a/aws-lc-rs/src/endian.rs b/aws-lc-rs/src/endian.rs index cfbca00513c..8aca349af14 100644 --- a/aws-lc-rs/src/endian.rs +++ b/aws-lc-rs/src/endian.rs @@ -26,8 +26,11 @@ pub trait ArrayEncoding { /// Work around the inability to implement `from` for arrays of `Encoding`s /// due to the coherence rules. -pub trait FromByteArray { - fn from_byte_array(a: &T) -> Self; +pub trait FromArray +where + Self: Sized, +{ + fn from_array(a: &[T; N]) -> [Self; N]; } macro_rules! define_endian { @@ -39,6 +42,8 @@ macro_rules! define_endian { } macro_rules! impl_array_encoding { + // This may be converted to use const generics once generic_const_exprs is stable. + // https://github.com/rust-lang/rust/issues/76560 ($endian:ident, $base:ident, $elems:expr) => { impl ArrayEncoding<[u8; $elems * core::mem::size_of::<$base>()]> for [$endian<$base>; $elems] @@ -70,6 +75,16 @@ macro_rules! impl_endian { } } + impl FromArray for $endian<$base> { + fn from_array(value: &[$base; N]) -> [Self; N] { + let mut result: [$endian<$base>; N] = [$endian::ZERO; N]; + for i in 0..N { + result[i] = $endian::from(value[i]); + } + return result; + } + } + impl_array_encoding!($endian, $base, 1); impl_array_encoding!($endian, $base, 2); impl_array_encoding!($endian, $base, 3); @@ -96,4 +111,21 @@ mod tests { assert_eq!(u32::from(x), 1); assert_eq!(u32::from(x2), 1); } + + #[test] + fn test_endian_from_array() { + let be: [BigEndian; 2] = + BigEndian::::from_array(&[0x_AABB_CCDD_u32, 0x_2233_4455_u32]); + let le: [LittleEndian; 2] = + LittleEndian::::from_array(&[0x_DDCC_BBAA_u32, 0x_5544_3322_u32]); + assert_eq!(be.as_byte_array(), le.as_byte_array()); + + let be: [BigEndian; 2] = + BigEndian::::from_array(&[0x_AABB_CCDD_EEFF_0011_u64, 0x_2233_4455_6677_8899_u64]); + let le: [LittleEndian; 2] = LittleEndian::::from_array(&[ + 0x_1100_FFEE_DDCC_BBAA_u64, + 0x_9988_7766_5544_3322_u64, + ]); + assert_eq!(be.as_byte_array(), le.as_byte_array()); + } }