pub enum MacKey {
None,
HmacSha256(hmac_sha256::Key),
}
impl MacKey {
pub fn len(&self) -> usize {
match self {
MacKey::None => 0,
MacKey::HmacSha256(_) => ssh_libsodium::hmac256::BYTES,
}
}
pub fn authenticate(&self, number: u32, b: &[u8], out: &mut [u8]) {
match self {
MacKey::None => {}
MacKey::HmacSha256(k) => hmac_sha256::authenticate(k, number, b, out),
}
}
pub fn verify(&self, number: u32, b: &[u8], out: &[u8]) -> bool {
match self {
MacKey::None => true,
MacKey::HmacSha256(k) => hmac_sha256::verify(k, number, b, out),
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct Name(pub &'static str);
impl AsRef<str> for Name {
fn as_ref(&self) -> &str {
self.0
}
}
pub struct Mac {
pub _name: Name,
pub key_len: usize,
pub make_key: fn(key: &[u8]) -> MacKey,
}
pub mod hmac_sha256 {
use byteorder::{BigEndian, ByteOrder};
pub const NAME: super::Name = super::Name("hmac-sha2-256");
pub struct Key([u8; ssh_libsodium::hmac256::KEY_BYTES]);
pub const MAC: super::Mac = super::Mac {
_name: NAME,
key_len: 32,
make_key,
};
fn make_key(b: &[u8]) -> super::MacKey {
let mut k = Key([0; ssh_libsodium::hmac256::KEY_BYTES]);
k.0.clone_from_slice(b);
super::MacKey::HmacSha256(k)
}
pub fn authenticate(k: &Key, number: u32, b: &[u8], out: &mut [u8]) {
let mut s = ssh_libsodium::hmac256::init_state(&k.0);
let mut n = [0; 4];
BigEndian::write_u32(&mut n, number);
ssh_libsodium::hmac256::update(&mut s, &n);
ssh_libsodium::hmac256::update(&mut s, b);
ssh_libsodium::hmac256::finalize(&mut s, out);
}
pub fn verify(k: &Key, number: u32, b: &[u8], h: &[u8]) -> bool {
let mut s = ssh_libsodium::hmac256::init_state(&k.0);
let mut n = [0; 4];
BigEndian::write_u32(&mut n, number);
ssh_libsodium::hmac256::update(&mut s, &n);
ssh_libsodium::hmac256::update(&mut s, b);
let mut out = [0; ssh_libsodium::hmac256::BYTES];
ssh_libsodium::hmac256::finalize(&mut s, &mut out);
debug!("out {:?} h {:?}", out, h);
ssh_libsodium::memcmp(&out, h)
}
}