use challenge::CHALLENGE_SIZE;
use context::Context;
use clear_on_drop::clear::Clear;
use cryptogram::{self, Cryptogram};
use identity::IdentityKeys;
use super::KEY_SIZE;
pub struct SessionKeys {
enc_key: [u8; KEY_SIZE],
mac_key: [u8; KEY_SIZE],
rmac_key: [u8; KEY_SIZE],
}
impl SessionKeys {
pub fn derive(static_keys: &IdentityKeys, context: &Context) -> Self {
let enc_key = derive_key(&static_keys.enc_key, 0b100, &context);
let mac_key = derive_key(&static_keys.mac_key, 0b110, &context);
let rmac_key = derive_key(&static_keys.mac_key, 0b111, &context);
Self {
enc_key,
mac_key,
rmac_key,
}
}
pub fn card_cryptogram(&self, context: &Context) -> Cryptogram {
let mut result_slice = [0u8; CHALLENGE_SIZE];
cryptogram::calculate(&self.mac_key, 0, context, &mut result_slice);
let result = Cryptogram::from_slice(&result_slice);
result_slice.clear();
result
}
}
impl Drop for SessionKeys {
fn drop(&mut self) {
self.enc_key.clear();
self.mac_key.clear();
self.rmac_key.clear();
}
}
fn derive_key(
parent_key: &[u8; KEY_SIZE],
derivation_constant: u8,
context: &Context,
) -> [u8; KEY_SIZE] {
let mut key = [0u8; KEY_SIZE];
cryptogram::calculate(parent_key, derivation_constant, context, &mut key);
key
}