ndn_security/
safe_data.rs

1use ndn_packet::Data;
2
3/// The trust path used to validate a `SafeData`.
4#[derive(Clone, Debug)]
5pub enum TrustPath {
6    /// Validated via full certificate chain.
7    CertChain(Vec<ndn_packet::Name>),
8    /// Trusted because it arrived on a local face with known process credentials.
9    LocalFace { uid: u32 },
10    /// Validated by verifying `SHA-256(signed_region) == sig_value`.
11    /// No key or trust anchor involved — self-contained integrity check only.
12    DigestSha256,
13}
14
15/// A Data packet whose signature has been verified.
16///
17/// `SafeData` can only be constructed by `Validator::validate()` or by the
18/// local-trust fast path (`SafeData::from_local_trusted`). The `pub(crate)`
19/// constructor prevents application code from bypassing verification.
20///
21/// Application callbacks receive `SafeData`, not `Data` — the compiler enforces
22/// that unverified data cannot be passed where verified data is required.
23#[derive(Debug)]
24pub struct SafeData {
25    pub(crate) inner: Data,
26    pub(crate) trust_path: TrustPath,
27    pub(crate) verified_at: u64,
28}
29
30impl SafeData {
31    /// Construct a `SafeData` from a Data packet that arrived on a trusted
32    /// local face (bypasses crypto verification).
33    #[allow(dead_code)]
34    pub(crate) fn from_local_trusted(data: Data, uid: u32) -> Self {
35        Self {
36            inner: data,
37            trust_path: TrustPath::LocalFace { uid },
38            verified_at: now_ns(),
39        }
40    }
41
42    pub fn data(&self) -> &Data {
43        &self.inner
44    }
45
46    pub fn trust_path(&self) -> &TrustPath {
47        &self.trust_path
48    }
49
50    pub fn verified_at(&self) -> u64 {
51        self.verified_at
52    }
53}
54
55#[allow(dead_code)]
56fn now_ns() -> u64 {
57    use std::time::{SystemTime, UNIX_EPOCH};
58    SystemTime::now()
59        .duration_since(UNIX_EPOCH)
60        .map(|d| d.as_nanos() as u64)
61        .unwrap_or(0)
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    fn minimal_data() -> Data {
69        use ndn_tlv::TlvWriter;
70        let nc = {
71            let mut w = TlvWriter::new();
72            w.write_tlv(0x08, b"test");
73            w.finish()
74        };
75        let name_tlv = {
76            let mut w = TlvWriter::new();
77            w.write_tlv(0x07, &nc);
78            w.finish()
79        };
80        let data_bytes = {
81            let mut w = TlvWriter::new();
82            w.write_tlv(0x06, &name_tlv);
83            w.finish()
84        };
85        Data::decode(data_bytes).unwrap()
86    }
87
88    #[test]
89    fn from_local_trusted_sets_uid() {
90        let data = minimal_data();
91        let safe = SafeData::from_local_trusted(data, 1000);
92        assert!(matches!(
93            safe.trust_path(),
94            TrustPath::LocalFace { uid: 1000 }
95        ));
96    }
97
98    #[test]
99    fn from_local_trusted_verified_at_is_nonzero() {
100        let data = minimal_data();
101        let safe = SafeData::from_local_trusted(data, 0);
102        assert!(safe.verified_at() > 0);
103    }
104
105    #[test]
106    fn data_accessor_returns_inner() {
107        let data = minimal_data();
108        let name_before = data.name.clone();
109        let safe = SafeData::from_local_trusted(data, 0);
110        assert_eq!(safe.data().name, name_before);
111    }
112}