use super::creator::JoinRequestCreator;
use super::keys::*;
use super::parser::{
DecryptedDataPayload, DecryptedJoinAcceptPayload, EncryptedDataPayload,
EncryptedJoinAcceptPayload, JoinRequestPayload,
};
use super::securityhelpers::generic_array::{typenum::U16, GenericArray};
use aes::block_cipher::{BlockCipher, NewBlockCipher};
use aes::Aes128;
use cmac::crypto_mac::NewMac;
pub type Cmac = cmac::Cmac<Aes128>;
#[derive(Default, Debug, PartialEq)]
pub struct DefaultFactory;
impl CryptoFactory for DefaultFactory {
type E = Aes128;
type D = Aes128;
type M = Cmac;
fn new_enc(&self, key: &AES128) -> Self::E {
Aes128::new(GenericArray::from_slice(&key.0[..]))
}
fn new_dec(&self, key: &AES128) -> Self::D {
Aes128::new(GenericArray::from_slice(&key.0[..]))
}
fn new_mac(&self, key: &AES128) -> Self::M {
let key = GenericArray::from_slice(&key.0[..]);
Cmac::new(&key)
}
}
impl Encrypter for Aes128 {
fn encrypt_block(&self, block: &mut GenericArray<u8, U16>) {
BlockCipher::encrypt_block(self, block);
}
}
impl Decrypter for Aes128 {
fn decrypt_block(&self, block: &mut GenericArray<u8, U16>) {
BlockCipher::decrypt_block(self, block);
}
}
impl Mac for Cmac {
fn input(&mut self, data: &[u8]) {
cmac::Mac::update(self, data);
}
fn reset(&mut self) {
cmac::Mac::reset(self);
}
fn result(self) -> GenericArray<u8, U16> {
cmac::Mac::finalize(self).into_bytes()
}
}
impl JoinRequestCreator<[u8; 23], DefaultFactory> {
pub fn new() -> Self {
Self::with_options([0; 23], DefaultFactory).unwrap()
}
}
impl<T: AsRef<[u8]>> JoinRequestPayload<T, DefaultFactory> {
pub fn new<'a>(data: T) -> Result<Self, &'a str> {
Self::new_with_factory(data, DefaultFactory)
}
}
impl<T: AsRef<[u8]> + AsMut<[u8]>> EncryptedJoinAcceptPayload<T, DefaultFactory> {
pub fn new<'a>(data: T) -> Result<Self, &'a str> {
Self::new_with_factory(data, DefaultFactory)
}
}
impl<T: AsRef<[u8]> + AsMut<[u8]>> DecryptedJoinAcceptPayload<T, DefaultFactory> {
pub fn new<'a, 'b>(data: T, key: &'a AES128) -> Result<Self, &'b str> {
Self::new_with_factory(data, key, DefaultFactory)
}
}
impl<T: AsRef<[u8]>> EncryptedDataPayload<T, DefaultFactory> {
pub fn new<'a>(data: T) -> Result<Self, &'a str> {
Self::new_with_factory(data, DefaultFactory)
}
}
impl<T: AsRef<[u8]> + AsMut<[u8]>> DecryptedDataPayload<T> {
pub fn new<'a, 'b>(
data: T,
nwk_skey: &'a AES128,
app_skey: Option<&'a AES128>,
fcnt: u32,
) -> Result<Self, &'b str> {
let t = EncryptedDataPayload::new(data)?;
if !t.validate_mic(nwk_skey, fcnt) {
return Err("invalid mic");
}
t.decrypt(Some(nwk_skey), app_skey, fcnt)
}
}