use alloy::primitives::{keccak256, FixedBytes};
pub const LOOPBACK_MAGIC: &[u8; 8] = b"NEWT_LBK";
pub const LOOPBACK_PCR0: [u8; 48] = [0u8; 48];
pub fn loopback_pcr0_hash() -> FixedBytes<32> {
keccak256(LOOPBACK_PCR0)
}
pub fn build_loopback_attestation(nonce: &[u8]) -> Vec<u8> {
let mut doc = Vec::with_capacity(LOOPBACK_MAGIC.len() + LOOPBACK_PCR0.len() + nonce.len());
doc.extend_from_slice(LOOPBACK_MAGIC);
doc.extend_from_slice(&LOOPBACK_PCR0);
doc.extend_from_slice(nonce);
doc
}
pub fn is_loopback_attestation(bytes: &[u8]) -> bool {
bytes.len() >= LOOPBACK_MAGIC.len() && bytes[..LOOPBACK_MAGIC.len()] == *LOOPBACK_MAGIC
}
pub fn parse_loopback_pcr0(bytes: &[u8]) -> Option<&[u8]> {
let pcr0_start = LOOPBACK_MAGIC.len();
let pcr0_end = pcr0_start + LOOPBACK_PCR0.len();
if is_loopback_attestation(bytes) && bytes.len() >= pcr0_end {
Some(&bytes[pcr0_start..pcr0_end])
} else {
None
}
}
pub fn parse_loopback_nonce(bytes: &[u8]) -> Option<&[u8]> {
let nonce_start = LOOPBACK_MAGIC.len() + LOOPBACK_PCR0.len();
if is_loopback_attestation(bytes) && bytes.len() >= nonce_start {
Some(&bytes[nonce_start..])
} else {
None
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn loopback_pcr0_hash_is_deterministic() {
let h1 = loopback_pcr0_hash();
let h2 = loopback_pcr0_hash();
assert_eq!(h1, h2);
assert_ne!(h1, FixedBytes::ZERO);
}
#[test]
fn build_and_parse_round_trips() {
let nonce = b"test-nonce-1234";
let doc = build_loopback_attestation(nonce);
assert!(is_loopback_attestation(&doc));
assert_eq!(parse_loopback_pcr0(&doc).unwrap(), &LOOPBACK_PCR0);
assert_eq!(parse_loopback_nonce(&doc).unwrap(), nonce);
}
#[test]
fn empty_nonce_round_trips() {
let doc = build_loopback_attestation(&[]);
assert!(is_loopback_attestation(&doc));
assert_eq!(doc.len(), 56);
assert_eq!(parse_loopback_pcr0(&doc).unwrap(), &LOOPBACK_PCR0);
assert_eq!(parse_loopback_nonce(&doc).unwrap(), &[] as &[u8]);
}
#[test]
fn real_cose_not_detected_as_loopback() {
let cose_tag_18 = [0xd2, 0x84, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
assert!(!is_loopback_attestation(&cose_tag_18));
}
#[test]
fn too_short_bytes_not_loopback() {
assert!(!is_loopback_attestation(&[]));
assert!(!is_loopback_attestation(b"NEWT"));
assert!(parse_loopback_pcr0(b"NEWT_LBK").is_none());
}
}