Skip to content

Commit 63fb20f

Browse files
authored
Add RawPadding trait to block-padding for padding blocks of arbitrary size (#870)
1 parent 734c63b commit 63fb20f

File tree

3 files changed

+79
-37
lines changed

3 files changed

+79
-37
lines changed

block-padding/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## 0.3.3 (2023-04-02)
8+
### Added
9+
- `RawPadding` trait for padding blocks of arbitrary size ([#870])
10+
11+
[#870]: https://github.com/RustCrypto/utils/pull/870
12+
713
## 0.3.2 (2022-03-10)
814
### Fixed
915
- Potential unsoundness for incorrect `Padding` implementations ([#748])

block-padding/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "block-padding"
3-
version = "0.3.2"
3+
version = "0.3.3"
44
description = "Padding and unpadding of messages divided into blocks."
55
authors = ["RustCrypto Developers"]
66
license = "MIT OR Apache-2.0"

block-padding/src/lib.rs

Lines changed: 72 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,25 @@ pub enum PadType {
2929
NoPadding,
3030
}
3131

32+
/// Trait for padding messages divided into blocks of arbitrary size
33+
pub trait RawPadding {
34+
/// Padding type
35+
const TYPE: PadType;
36+
37+
/// Pads `block` filled with data up to `pos` (i.e length of a message
38+
/// stored in the block is equal to `pos`).
39+
///
40+
/// # Panics
41+
/// If `pos` is bigger than `block.len()`. Most padding algorithms also
42+
/// panic if they are equal.
43+
fn raw_pad(block: &mut [u8], pos: usize);
44+
45+
/// Unpad data in the `block`.
46+
///
47+
/// Returns `Err(UnpadError)` if the block contains malformed padding.
48+
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError>;
49+
}
50+
3251
/// Block size.
3352
pub type Block<B> = GenericArray<u8, B>;
3453

@@ -73,6 +92,23 @@ pub trait Padding<BlockSize: ArrayLength<u8>> {
7392
}
7493
}
7594

95+
impl<T, B: ArrayLength<u8>> Padding<B> for T
96+
where
97+
T: RawPadding,
98+
{
99+
const TYPE: PadType = T::TYPE;
100+
101+
#[inline]
102+
fn pad(block: &mut Block<B>, pos: usize) {
103+
T::raw_pad(block.as_mut_slice(), pos);
104+
}
105+
106+
#[inline]
107+
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
108+
T::raw_unpad(block.as_slice())
109+
}
110+
}
111+
76112
/// Pad block with zeros.
77113
///
78114
/// ```
@@ -94,12 +130,12 @@ pub trait Padding<BlockSize: ArrayLength<u8>> {
94130
#[derive(Clone, Copy, Debug)]
95131
pub struct ZeroPadding;
96132

97-
impl<B: ArrayLength<u8>> Padding<B> for ZeroPadding {
133+
impl RawPadding for ZeroPadding {
98134
const TYPE: PadType = PadType::Ambiguous;
99135

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

110146
#[inline]
111-
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
112-
for i in (0..B::USIZE).rev() {
147+
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
148+
for i in (0..block.len()).rev() {
113149
if block[i] != 0 {
114150
return Ok(&block[..i + 1]);
115151
}
@@ -140,12 +176,12 @@ pub struct Pkcs7;
140176

141177
impl Pkcs7 {
142178
#[inline]
143-
fn unpad<B: ArrayLength<u8>>(block: &Block<B>, strict: bool) -> Result<&[u8], UnpadError> {
179+
fn unpad(block: &[u8], strict: bool) -> Result<&[u8], UnpadError> {
144180
// TODO: use bounds to check it at compile time
145-
if B::USIZE > 255 {
181+
if block.len() > 255 {
146182
panic!("block size is too big for PKCS#7");
147183
}
148-
let bs = B::USIZE;
184+
let bs = block.len();
149185
let n = block[bs - 1];
150186
if n == 0 || n as usize > bs {
151187
return Err(UnpadError);
@@ -158,26 +194,26 @@ impl Pkcs7 {
158194
}
159195
}
160196

161-
impl<B: ArrayLength<u8>> Padding<B> for Pkcs7 {
197+
impl RawPadding for Pkcs7 {
162198
const TYPE: PadType = PadType::Reversible;
163199

164200
#[inline]
165-
fn pad(block: &mut Block<B>, pos: usize) {
166-
// TODO: use bounds to check it at compile time
167-
if B::USIZE > 255 {
201+
fn raw_pad(block: &mut [u8], pos: usize) {
202+
// TODO: use bounds to check it at compile time for Padding<B>
203+
if block.len() > 255 {
168204
panic!("block size is too big for PKCS#7");
169205
}
170-
if pos >= B::USIZE {
206+
if pos >= block.len() {
171207
panic!("`pos` is bigger or equal to block size");
172208
}
173-
let n = (B::USIZE - pos) as u8;
209+
let n = (block.len() - pos) as u8;
174210
for b in &mut block[pos..] {
175211
*b = n;
176212
}
177213
}
178214

179215
#[inline]
180-
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
216+
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
181217
Pkcs7::unpad(block, true)
182218
}
183219
}
@@ -202,18 +238,18 @@ impl<B: ArrayLength<u8>> Padding<B> for Pkcs7 {
202238
#[derive(Clone, Copy, Debug)]
203239
pub struct Iso10126;
204240

205-
impl<B: ArrayLength<u8>> Padding<B> for Iso10126 {
241+
impl RawPadding for Iso10126 {
206242
const TYPE: PadType = PadType::Reversible;
207243

208244
#[inline]
209-
fn pad(block: &mut Block<B>, pos: usize) {
245+
fn raw_pad(block: &mut [u8], pos: usize) {
210246
// Instead of generating random bytes as specified by Iso10126 we
211247
// simply use Pkcs7 padding.
212-
Pkcs7::pad(block, pos)
248+
Pkcs7::raw_pad(block, pos)
213249
}
214250

215251
#[inline]
216-
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
252+
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
217253
Pkcs7::unpad(block, false)
218254
}
219255
}
@@ -237,32 +273,32 @@ impl<B: ArrayLength<u8>> Padding<B> for Iso10126 {
237273
#[derive(Clone, Copy, Debug)]
238274
pub struct AnsiX923;
239275

240-
impl<B: ArrayLength<u8>> Padding<B> for AnsiX923 {
276+
impl RawPadding for AnsiX923 {
241277
const TYPE: PadType = PadType::Reversible;
242278

243279
#[inline]
244-
fn pad(block: &mut Block<B>, pos: usize) {
280+
fn raw_pad(block: &mut [u8], pos: usize) {
245281
// TODO: use bounds to check it at compile time
246-
if B::USIZE > 255 {
282+
if block.len() > 255 {
247283
panic!("block size is too big for PKCS#7");
248284
}
249-
if pos >= B::USIZE {
285+
if pos >= block.len() {
250286
panic!("`pos` is bigger or equal to block size");
251287
}
252-
let bs = B::USIZE;
288+
let bs = block.len();
253289
for b in &mut block[pos..bs - 1] {
254290
*b = 0;
255291
}
256292
block[bs - 1] = (bs - pos) as u8;
257293
}
258294

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

296-
impl<B: ArrayLength<u8>> Padding<B> for Iso7816 {
332+
impl RawPadding for Iso7816 {
297333
const TYPE: PadType = PadType::Reversible;
298334

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

310346
#[inline]
311-
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
312-
for i in (0..B::USIZE).rev() {
347+
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
348+
for i in (0..block.len()).rev() {
313349
match block[i] {
314350
0x80 => return Ok(&block[..i]),
315351
0x00 => continue,
@@ -344,18 +380,18 @@ impl<B: ArrayLength<u8>> Padding<B> for Iso7816 {
344380
#[derive(Clone, Copy, Debug)]
345381
pub struct NoPadding;
346382

347-
impl<B: ArrayLength<u8>> Padding<B> for NoPadding {
383+
impl RawPadding for NoPadding {
348384
const TYPE: PadType = PadType::NoPadding;
349385

350386
#[inline]
351-
fn pad(_block: &mut Block<B>, pos: usize) {
352-
if pos > B::USIZE {
387+
fn raw_pad(block: &mut [u8], pos: usize) {
388+
if pos > block.len() {
353389
panic!("`pos` is bigger than block size");
354390
}
355391
}
356392

357393
#[inline]
358-
fn unpad(block: &Block<B>) -> Result<&[u8], UnpadError> {
394+
fn raw_unpad(block: &[u8]) -> Result<&[u8], UnpadError> {
359395
Ok(block)
360396
}
361397
}

0 commit comments

Comments
 (0)