use core::convert::TryInto;
use trussed::{client, syscall, types::KeyId};
use crate::oath;
pub fn calculate<T>(trussed: &mut T, algorithm: oath::Algorithm, challenge: &[u8], key: KeyId)
-> [u8; 4]
where
T: client::Client + client::HmacSha1 + client::HmacSha256 + client::Sha256,
{
use oath::Algorithm::*;
let truncated = match algorithm {
Sha1 => {
let digest = syscall!(trussed.sign_hmacsha1(key, challenge)).signature;
dynamic_truncation(&digest)
}
Sha256 => {
let digest = syscall!(trussed.sign_hmacsha256(key, challenge)).signature;
dynamic_truncation(&digest)
}
Sha512 => unimplemented!(),
};
truncated.to_be_bytes()
}
fn dynamic_truncation(digest: &[u8]) -> u32 {
let offset_bits = (*digest.last().unwrap() & 0xf) as usize;
let p = u32::from_be_bytes(digest[offset_bits..][..4].try_into().unwrap());
p & 0x7fff_ffff
}