From aa2ccfcdef0540cc882fee553e03fa87854d43cb 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?= Date: Mon, 19 Dec 2022 16:10:45 +0300 Subject: [PATCH 1/5] block-buffer v0.11 --- .github/workflows/block-buffer.yml | 4 +- Cargo.lock | 53 +++--- block-buffer/CHANGELOG.md | 15 ++ block-buffer/Cargo.toml | 7 +- block-buffer/src/lib.rs | 230 ++++++++++++------------ block-buffer/src/read.rs | 144 +++++++++++++++ block-buffer/src/sealed.rs | 41 ++++- block-buffer/tests/mod.rs | 269 ++++++++++++++++++++++------- 8 files changed, 557 insertions(+), 206 deletions(-) create mode 100644 block-buffer/src/read.rs diff --git a/.github/workflows/block-buffer.yml b/.github/workflows/block-buffer.yml index 2aba09d4..7ea492b2 100644 --- a/.github/workflows/block-buffer.yml +++ b/.github/workflows/block-buffer.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: rust: - - 1.41.0 # MSRV + - 1.56.0 # MSRV - stable target: - thumbv7em-none-eabi @@ -50,7 +50,7 @@ jobs: strategy: matrix: rust: - - 1.41.0 # MSRV + - 1.56.0 # MSRV - stable steps: - uses: actions/checkout@v3 diff --git a/Cargo.lock b/Cargo.lock index f5c0b4ef..d4740fdf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,9 +11,10 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.10.3" +version = "0.11.0" dependencies = [ "generic-array", + "hex-literal 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -74,6 +75,12 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" name = "hex-literal" version = "0.3.4" +[[package]] +name = "hex-literal" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebdb29d2ea9ed0083cd8cece49bbd968021bd99b0849edb4a9a7ee0fdf6a4e0" + [[package]] name = "hybrid-array" version = "0.1.0" @@ -91,15 +98,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754" +checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440" [[package]] name = "libc" -version = "0.2.132" +version = "0.2.138" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5" +checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8" [[package]] name = "opaque-debug" @@ -107,42 +114,42 @@ version = "0.3.0" [[package]] name = "proc-macro2" -version = "1.0.47" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725" +checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179" +checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b" dependencies = [ "proc-macro2", ] [[package]] name = "ryu" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" +checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" [[package]] name = "serde" -version = "1.0.144" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8" dependencies = [ "proc-macro2", "quote", @@ -151,9 +158,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.85" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" +checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ "itoa", "ryu", @@ -162,9 +169,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.99" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13" +checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5" dependencies = [ "proc-macro2", "quote", @@ -191,15 +198,15 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-ident" -version = "1.0.3" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf" +checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc" [[package]] name = "unicode-xid" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" +checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" [[package]] name = "version_check" diff --git a/block-buffer/CHANGELOG.md b/block-buffer/CHANGELOG.md index 8f1fd1c0..18619b5e 100644 --- a/block-buffer/CHANGELOG.md +++ b/block-buffer/CHANGELOG.md @@ -4,6 +4,21 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## UNRELEASED +### Added +- `ReadBuffer` type +- `serialize` and `deserialize` methods + +### Changed +- Supported block sizes are now bounded by sealed `BlockSizes` trait + implemented for types from `U1` to `U255` +- Size of `EagerBuffer` is equal to buffer size, while previously it was equal + to buffer size plus one byte. +- MSRV bumped to 1.56 + +### Removed +- `EagerBuffer::set_data` method. Use the `ReadBuffer` type instead. + ## 0.10.3 (2022-09-04) ### Added - `try_new` method ([#799]) diff --git a/block-buffer/Cargo.toml b/block-buffer/Cargo.toml index fc095c8d..d1e02a51 100644 --- a/block-buffer/Cargo.toml +++ b/block-buffer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "block-buffer" -version = "0.10.3" +version = "0.11.0" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Buffer type for block processing of data" @@ -8,8 +8,11 @@ documentation = "https://docs.rs/block-buffer" repository = "https://github.com/RustCrypto/utils" keywords = ["block", "buffer"] categories = ["cryptography", "no-std"] -edition = "2018" +edition = "2021" readme = "README.md" [dependencies] generic-array = "0.14" + +[dev-dependencies] +hex-literal = "0.3.3" diff --git a/block-buffer/src/lib.rs b/block-buffer/src/lib.rs index ac9055e3..7292808a 100644 --- a/block-buffer/src/lib.rs +++ b/block-buffer/src/lib.rs @@ -8,17 +8,22 @@ pub use generic_array; -use core::{fmt, marker::PhantomData, slice}; +use core::{fmt, ops::Add, slice}; use generic_array::{ - typenum::{IsLess, Le, NonZero, U256}, + typenum::{Add1, B1}, ArrayLength, GenericArray, }; +mod read; mod sealed; +pub use read::ReadBuffer; + /// Block on which `BlockBuffer` operates. pub type Block = GenericArray; +type BlockP1 = GenericArray>; + /// Trait for buffer kinds. pub trait BufferKind: sealed::Sealed {} @@ -33,6 +38,7 @@ pub struct Eager {} pub struct Lazy {} impl BufferKind for Eager {} + impl BufferKind for Lazy {} /// Eager block buffer. @@ -50,55 +56,39 @@ impl fmt::Display for Error { } } +/// Trait implemented for supported block sizes, i.e. for types from `U1` to `U255`. +pub trait BlockSizes: ArrayLength + sealed::BlockSizes {} + +impl + sealed::BlockSizes> BlockSizes for T {} + /// Buffer for block processing of data. #[derive(Debug)] -pub struct BlockBuffer -where - BlockSize: ArrayLength + IsLess, - Le: NonZero, - Kind: BufferKind, -{ - buffer: Block, - pos: u8, - _pd: PhantomData, +pub struct BlockBuffer { + buffer: Block, + pos: K::Pos, } -impl Default for BlockBuffer -where - BlockSize: ArrayLength + IsLess, - Le: NonZero, - Kind: BufferKind, -{ +impl Default for BlockBuffer { + #[inline] fn default() -> Self { Self { buffer: Default::default(), - pos: 0, - _pd: PhantomData, + pos: Default::default(), } } } -impl Clone for BlockBuffer -where - BlockSize: ArrayLength + IsLess, - Le: NonZero, - Kind: BufferKind, -{ +impl Clone for BlockBuffer { + #[inline] fn clone(&self) -> Self { Self { buffer: self.buffer.clone(), - pos: self.pos, - _pd: PhantomData, + pos: self.pos.clone(), } } } -impl BlockBuffer -where - BlockSize: ArrayLength + IsLess, - Le: NonZero, - Kind: BufferKind, -{ +impl BlockBuffer { /// Create new buffer from slice. /// /// # Panics @@ -114,26 +104,19 @@ where #[inline(always)] pub fn try_new(buf: &[u8]) -> Result { let pos = buf.len(); - if !Kind::invariant(pos, BlockSize::USIZE) { + if !K::invariant(pos, BS::USIZE) { return Err(Error); } - let mut buffer = Block::::default(); - buffer[..pos].copy_from_slice(buf); - Ok(Self { - buffer, - pos: pos as u8, - _pd: PhantomData, - }) + let mut res = Self::default(); + res.buffer[..pos].copy_from_slice(buf); + K::set_pos(&mut res.buffer, &mut res.pos, pos); + Ok(res) } /// Digest data in `input` in blocks of size `BlockSize` using /// the `compress` function, which accepts slice of blocks. #[inline] - pub fn digest_blocks( - &mut self, - mut input: &[u8], - mut compress: impl FnMut(&[Block]), - ) { + pub fn digest_blocks(&mut self, mut input: &[u8], mut compress: impl FnMut(&[Block])) { let pos = self.get_pos(); // using `self.remaining()` for some reason // prevents panic elimination @@ -146,7 +129,7 @@ where // `pos + n` which results in it inserting unreachable // panic branches. Using `unreachable_unchecked` in `get_pos` // we convince compiler that `BlockSize - pos` never underflows. - if Kind::invariant(n, rem) { + if K::invariant(n, rem) { // double slicing allows to remove panic branches self.buffer[pos..][..n].copy_from_slice(input); self.set_pos_unchecked(pos + n); @@ -159,7 +142,7 @@ where compress(slice::from_ref(&self.buffer)); } - let (blocks, leftover) = Kind::split_blocks(input); + let (blocks, leftover) = K::split_blocks(input); if !blocks.is_empty() { compress(blocks); } @@ -177,18 +160,19 @@ where /// Pad remaining data with zeros and return resulting block. #[inline(always)] - pub fn pad_with_zeros(&mut self) -> &mut Block { + pub fn pad_with_zeros(&mut self) -> Block { let pos = self.get_pos(); - self.buffer[pos..].iter_mut().for_each(|b| *b = 0); + let mut res = self.buffer.clone(); + res[pos..].iter_mut().for_each(|b| *b = 0); self.set_pos_unchecked(0); - &mut self.buffer + res } /// Return current cursor position. #[inline(always)] pub fn get_pos(&self) -> usize { - let pos = self.pos as usize; - if !Kind::invariant(pos, BlockSize::USIZE) { + let pos = K::get_pos(&self.buffer, &self.pos); + if !K::invariant(pos, BS::USIZE) { debug_assert!(false); // SAFETY: `pos` never breaks the invariant unsafe { @@ -209,8 +193,8 @@ where /// # Panics /// If `pos` is bigger or equal to block size. #[inline] - pub fn set(&mut self, buf: Block, pos: usize) { - assert!(Kind::invariant(pos, BlockSize::USIZE)); + pub fn set(&mut self, buf: Block, pos: usize) { + assert!(K::invariant(pos, BS::USIZE)); self.buffer = buf; self.set_pos_unchecked(pos); } @@ -218,7 +202,7 @@ where /// Return size of the internal buffer in bytes. #[inline(always)] pub fn size(&self) -> usize { - BlockSize::USIZE + BS::USIZE } /// Return number of remaining bytes in the internal buffer. @@ -229,51 +213,12 @@ where #[inline(always)] fn set_pos_unchecked(&mut self, pos: usize) { - debug_assert!(Kind::invariant(pos, BlockSize::USIZE)); - self.pos = pos as u8; + debug_assert!(K::invariant(pos, BS::USIZE)); + K::set_pos(&mut self.buffer, &mut self.pos, pos) } } -impl BlockBuffer -where - BlockSize: ArrayLength + IsLess, - Le: NonZero, -{ - /// Set `data` to generated blocks. - #[inline] - pub fn set_data( - &mut self, - mut data: &mut [u8], - mut process_blocks: impl FnMut(&mut [Block]), - ) { - let pos = self.get_pos(); - let r = self.remaining(); - let n = data.len(); - if pos != 0 { - if n < r { - // double slicing allows to remove panic branches - data.copy_from_slice(&self.buffer[pos..][..n]); - self.set_pos_unchecked(pos + n); - return; - } - let (left, right) = data.split_at_mut(r); - data = right; - left.copy_from_slice(&self.buffer[pos..]); - } - - let (blocks, leftover) = to_blocks_mut(data); - process_blocks(blocks); - - let n = leftover.len(); - if n != 0 { - let mut block = Default::default(); - process_blocks(slice::from_mut(&mut block)); - leftover.copy_from_slice(&block[..n]); - self.buffer = block; - } - self.set_pos_unchecked(n); - } - +impl BlockBuffer { /// Compress remaining data after padding it with `delim`, zeros and /// the `suffix` bytes. If there is not enough unused space, `compress` /// will be called twice. @@ -281,13 +226,8 @@ where /// # Panics /// If suffix length is bigger than block size. #[inline(always)] - pub fn digest_pad( - &mut self, - delim: u8, - suffix: &[u8], - mut compress: impl FnMut(&Block), - ) { - if suffix.len() > BlockSize::USIZE { + pub fn digest_pad(&mut self, delim: u8, suffix: &[u8], mut compress: impl FnMut(&Block)) { + if suffix.len() > BS::USIZE { panic!("suffix is too long"); } let pos = self.get_pos(); @@ -299,7 +239,7 @@ where let n = self.size() - suffix.len(); if self.size() - pos - 1 < suffix.len() { compress(&self.buffer); - let mut block = Block::::default(); + let mut block = Block::::default(); block[n..].copy_from_slice(suffix); compress(&block); } else { @@ -312,33 +252,85 @@ where /// Pad message with 0x80, zeros and 64-bit message length using /// big-endian byte order. #[inline] - pub fn len64_padding_be(&mut self, data_len: u64, compress: impl FnMut(&Block)) { + pub fn len64_padding_be(&mut self, data_len: u64, compress: impl FnMut(&Block)) { self.digest_pad(0x80, &data_len.to_be_bytes(), compress); } /// Pad message with 0x80, zeros and 64-bit message length using /// little-endian byte order. #[inline] - pub fn len64_padding_le(&mut self, data_len: u64, compress: impl FnMut(&Block)) { + pub fn len64_padding_le(&mut self, data_len: u64, compress: impl FnMut(&Block)) { self.digest_pad(0x80, &data_len.to_le_bytes(), compress); } /// Pad message with 0x80, zeros and 128-bit message length using /// big-endian byte order. #[inline] - pub fn len128_padding_be(&mut self, data_len: u128, compress: impl FnMut(&Block)) { + pub fn len128_padding_be(&mut self, data_len: u128, compress: impl FnMut(&Block)) { self.digest_pad(0x80, &data_len.to_be_bytes(), compress); } + + /// Serialize buffer into a byte array. + #[inline] + pub fn serialize(&self) -> Block { + let mut res = self.buffer.clone(); + let pos = self.get_pos(); + // zeroize "garbage" data + for b in res[pos..BS::USIZE - 1].iter_mut() { + *b = 0; + } + res + } + + /// Deserialize buffer from a byte array. + #[inline] + pub fn deserialize(buffer: &Block) -> Result { + let pos = buffer[BS::USIZE - 1] as usize; + if !::invariant(pos, BS::USIZE) { + return Err(Error); + } + if buffer[pos..BS::USIZE - 1].iter().any(|&b| b != 0) { + return Err(Error); + } + Ok(Self { + buffer: buffer.clone(), + pos: Default::default(), + }) + } } -/// Split message into mutable slice of parallel blocks, blocks, and leftover bytes. -#[inline(always)] -fn to_blocks_mut>(data: &mut [u8]) -> (&mut [Block], &mut [u8]) { - let nb = data.len() / N::USIZE; - let (left, right) = data.split_at_mut(nb * N::USIZE); - let p = left.as_mut_ptr() as *mut Block; - // SAFETY: we guarantee that `blocks` does not point outside of `data`, and `p` is valid for - // mutation - let blocks = unsafe { slice::from_raw_parts_mut(p, nb) }; - (blocks, right) +impl BlockBuffer { + /// Serialize buffer into a byte array. + #[inline] + pub fn serialize(&self) -> BlockP1 + where + BS: Add, + Add1: ArrayLength, + { + let mut res = BlockP1::::default(); + res[0] = self.pos; + let data = self.get_data(); + res[1..][..data.len()].copy_from_slice(data); + res + } + + /// Deserialize buffer from a byte array. + #[inline] + pub fn deserialize(buffer: &BlockP1) -> Result + where + BS: Add, + Add1: ArrayLength, + { + let pos = buffer[0]; + if !::invariant(pos as usize, BS::USIZE) { + return Err(Error); + } + if buffer[1..][pos as usize..].iter().any(|&b| b != 0) { + return Err(Error); + } + Ok(Self { + buffer: GenericArray::clone_from_slice(&buffer[1..]), + pos: pos, + }) + } } diff --git a/block-buffer/src/read.rs b/block-buffer/src/read.rs new file mode 100644 index 00000000..94aa5d28 --- /dev/null +++ b/block-buffer/src/read.rs @@ -0,0 +1,144 @@ +use super::{Block, BlockSizes, Error}; +use core::{fmt, slice}; +use generic_array::ArrayLength; + +/// Buffer for reading block-generated data. +pub struct ReadBuffer { + // The first byte of the block is used as position. + buffer: Block, +} + +impl fmt::Debug for ReadBuffer { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ReadBuffer") + .field("remaining_data", &self.get_pos()) + .finish() + } +} + +impl Default for ReadBuffer { + #[inline] + fn default() -> Self { + let mut buffer = Block::::default(); + buffer[0] = BS::U8; + Self { buffer } + } +} + +impl Clone for ReadBuffer { + #[inline] + fn clone(&self) -> Self { + Self { + buffer: self.buffer.clone(), + } + } +} + +impl ReadBuffer { + /// Return current cursor position. + #[inline(always)] + pub fn get_pos(&self) -> usize { + let pos = self.buffer[0]; + if pos == 0 || pos > BS::U8 { + debug_assert!(false); + // SAFETY: `pos` never breaks the invariant + unsafe { + core::hint::unreachable_unchecked(); + } + } + pos as usize + } + + /// Return size of the internal buffer in bytes. + #[inline(always)] + pub fn size(&self) -> usize { + BS::USIZE + } + + /// Return number of remaining bytes in the internal buffer. + #[inline(always)] + pub fn remaining(&self) -> usize { + self.size() - self.get_pos() + } + + #[inline(always)] + fn set_pos_unchecked(&mut self, pos: usize) { + debug_assert!(pos <= BS::USIZE); + self.buffer[0] = pos as u8; + } + + /// Write remaining data inside buffer into `data`, fill remaining space + /// in `data` with blocks generated by `gen_block`, and save leftover data + /// from the last generated block into buffer for future use. + #[inline] + pub fn read(&mut self, mut data: &mut [u8], mut gen_block: impl FnMut(&mut Block)) { + let pos = self.get_pos(); + let r = self.remaining(); + let n = data.len(); + + if r != 0 { + if n < r { + // double slicing allows to remove panic branches + data.copy_from_slice(&self.buffer[pos..][..n]); + self.set_pos_unchecked(pos + n); + return; + } + let (left, right) = data.split_at_mut(r); + data = right; + left.copy_from_slice(&self.buffer[pos..]); + } + + let (blocks, leftover) = to_blocks_mut(data); + for block in blocks { + gen_block(block); + } + + let n = leftover.len(); + if n != 0 { + let mut block = Default::default(); + gen_block(&mut block); + leftover.copy_from_slice(&block[..n]); + self.buffer = block; + self.set_pos_unchecked(n); + } else { + self.set_pos_unchecked(BS::USIZE); + } + } + + /// Serialize buffer into a byte array. + #[inline] + pub fn serialize(&self) -> Block { + let mut res = self.buffer.clone(); + let pos = self.get_pos(); + // zeroize "garbage" data + for b in res[1..pos].iter_mut() { + *b = 0; + } + res + } + + /// Deserialize buffer from a byte array. + #[inline] + pub fn deserialize(buffer: &Block) -> Result { + let pos = buffer[0]; + if pos == 0 || pos > BS::U8 || buffer[1..pos as usize].iter().any(|&b| b != 0) { + return Err(Error); + } else { + Ok(Self { + buffer: buffer.clone(), + }) + } + } +} + +/// Split message into mutable slice of parallel blocks, blocks, and leftover bytes. +#[inline(always)] +fn to_blocks_mut>(data: &mut [u8]) -> (&mut [Block], &mut [u8]) { + let nb = data.len() / N::USIZE; + let (left, right) = data.split_at_mut(nb * N::USIZE); + let p = left.as_mut_ptr() as *mut Block; + // SAFETY: we guarantee that `blocks` does not point outside of `data`, and `p` is valid for + // mutation + let blocks = unsafe { slice::from_raw_parts_mut(p, nb) }; + (blocks, right) +} diff --git a/block-buffer/src/sealed.rs b/block-buffer/src/sealed.rs index 247dec23..d8c51912 100644 --- a/block-buffer/src/sealed.rs +++ b/block-buffer/src/sealed.rs @@ -1,8 +1,15 @@ use super::{ArrayLength, Block}; -use core::slice; +use core::{ops::Sub, slice}; +use generic_array::typenum::{Gr, IsGreater, IsLess, Le, NonZero, Unsigned, B1, U1, U256}; /// Sealed trait for buffer kinds. pub trait Sealed { + type Pos: Default + Clone; + + fn get_pos(buf: &[u8], pos: &Self::Pos) -> usize; + + fn set_pos(buf_val: &mut [u8], pos: &mut Self::Pos, val: usize); + /// Invariant guaranteed by a buffer kind, i.e. with correct /// buffer code this function always returns true. fn invariant(pos: usize, block_size: usize) -> bool; @@ -12,6 +19,17 @@ pub trait Sealed { } impl Sealed for super::Eager { + type Pos = (); + + fn get_pos(buf: &[u8], _pos: &Self::Pos) -> usize { + buf[buf.len() - 1] as usize + } + + fn set_pos(buf: &mut [u8], _pos: &mut Self::Pos, val: usize) { + debug_assert!(val <= u8::MAX as usize); + buf[buf.len() - 1] = val as u8; + } + #[inline(always)] fn invariant(pos: usize, block_size: usize) -> bool { pos < block_size @@ -36,6 +54,17 @@ impl Sealed for super::Eager { } impl Sealed for super::Lazy { + type Pos = u8; + + fn get_pos(_buf_val: &[u8], pos: &Self::Pos) -> usize { + *pos as usize + } + + fn set_pos(_buf_val: &mut [u8], pos: &mut Self::Pos, val: usize) { + debug_assert!(val <= u8::MAX as usize); + *pos = val as u8; + } + #[inline(always)] fn invariant(pos: usize, block_size: usize) -> bool { pos <= block_size @@ -65,3 +94,13 @@ impl Sealed for super::Lazy { } } } + +pub trait BlockSizes {} + +impl BlockSizes for T +where + Self: IsLess + IsGreater + Sub, + Le: NonZero, + Gr: NonZero, +{ +} diff --git a/block-buffer/tests/mod.rs b/block-buffer/tests/mod.rs index ee08f979..966f8cbe 100644 --- a/block-buffer/tests/mod.rs +++ b/block-buffer/tests/mod.rs @@ -1,7 +1,11 @@ use block_buffer::{ - generic_array::typenum::{U10, U16, U24, U4, U8}, - Block, EagerBuffer, LazyBuffer, + generic_array::{ + typenum::{U10, U16, U24, U4, U8}, + GenericArray, + }, + Block, EagerBuffer, LazyBuffer, ReadBuffer, }; +use hex_literal::hex; #[test] fn test_eager_digest_pad() { @@ -73,32 +77,34 @@ fn test_lazy_digest_pad() { } #[test] -fn test_eager_set_data() { - let mut buf = EagerBuffer::::default(); +fn test_read() { + let mut buf = ReadBuffer::::default(); let mut n = 0u8; - let mut gen = |blocks: &mut [Block]| { - for block in blocks { - block.iter_mut().for_each(|b| *b = n); - n += 1; - } + let mut gen = |block: &mut Block| { + block.iter_mut().for_each(|b| *b = n); + n += 1; }; let mut out = [0u8; 6]; - buf.set_data(&mut out, &mut gen); + buf.read(&mut out, &mut gen); assert_eq!(out, [0, 0, 0, 0, 1, 1]); assert_eq!(buf.get_pos(), 2); + assert_eq!(buf.remaining(), 2); let mut out = [0u8; 3]; - buf.set_data(&mut out, &mut gen); + buf.read(&mut out, &mut gen); assert_eq!(out, [1, 1, 2]); assert_eq!(buf.get_pos(), 1); + assert_eq!(buf.remaining(), 3); let mut out = [0u8; 3]; - buf.set_data(&mut out, &mut gen); + buf.read(&mut out, &mut gen); assert_eq!(out, [2, 2, 2]); + assert_eq!(buf.get_pos(), 4); + assert_eq!(buf.remaining(), 0); + assert_eq!(n, 3); - assert_eq!(buf.get_pos(), 0); } #[test] @@ -112,20 +118,8 @@ fn test_eager_paddings() { buf_be.len64_padding_be(len, |block| out_be.extend(block)); buf_le.len64_padding_le(len, |block| out_le.extend(block)); - assert_eq!( - out_be, - [ - 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - ], - ); - assert_eq!( - out_le, - [ - 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00, - ], - ); + assert_eq!(out_be, hex!("42800000000000000001020304050607")); + assert_eq!(out_le, hex!("42800000000000000706050403020100")); let mut buf_be = EagerBuffer::::new(&[0x42]); let mut buf_le = buf_be.clone(); @@ -134,14 +128,8 @@ fn test_eager_paddings() { buf_be.len64_padding_be(len, |block| out_be.extend(block)); buf_le.len64_padding_le(len, |block| out_le.extend(block)); - assert_eq!( - out_be, - [0x42, 0x80, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07], - ); - assert_eq!( - out_le, - [0x42, 0x80, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00], - ); + assert_eq!(out_be, hex!("42800001020304050607")); + assert_eq!(out_le, hex!("42800706050403020100")); let mut buf = EagerBuffer::::new(&[0x42]); let mut out = Vec::::new(); @@ -149,42 +137,24 @@ fn test_eager_paddings() { buf.len128_padding_be(len, |block| out.extend(block)); assert_eq!( out, - [ - 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - ], + hex!("42800000000000000000000000000000000102030405060708090a0b0c0d0e0f"), ); let mut buf = EagerBuffer::::new(&[0x42]); let mut out = Vec::::new(); let len = 0x0001_0203_0405_0607_0809_0a0b_0c0d_0e0f; buf.len128_padding_be(len, |block| out.extend(block)); - assert_eq!( - out, - [ - 0x42, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - ], - ); + assert_eq!(out, hex!("4280000000000000000102030405060708090a0b0c0d0e0f")); let mut buf = EagerBuffer::::new(&[0x42]); let mut out = Vec::::new(); - buf.digest_pad(0xff, &[0x10, 0x11, 0x12], |block| out.extend(block)); - assert_eq!( - out, - [0x42, 0xff, 0x00, 0x00, 0x00, 0x10, 0x11, 0x12], - ); + buf.digest_pad(0xff, &hex!("101112"), |block| out.extend(block)); + assert_eq!(out, hex!("42ff000000101112")); let mut buf = EagerBuffer::::new(&[0x42]); let mut out = Vec::::new(); - buf.digest_pad(0xff, &[0x10, 0x11], |block| out.extend(block)); - assert_eq!( - out, - [0x42, 0xff, 0x10, 0x11], - ); + buf.digest_pad(0xff, &hex!("1011"), |block| out.extend(block)); + assert_eq!(out, hex!("42ff1011")); } #[test] @@ -194,3 +164,184 @@ fn test_try_new() { assert!(LazyBuffer::::try_new(&[0; 4]).is_ok()); assert!(LazyBuffer::::try_new(&[0; 5]).is_err()); } + +#[test] +fn test_eager_serialize() { + type Buf = EagerBuffer; + + let mut buf1 = Buf::default(); + let ser0 = buf1.serialize(); + assert_eq!(&ser0[..], &[0, 0, 0, 0]); + assert_eq!(Buf::deserialize(&ser0).unwrap().serialize(), ser0); + + buf1.digest_blocks(&[41, 42], |_| {}); + + let ser1 = buf1.serialize(); + assert_eq!(&ser1[..], &[41, 42, 0, 2]); + + let mut buf2 = Buf::deserialize(&ser1).unwrap(); + assert_eq!(buf1.serialize(), ser1); + + buf1.digest_blocks(&[43], |_| {}); + buf2.digest_blocks(&[43], |_| {}); + + let ser2 = buf1.serialize(); + assert_eq!(&ser2[..], &[41, 42, 43, 3]); + assert_eq!(buf1.serialize(), ser2); + + let mut buf3 = Buf::deserialize(&ser2).unwrap(); + assert_eq!(buf3.serialize(), ser2); + + buf1.digest_blocks(&[44], |_| {}); + buf2.digest_blocks(&[44], |_| {}); + buf3.digest_blocks(&[44], |_| {}); + + let ser3 = buf1.serialize(); + assert_eq!(&ser3[..], &[0, 0, 0, 0]); + assert_eq!(buf2.serialize(), ser3); + assert_eq!(buf3.serialize(), ser3); + + // Invalid position + let buf = GenericArray::from_slice(&[0, 0, 0, 4]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[0, 0, 0, 10]); + assert!(Buf::deserialize(buf).is_err()); + // "Garbage" bytes are not zeroized + let buf = GenericArray::from_slice(&[1, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[0, 1, 0, 1]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[0, 0, 1, 2]); + assert!(Buf::deserialize(buf).is_err()); +} + +#[test] +fn test_lazy_serialize() { + type Buf = LazyBuffer; + + let mut buf1 = Buf::default(); + let ser0 = buf1.serialize(); + assert_eq!(&ser0[..], &[0, 0, 0, 0, 0]); + assert_eq!(Buf::deserialize(&ser0).unwrap().serialize(), ser0); + + buf1.digest_blocks(&[41, 42], |_| {}); + + let ser1 = buf1.serialize(); + assert_eq!(&ser1[..], &[2, 41, 42, 0, 0]); + + let mut buf2 = Buf::deserialize(&ser1).unwrap(); + assert_eq!(buf1.serialize(), ser1); + + buf1.digest_blocks(&[43], |_| {}); + buf2.digest_blocks(&[43], |_| {}); + + let ser2 = buf1.serialize(); + assert_eq!(&ser2[..], &[3, 41, 42, 43, 0]); + assert_eq!(buf1.serialize(), ser2); + + let mut buf3 = Buf::deserialize(&ser2).unwrap(); + assert_eq!(buf3.serialize(), ser2); + + buf1.digest_blocks(&[44], |_| {}); + buf2.digest_blocks(&[44], |_| {}); + buf3.digest_blocks(&[44], |_| {}); + + let ser3 = buf1.serialize(); + assert_eq!(&ser3[..], &[4, 41, 42, 43, 44]); + assert_eq!(buf2.serialize(), ser3); + assert_eq!(buf3.serialize(), ser3); + + buf1.digest_blocks(&[45], |_| {}); + buf2.digest_blocks(&[45], |_| {}); + buf3.digest_blocks(&[45], |_| {}); + + let ser4 = buf1.serialize(); + assert_eq!(&ser4[..], &[1, 45, 0, 0, 0]); + assert_eq!(buf2.serialize(), ser4); + assert_eq!(buf3.serialize(), ser4); + + // Invalid position + let buf = GenericArray::from_slice(&[10, 0, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[5, 0, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + // "Garbage" bytes are not zeroized + let buf = GenericArray::from_slice(&[0, 1, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[1, 0, 1, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[2, 0, 0, 1, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[3, 0, 0, 0, 1]); + assert!(Buf::deserialize(buf).is_err()); +} + +#[test] +fn test_read_serialize() { + type Buf = ReadBuffer; + + let mut n = 42u8; + let mut gen = |block: &mut Block| { + block.iter_mut().for_each(|b| { + *b = n; + n += 1; + }); + }; + + let mut buf1 = Buf::default(); + let ser0 = buf1.serialize(); + assert_eq!(&ser0[..], &[4, 0, 0, 0]); + assert_eq!(Buf::deserialize(&ser0).unwrap().serialize(), ser0); + + buf1.read(&mut [0; 2], &mut gen); + + let ser1 = buf1.serialize(); + assert_eq!(&ser1[..], &[2, 0, 44, 45]); + + let mut buf2 = Buf::deserialize(&ser1).unwrap(); + assert_eq!(buf1.serialize(), ser1); + + buf1.read(&mut [0; 1], &mut gen); + buf2.read(&mut [0; 1], &mut gen); + + let ser2 = buf1.serialize(); + assert_eq!(&ser2[..], &[3, 0, 0, 45]); + assert_eq!(buf1.serialize(), ser2); + + let mut buf3 = Buf::deserialize(&ser2).unwrap(); + assert_eq!(buf3.serialize(), ser2); + + buf1.read(&mut [0; 1], &mut gen); + buf2.read(&mut [0; 1], &mut gen); + buf3.read(&mut [0; 1], &mut gen); + + let ser3 = buf1.serialize(); + assert_eq!(&ser3[..], &[4, 0, 0, 0]); + assert_eq!(buf2.serialize(), ser3); + assert_eq!(buf3.serialize(), ser3); + + buf1.read(&mut [0; 1], &mut gen); + buf2.read(&mut [0; 1], &mut gen); + buf3.read(&mut [0; 1], &mut gen); + + // note that each buffer calls `gen`, so they get filled + // with different data + assert_eq!(&buf1.serialize()[..], &[1, 47, 48, 49]); + assert_eq!(&buf2.serialize()[..], &[1, 51, 52, 53]); + assert_eq!(&buf3.serialize()[..], &[1, 55, 56, 57]); + + // Invalid position + let buf = GenericArray::from_slice(&[0, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[5, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[10, 0, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + // "Garbage" bytes are not zeroized + let buf = GenericArray::from_slice(&[2, 1, 0, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[3, 0, 1, 0]); + assert!(Buf::deserialize(buf).is_err()); + let buf = GenericArray::from_slice(&[4, 0, 0, 1]); + assert!(Buf::deserialize(buf).is_err()); +} From ca299cd217413bc8aee13f459e087df53b36b669 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?= Date: Mon, 19 Dec 2022 17:29:23 +0300 Subject: [PATCH 2/5] Use crypto-common --- Cargo.lock | 10 +++++++++ block-buffer/Cargo.toml | 1 + block-buffer/src/lib.rs | 39 ++++++++++++++++----------------- block-buffer/src/read.rs | 44 +++++++++++++++++++++----------------- block-buffer/src/sealed.rs | 25 ++++++---------------- block-buffer/tests/mod.rs | 7 +++--- 6 files changed, 65 insertions(+), 61 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d4740fdf..1334c102 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,6 +13,7 @@ dependencies = [ name = "block-buffer" version = "0.11.0" dependencies = [ + "crypto-common", "generic-array", "hex-literal 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -39,6 +40,15 @@ dependencies = [ "libc", ] +[[package]] +name = "crypto-common" +version = "0.2.0-pre" +source = "git+https://github.com/RustCrypto/traits/?branch=crypto_common_v0.2#48d751024011dd39abb3926dacb66b6ca7d7ef37" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "dbl" version = "0.3.2" diff --git a/block-buffer/Cargo.toml b/block-buffer/Cargo.toml index d1e02a51..b3dc309d 100644 --- a/block-buffer/Cargo.toml +++ b/block-buffer/Cargo.toml @@ -12,6 +12,7 @@ edition = "2021" readme = "README.md" [dependencies] +crypto-common = { git = "https://github.com/RustCrypto/traits/", branch = "crypto_common_v0.2" } generic-array = "0.14" [dev-dependencies] diff --git a/block-buffer/src/lib.rs b/block-buffer/src/lib.rs index 7292808a..61438e71 100644 --- a/block-buffer/src/lib.rs +++ b/block-buffer/src/lib.rs @@ -9,6 +9,8 @@ pub use generic_array; use core::{fmt, ops::Add, slice}; +pub use crypto_common::Block; +use crypto_common::{BlockSizeUser, BlockSizes}; use generic_array::{ typenum::{Add1, B1}, ArrayLength, GenericArray, @@ -19,9 +21,7 @@ mod sealed; pub use read::ReadBuffer; -/// Block on which `BlockBuffer` operates. -pub type Block = GenericArray; - +/// Block with additional one byte type BlockP1 = GenericArray>; /// Trait for buffer kinds. @@ -56,18 +56,17 @@ impl fmt::Display for Error { } } -/// Trait implemented for supported block sizes, i.e. for types from `U1` to `U255`. -pub trait BlockSizes: ArrayLength + sealed::BlockSizes {} - -impl + sealed::BlockSizes> BlockSizes for T {} - /// Buffer for block processing of data. #[derive(Debug)] pub struct BlockBuffer { - buffer: Block, + buffer: Block, pos: K::Pos, } +impl BlockSizeUser for BlockBuffer { + type BlockSize = BS; +} + impl Default for BlockBuffer { #[inline] fn default() -> Self { @@ -116,7 +115,7 @@ impl BlockBuffer { /// Digest data in `input` in blocks of size `BlockSize` using /// the `compress` function, which accepts slice of blocks. #[inline] - pub fn digest_blocks(&mut self, mut input: &[u8], mut compress: impl FnMut(&[Block])) { + pub fn digest_blocks(&mut self, mut input: &[u8], mut compress: impl FnMut(&[Block])) { let pos = self.get_pos(); // using `self.remaining()` for some reason // prevents panic elimination @@ -160,7 +159,7 @@ impl BlockBuffer { /// Pad remaining data with zeros and return resulting block. #[inline(always)] - pub fn pad_with_zeros(&mut self) -> Block { + pub fn pad_with_zeros(&mut self) -> Block { let pos = self.get_pos(); let mut res = self.buffer.clone(); res[pos..].iter_mut().for_each(|b| *b = 0); @@ -193,7 +192,7 @@ impl BlockBuffer { /// # Panics /// If `pos` is bigger or equal to block size. #[inline] - pub fn set(&mut self, buf: Block, pos: usize) { + pub fn set(&mut self, buf: Block, pos: usize) { assert!(K::invariant(pos, BS::USIZE)); self.buffer = buf; self.set_pos_unchecked(pos); @@ -226,7 +225,7 @@ impl BlockBuffer { /// # Panics /// If suffix length is bigger than block size. #[inline(always)] - pub fn digest_pad(&mut self, delim: u8, suffix: &[u8], mut compress: impl FnMut(&Block)) { + pub fn digest_pad(&mut self, delim: u8, suffix: &[u8], mut compress: impl FnMut(&Block)) { if suffix.len() > BS::USIZE { panic!("suffix is too long"); } @@ -239,7 +238,7 @@ impl BlockBuffer { let n = self.size() - suffix.len(); if self.size() - pos - 1 < suffix.len() { compress(&self.buffer); - let mut block = Block::::default(); + let mut block = Block::::default(); block[n..].copy_from_slice(suffix); compress(&block); } else { @@ -252,27 +251,27 @@ impl BlockBuffer { /// Pad message with 0x80, zeros and 64-bit message length using /// big-endian byte order. #[inline] - pub fn len64_padding_be(&mut self, data_len: u64, compress: impl FnMut(&Block)) { + pub fn len64_padding_be(&mut self, data_len: u64, compress: impl FnMut(&Block)) { self.digest_pad(0x80, &data_len.to_be_bytes(), compress); } /// Pad message with 0x80, zeros and 64-bit message length using /// little-endian byte order. #[inline] - pub fn len64_padding_le(&mut self, data_len: u64, compress: impl FnMut(&Block)) { + pub fn len64_padding_le(&mut self, data_len: u64, compress: impl FnMut(&Block)) { self.digest_pad(0x80, &data_len.to_le_bytes(), compress); } /// Pad message with 0x80, zeros and 128-bit message length using /// big-endian byte order. #[inline] - pub fn len128_padding_be(&mut self, data_len: u128, compress: impl FnMut(&Block)) { + pub fn len128_padding_be(&mut self, data_len: u128, compress: impl FnMut(&Block)) { self.digest_pad(0x80, &data_len.to_be_bytes(), compress); } /// Serialize buffer into a byte array. #[inline] - pub fn serialize(&self) -> Block { + pub fn serialize(&self) -> Block { let mut res = self.buffer.clone(); let pos = self.get_pos(); // zeroize "garbage" data @@ -284,7 +283,7 @@ impl BlockBuffer { /// Deserialize buffer from a byte array. #[inline] - pub fn deserialize(buffer: &Block) -> Result { + pub fn deserialize(buffer: &Block) -> Result { let pos = buffer[BS::USIZE - 1] as usize; if !::invariant(pos, BS::USIZE) { return Err(Error); @@ -330,7 +329,7 @@ impl BlockBuffer { } Ok(Self { buffer: GenericArray::clone_from_slice(&buffer[1..]), - pos: pos, + pos, }) } } diff --git a/block-buffer/src/read.rs b/block-buffer/src/read.rs index 94aa5d28..fa9237a1 100644 --- a/block-buffer/src/read.rs +++ b/block-buffer/src/read.rs @@ -1,11 +1,15 @@ -use super::{Block, BlockSizes, Error}; +use super::{Block, Error}; use core::{fmt, slice}; -use generic_array::ArrayLength; +use crypto_common::{BlockSizeUser, BlockSizes}; /// Buffer for reading block-generated data. pub struct ReadBuffer { // The first byte of the block is used as position. - buffer: Block, + buffer: Block, +} + +impl BlockSizeUser for ReadBuffer { + type BlockSize = BS; } impl fmt::Debug for ReadBuffer { @@ -19,7 +23,7 @@ impl fmt::Debug for ReadBuffer { impl Default for ReadBuffer { #[inline] fn default() -> Self { - let mut buffer = Block::::default(); + let mut buffer = Block::::default(); buffer[0] = BS::U8; Self { buffer } } @@ -71,7 +75,7 @@ impl ReadBuffer { /// in `data` with blocks generated by `gen_block`, and save leftover data /// from the last generated block into buffer for future use. #[inline] - pub fn read(&mut self, mut data: &mut [u8], mut gen_block: impl FnMut(&mut Block)) { + pub fn read(&mut self, mut data: &mut [u8], mut gen_block: impl FnMut(&mut Block)) { let pos = self.get_pos(); let r = self.remaining(); let n = data.len(); @@ -88,7 +92,7 @@ impl ReadBuffer { left.copy_from_slice(&self.buffer[pos..]); } - let (blocks, leftover) = to_blocks_mut(data); + let (blocks, leftover) = Self::to_blocks_mut(data); for block in blocks { gen_block(block); } @@ -107,7 +111,7 @@ impl ReadBuffer { /// Serialize buffer into a byte array. #[inline] - pub fn serialize(&self) -> Block { + pub fn serialize(&self) -> Block { let mut res = self.buffer.clone(); let pos = self.get_pos(); // zeroize "garbage" data @@ -119,26 +123,26 @@ impl ReadBuffer { /// Deserialize buffer from a byte array. #[inline] - pub fn deserialize(buffer: &Block) -> Result { + pub fn deserialize(buffer: &Block) -> Result { let pos = buffer[0]; if pos == 0 || pos > BS::U8 || buffer[1..pos as usize].iter().any(|&b| b != 0) { - return Err(Error); + Err(Error) } else { Ok(Self { buffer: buffer.clone(), }) } } -} -/// Split message into mutable slice of parallel blocks, blocks, and leftover bytes. -#[inline(always)] -fn to_blocks_mut>(data: &mut [u8]) -> (&mut [Block], &mut [u8]) { - let nb = data.len() / N::USIZE; - let (left, right) = data.split_at_mut(nb * N::USIZE); - let p = left.as_mut_ptr() as *mut Block; - // SAFETY: we guarantee that `blocks` does not point outside of `data`, and `p` is valid for - // mutation - let blocks = unsafe { slice::from_raw_parts_mut(p, nb) }; - (blocks, right) + /// Split message into mutable slice of parallel blocks, blocks, and leftover bytes. + #[inline(always)] + fn to_blocks_mut(data: &mut [u8]) -> (&mut [Block], &mut [u8]) { + let nb = data.len() / BS::USIZE; + let (left, right) = data.split_at_mut(nb * BS::USIZE); + let p = left.as_mut_ptr() as *mut Block; + // SAFETY: we guarantee that `blocks` does not point outside of `data`, and `p` is valid for + // mutation + let blocks = unsafe { slice::from_raw_parts_mut(p, nb) }; + (blocks, right) + } } diff --git a/block-buffer/src/sealed.rs b/block-buffer/src/sealed.rs index d8c51912..cc7b3ef6 100644 --- a/block-buffer/src/sealed.rs +++ b/block-buffer/src/sealed.rs @@ -1,6 +1,5 @@ -use super::{ArrayLength, Block}; -use core::{ops::Sub, slice}; -use generic_array::typenum::{Gr, IsGreater, IsLess, Le, NonZero, Unsigned, B1, U1, U256}; +use core::slice; +use generic_array::{ArrayLength, GenericArray}; /// Sealed trait for buffer kinds. pub trait Sealed { @@ -15,7 +14,7 @@ pub trait Sealed { fn invariant(pos: usize, block_size: usize) -> bool; /// Split input data into slice of blocks and tail. - fn split_blocks>(data: &[u8]) -> (&[Block], &[u8]); + fn split_blocks>(data: &[u8]) -> (&[GenericArray], &[u8]); } impl Sealed for super::Eager { @@ -36,14 +35,14 @@ impl Sealed for super::Eager { } #[inline(always)] - fn split_blocks>(data: &[u8]) -> (&[Block], &[u8]) { + fn split_blocks>(data: &[u8]) -> (&[GenericArray], &[u8]) { let nb = data.len() / N::USIZE; let blocks_len = nb * N::USIZE; let tail_len = data.len() - blocks_len; // SAFETY: we guarantee that created slices do not point // outside of `data` unsafe { - let blocks_ptr = data.as_ptr() as *const Block; + let blocks_ptr = data.as_ptr() as *const GenericArray; let tail_ptr = data.as_ptr().add(blocks_len); ( slice::from_raw_parts(blocks_ptr, nb), @@ -71,7 +70,7 @@ impl Sealed for super::Lazy { } #[inline(always)] - fn split_blocks>(data: &[u8]) -> (&[Block], &[u8]) { + fn split_blocks>(data: &[u8]) -> (&[GenericArray], &[u8]) { if data.is_empty() { return (&[], &[]); } @@ -85,7 +84,7 @@ impl Sealed for super::Lazy { // SAFETY: we guarantee that created slices do not point // outside of `data` unsafe { - let blocks_ptr = data.as_ptr() as *const Block; + let blocks_ptr = data.as_ptr() as *const GenericArray; let tail_ptr = data.as_ptr().add(blocks_len); ( slice::from_raw_parts(blocks_ptr, nb), @@ -94,13 +93,3 @@ impl Sealed for super::Lazy { } } } - -pub trait BlockSizes {} - -impl BlockSizes for T -where - Self: IsLess + IsGreater + Sub, - Le: NonZero, - Gr: NonZero, -{ -} diff --git a/block-buffer/tests/mod.rs b/block-buffer/tests/mod.rs index 966f8cbe..da2a651b 100644 --- a/block-buffer/tests/mod.rs +++ b/block-buffer/tests/mod.rs @@ -78,10 +78,11 @@ fn test_lazy_digest_pad() { #[test] fn test_read() { - let mut buf = ReadBuffer::::default(); + type Buf = ReadBuffer; + let mut buf = Buf::default(); let mut n = 0u8; - let mut gen = |block: &mut Block| { + let mut gen = |block: &mut Block| { block.iter_mut().for_each(|b| *b = n); n += 1; }; @@ -281,7 +282,7 @@ fn test_read_serialize() { type Buf = ReadBuffer; let mut n = 42u8; - let mut gen = |block: &mut Block| { + let mut gen = |block: &mut Block| { block.iter_mut().for_each(|b| { *b = n; n += 1; From 772390c753dc4b9aa1816c61bb1116d2a8d79ac2 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?= Date: Mon, 19 Dec 2022 17:32:49 +0300 Subject: [PATCH 3/5] Update changelog --- block-buffer/CHANGELOG.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/block-buffer/CHANGELOG.md b/block-buffer/CHANGELOG.md index 18619b5e..14fa050b 100644 --- a/block-buffer/CHANGELOG.md +++ b/block-buffer/CHANGELOG.md @@ -6,18 +6,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## UNRELEASED ### Added -- `ReadBuffer` type -- `serialize` and `deserialize` methods +- `ReadBuffer` type ([#823]) +- `serialize` and `deserialize` methods ([#823]) ### Changed -- Supported block sizes are now bounded by sealed `BlockSizes` trait - implemented for types from `U1` to `U255` +- Supported block sizes are now bounded by the `crypto_common::BlockSizes` trait, + which is implemented for types from `U1` to `U255` ([#823]) - Size of `EagerBuffer` is equal to buffer size, while previously it was equal - to buffer size plus one byte. -- MSRV bumped to 1.56 + to buffer size plus one byte ([#823]) +- Edition changed to 2021 and MSRV bumped to 1.56 ([#823]) ### Removed -- `EagerBuffer::set_data` method. Use the `ReadBuffer` type instead. +- `EagerBuffer::set_data` method. Use the `ReadBuffer` type instead. ([#823]) + +[#823]: https://github.com/RustCrypto/utils/pull/823 ## 0.10.3 (2022-09-04) ### Added From b7630ebd7df40ed4f3baa5bcab976543469bf378 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?= Date: Mon, 19 Dec 2022 17:50:48 +0300 Subject: [PATCH 4/5] Change version to v0.11.0-pre --- block-buffer/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block-buffer/Cargo.toml b/block-buffer/Cargo.toml index b3dc309d..62a6eaec 100644 --- a/block-buffer/Cargo.toml +++ b/block-buffer/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "block-buffer" -version = "0.11.0" +version = "0.11.0-pre" authors = ["RustCrypto Developers"] license = "MIT OR Apache-2.0" description = "Buffer type for block processing of data" From 826460784865f9a560831b4b0b2993c06bb0b49e 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?= Date: Mon, 19 Dec 2022 20:13:01 +0300 Subject: [PATCH 5/5] Use crypto-common v0.2.0-pre --- Cargo.lock | 5 +++-- block-buffer/Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1334c102..b7428d0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,7 +11,7 @@ dependencies = [ [[package]] name = "block-buffer" -version = "0.11.0" +version = "0.11.0-pre" dependencies = [ "crypto-common", "generic-array", @@ -43,7 +43,8 @@ dependencies = [ [[package]] name = "crypto-common" version = "0.2.0-pre" -source = "git+https://github.com/RustCrypto/traits/?branch=crypto_common_v0.2#48d751024011dd39abb3926dacb66b6ca7d7ef37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6faaa83e7700e0832cbbf84854d4c356270526907d9b14fab927fc7a9b5befb8" dependencies = [ "generic-array", "typenum", diff --git a/block-buffer/Cargo.toml b/block-buffer/Cargo.toml index 62a6eaec..7b121f95 100644 --- a/block-buffer/Cargo.toml +++ b/block-buffer/Cargo.toml @@ -12,7 +12,7 @@ edition = "2021" readme = "README.md" [dependencies] -crypto-common = { git = "https://github.com/RustCrypto/traits/", branch = "crypto_common_v0.2" } +crypto-common = "0.2.0-pre" generic-array = "0.14" [dev-dependencies]