From 9fa6605af6ea3b98055aa6bb25fc448868450ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 13 Aug 2025 17:55:34 +0300 Subject: [PATCH 1/7] cipher: use `block_buffer::ReadBuffer` in `StreamCipherCoreWrapper` --- Cargo.lock | 7 +- Cargo.toml | 3 +- cipher/Cargo.toml | 4 +- cipher/src/lib.rs | 1 + cipher/src/stream.rs | 2 + cipher/src/stream/wrapper.rs | 221 +++++++------------------------- digest/src/buffer_macros/xof.rs | 16 ++- 7 files changed, 73 insertions(+), 181 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index de2cf1a0b..e5ad97cfb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,7 +75,7 @@ source = "git+https://github.com/RustCrypto/utils#f5ac85f6aa02aa39614f62a6a1add9 [[package]] name = "block-buffer" version = "0.11.0-rc.4" -source = "git+https://github.com/RustCrypto/utils#f5ac85f6aa02aa39614f62a6a1add9468be67892" +source = "git+https://github.com/RustCrypto/utils?branch=block-buffer%2Fread-buf#21054d717f77c160fa0a70f79bdef2435c578d17" dependencies = [ "hybrid-array", "zeroize", @@ -113,6 +113,7 @@ name = "cipher" version = "0.5.0-rc.0" dependencies = [ "blobby", + "block-buffer", "crypto-common", "inout", "zeroize", @@ -429,9 +430,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.96" +version = "1.0.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "beef09f85ae72cea1ef96ba6870c51e6382ebfa4f0e85b643459331f3daa5be0" +checksum = "d61789d7719defeb74ea5fe81f2fdfdbd28a803847077cecce2ff14e1472f6f1" dependencies = [ "unicode-ident", ] diff --git a/Cargo.toml b/Cargo.toml index 7f57fc98b..63c918333 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,4 +21,5 @@ signature = { path = "signature" } blobby = { git = "https://github.com/RustCrypto/utils" } # https://github.com/RustCrypto/utils/pull/1192 # https://github.com/RustCrypto/utils/pull/1200 -block-buffer = { git = "https://github.com/RustCrypto/utils" } +# https://github.com/RustCrypto/utils/pull/1201 +block-buffer = { git = "https://github.com/RustCrypto/utils", branch = "block-buffer/read-buf" } diff --git a/cipher/Cargo.toml b/cipher/Cargo.toml index 393703371..ac7cedecb 100644 --- a/cipher/Cargo.toml +++ b/cipher/Cargo.toml @@ -18,16 +18,18 @@ inout = "0.2.0-rc.4" # optional dependencies blobby = { version = "0.4.0-pre.0", optional = true } +block-buffer = { version = "0.11.0-rc.4", optional = true} zeroize = { version = "1.8", optional = true, default-features = false } [features] alloc = [] block-padding = ["inout/block-padding"] +stream-wrapper = ["block-buffer"] # Enable random key and IV generation methods rand_core = ["crypto-common/rand_core"] os_rng = ["crypto-common/os_rng", "rand_core"] dev = ["blobby"] -zeroize = ["dep:zeroize", "crypto-common/zeroize"] +zeroize = ["dep:zeroize", "crypto-common/zeroize", "block-buffer?/zeroize"] [package.metadata.docs.rs] all-features = true diff --git a/cipher/src/lib.rs b/cipher/src/lib.rs index 009a8b8a9..af95d9fc7 100644 --- a/cipher/src/lib.rs +++ b/cipher/src/lib.rs @@ -17,6 +17,7 @@ unused_lifetimes, missing_debug_implementations )] +#![forbid(unsafe_code)] #[cfg(feature = "alloc")] extern crate alloc; diff --git a/cipher/src/stream.rs b/cipher/src/stream.rs index a1ba34347..f6169595d 100644 --- a/cipher/src/stream.rs +++ b/cipher/src/stream.rs @@ -9,6 +9,7 @@ use inout::{InOutBuf, NotEqualError}; mod core_api; mod errors; +#[cfg(feature = "stream-wrapper")] mod wrapper; pub use core_api::{ @@ -16,6 +17,7 @@ pub use core_api::{ StreamCipherSeekCore, }; pub use errors::{OverflowError, StreamCipherError}; +#[cfg(feature = "stream-wrapper")] pub use wrapper::StreamCipherCoreWrapper; /// Marker trait for block-level asynchronous stream ciphers diff --git a/cipher/src/stream/wrapper.rs b/cipher/src/stream/wrapper.rs index 3dbc7e1b5..74c0151d2 100644 --- a/cipher/src/stream/wrapper.rs +++ b/cipher/src/stream/wrapper.rs @@ -1,29 +1,22 @@ use super::{ - Block, OverflowError, SeekNum, StreamCipher, StreamCipherCore, StreamCipherSeek, - StreamCipherSeekCore, errors::StreamCipherError, + OverflowError, SeekNum, StreamCipher, StreamCipherCore, StreamCipherSeek, StreamCipherSeekCore, + errors::StreamCipherError, }; +use block_buffer::ReadBuffer; use core::fmt; use crypto_common::{ Iv, IvSizeUser, Key, KeyInit, KeyIvInit, KeySizeUser, array::Array, typenum::Unsigned, }; use inout::InOutBuf; #[cfg(feature = "zeroize")] -use zeroize::{Zeroize, ZeroizeOnDrop}; +use zeroize::ZeroizeOnDrop; /// Buffering wrapper around a [`StreamCipherCore`] implementation. /// /// It handles data buffering and implements the slice-based traits. pub struct StreamCipherCoreWrapper { core: T, - // First byte is used as position - buffer: Block, -} - -impl Default for StreamCipherCoreWrapper { - #[inline] - fn default() -> Self { - Self::from_core(T::default()) - } + buffer: ReadBuffer, } impl Clone for StreamCipherCoreWrapper { @@ -38,70 +31,19 @@ impl Clone for StreamCipherCoreWrapper { impl fmt::Debug for StreamCipherCoreWrapper { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let pos = self.get_pos().into(); - let buf_data = &self.buffer[pos..]; f.debug_struct("StreamCipherCoreWrapper") - .field("core", &self.core) - .field("buffer_data", &buf_data) - .finish() + .finish_non_exhaustive() } } impl StreamCipherCoreWrapper { - /// Return reference to the core type. - pub fn get_core(&self) -> &T { - &self.core - } - - /// Return reference to the core type. - pub fn from_core(core: T) -> Self { - let mut buffer: Block = Default::default(); - buffer[0] = T::BlockSize::U8; - Self { core, buffer } - } - - /// Return current cursor position. - #[inline] - fn get_pos(&self) -> u8 { - let pos = self.buffer[0]; - if pos == 0 || pos > T::BlockSize::U8 { - debug_assert!(false); - // SAFETY: `pos` never breaks the invariant - unsafe { - core::hint::unreachable_unchecked(); - } - } - pos - } - - /// Set buffer position without checking that it's smaller - /// than buffer size. - /// - /// # Safety - /// `pos` MUST be bigger than zero and smaller or equal to `T::BlockSize::USIZE`. - #[inline] - unsafe fn set_pos_unchecked(&mut self, pos: usize) { - debug_assert!(pos != 0 && pos <= T::BlockSize::USIZE); - // Block size is always smaller than 256 because of the `BlockSizes` bound, - // so if the safety condition is satisfied, the `as` cast does not truncate - // any non-zero bits. - self.buffer[0] = pos as u8; - } - - /// Return number of remaining bytes in the internal buffer. - #[inline] - fn remaining(&self) -> u8 { - // This never underflows because of the safety invariant - T::BlockSize::U8 - self.get_pos() - } - fn check_remaining(&self, data_len: usize) -> Result<(), StreamCipherError> { let rem_blocks = match self.core.remaining_blocks() { Some(v) => v, None => return Ok(()), }; - let buf_rem = usize::from(self.remaining()); + let buf_rem = self.buffer.remaining(); let data_len = match data_len.checked_sub(buf_rem) { Some(0) | None => return Ok(()), Some(res) => res, @@ -121,106 +63,46 @@ impl StreamCipher for StreamCipherCoreWrapper { #[inline] fn try_apply_keystream_inout( &mut self, - mut data: InOutBuf<'_, '_, u8>, + data: InOutBuf<'_, '_, u8>, ) -> Result<(), StreamCipherError> { self.check_remaining(data.len())?; - let pos = usize::from(self.get_pos()); - let rem = usize::from(self.remaining()); - let data_len = data.len(); - - if rem != 0 { - if data_len <= rem { - data.xor_in2out(&self.buffer[pos..][..data_len]); - // SAFETY: we have checked that `data_len` is less or equal to length - // of remaining keystream data, thus `pos + data_len` can not be bigger - // than block size. Since `pos` is never zero, `pos + data_len` can not - // be zero. Thus `pos + data_len` satisfies the safety invariant required - // by `set_pos_unchecked`. - unsafe { - self.set_pos_unchecked(pos + data_len); - } - return Ok(()); - } - let (mut left, right) = data.split_at(rem); - data = right; - left.xor_in2out(&self.buffer[pos..]); - } + let head_ks = self.buffer.read_cached(data.len()); + let (mut head, data) = data.split_at(head_ks.len()); let (blocks, mut tail) = data.into_chunks(); - self.core.apply_keystream_blocks_inout(blocks); - let new_pos = if tail.is_empty() { - T::BlockSize::USIZE - } else { - // Note that we temporarily write a pseudo-random byte into - // the first byte of `self.buffer`. It may break the safety invariant, - // but after XORing keystream block with `tail`, we immediately - // overwrite the first byte with a correct value. - self.core.write_keystream_block(&mut self.buffer); - tail.xor_in2out(&self.buffer[..tail.len()]); - tail.len() - }; + head.xor_in2out(head_ks); + self.core.apply_keystream_blocks_inout(blocks); - // SAFETY: `into_chunks` always returns tail with size - // less than block size. If `tail.len()` is zero, we replace - // it with block size. Thus the invariant required by - // `set_pos_unchecked` is satisfied. - unsafe { - self.set_pos_unchecked(new_pos); - } + self.buffer.write_block( + tail.len(), + |b| self.core.write_keystream_block(b), + |tail_ks| { + tail.xor_in2out(tail_ks); + }, + ); Ok(()) } #[inline] - fn try_write_keystream(&mut self, mut data: &mut [u8]) -> Result<(), StreamCipherError> { + fn try_write_keystream(&mut self, data: &mut [u8]) -> Result<(), StreamCipherError> { self.check_remaining(data.len())?; - let pos = usize::from(self.get_pos()); - let rem = usize::from(self.remaining()); - let data_len = data.len(); - - if rem != 0 { - if data_len <= rem { - data.copy_from_slice(&self.buffer[pos..][..data_len]); - // SAFETY: we have checked that `data_len` is less or equal to length - // of remaining keystream data, thus `pos + data_len` can not be bigger - // than block size. Since `pos` is never zero, `pos + data_len` can not - // be zero. Thus `pos + data_len` satisfies the safety invariant required - // by `set_pos_unchecked`. - unsafe { - self.set_pos_unchecked(pos + data_len); - } - return Ok(()); - } - let (left, right) = data.split_at_mut(rem); - data = right; - left.copy_from_slice(&self.buffer[pos..]); - } + let head_ks = self.buffer.read_cached(data.len()); + let (head, data) = data.split_at_mut(head_ks.len()); let (blocks, tail) = Array::slice_as_chunks_mut(data); - self.core.write_keystream_blocks(blocks); - let new_pos = if tail.is_empty() { - T::BlockSize::USIZE - } else { - // Note that we temporarily write a pseudo-random byte into - // the first byte of `self.buffer`. It may break the safety invariant, - // but after writing keystream block with `tail`, we immediately - // overwrite the first byte with a correct value. - self.core.write_keystream_block(&mut self.buffer); - tail.copy_from_slice(&self.buffer[..tail.len()]); - tail.len() - }; + head.copy_from_slice(head_ks); + self.core.write_keystream_blocks(blocks); - // SAFETY: `into_chunks` always returns tail with size - // less than block size. If `tail.len()` is zero, we replace - // it with block size. Thus the invariant required by - // `set_pos_unchecked` is satisfied. - unsafe { - self.set_pos_unchecked(new_pos); - } + self.buffer.write_block( + tail.len(), + |b| self.core.write_keystream_block(b), + |tail_ks| tail.copy_from_slice(tail_ks), + ); Ok(()) } @@ -228,7 +110,8 @@ impl StreamCipher for StreamCipherCoreWrapper { impl StreamCipherSeek for StreamCipherCoreWrapper { fn try_current_pos(&self) -> Result { - let pos = self.get_pos(); + let pos = u8::try_from(self.buffer.get_pos()) + .expect("buffer position is always smaller than 256"); SN::from_block_byte(self.core.get_block_pos(), pos, T::BlockSize::U8) } @@ -239,19 +122,12 @@ impl StreamCipherSeek for StreamCipherCoreWrapper { assert!(byte_pos < T::BlockSize::U8); self.core.set_block_pos(block_pos); - let new_pos = if byte_pos != 0 { - // See comment in `try_apply_keystream_inout` for use of `write_keystream_block` - self.core.write_keystream_block(&mut self.buffer); - byte_pos.into() - } else { - T::BlockSize::USIZE - }; - // SAFETY: we assert that `byte_pos` is always smaller than block size. - // If `byte_pos` is zero, we replace it with block size. Thus the invariant - // required by `set_pos_unchecked` is satisfied. - unsafe { - self.set_pos_unchecked(new_pos); - } + + self.buffer.write_block( + usize::from(byte_pos), + |b| self.core.write_keystream_block(b), + |_| {}, + ); Ok(()) } } @@ -272,11 +148,9 @@ impl IvSizeUser for StreamCipherCoreWrapper impl KeyIvInit for StreamCipherCoreWrapper { #[inline] fn new(key: &Key, iv: &Iv) -> Self { - let mut buffer = Block::::default(); - buffer[0] = T::BlockSize::U8; Self { core: T::new(key, iv), - buffer, + buffer: Default::default(), } } } @@ -284,22 +158,21 @@ impl KeyIvInit for StreamCipherCoreWrapper { impl KeyInit for StreamCipherCoreWrapper { #[inline] fn new(key: &Key) -> Self { - let mut buffer = Block::::default(); - buffer[0] = T::BlockSize::U8; Self { core: T::new(key), - buffer, + buffer: Default::default(), } } } #[cfg(feature = "zeroize")] -impl Drop for StreamCipherCoreWrapper { - fn drop(&mut self) { - // If present, `core` will be zeroized by its own `Drop`. - self.buffer.zeroize(); - } -} +impl ZeroizeOnDrop for StreamCipherCoreWrapper {} +// Assert that `ReadBuffer` implements `ZeroizeOnDrop` #[cfg(feature = "zeroize")] -impl ZeroizeOnDrop for StreamCipherCoreWrapper {} +const _: () = { + #[allow(dead_code)] + fn check_buffer(v: &ReadBuffer) { + let _ = v as &dyn crate::zeroize::ZeroizeOnDrop; + } +}; diff --git a/digest/src/buffer_macros/xof.rs b/digest/src/buffer_macros/xof.rs index c8cbe72c7..e6a755a52 100644 --- a/digest/src/buffer_macros/xof.rs +++ b/digest/src/buffer_macros/xof.rs @@ -52,9 +52,21 @@ macro_rules! buffer_xof { #[inline] fn read(&mut self, buf: &mut [u8]) { let Self { core, buffer } = self; - buffer.read(buf, |block| { + + let head_ks = self.buffer.read_cached(buf.len()); + let (head, buf) = buf.split_at_mut(head_ks.len()); + let (blocks, tail) = $crate::array::Array::slice_as_chunks_mut(buf); + + head.copy_from_slice(head_ks); + for block in blocks { *block = $crate::block_api::XofReaderCore::read_block(core); - }); + } + + self.buffer.write_block( + tail.len(), + |block| *block = $crate::block_api::XofReaderCore::read_block(core), + |tail_ks| tail.copy_from_slice(tail_ks), + ); } } From a6576450a8d98c8de2d835a7284fbe9e6d2bfa7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 13 Aug 2025 18:14:29 +0300 Subject: [PATCH 2/7] revert `digest` changes --- Cargo.lock | 2 +- digest/src/buffer_macros/xof.rs | 15 ++------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e5ad97cfb..0d02c36b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,7 +75,7 @@ source = "git+https://github.com/RustCrypto/utils#f5ac85f6aa02aa39614f62a6a1add9 [[package]] name = "block-buffer" version = "0.11.0-rc.4" -source = "git+https://github.com/RustCrypto/utils?branch=block-buffer%2Fread-buf#21054d717f77c160fa0a70f79bdef2435c578d17" +source = "git+https://github.com/RustCrypto/utils?branch=block-buffer%2Fread-buf#1be52dc741e6adb5202c3ae536a706d252c361a9" dependencies = [ "hybrid-array", "zeroize", diff --git a/digest/src/buffer_macros/xof.rs b/digest/src/buffer_macros/xof.rs index e6a755a52..77c78c8f5 100644 --- a/digest/src/buffer_macros/xof.rs +++ b/digest/src/buffer_macros/xof.rs @@ -53,20 +53,9 @@ macro_rules! buffer_xof { fn read(&mut self, buf: &mut [u8]) { let Self { core, buffer } = self; - let head_ks = self.buffer.read_cached(buf.len()); - let (head, buf) = buf.split_at_mut(head_ks.len()); - let (blocks, tail) = $crate::array::Array::slice_as_chunks_mut(buf); - - head.copy_from_slice(head_ks); - for block in blocks { + buffer.read(buf, |block| { *block = $crate::block_api::XofReaderCore::read_block(core); - } - - self.buffer.write_block( - tail.len(), - |block| *block = $crate::block_api::XofReaderCore::read_block(core), - |tail_ks| tail.copy_from_slice(tail_ks), - ); + }); } } From 4d675b7b82f1ccf26a0f20fad1dac4391be60bac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 13 Aug 2025 18:14:57 +0300 Subject: [PATCH 3/7] remove newline --- digest/src/buffer_macros/xof.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/digest/src/buffer_macros/xof.rs b/digest/src/buffer_macros/xof.rs index 77c78c8f5..c8cbe72c7 100644 --- a/digest/src/buffer_macros/xof.rs +++ b/digest/src/buffer_macros/xof.rs @@ -52,7 +52,6 @@ macro_rules! buffer_xof { #[inline] fn read(&mut self, buf: &mut [u8]) { let Self { core, buffer } = self; - buffer.read(buf, |block| { *block = $crate::block_api::XofReaderCore::read_block(core); }); From 7db02b9ed5ec0c69c97cba205aacd76ca0ae7567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 13 Aug 2025 18:25:39 +0300 Subject: [PATCH 4/7] fix dev macro --- cipher/src/dev/stream.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cipher/src/dev/stream.rs b/cipher/src/dev/stream.rs index 00dc14f54..0e6f4ea7c 100644 --- a/cipher/src/dev/stream.rs +++ b/cipher/src/dev/stream.rs @@ -58,7 +58,7 @@ macro_rules! stream_cipher_test { for (i, tv) in TEST_VECTORS.iter().enumerate() { let res = $crate::dev::stream::stream_cipher_test(tv); - if Err(reason) = res { + if let Err(reason) = res { panic!( "\n\ Failed test #{i}\n\ From 57234c5d3978516bf4b6685d4de455ffe7e5ca67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 13 Aug 2025 18:26:37 +0300 Subject: [PATCH 5/7] fix dev macro --- cipher/src/dev/stream.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cipher/src/dev/stream.rs b/cipher/src/dev/stream.rs index 0e6f4ea7c..50e13b28f 100644 --- a/cipher/src/dev/stream.rs +++ b/cipher/src/dev/stream.rs @@ -57,7 +57,7 @@ macro_rules! stream_cipher_test { ); for (i, tv) in TEST_VECTORS.iter().enumerate() { - let res = $crate::dev::stream::stream_cipher_test(tv); + let res = $crate::dev::stream::stream_cipher_test::<$cipher>(tv); if let Err(reason) = res { panic!( "\n\ From 62af97de9cb8e109cbb3edd2546c568261294b1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 13 Aug 2025 18:48:42 +0300 Subject: [PATCH 6/7] fix seek --- cipher/src/stream/wrapper.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cipher/src/stream/wrapper.rs b/cipher/src/stream/wrapper.rs index 74c0151d2..d25f006f4 100644 --- a/cipher/src/stream/wrapper.rs +++ b/cipher/src/stream/wrapper.rs @@ -124,7 +124,7 @@ impl StreamCipherSeek for StreamCipherCoreWrapper { self.core.set_block_pos(block_pos); self.buffer.write_block( - usize::from(byte_pos), + T::BlockSize::USIZE - usize::from(byte_pos), |b| self.core.write_keystream_block(b), |_| {}, ); From f63bd790c8a4f5383915f3b5a32c587be5854282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=91=D0=BC=20=D0=9F=D0=B0=D0=B2=D0=BB?= =?UTF-8?q?=D0=BE=D0=B2=20=5BArtyom=20Pavlov=5D?= Date: Wed, 13 Aug 2025 19:23:07 +0300 Subject: [PATCH 7/7] fix seek impl --- Cargo.lock | 2 +- cipher/src/stream/wrapper.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0d02c36b8..91d3a73b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,7 +75,7 @@ source = "git+https://github.com/RustCrypto/utils#f5ac85f6aa02aa39614f62a6a1add9 [[package]] name = "block-buffer" version = "0.11.0-rc.4" -source = "git+https://github.com/RustCrypto/utils?branch=block-buffer%2Fread-buf#1be52dc741e6adb5202c3ae536a706d252c361a9" +source = "git+https://github.com/RustCrypto/utils?branch=block-buffer%2Fread-buf#79e12dfd745e732d24ba1566f705f35ba409edc6" dependencies = [ "hybrid-array", "zeroize", diff --git a/cipher/src/stream/wrapper.rs b/cipher/src/stream/wrapper.rs index d25f006f4..5789cdddd 100644 --- a/cipher/src/stream/wrapper.rs +++ b/cipher/src/stream/wrapper.rs @@ -123,8 +123,10 @@ impl StreamCipherSeek for StreamCipherCoreWrapper { self.core.set_block_pos(block_pos); + self.buffer.reset(); + self.buffer.write_block( - T::BlockSize::USIZE - usize::from(byte_pos), + usize::from(byte_pos), |b| self.core.write_keystream_block(b), |_| {}, );