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

cipher: restore allocating padded encrypt/decrypt #936

Merged
merged 3 commits into from
Feb 16, 2022
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
2 changes: 2 additions & 0 deletions .github/workflows/workspace.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:
override: true
profile: minimal
- run: cargo clippy --all --all-features -- -D warnings
- run: cargo clippy --all --all-features -- -D warnings
working-directory: cipher
- run: cargo clippy --all --all-features -- -D warnings
working-directory: crypto
- run: cargo clippy --all --all-features -- -D warnings
Expand Down
6 changes: 6 additions & 0 deletions cipher/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,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).

## UNRELEASED
### Added
- Allocating padded encrypt/decrypt ([#936])

Keruspe marked this conversation as resolved.
Show resolved Hide resolved
[#936]: https://github.com/RustCrypto/traits/pull/936

## 0.3.0 (2022-02-10)
### Changed
- Major rework of traits. Core functionality of block and stream ciphers
Expand Down
4 changes: 3 additions & 1 deletion cipher/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ blobby = { version = "0.3", optional = true }
zeroize = { version = "1.5", optional = true, default-features = false }

[features]
std = ["crypto-common/std", "inout/std"]
default = ["alloc"]
alloc = []
std = ["alloc", "crypto-common/std", "inout/std"]
block-padding = ["inout/block-padding"]
rand_core = ["crypto-common/rand_core"] # Enable random key and IV generation methods
dev = ["blobby"]
Expand Down
84 changes: 78 additions & 6 deletions cipher/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
//! [3]: https://en.wikipedia.org/wiki/Symmetric-key_algorithm

use crate::{ParBlocks, ParBlocksSizeUser};
#[cfg(all(feature = "block-padding", feature = "alloc"))]
use alloc::{vec, vec::Vec};
#[cfg(feature = "block-padding")]
use inout::{
block_padding::{Padding, UnpadError},
Expand Down Expand Up @@ -173,6 +175,20 @@ pub trait BlockEncrypt: BlockSizeUser + Sized {
let buf = InOutBufReserved::from_slices(msg, out_buf).map_err(|_| PadError)?;
self.encrypt_padded_inout::<P>(buf)
}

/// Pad input and encrypt into a newly allocated Vec. Returns resulting ciphertext Vec.
#[cfg(all(feature = "block-padding", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "block-padding", feature = "alloc"))))]
#[inline]
fn encrypt_padded_vec<P: Padding<Self::BlockSize>>(&self, msg: &[u8]) -> Vec<u8> {
let mut out = allocate_out_vec::<Self>(msg.len());
let len = self
.encrypt_padded_b2b::<P>(msg, &mut out)
.expect("enough space for encrypting is allocated")
.len();
out.truncate(len);
out
}
}

/// Decrypt-only functionality for block ciphers.
Expand Down Expand Up @@ -281,6 +297,24 @@ pub trait BlockDecrypt: BlockSizeUser {
let buf = InOutBuf::new(in_buf, &mut out_buf[..n]).map_err(|_| UnpadError)?;
self.decrypt_padded_inout::<P>(buf)
}

/// Decrypt input and unpad it in a newly allocated Vec. Returns resulting
/// ciphertext Vec.
///
/// Returns [`UnpadError`] if padding is malformed or if input length is
/// not multiple of `Self::BlockSize`.
#[cfg(all(feature = "block-padding", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "block-padding", feature = "alloc"))))]
#[inline]
fn decrypt_padded_vec<P: Padding<Self::BlockSize>>(
&self,
buf: &[u8],
) -> Result<Vec<u8>, UnpadError> {
let mut out = vec![0; buf.len()];
let len = self.decrypt_padded_b2b::<P>(buf, &mut out)?.len();
out.truncate(len);
Ok(out)
}
}

/// Encrypt-only functionality for block ciphers and modes with mutable access to `self`.
Expand Down Expand Up @@ -363,11 +397,11 @@ pub trait BlockEncryptMut: BlockSizeUser + Sized {
#[cfg(feature = "block-padding")]
#[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))]
#[inline]
fn encrypt_padded_mut<'a, P: Padding<Self::BlockSize>>(
fn encrypt_padded_mut<P: Padding<Self::BlockSize>>(
self,
buf: &'a mut [u8],
buf: &mut [u8],
msg_len: usize,
) -> Result<&'a [u8], PadError> {
) -> Result<&[u8], PadError> {
let buf = InOutBufReserved::from_mut_slice(buf, msg_len).map_err(|_| PadError)?;
self.encrypt_padded_inout_mut::<P>(buf)
}
Expand All @@ -386,6 +420,20 @@ pub trait BlockEncryptMut: BlockSizeUser + Sized {
let buf = InOutBufReserved::from_slices(msg, out_buf).map_err(|_| PadError)?;
self.encrypt_padded_inout_mut::<P>(buf)
}

/// Pad input and encrypt into a newly allocated Vec. Returns resulting ciphertext Vec.
#[cfg(all(feature = "block-padding", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "block-padding", feature = "alloc"))))]
#[inline]
fn encrypt_padded_vec_mut<P: Padding<Self::BlockSize>>(self, msg: &[u8]) -> Vec<u8> {
let mut out = allocate_out_vec::<Self>(msg.len());
let len = self
.encrypt_padded_b2b_mut::<P>(msg, &mut out)
.expect("enough space for encrypting is allocated")
.len();
out.truncate(len);
out
}
}

/// Decrypt-only functionality for block ciphers and modes with mutable access to `self`.
Expand Down Expand Up @@ -470,10 +518,10 @@ pub trait BlockDecryptMut: BlockSizeUser + Sized {
#[cfg(feature = "block-padding")]
#[cfg_attr(docsrs, doc(cfg(feature = "block-padding")))]
#[inline]
fn decrypt_padded_mut<'a, P: Padding<Self::BlockSize>>(
fn decrypt_padded_mut<P: Padding<Self::BlockSize>>(
self,
buf: &'a mut [u8],
) -> Result<&'a [u8], UnpadError> {
buf: &mut [u8],
) -> Result<&[u8], UnpadError> {
self.decrypt_padded_inout_mut::<P>(buf.into())
}

Expand All @@ -498,6 +546,24 @@ pub trait BlockDecryptMut: BlockSizeUser + Sized {
let buf = InOutBuf::new(in_buf, &mut out_buf[..n]).map_err(|_| UnpadError)?;
self.decrypt_padded_inout_mut::<P>(buf)
}

/// Decrypt input and unpad it in a newly allocated Vec. Returns resulting
/// ciphertext Vec.
///
/// Returns [`UnpadError`] if padding is malformed or if input length is
/// not multiple of `Self::BlockSize`.
#[cfg(all(feature = "block-padding", feature = "alloc"))]
#[cfg_attr(docsrs, doc(cfg(all(feature = "block-padding", feature = "alloc"))))]
#[inline]
fn decrypt_padded_vec<P: Padding<Self::BlockSize>>(
self,
buf: &[u8],
) -> Result<Vec<u8>, UnpadError> {
let mut out = vec![0; buf.len()];
let len = self.decrypt_padded_b2b_mut::<P>(buf, &mut out)?.len();
out.truncate(len);
Ok(out)
}
}

impl<Alg: BlockEncrypt> BlockEncryptMut for Alg {
Expand Down Expand Up @@ -568,6 +634,12 @@ impl<'inp, 'out, BS: ArrayLength<u8>> BlockClosure for BlocksCtx<'inp, 'out, BS>
}
}

#[cfg(all(feature = "block-padding", feature = "alloc"))]
fn allocate_out_vec<BS: BlockSizeUser>(len: usize) -> Vec<u8> {
let bs = BS::BlockSize::USIZE;
vec![0; bs * (len / bs + 1)]
}

/// Implement simple block backend
#[macro_export]
macro_rules! impl_simple_block_encdec {
Expand Down
3 changes: 3 additions & 0 deletions cipher/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
pub use crypto_common;
pub use inout;

#[cfg(all(feature = "block-padding", feature = "alloc"))]
extern crate alloc;

#[cfg(feature = "std")]
extern crate std;

Expand Down