#![no_std]
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
#[derive(Clone, Copy, Debug)]
pub struct PadError;
#[derive(Clone, Copy, Debug)]
pub struct UnpadError;
pub trait Padding {
fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError>;
fn pad(buf: &mut [u8], pos: usize, block_size: usize) -> Result<&mut [u8], PadError> {
let bs = block_size * (pos / block_size);
if buf.len() < bs || buf.len() - bs < block_size {
Err(PadError)?
}
Self::pad_block(&mut buf[bs..bs + block_size], pos - bs)?;
Ok(&mut buf[..bs + block_size])
}
fn unpad(data: &[u8]) -> Result<&[u8], UnpadError>;
}
#[derive(Clone, Copy, Debug)]
pub enum ZeroPadding {}
impl Padding for ZeroPadding {
fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError> {
if pos > block.len() {
Err(PadError)?
}
set(&mut block[pos..], 0);
Ok(())
}
fn pad(buf: &mut [u8], pos: usize, block_size: usize) -> Result<&mut [u8], PadError> {
if pos % block_size == 0 {
Ok(&mut buf[..pos])
} else {
let bs = block_size * (pos / block_size);
let be = bs + block_size;
if buf.len() < be {
Err(PadError)?
}
Self::pad_block(&mut buf[bs..be], pos - bs)?;
Ok(&mut buf[..be])
}
}
fn unpad(data: &[u8]) -> Result<&[u8], UnpadError> {
let mut n = data.len() - 1;
while n != 0 {
if data[n] != 0 {
break;
}
n -= 1;
}
Ok(&data[..n + 1])
}
}
#[derive(Clone, Copy, Debug)]
pub enum Pkcs7 {}
impl Padding for Pkcs7 {
fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError> {
if block.len() > 255 {
Err(PadError)?
}
if pos >= block.len() {
Err(PadError)?
}
let n = block.len() - pos;
set(&mut block[pos..], n as u8);
Ok(())
}
fn unpad(data: &[u8]) -> Result<&[u8], UnpadError> {
if data.is_empty() {
Err(UnpadError)?
}
let l = data.len();
let n = data[l - 1];
if n == 0 || n as usize > l {
Err(UnpadError)?
}
for v in &data[l - n as usize..l - 1] {
if *v != n {
Err(UnpadError)?
}
}
Ok(&data[..l - n as usize])
}
}
#[derive(Clone, Copy, Debug)]
pub enum AnsiX923 {}
impl Padding for AnsiX923 {
fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError> {
if block.len() > 255 {
Err(PadError)?
}
if pos >= block.len() {
Err(PadError)?
}
let bs = block.len();
set(&mut block[pos..bs - 1], 0);
block[bs - 1] = (bs - pos) as u8;
Ok(())
}
fn unpad(data: &[u8]) -> Result<&[u8], UnpadError> {
if data.is_empty() {
Err(UnpadError)?
}
let l = data.len();
let n = data[l - 1] as usize;
if n == 0 || n > l {
return Err(UnpadError);
}
for v in &data[l - n..l - 1] {
if *v != 0 {
Err(UnpadError)?
}
}
Ok(&data[..l - n])
}
}
#[derive(Clone, Copy, Debug)]
pub enum Iso7816 {}
impl Padding for Iso7816 {
fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError> {
if pos >= block.len() {
Err(PadError)?
}
block[pos] = 0x80;
set(&mut block[pos + 1..], 0);
Ok(())
}
fn unpad(data: &[u8]) -> Result<&[u8], UnpadError> {
if data.is_empty() {
Err(UnpadError)?
}
let mut n = data.len() - 1;
while n != 0 {
if data[n] != 0 {
break;
}
n -= 1;
}
if data[n] != 0x80 {
Err(UnpadError)?
}
Ok(&data[..n])
}
}
#[derive(Clone, Copy, Debug)]
pub enum NoPadding {}
impl Padding for NoPadding {
fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError> {
if pos % block.len() != 0 {
Err(PadError)?
}
Ok(())
}
fn pad(buf: &mut [u8], pos: usize, block_size: usize) -> Result<&mut [u8], PadError> {
if pos % block_size != 0 {
Err(PadError)?
}
Ok(&mut buf[..pos])
}
fn unpad(data: &[u8]) -> Result<&[u8], UnpadError> {
Ok(data)
}
}
#[inline(always)]
fn set(dst: &mut [u8], value: u8) {
unsafe {
core::ptr::write_bytes(dst.as_mut_ptr(), value, dst.len());
}
}