pub trait U8Array: Sized {
fn new() -> Self;
fn new_with(_: u8) -> Self;
fn from_slice(_: &[u8]) -> Self;
fn len() -> usize;
fn as_slice(&self) -> &[u8];
fn as_mut(&mut self) -> &mut [u8];
fn clone(&self) -> Self {
Self::from_slice(self.as_slice())
}
}
macro_rules! impl_array {
($len:expr) => {
impl U8Array for [u8; $len] {
fn new() -> Self {
[0u8; $len]
}
fn new_with(x: u8) -> Self {
[x; $len]
}
fn from_slice(data: &[u8]) -> Self {
let mut a = [0u8; $len];
a.copy_from_slice(data);
a
}
fn len() -> usize {
$len
}
fn as_slice(&self) -> &[u8] {
self
}
fn as_mut(&mut self) -> &mut [u8] {
self
}
}
};
}
impl_array!(32);
impl_array!(64);
impl_array!(128);
pub trait DH {
type Key: U8Array;
type Pubkey: U8Array;
type Output: U8Array;
fn name() -> &'static str;
fn genkey() -> Self::Key;
fn pubkey(_: &Self::Key) -> Self::Pubkey;
fn dh(_: &Self::Key, _: &Self::Pubkey) -> Result<Self::Output, ()>;
}
pub trait Cipher {
fn name() -> &'static str;
type Key: U8Array;
fn key_len() -> usize {
Self::Key::len()
}
fn tag_len() -> usize {
16
}
fn encrypt(k: &Self::Key, nonce: u64, ad: &[u8], plaintext: &[u8], out: &mut [u8]);
fn encrypt_in_place(
k: &Self::Key,
nonce: u64,
ad: &[u8],
in_out: &mut [u8],
plaintext_len: usize,
) -> usize;
fn decrypt(
k: &Self::Key,
nonce: u64,
ad: &[u8],
ciphertext: &[u8],
out: &mut [u8],
) -> Result<(), ()>;
fn decrypt_in_place(
k: &Self::Key,
nonce: u64,
ad: &[u8],
in_out: &mut [u8],
ciphertext_len: usize,
) -> Result<usize, ()>;
fn rekey(k: &Self::Key) -> Self::Key {
let mut k1 = [0u8; 48];
Self::encrypt(k, 0u64.wrapping_sub(1), &[], &[0; 32], &mut k1);
Self::Key::from_slice(&k1[..32])
}
}
pub trait Hash: Default {
fn name() -> &'static str;
type Block: U8Array;
type Output: U8Array;
fn block_len() -> usize {
Self::Block::len()
}
fn hash_len() -> usize {
Self::Output::len()
}
fn reset(&mut self) {
*self = Default::default();
}
fn input(&mut self, data: &[u8]);
fn result(&mut self) -> Self::Output;
fn hash(data: &[u8]) -> Self::Output {
let mut h: Self = Default::default();
h.input(data);
h.result()
}
fn hmac_many(key: &[u8], data: &[&[u8]]) -> Self::Output {
assert!(key.len() <= Self::block_len());
let mut ipad = Self::Block::new_with(0x36u8);
let mut opad = Self::Block::new_with(0x5cu8);
let ipad = ipad.as_mut();
let opad = opad.as_mut();
for (i, b) in key.iter().enumerate() {
ipad[i] ^= b;
opad[i] ^= b;
}
let mut hasher: Self = Default::default();
hasher.input(ipad);
for d in data {
hasher.input(d);
}
let inner_output = hasher.result();
hasher.reset();
hasher.input(opad);
hasher.input(inner_output.as_slice());
hasher.result()
}
fn hmac(key: &[u8], data: &[u8]) -> Self::Output {
Self::hmac_many(key, &[data])
}
fn hkdf(chaining_key: &[u8], input_key_material: &[u8]) -> (Self::Output, Self::Output) {
let temp_key = Self::hmac(chaining_key, input_key_material);
let out1 = Self::hmac(temp_key.as_slice(), &[1u8]);
let out2 = Self::hmac_many(temp_key.as_slice(), &[out1.as_slice(), &[2u8]]);
(out1, out2)
}
fn hkdf3(
chaining_key: &[u8],
input_key_material: &[u8],
) -> (Self::Output, Self::Output, Self::Output) {
let temp_key = Self::hmac(chaining_key, input_key_material);
let out1 = Self::hmac(temp_key.as_slice(), &[1u8]);
let out2 = Self::hmac_many(temp_key.as_slice(), &[out1.as_slice(), &[2u8]]);
let out3 = Self::hmac_many(temp_key.as_slice(), &[out2.as_slice(), &[3u8]]);
(out1, out2, out3)
}
}