Skip to content

Commit 021e014

Browse files
authored
block-buffer: remove dependency on crypto-common (#1115)
Dependency on `crypto-common` causes some annoyances as mentioned in RustCrypto/traits#1662. Instead of using the sealed `BlockSizes` trait, the new code uses monomorphization errors to enforce block size correctness. This is somewhat non-idiomatic, but should be fine in practice since block buffers are usually used with fixed block sizes. After this change `BlockSizes` probably can be removed from `crypto-common`. I decided against vendoring `block-buffer` code into `digest` as was proposed in the linked issue because `block-buffer` has third-party users and having a separate crate should make it a bit easier for reviewers.
1 parent b5d80a2 commit 021e014

8 files changed

Lines changed: 106 additions & 72 deletions

File tree

.github/workflows/block-buffer.yml

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -39,11 +39,10 @@ jobs:
3939
targets: ${{ matrix.target }}
4040
- run: cargo build --target ${{ matrix.target }}
4141

42-
# TODO(tarcieri): re-enable after next `crypto-common` release
43-
#minimal-versions:
44-
# uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master
45-
# with:
46-
# working-directory: ${{ github.workflow }}
42+
minimal-versions:
43+
uses: RustCrypto/actions/.github/workflows/minimal-versions.yml@master
44+
with:
45+
working-directory: ${{ github.workflow }}
4746

4847
test:
4948
runs-on: ubuntu-latest

Cargo.lock

Lines changed: 1 addition & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

block-buffer/CHANGELOG.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111
- Optional implementation of the `Zeroize` trait ([#963])
1212

1313
### Changed
14-
- Supported block sizes are now bounded by the `crypto_common::BlockSizes` trait,
15-
which is implemented for types from `U1` to `U255` ([#823])
14+
- Block sizes must be bigger than 0 and smaller than 256.
15+
This is enforced using compile-time monomorphization errors. ([#1115])
1616
- Size of `EagerBuffer` is equal to buffer size, while previously it was equal
1717
to buffer size plus one byte ([#823])
18-
- Edition changed to 2021 and MSRV bumped to 1.56 ([#823])
18+
- Edition changed to 2021 and MSRV bumped to 1.81 ([#823], [#1116])
1919

2020
### Removed
2121
- `EagerBuffer::set_data` method. Use the `ReadBuffer` type instead. ([#823])
2222

2323
[#823]: https://github.com/RustCrypto/utils/pull/823
2424
[#963]: https://github.com/RustCrypto/utils/pull/963
25+
[#1115]: https://github.com/RustCrypto/utils/pull/1115
26+
[#1115]: https://github.com/RustCrypto/utils/pull/1116
2527

2628
## 0.10.3 (2022-09-04)
2729
### Added

block-buffer/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ readme = "README.md"
1313
rust-version = "1.81"
1414

1515
[dependencies]
16-
crypto-common = "0.2.0-rc.1"
16+
hybrid-array = "0.2.0-rc.10"
1717
zeroize = { version = "1.4", optional = true, default-features = false }
1818

1919
[dev-dependencies]

block-buffer/src/lib.rs

Lines changed: 76 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,52 @@
11
//! Fixed size buffer for block processing of data.
2+
//!
3+
//! # Examples
4+
//! ```
5+
//! use block_buffer::{EagerBuffer, array::typenum::U4};
6+
//!
7+
//! let mut buf = EagerBuffer::<U4>::default();
8+
//!
9+
//! let mut accum = Vec::new();
10+
//! let msg1: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
11+
//! let msg2: &[u8] = &[10, 11, 12];
12+
//!
13+
//! buf.digest_blocks(msg1, |blocks| accum.extend_from_slice(blocks));
14+
//! buf.digest_blocks(msg2, |blocks| accum.extend_from_slice(blocks));
15+
//!
16+
//! assert_eq!(accum.len(), 3);
17+
//! assert_eq!(accum[0], [0, 1, 2, 3]);
18+
//! assert_eq!(accum[1], [4, 5, 6, 7]);
19+
//! assert_eq!(accum[2], [8, 9, 10, 11]);
20+
//!
21+
//! let padded_block = buf.pad_with_zeros();
22+
//! assert_eq!(padded_block, [12, 0, 0, 0]);
23+
//! ```
24+
//!
25+
//! Note that block size used with buffers MUST be bigger than zero and smaller than 256.
26+
//! You will get a compilation error with an invalid block size:
27+
//!
28+
//! ```compile_fail
29+
//! use block_buffer::{EagerBuffer, array::typenum::U0};
30+
//! let buf = EagerBuffer::<U0>::default();
31+
//! ```
32+
//! ```compile_fail
33+
//! use block_buffer::{EagerBuffer, array::typenum::U256};
34+
//! let buf = EagerBuffer::<U256>::default();
35+
//! ```
236
#![no_std]
337
#![doc(
438
html_logo_url = "https://github.com/RustCrypto/media/6ee8e381/logo.svg",
539
html_favicon_url = "https://github.com/RustCrypto/media/6ee8e381/logo.svg"
640
)]
741
#![warn(missing_docs, rust_2018_idioms)]
842

9-
pub use crypto_common::{array, Block};
43+
pub use hybrid_array as array;
1044

1145
use array::{
1246
typenum::{Add1, B1},
1347
Array, ArraySize,
1448
};
1549
use core::{fmt, mem::MaybeUninit, ops::Add, ptr, slice};
16-
use crypto_common::{BlockSizeUser, BlockSizes};
1750

1851
#[cfg(feature = "zeroize")]
1952
use zeroize::Zeroize;
@@ -23,9 +56,6 @@ mod sealed;
2356

2457
pub use read::ReadBuffer;
2558

26-
/// Block with additional one byte
27-
type BlockP1<BlockSize> = Array<u8, Add1<BlockSize>>;
28-
2959
/// Trait for buffer kinds.
3060
pub trait BufferKind: sealed::Sealed {}
3161

@@ -59,26 +89,36 @@ impl fmt::Display for Error {
5989
}
6090

6191
/// Buffer for block processing of data.
62-
pub struct BlockBuffer<BS: BlockSizes, K: BufferKind> {
63-
buffer: MaybeUninit<Block<Self>>,
92+
pub struct BlockBuffer<BS: ArraySize, K: BufferKind> {
93+
buffer: MaybeUninit<Array<u8, BS>>,
6494
pos: K::Pos,
6595
}
6696

67-
impl<BS: BlockSizes, K: BufferKind> BlockSizeUser for BlockBuffer<BS, K> {
68-
type BlockSize = BS;
97+
impl<BS: ArraySize, K: BufferKind> BlockBuffer<BS, K> {
98+
/// This associated constant is used to assert block size correctness at compile time.
99+
const BLOCK_SIZE_ASSERT: bool = {
100+
if BS::USIZE == 0 {
101+
panic!("Block size can not be equal to zero!");
102+
}
103+
if BS::USIZE > 255 {
104+
panic!("Block size can not be bigger than 255!");
105+
}
106+
true
107+
};
69108
}
70109

71-
impl<BS: BlockSizes, K: BufferKind> Default for BlockBuffer<BS, K> {
110+
impl<BS: ArraySize, K: BufferKind> Default for BlockBuffer<BS, K> {
72111
#[inline]
73112
fn default() -> Self {
113+
assert!(Self::BLOCK_SIZE_ASSERT);
74114
let mut buffer = MaybeUninit::uninit();
75115
let mut pos = Default::default();
76116
K::set_pos(&mut buffer, &mut pos, 0);
77117
Self { buffer, pos }
78118
}
79119
}
80120

81-
impl<BS: BlockSizes, K: BufferKind> Clone for BlockBuffer<BS, K> {
121+
impl<BS: ArraySize, K: BufferKind> Clone for BlockBuffer<BS, K> {
82122
#[inline]
83123
fn clone(&self) -> Self {
84124
// SAFETY: `BlockBuffer` does not implement `Drop` (i.e. it could be a `Copy` type),
@@ -87,7 +127,7 @@ impl<BS: BlockSizes, K: BufferKind> Clone for BlockBuffer<BS, K> {
87127
}
88128
}
89129

90-
impl<BS: BlockSizes, K: BufferKind> fmt::Debug for BlockBuffer<BS, K> {
130+
impl<BS: ArraySize, K: BufferKind> fmt::Debug for BlockBuffer<BS, K> {
91131
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
92132
f.debug_struct(K::NAME)
93133
.field("pos", &self.get_pos())
@@ -97,7 +137,7 @@ impl<BS: BlockSizes, K: BufferKind> fmt::Debug for BlockBuffer<BS, K> {
97137
}
98138
}
99139

100-
impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
140+
impl<BS: ArraySize, K: BufferKind> BlockBuffer<BS, K> {
101141
/// Create new buffer from slice.
102142
///
103143
/// # Panics
@@ -112,6 +152,7 @@ impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
112152
/// Returns an error if slice length is not valid for used buffer kind.
113153
#[inline(always)]
114154
pub fn try_new(buf: &[u8]) -> Result<Self, Error> {
155+
assert!(Self::BLOCK_SIZE_ASSERT);
115156
if !K::invariant(buf.len(), BS::USIZE) {
116157
return Err(Error);
117158
}
@@ -126,7 +167,7 @@ impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
126167
/// Digest data in `input` in blocks of size `BlockSize` using
127168
/// the `compress` function, which accepts slice of blocks.
128169
#[inline]
129-
pub fn digest_blocks(&mut self, mut input: &[u8], mut compress: impl FnMut(&[Block<Self>])) {
170+
pub fn digest_blocks(&mut self, mut input: &[u8], mut compress: impl FnMut(&[Array<u8, BS>])) {
130171
let pos = self.get_pos();
131172
// using `self.remaining()` for some reason
132173
// prevents panic elimination
@@ -186,8 +227,8 @@ impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
186227

187228
/// Pad remaining data with zeros and return resulting block.
188229
#[inline(always)]
189-
pub fn pad_with_zeros(&mut self) -> Block<Self> {
190-
let mut res = Block::<Self>::default();
230+
pub fn pad_with_zeros(&mut self) -> Array<u8, BS> {
231+
let mut res = Array::<u8, BS>::default();
191232
let data = self.get_data();
192233
res[..data.len()].copy_from_slice(data);
193234
self.reset();
@@ -221,7 +262,7 @@ impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
221262
/// # Panics
222263
/// If `pos` is bigger or equal to block size.
223264
#[inline]
224-
pub fn set(&mut self, buf: Block<Self>, pos: usize) {
265+
pub fn set(&mut self, buf: Array<u8, BS>, pos: usize) {
225266
assert!(K::invariant(pos, BS::USIZE));
226267
self.buffer = MaybeUninit::new(buf);
227268
// SAFETY: we have asserted that `pos` satisfies the invariant and
@@ -271,15 +312,20 @@ impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
271312
}
272313
}
273314

274-
impl<BS: BlockSizes> BlockBuffer<BS, Eager> {
315+
impl<BS: ArraySize> BlockBuffer<BS, Eager> {
275316
/// Compress remaining data after padding it with `delim`, zeros and
276317
/// the `suffix` bytes. If there is not enough unused space, `compress`
277318
/// will be called twice.
278319
///
279320
/// # Panics
280321
/// If suffix length is bigger than block size.
281322
#[inline(always)]
282-
pub fn digest_pad(&mut self, delim: u8, suffix: &[u8], mut compress: impl FnMut(&Block<Self>)) {
323+
pub fn digest_pad(
324+
&mut self,
325+
delim: u8,
326+
suffix: &[u8],
327+
mut compress: impl FnMut(&Array<u8, BS>),
328+
) {
283329
if suffix.len() > BS::USIZE {
284330
panic!("suffix is too long");
285331
}
@@ -303,28 +349,28 @@ impl<BS: BlockSizes> BlockBuffer<BS, Eager> {
303349
/// Pad message with 0x80, zeros and 64-bit message length using
304350
/// big-endian byte order.
305351
#[inline]
306-
pub fn len64_padding_be(&mut self, data_len: u64, compress: impl FnMut(&Block<Self>)) {
352+
pub fn len64_padding_be(&mut self, data_len: u64, compress: impl FnMut(&Array<u8, BS>)) {
307353
self.digest_pad(0x80, &data_len.to_be_bytes(), compress);
308354
}
309355

310356
/// Pad message with 0x80, zeros and 64-bit message length using
311357
/// little-endian byte order.
312358
#[inline]
313-
pub fn len64_padding_le(&mut self, data_len: u64, compress: impl FnMut(&Block<Self>)) {
359+
pub fn len64_padding_le(&mut self, data_len: u64, compress: impl FnMut(&Array<u8, BS>)) {
314360
self.digest_pad(0x80, &data_len.to_le_bytes(), compress);
315361
}
316362

317363
/// Pad message with 0x80, zeros and 128-bit message length using
318364
/// big-endian byte order.
319365
#[inline]
320-
pub fn len128_padding_be(&mut self, data_len: u128, compress: impl FnMut(&Block<Self>)) {
366+
pub fn len128_padding_be(&mut self, data_len: u128, compress: impl FnMut(&Array<u8, BS>)) {
321367
self.digest_pad(0x80, &data_len.to_be_bytes(), compress);
322368
}
323369

324370
/// Serialize buffer into a byte array.
325371
#[inline]
326-
pub fn serialize(&self) -> Block<Self> {
327-
let mut res = Block::<Self>::default();
372+
pub fn serialize(&self) -> Array<u8, BS> {
373+
let mut res = Array::<u8, BS>::default();
328374
let data = self.get_data();
329375
res[..data.len()].copy_from_slice(data);
330376
res[BS::USIZE - 1] = data.len() as u8;
@@ -333,7 +379,7 @@ impl<BS: BlockSizes> BlockBuffer<BS, Eager> {
333379

334380
/// Deserialize buffer from a byte array.
335381
#[inline]
336-
pub fn deserialize(buffer: &Block<Self>) -> Result<Self, Error> {
382+
pub fn deserialize(buffer: &Array<u8, BS>) -> Result<Self, Error> {
337383
let pos = buffer[BS::USIZE - 1] as usize;
338384
if !<Eager as sealed::Sealed>::invariant(pos, BS::USIZE) {
339385
return Err(Error);
@@ -348,15 +394,15 @@ impl<BS: BlockSizes> BlockBuffer<BS, Eager> {
348394
}
349395
}
350396

351-
impl<BS: BlockSizes> BlockBuffer<BS, Lazy> {
397+
impl<BS: ArraySize> BlockBuffer<BS, Lazy> {
352398
/// Serialize buffer into a byte array.
353399
#[inline]
354-
pub fn serialize(&self) -> BlockP1<BS>
400+
pub fn serialize(&self) -> Array<u8, Add1<BS>>
355401
where
356402
BS: Add<B1>,
357403
Add1<BS>: ArraySize,
358404
{
359-
let mut res = BlockP1::<BS>::default();
405+
let mut res = Array::<u8, Add1<BS>>::default();
360406
res[0] = self.pos;
361407
let data = self.get_data();
362408
res[1..][..data.len()].copy_from_slice(data);
@@ -365,7 +411,7 @@ impl<BS: BlockSizes> BlockBuffer<BS, Lazy> {
365411

366412
/// Deserialize buffer from a byte array.
367413
#[inline]
368-
pub fn deserialize(buffer: &BlockP1<BS>) -> Result<Self, Error>
414+
pub fn deserialize(buffer: &Array<u8, Add1<BS>>) -> Result<Self, Error>
369415
where
370416
BS: Add<B1>,
371417
Add1<BS>: ArraySize,
@@ -386,7 +432,7 @@ impl<BS: BlockSizes> BlockBuffer<BS, Lazy> {
386432
}
387433

388434
#[cfg(feature = "zeroize")]
389-
impl<BS: BlockSizes, K: BufferKind> Zeroize for BlockBuffer<BS, K> {
435+
impl<BS: ArraySize, K: BufferKind> Zeroize for BlockBuffer<BS, K> {
390436
#[inline]
391437
fn zeroize(&mut self) {
392438
self.buffer.zeroize();

0 commit comments

Comments
 (0)