Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

block-buffer: remove dependency on crypto-common #1115

Merged
merged 2 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions .github/workflows/block-buffer.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,10 @@ jobs:
targets: ${{ matrix.target }}
- run: cargo build --target ${{ matrix.target }}

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

test:
runs-on: ubuntu-latest
Expand Down
11 changes: 1 addition & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 5 additions & 3 deletions block-buffer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Optional implementation of the `Zeroize` trait ([#963])

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

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

[#823]: https://github.com/RustCrypto/utils/pull/823
[#963]: https://github.com/RustCrypto/utils/pull/963
[#1115]: https://github.com/RustCrypto/utils/pull/1115
[#1115]: https://github.com/RustCrypto/utils/pull/1116

## 0.10.3 (2022-09-04)
### Added
Expand Down
2 changes: 1 addition & 1 deletion block-buffer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ readme = "README.md"
rust-version = "1.81"

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

[dev-dependencies]
Expand Down
106 changes: 76 additions & 30 deletions block-buffer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,52 @@
//! Fixed size buffer for block processing of data.
//!
//! # Examples
//! ```
//! use block_buffer::{EagerBuffer, array::typenum::U4};
//!
//! let mut buf = EagerBuffer::<U4>::default();
//!
//! let mut accum = Vec::new();
//! let msg1: &[u8] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
//! let msg2: &[u8] = &[10, 11, 12];
//!
//! buf.digest_blocks(msg1, |blocks| accum.extend_from_slice(blocks));
//! buf.digest_blocks(msg2, |blocks| accum.extend_from_slice(blocks));
//!
//! assert_eq!(accum.len(), 3);
//! assert_eq!(accum[0], [0, 1, 2, 3]);
//! assert_eq!(accum[1], [4, 5, 6, 7]);
//! assert_eq!(accum[2], [8, 9, 10, 11]);
//!
//! let padded_block = buf.pad_with_zeros();
//! assert_eq!(padded_block, [12, 0, 0, 0]);
//! ```
//!
//! Note that block size used with buffers MUST be bigger than zero and smaller than 256.
//! You will get a compilation error with an invalid block size:
//!
//! ```compile_fail
//! use block_buffer::{EagerBuffer, array::typenum::U0};
//! let buf = EagerBuffer::<U0>::default();
//! ```
//! ```compile_fail
//! use block_buffer::{EagerBuffer, array::typenum::U256};
//! let buf = EagerBuffer::<U256>::default();
//! ```
#![no_std]
#![doc(
html_logo_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg",
html_favicon_url = "https://raw.githubusercontent.com/RustCrypto/media/6ee8e381/logo.svg"
)]
#![warn(missing_docs, rust_2018_idioms)]

pub use crypto_common::{array, Block};
pub use hybrid_array as array;

use array::{
typenum::{Add1, B1},
Array, ArraySize,
};
use core::{fmt, mem::MaybeUninit, ops::Add, ptr, slice};
use crypto_common::{BlockSizeUser, BlockSizes};

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

pub use read::ReadBuffer;

/// Block with additional one byte
type BlockP1<BlockSize> = Array<u8, Add1<BlockSize>>;

/// Trait for buffer kinds.
pub trait BufferKind: sealed::Sealed {}

Expand Down Expand Up @@ -59,26 +89,36 @@ impl fmt::Display for Error {
}

/// Buffer for block processing of data.
pub struct BlockBuffer<BS: BlockSizes, K: BufferKind> {
buffer: MaybeUninit<Block<Self>>,
pub struct BlockBuffer<BS: ArraySize, K: BufferKind> {
buffer: MaybeUninit<Array<u8, BS>>,
pos: K::Pos,
}

impl<BS: BlockSizes, K: BufferKind> BlockSizeUser for BlockBuffer<BS, K> {
type BlockSize = BS;
impl<BS: ArraySize, K: BufferKind> BlockBuffer<BS, K> {
/// This associated constant is used to assert block size correctness at compile time.
const BLOCK_SIZE_ASSERT: bool = {
if BS::USIZE == 0 {
panic!("Block size can not be equal to zero!");
}
if BS::USIZE > 255 {
panic!("Block size can not be bigger than 255!");
}
true
};
}

impl<BS: BlockSizes, K: BufferKind> Default for BlockBuffer<BS, K> {
impl<BS: ArraySize, K: BufferKind> Default for BlockBuffer<BS, K> {
#[inline]
fn default() -> Self {
assert!(Self::BLOCK_SIZE_ASSERT);
let mut buffer = MaybeUninit::uninit();
let mut pos = Default::default();
K::set_pos(&mut buffer, &mut pos, 0);
Self { buffer, pos }
}
}

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

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

impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
impl<BS: ArraySize, K: BufferKind> BlockBuffer<BS, K> {
/// Create new buffer from slice.
///
/// # Panics
Expand All @@ -112,6 +152,7 @@ impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
/// Returns an error if slice length is not valid for used buffer kind.
#[inline(always)]
pub fn try_new(buf: &[u8]) -> Result<Self, Error> {
assert!(Self::BLOCK_SIZE_ASSERT);
if !K::invariant(buf.len(), BS::USIZE) {
return Err(Error);
}
Expand All @@ -126,7 +167,7 @@ impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
/// 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<Self>])) {
pub fn digest_blocks(&mut self, mut input: &[u8], mut compress: impl FnMut(&[Array<u8, BS>])) {
let pos = self.get_pos();
// using `self.remaining()` for some reason
// prevents panic elimination
Expand Down Expand Up @@ -186,8 +227,8 @@ impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {

/// Pad remaining data with zeros and return resulting block.
#[inline(always)]
pub fn pad_with_zeros(&mut self) -> Block<Self> {
let mut res = Block::<Self>::default();
pub fn pad_with_zeros(&mut self) -> Array<u8, BS> {
let mut res = Array::<u8, BS>::default();
let data = self.get_data();
res[..data.len()].copy_from_slice(data);
self.reset();
Expand Down Expand Up @@ -221,7 +262,7 @@ impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
/// # Panics
/// If `pos` is bigger or equal to block size.
#[inline]
pub fn set(&mut self, buf: Block<Self>, pos: usize) {
pub fn set(&mut self, buf: Array<u8, BS>, pos: usize) {
assert!(K::invariant(pos, BS::USIZE));
self.buffer = MaybeUninit::new(buf);
// SAFETY: we have asserted that `pos` satisfies the invariant and
Expand Down Expand Up @@ -271,15 +312,20 @@ impl<BS: BlockSizes, K: BufferKind> BlockBuffer<BS, K> {
}
}

impl<BS: BlockSizes> BlockBuffer<BS, Eager> {
impl<BS: ArraySize> BlockBuffer<BS, Eager> {
/// 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.
///
/// # 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<Self>)) {
pub fn digest_pad(
&mut self,
delim: u8,
suffix: &[u8],
mut compress: impl FnMut(&Array<u8, BS>),
) {
if suffix.len() > BS::USIZE {
panic!("suffix is too long");
}
Expand All @@ -303,28 +349,28 @@ impl<BS: BlockSizes> BlockBuffer<BS, Eager> {
/// 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<Self>)) {
pub fn len64_padding_be(&mut self, data_len: u64, compress: impl FnMut(&Array<u8, BS>)) {
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<Self>)) {
pub fn len64_padding_le(&mut self, data_len: u64, compress: impl FnMut(&Array<u8, BS>)) {
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<Self>)) {
pub fn len128_padding_be(&mut self, data_len: u128, compress: impl FnMut(&Array<u8, BS>)) {
self.digest_pad(0x80, &data_len.to_be_bytes(), compress);
}

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

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

impl<BS: BlockSizes> BlockBuffer<BS, Lazy> {
impl<BS: ArraySize> BlockBuffer<BS, Lazy> {
/// Serialize buffer into a byte array.
#[inline]
pub fn serialize(&self) -> BlockP1<BS>
pub fn serialize(&self) -> Array<u8, Add1<BS>>
where
BS: Add<B1>,
Add1<BS>: ArraySize,
{
let mut res = BlockP1::<BS>::default();
let mut res = Array::<u8, Add1<BS>>::default();
res[0] = self.pos;
let data = self.get_data();
res[1..][..data.len()].copy_from_slice(data);
Expand All @@ -365,7 +411,7 @@ impl<BS: BlockSizes> BlockBuffer<BS, Lazy> {

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

#[cfg(feature = "zeroize")]
impl<BS: BlockSizes, K: BufferKind> Zeroize for BlockBuffer<BS, K> {
impl<BS: ArraySize, K: BufferKind> Zeroize for BlockBuffer<BS, K> {
#[inline]
fn zeroize(&mut self) {
self.buffer.zeroize();
Expand Down
Loading
Loading