use crate::attestation::x509::Paa;
#[derive(Debug, Clone)]
pub struct PaaTrustStore {
roots: Vec<Paa>,
}
impl PaaTrustStore {
pub fn empty() -> Self {
Self { roots: Vec::new() }
}
pub fn with_example_device_roots() -> Self {
const PAA_FFF1: &[u8] = include_bytes!("csa_test_roots/Chip-Test-PAA-FFF1-Cert.der");
const PAA_NOVID: &[u8] = include_bytes!("csa_test_roots/Chip-Test-PAA-NoVID-Cert.der");
#[allow(clippy::expect_used)]
let roots = vec![
Paa::from_der(PAA_FFF1)
.expect("bundled CSA test PAA FFF1 must parse — build-tree integrity issue"),
Paa::from_der(PAA_NOVID)
.expect("bundled CSA test PAA NoVID must parse — build-tree integrity issue"),
];
Self { roots }
}
pub fn add(&mut self, paa: Paa) {
self.roots.push(paa);
}
pub fn len(&self) -> usize {
self.roots.len()
}
pub fn is_empty(&self) -> bool {
self.roots.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &Paa> {
self.roots.iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::attestation::extensions::VendorId;
use crate::attestation::x509::Paa;
const PAA_FFF1_DER: &[u8] = include_bytes!("csa_test_roots/Chip-Test-PAA-FFF1-Cert.der");
#[test]
fn empty_store_is_empty_and_zero_length() {
let s = PaaTrustStore::empty();
assert!(s.is_empty());
assert_eq!(s.len(), 0);
assert!(s.iter().next().is_none());
}
#[test]
#[allow(clippy::unwrap_used)] fn add_grows_the_store() {
let mut s = PaaTrustStore::empty();
s.add(Paa::from_der(PAA_FFF1_DER).unwrap());
assert_eq!(s.len(), 1);
assert!(!s.is_empty());
}
#[test]
#[allow(clippy::unwrap_used)] fn iter_returns_paas_in_insertion_order() {
let mut s = PaaTrustStore::empty();
let a = Paa::from_der(PAA_FFF1_DER).unwrap();
let b = Paa::from_der(PAA_FFF1_DER).unwrap();
s.add(a);
s.add(b);
let collected: Vec<&[u8]> = s.iter().map(Paa::der).collect();
assert_eq!(collected.len(), 2);
assert_eq!(collected[0], PAA_FFF1_DER);
assert_eq!(collected[1], PAA_FFF1_DER);
}
#[test]
fn with_example_device_roots_loads_both() {
let s = PaaTrustStore::with_example_device_roots();
assert_eq!(s.len(), 2, "exactly two bundled CSA test roots");
}
#[test]
fn with_example_device_roots_contains_vid_scoped_fff1() {
let s = PaaTrustStore::with_example_device_roots();
let has_fff1 = s
.iter()
.any(|paa| paa.subject_vid() == Some(VendorId::new(0xFFF1)));
assert!(has_fff1, "bundled roots include the VID 0xFFF1 PAA");
}
#[test]
fn with_example_device_roots_contains_unscoped() {
let s = PaaTrustStore::with_example_device_roots();
let has_unscoped = s.iter().any(|paa| paa.subject_vid().is_none());
assert!(has_unscoped, "bundled roots include a non-VID-scoped PAA");
}
}