use crate::tls::Error;
use crate::x509::{AnyPublicKey, Certificate};
use alloc::vec::Vec;
#[derive(Clone)]
pub(crate) struct TrustAnchor {
pub(crate) subject_der: Vec<u8>,
pub(crate) key: AnyPublicKey,
}
#[derive(Clone, Default)]
pub struct RootCertStore {
anchors: Vec<TrustAnchor>,
}
impl RootCertStore {
pub fn new() -> Self {
RootCertStore {
anchors: Vec::new(),
}
}
pub fn add_der(&mut self, der: Vec<u8>) -> Result<(), Error> {
let cert = Certificate::from_der(der).map_err(|_| Error::BadCertificate)?;
let subject_der = cert
.subject_der()
.map_err(|_| Error::BadCertificate)?
.to_vec();
let key = cert
.subject_public_key()
.map_err(|_| Error::BadCertificate)?;
self.anchors.push(TrustAnchor { subject_der, key });
Ok(())
}
pub fn add_pem(&mut self, pem: &str) -> Result<(), Error> {
let cert = Certificate::from_pem(pem).map_err(|_| Error::BadCertificate)?;
self.add_der(cert.to_der().to_vec())
}
pub fn len(&self) -> usize {
self.anchors.len()
}
pub fn is_empty(&self) -> bool {
self.anchors.is_empty()
}
#[cfg(feature = "embedded-roots")]
pub fn with_embedded_roots() -> Self {
let mut store = RootCertStore::new();
store.add_embedded_roots();
store
}
#[cfg(feature = "embedded-roots")]
pub fn add_embedded_roots(&mut self) -> usize {
let mut added = 0;
for ca in cacrt::all() {
if self.add_der(ca.der().to_vec()).is_ok() {
added += 1;
}
}
added
}
pub fn clone_store(&self) -> Self {
self.clone()
}
pub(crate) fn anchors_with_subject<'a>(
&'a self,
name_der: &'a [u8],
) -> impl Iterator<Item = &'a TrustAnchor> + 'a {
self.anchors
.iter()
.filter(move |a| a.subject_der.as_slice() == name_der)
}
}
#[cfg(all(test, feature = "embedded-roots"))]
mod embedded_roots_tests {
use super::RootCertStore;
#[test]
fn with_embedded_roots_is_populated() {
let store = RootCertStore::with_embedded_roots();
assert!(
store.len() > 50,
"embedded root store unexpectedly small: {}",
store.len()
);
assert!(!store.is_empty());
}
#[test]
fn add_embedded_roots_reports_count() {
let mut store = RootCertStore::new();
let added = store.add_embedded_roots();
assert_eq!(added, store.len());
assert!(added > 50);
}
}