use crate::id::TrustAnchorId;
use crate::tree::HASH_SIZE;
use crate::{Error, Result, SignatureAlgorithm};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CosignerInfo {
pub id: TrustAnchorId,
pub algorithm: SignatureAlgorithm,
pub spki_der: Vec<u8>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CosignerGroup {
pub members: Vec<CosignerInfo>,
pub threshold: usize,
}
impl CosignerGroup {
pub fn new(members: Vec<CosignerInfo>, threshold: usize) -> Result<Self> {
if threshold == 0 || threshold > members.len() {
return Err(Error::Malformed("cosigner group threshold"));
}
Ok(Self { members, threshold })
}
pub fn single(member: CosignerInfo) -> Self {
Self {
members: vec![member],
threshold: 1,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TrustedSubtree {
pub log_number: u16,
pub start: u64,
pub end: u64,
pub hash: [u8; HASH_SIZE],
}
#[derive(Clone, Debug)]
pub struct CaTrust {
pub ca_id: TrustAnchorId,
pub ca_cosigner: CosignerInfo,
pub required_groups: Vec<CosignerGroup>,
pub revoked_ranges: Vec<core::ops::RangeInclusive<u64>>,
pub trusted_subtrees: Vec<TrustedSubtree>,
}
impl CaTrust {
pub fn new(ca_id: TrustAnchorId, ca_cosigner: CosignerInfo) -> Self {
Self {
ca_id,
ca_cosigner,
required_groups: Vec::new(),
revoked_ranges: Vec::new(),
trusted_subtrees: Vec::new(),
}
}
pub fn require_cosigner(&mut self, cosigner: CosignerInfo) {
self.required_groups.push(CosignerGroup::single(cosigner));
}
pub fn require_group(&mut self, group: CosignerGroup) {
self.required_groups.push(group);
}
pub fn revoke_range(&mut self, first: u64, last: u64) {
self.revoked_ranges.push(first..=last);
}
pub fn trust_subtree(&mut self, subtree: TrustedSubtree) {
self.trusted_subtrees.push(subtree);
}
pub(crate) fn cosigner(&self, id: &TrustAnchorId) -> Option<&CosignerInfo> {
if self.ca_cosigner.id == *id {
return Some(&self.ca_cosigner);
}
self.required_groups
.iter()
.flat_map(|group| group.members.iter())
.find(|c| c.id == *id)
}
}
#[derive(Clone, Debug, Default)]
pub struct TrustStore {
pub cas: Vec<CaTrust>,
pub required_for_all: Vec<CosignerGroup>,
}
impl TrustStore {
pub fn new() -> Self {
Self::default()
}
pub fn add_ca(&mut self, ca: CaTrust) {
self.cas.push(ca);
}
pub fn require_group_for_all(&mut self, group: CosignerGroup) {
self.required_for_all.push(group);
}
pub fn ca(&self, ca_id: &TrustAnchorId) -> Option<&CaTrust> {
self.cas.iter().find(|ca| ca.ca_id == *ca_id)
}
}