diff --git a/src/aead/aes.rs b/src/aead/aes.rs index 0df2838d3..ebfc37f2f 100644 --- a/src/aead/aes.rs +++ b/src/aead/aes.rs @@ -196,7 +196,7 @@ fn encrypt_iv_xor_block_using_encrypt_block( #[allow(dead_code)] fn encrypt_iv_xor_block_using_ctr32(key: &impl EncryptCtr32, iv: Iv, mut block: Block) -> Block { let mut ctr = Counter(iv.0); // This is OK because we're only encrypting one block. - key.ctr32_encrypt_within(Overlapping::in_place(&mut block), &mut ctr); + key.ctr32_encrypt_within(block.as_mut().into(), &mut ctr); block } diff --git a/src/aead/aes_gcm.rs b/src/aead/aes_gcm.rs index 670bc3a3c..712cec839 100644 --- a/src/aead/aes_gcm.rs +++ b/src/aead/aes_gcm.rs @@ -177,10 +177,9 @@ pub(super) fn seal( } }; let (whole, remainder) = slice::as_chunks_mut(ramaining); - aes_key - .ctr32_encrypt_within(Overlapping::in_place(slice::flatten_mut(whole)), &mut ctr); + aes_key.ctr32_encrypt_within(slice::flatten_mut(whole).into(), &mut ctr); auth.update_blocks(whole); - let remainder = OverlappingPartialBlock::new(Overlapping::in_place(remainder)) + let remainder = OverlappingPartialBlock::new(remainder.into()) .unwrap_or_else(|InputTooLongError { .. }| unreachable!()); seal_finish(aes_key, auth, remainder, ctr, tag_iv) } @@ -220,7 +219,7 @@ pub(super) fn seal( ) } } - let remainder = OverlappingPartialBlock::new(Overlapping::in_place(remainder)) + let remainder = OverlappingPartialBlock::new(remainder.into()) .unwrap_or_else(|InputTooLongError { .. }| unreachable!()); seal_finish(aes_key, auth, remainder, ctr, tag_iv) } @@ -268,11 +267,11 @@ fn seal_strided( + pub(super) fn encrypt_single_block_with_ctr_0( &self, nonce: Nonce, in_out: &mut [u8; N], + cpu: cpu::Features, ) -> Counter { assert!(N <= BLOCK_LEN); let (zero, one) = Counter::zero_one_less_safe(nonce); - self.encrypt_within(zero, Overlapping::in_place(in_out)); + self.encrypt(zero, in_out.as_mut().into(), cpu); one } #[inline] pub fn new_mask(&self, sample: Sample) -> [u8; 5] { + let cpu = cpu::features(); // TODO: Remove this. let (ctr, nonce) = sample.split_at(4); let ctr = u32::from_le_bytes(ctr.try_into().unwrap()); let nonce = Nonce::assume_unique_for_key(nonce.try_into().unwrap()); let ctr = Counter::from_nonce_and_ctr(nonce, ctr); let mut out: [u8; 5] = [0; 5]; - self.encrypt_within(ctr, Overlapping::in_place(&mut out)); + self.encrypt(ctr, out.as_mut().into(), cpu); out } #[inline(always)] - pub fn encrypt_within(&self, counter: Counter, in_out: Overlapping<'_>) { + pub(super) fn encrypt(&self, counter: Counter, in_out: Overlapping<'_>, _cpu: cpu::Features) { #[cfg(any( all(target_arch = "aarch64", target_endian = "little"), all(target_arch = "arm", target_endian = "little"), @@ -95,7 +93,7 @@ impl Key { all(target_arch = "aarch64", target_endian = "little"), target_arch = "x86_64" )))] - let in_out = Overlapping::in_place(in_out.copy_within()); + let in_out = Overlapping::from(in_out.copy_within()); let (input, output, len) = in_out.into_input_output_len(); @@ -197,13 +195,15 @@ mod tests { } else { MAX_ALIGNMENT_AND_OFFSET_SUBSET }; - chacha20_test(max_offset, Key::encrypt_within); + chacha20_test(max_offset, Key::encrypt); } // Smoketest the fallback implementation. #[test] fn chacha20_test_fallback() { - chacha20_test(MAX_ALIGNMENT_AND_OFFSET_SUBSET, fallback::ChaCha20_ctr32); + chacha20_test(MAX_ALIGNMENT_AND_OFFSET_SUBSET, |key, ctr, in_out, _cpu| { + fallback::ChaCha20_ctr32(key, ctr, in_out) + }); } // Verifies the encryption is successful when done on overlapping buffers. @@ -215,8 +215,10 @@ mod tests { // works around that. fn chacha20_test( max_alignment_and_offset: (usize, usize), - f: impl for<'k, 'o> Fn(&'k Key, Counter, Overlapping<'o>), + f: impl for<'k, 'o> Fn(&'k Key, Counter, Overlapping<'o>, cpu::Features), ) { + let cpu = cpu::features(); + // Reuse a buffer to avoid slowing down the tests with allocations. let mut buf = vec![0u8; 1300]; @@ -245,6 +247,7 @@ mod tests { &output[..len], &mut buf, max_alignment_and_offset, + cpu, &f, ); } @@ -261,7 +264,8 @@ mod tests { expected: &[u8], buf: &mut [u8], (max_alignment, max_offset): (usize, usize), - f: &impl for<'k, 'o> Fn(&'k Key, Counter, Overlapping<'o>), + cpu: cpu::Features, + f: &impl for<'k, 'o> Fn(&'k Key, Counter, Overlapping<'o>, cpu::Features), ) { const ARBITRARY: u8 = 123; @@ -281,7 +285,7 @@ mod tests { let in_out = Overlapping::new(buf, src) .map_err(error::erase::) .unwrap(); - f(key, ctr, in_out); + f(key, ctr, in_out, cpu); assert_eq!(&buf[..input.len()], expected) } } diff --git a/src/aead/chacha20_poly1305/mod.rs b/src/aead/chacha20_poly1305/mod.rs index c45de4b0a..c05417827 100644 --- a/src/aead/chacha20_poly1305/mod.rs +++ b/src/aead/chacha20_poly1305/mod.rs @@ -71,13 +71,13 @@ pub(super) fn seal_fallback( nonce: Nonce, aad: Aad<&[u8]>, in_out: &mut [u8], - cpu_features: cpu::Features, + cpu: cpu::Features, ) -> Result { - let (counter, poly1305_key) = begin(chacha20_key, nonce, aad, in_out)?; - let mut auth = poly1305::Context::from_key(poly1305_key, cpu_features); + let (counter, poly1305_key) = begin(chacha20_key, nonce, aad, in_out, cpu)?; + let mut auth = poly1305::Context::from_key(poly1305_key, cpu); poly1305_update_padded_16(&mut auth, aad.as_ref()); - chacha20_key.encrypt_in_place(counter, in_out); + chacha20_key.encrypt(counter, in_out.into(), cpu); poly1305_update_padded_16(&mut auth, in_out); Ok(finish(auth, aad.as_ref().len(), in_out.len())) } @@ -105,15 +105,15 @@ pub(super) fn open_fallback( nonce: Nonce, aad: Aad<&[u8]>, in_out: Overlapping<'_>, - cpu_features: cpu::Features, + cpu: cpu::Features, ) -> Result { - let (counter, poly1305_key) = begin(chacha20_key, nonce, aad, in_out.input())?; - let mut auth = poly1305::Context::from_key(poly1305_key, cpu_features); + let (counter, poly1305_key) = begin(chacha20_key, nonce, aad, in_out.input(), cpu)?; + let mut auth = poly1305::Context::from_key(poly1305_key, cpu); poly1305_update_padded_16(&mut auth, aad.as_ref()); poly1305_update_padded_16(&mut auth, in_out.input()); let in_out_len = in_out.len(); - chacha20_key.encrypt_within(counter, in_out); + chacha20_key.encrypt(counter, in_out, cpu); Ok(finish(auth, aad.as_ref().len(), in_out_len)) } @@ -137,11 +137,12 @@ pub(super) fn begin( nonce: Nonce, aad: Aad<&[u8]>, input: &[u8], + cpu: cpu::Features, ) -> Result<(Counter, poly1305::Key), InputTooLongError> { check_input_lengths(aad, input)?; let mut key_bytes = [0u8; poly1305::KEY_LEN]; - let counter = key.encrypt_single_block_with_ctr_0(nonce, &mut key_bytes); + let counter = key.encrypt_single_block_with_ctr_0(nonce, &mut key_bytes, cpu); let poly1305_key = poly1305::Key::new(key_bytes); Ok((counter, poly1305_key)) } diff --git a/src/aead/chacha20_poly1305_openssh.rs b/src/aead/chacha20_poly1305_openssh.rs index cc6a19237..83015cf0f 100644 --- a/src/aead/chacha20_poly1305_openssh.rs +++ b/src/aead/chacha20_poly1305_openssh.rs @@ -77,26 +77,28 @@ impl SealingKey { let (len_in_out, data_and_padding_in_out): (&mut [u8; PACKET_LENGTH_LEN], _) = slice::split_first_chunk_mut(plaintext_in_ciphertext_out).unwrap(); - let cpu_features = cpu::features(); + let cpu = cpu::features(); // XXX/TODO(SemVer): Refactor API to return an error. let (counter, poly_key) = chacha20_poly1305::begin( &self.key.k_2, make_nonce(sequence_number), Aad::from(len_in_out), data_and_padding_in_out, + cpu, ) .map_err(error::erase::) .unwrap(); - let _: Counter = self - .key - .k_1 - .encrypt_single_block_with_ctr_0(make_nonce(sequence_number), len_in_out); + let _: Counter = self.key.k_1.encrypt_single_block_with_ctr_0( + make_nonce(sequence_number), + len_in_out, + cpu, + ); self.key .k_2 - .encrypt_in_place(counter, data_and_padding_in_out); + .encrypt(counter, data_and_padding_in_out.into(), cpu); - let Tag(tag) = poly1305::sign(poly_key, plaintext_in_ciphertext_out, cpu_features); + let Tag(tag) = poly1305::sign(poly_key, plaintext_in_ciphertext_out, cpu); *tag_out = tag; } } @@ -123,11 +125,13 @@ impl OpeningKey { sequence_number: u32, encrypted_packet_length: [u8; PACKET_LENGTH_LEN], ) -> [u8; PACKET_LENGTH_LEN] { + let cpu = cpu::features(); let mut packet_length = encrypted_packet_length; - let _: Counter = self - .key - .k_1 - .encrypt_single_block_with_ctr_0(make_nonce(sequence_number), &mut packet_length); + let _: Counter = self.key.k_1.encrypt_single_block_with_ctr_0( + make_nonce(sequence_number), + &mut packet_length, + cpu, + ); packet_length } @@ -155,6 +159,7 @@ impl OpeningKey { make_nonce(sequence_number), Aad::from(packet_length), after_packet_length, + cpu, ) .map_err(error::erase::)?; @@ -167,7 +172,9 @@ impl OpeningKey { // Won't panic because the length was checked above. let after_packet_length = &mut ciphertext_in_plaintext_out[PACKET_LENGTH_LEN..]; - self.key.k_2.encrypt_in_place(counter, after_packet_length); + self.key + .k_2 + .encrypt(counter, after_packet_length.into(), cpu); Ok(after_packet_length) } diff --git a/src/aead/overlapping/base.rs b/src/aead/overlapping/base.rs index cf70315f1..bd57f6e44 100644 --- a/src/aead/overlapping/base.rs +++ b/src/aead/overlapping/base.rs @@ -22,11 +22,13 @@ pub struct Overlapping<'o, T> { src: RangeFrom, } -impl<'o, T> Overlapping<'o, T> { - pub fn in_place(in_out: &'o mut [T]) -> Self { +impl<'o, T> From<&'o mut [T]> for Overlapping<'o, T> { + fn from(in_out: &'o mut [T]) -> Self { Self { in_out, src: 0.. } } +} +impl<'o, T> Overlapping<'o, T> { pub fn new(in_out: &'o mut [T], src: RangeFrom) -> Result { match in_out.get(src.clone()) { Some(_) => Ok(Self { in_out, src }),