use crate::path::standard::{mac::algo::calculate_hop_mac, types::HopFieldMac};
pub type ForwardingKey = [u8; 16];
pub(crate) trait HopMacInputSource {
fn get_mac_input(&self) -> HopMacInput;
}
pub trait HopMacCalculate {
fn calculate_mac(
&self,
mac_chain_beta: u16,
info_timestamp: u32,
key: &ForwardingKey,
) -> HopFieldMac;
}
impl<AnySource: HopMacInputSource> HopMacCalculate for AnySource {
#[inline]
fn calculate_mac(
&self,
mac_chain_beta: u16,
info_timestamp: u32,
key: &ForwardingKey,
) -> HopFieldMac {
let HopMacInput {
exp_time,
cons_ingress,
cons_egress,
} = self.get_mac_input();
let mac = calculate_hop_mac(
mac_chain_beta,
info_timestamp,
exp_time,
cons_ingress,
cons_egress,
key,
);
HopFieldMac(mac)
}
}
pub(crate) struct HopMacInput {
pub exp_time: u8,
pub cons_ingress: u16,
pub cons_egress: u16,
}
pub mod algo {
use crate::path::standard::mac::ForwardingKey;
#[inline]
pub fn calculate_hop_mac(
mac_chain_beta: u16,
timestamp: u32,
exp_time: u8,
cons_ingress: u16,
cons_egress: u16,
key: &ForwardingKey,
) -> [u8; 6] {
use cmac::Mac;
let mut mac_input_data = [0u8; 16];
mac_input_data[2..4].copy_from_slice(&mac_chain_beta.to_be_bytes());
mac_input_data[4..8].copy_from_slice(×tamp.to_be_bytes());
mac_input_data[9] = exp_time;
mac_input_data[10..12].copy_from_slice(&cons_ingress.to_be_bytes());
mac_input_data[12..14].copy_from_slice(&cons_egress.to_be_bytes());
let mut maccer = cmac::Cmac::<aes::Aes128>::new(key.into());
maccer.update(&mac_input_data);
let mac: [u8; 16] = maccer.finalize().into_bytes().into();
let mut result = [0u8; 6];
result.copy_from_slice(&mac[..6]);
result
}
#[inline]
pub fn mac_chaining_beta(segment_id: u16, hop_macs: impl Iterator<Item = [u8; 6]>) -> u16 {
let mut accumulator = segment_id;
for hop_mac in hop_macs {
accumulator = mac_beta_step(accumulator, hop_mac);
}
accumulator
}
#[inline]
pub fn mac_beta_step(accumulator: u16, hop_mac: [u8; 6]) -> u16 {
let partial_mac = u16::from_be_bytes([hop_mac[0], hop_mac[1]]); accumulator ^ partial_mac
}
}