#![no_std]
#![doc(html_logo_url =
"https://raw.githubusercontent.com/RustCrypto/meta/master/logo_small.png")]
extern crate byte_tools;
use byte_tools::{zero, set};
#[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>;
}
pub enum ZeroPadding{}
impl Padding for ZeroPadding {
fn pad_block(block: &mut [u8], pos: usize) -> Result<(), PadError> {
if pos > block.len() { Err(PadError)? }
zero(&mut block[pos..]);
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])
}
}
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])
}
}
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();
zero(&mut block[pos..bs-1]);
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])
}
}
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;
zero(&mut block[pos+1..]);
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])
}
}