Skip to content

Commit

Permalink
Add RawPadding trait to block-padding for padding blocks of arbitrary…
Browse files Browse the repository at this point in the history
… size (#870)
  • Loading branch information
czinn authored Apr 1, 2023
1 parent 734c63b commit 63fb20f
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 37 deletions.
6 changes: 6 additions & 0 deletions block-padding/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ 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).

## 0.3.3 (2023-04-02)
### Added
- `RawPadding` trait for padding blocks of arbitrary size ([#870])

[#870]: https:/RustCrypto/utils/pull/870

## 0.3.2 (2022-03-10)
### Fixed
- Potential unsoundness for incorrect `Padding` implementations ([#748])
Expand Down
2 changes: 1 addition & 1 deletion block-padding/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "block-padding"
version = "0.3.2"
version = "0.3.3"
description = "Padding and unpadding of messages divided into blocks."
authors = ["RustCrypto Developers"]
license = "MIT OR Apache-2.0"
Expand Down
108 changes: 72 additions & 36 deletions block-padding/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,25 @@ pub enum PadType {
NoPadding,
}

/// Trait for padding messages divided into blocks of arbitrary size
pub trait RawPadding {
/// Padding type
const TYPE: PadType;

/// Pads `block` filled with data up to `pos` (i.e length of a message
/// stored in the block is equal to `pos`).
///
/// # Panics
/// If `pos` is bigger than `block.len()`. Most padding algorithms also
/// panic if they are equal.
fn raw_pad(block: &mut [u8], pos: usize);

/// Unpad data in the `block`.
///
/// Returns `Err(UnpadError)` if the block contains malformed padding.
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError>;
}

/// Block size.
pub type Block<B> = GenericArray<u8, B>;

Expand Down Expand Up @@ -73,6 +92,23 @@ pub trait Padding<BlockSize: ArrayLength<u8>> {
}
}

impl<T, B: ArrayLength<u8>> Padding<B> for T
where
T: RawPadding,
{
const TYPE: PadType = T::TYPE;

#[inline]
fn pad(block: &mut Block<B>, pos: usize) {
T::raw_pad(block.as_mut_slice(), pos);
}

#[inline]
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
T::raw_unpad(block.as_slice())
}
}

/// Pad block with zeros.
///
/// ```
Expand All @@ -94,12 +130,12 @@ pub trait Padding<BlockSize: ArrayLength<u8>> {
#[derive(Clone, Copy, Debug)]
pub struct ZeroPadding;

impl<B: ArrayLength<u8>> Padding<B> for ZeroPadding {
impl RawPadding for ZeroPadding {
const TYPE: PadType = PadType::Ambiguous;

#[inline]
fn pad(block: &mut Block<B>, pos: usize) {
if pos > B::USIZE {
fn raw_pad(block: &mut [u8], pos: usize) {
if pos > block.len() {
panic!("`pos` is bigger than block size");
}
for b in &mut block[pos..] {
Expand All @@ -108,8 +144,8 @@ impl<B: ArrayLength<u8>> Padding<B> for ZeroPadding {
}

#[inline]
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
for i in (0..B::USIZE).rev() {
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
for i in (0..block.len()).rev() {
if block[i] != 0 {
return Ok(&block[..i + 1]);
}
Expand Down Expand Up @@ -140,12 +176,12 @@ pub struct Pkcs7;

impl Pkcs7 {
#[inline]
fn unpad<B: ArrayLength<u8>>(block: &Block<B>, strict: bool) -> Result<&[u8], UnpadError> {
fn unpad(block: &[u8], strict: bool) -> Result<&[u8], UnpadError> {
// TODO: use bounds to check it at compile time
if B::USIZE > 255 {
if block.len() > 255 {
panic!("block size is too big for PKCS#7");
}
let bs = B::USIZE;
let bs = block.len();
let n = block[bs - 1];
if n == 0 || n as usize > bs {
return Err(UnpadError);
Expand All @@ -158,26 +194,26 @@ impl Pkcs7 {
}
}

impl<B: ArrayLength<u8>> Padding<B> for Pkcs7 {
impl RawPadding for Pkcs7 {
const TYPE: PadType = PadType::Reversible;

#[inline]
fn pad(block: &mut Block<B>, pos: usize) {
// TODO: use bounds to check it at compile time
if B::USIZE > 255 {
fn raw_pad(block: &mut [u8], pos: usize) {
// TODO: use bounds to check it at compile time for Padding<B>
if block.len() > 255 {
panic!("block size is too big for PKCS#7");
}
if pos >= B::USIZE {
if pos >= block.len() {
panic!("`pos` is bigger or equal to block size");
}
let n = (B::USIZE - pos) as u8;
let n = (block.len() - pos) as u8;
for b in &mut block[pos..] {
*b = n;
}
}

#[inline]
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
Pkcs7::unpad(block, true)
}
}
Expand All @@ -202,18 +238,18 @@ impl<B: ArrayLength<u8>> Padding<B> for Pkcs7 {
#[derive(Clone, Copy, Debug)]
pub struct Iso10126;

impl<B: ArrayLength<u8>> Padding<B> for Iso10126 {
impl RawPadding for Iso10126 {
const TYPE: PadType = PadType::Reversible;

#[inline]
fn pad(block: &mut Block<B>, pos: usize) {
fn raw_pad(block: &mut [u8], pos: usize) {
// Instead of generating random bytes as specified by Iso10126 we
// simply use Pkcs7 padding.
Pkcs7::pad(block, pos)
Pkcs7::raw_pad(block, pos)
}

#[inline]
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
Pkcs7::unpad(block, false)
}
}
Expand All @@ -237,32 +273,32 @@ impl<B: ArrayLength<u8>> Padding<B> for Iso10126 {
#[derive(Clone, Copy, Debug)]
pub struct AnsiX923;

impl<B: ArrayLength<u8>> Padding<B> for AnsiX923 {
impl RawPadding for AnsiX923 {
const TYPE: PadType = PadType::Reversible;

#[inline]
fn pad(block: &mut Block<B>, pos: usize) {
fn raw_pad(block: &mut [u8], pos: usize) {
// TODO: use bounds to check it at compile time
if B::USIZE > 255 {
if block.len() > 255 {
panic!("block size is too big for PKCS#7");
}
if pos >= B::USIZE {
if pos >= block.len() {
panic!("`pos` is bigger or equal to block size");
}
let bs = B::USIZE;
let bs = block.len();
for b in &mut block[pos..bs - 1] {
*b = 0;
}
block[bs - 1] = (bs - pos) as u8;
}

#[inline]
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
// TODO: use bounds to check it at compile time
if B::USIZE > 255 {
if block.len() > 255 {
panic!("block size is too big for PKCS#7");
}
let bs = B::USIZE;
let bs = block.len();
let n = block[bs - 1] as usize;
if n == 0 || n > bs {
return Err(UnpadError);
Expand Down Expand Up @@ -293,12 +329,12 @@ impl<B: ArrayLength<u8>> Padding<B> for AnsiX923 {
#[derive(Clone, Copy, Debug)]
pub struct Iso7816;

impl<B: ArrayLength<u8>> Padding<B> for Iso7816 {
impl RawPadding for Iso7816 {
const TYPE: PadType = PadType::Reversible;

#[inline]
fn pad(block: &mut Block<B>, pos: usize) {
if pos >= B::USIZE {
fn raw_pad(block: &mut [u8], pos: usize) {
if pos >= block.len() {
panic!("`pos` is bigger or equal to block size");
}
block[pos] = 0x80;
Expand All @@ -308,8 +344,8 @@ impl<B: ArrayLength<u8>> Padding<B> for Iso7816 {
}

#[inline]
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
for i in (0..B::USIZE).rev() {
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
for i in (0..block.len()).rev() {
match block[i] {
0x80 => return Ok(&block[..i]),
0x00 => continue,
Expand Down Expand Up @@ -344,18 +380,18 @@ impl<B: ArrayLength<u8>> Padding<B> for Iso7816 {
#[derive(Clone, Copy, Debug)]
pub struct NoPadding;

impl<B: ArrayLength<u8>> Padding<B> for NoPadding {
impl RawPadding for NoPadding {
const TYPE: PadType = PadType::NoPadding;

#[inline]
fn pad(_block: &mut Block<B>, pos: usize) {
if pos > B::USIZE {
fn raw_pad(block: &mut [u8], pos: usize) {
if pos > block.len() {
panic!("`pos` is bigger than block size");
}
}

#[inline]
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
Ok(block)
}
}
Expand Down

0 comments on commit 63fb20f

Please sign in to comment.