1use crate::TrustError;
2use bytes::Bytes;
3use dashmap::DashMap;
4use ndn_packet::tlv_type;
5use ndn_packet::{Data, Name};
6use ndn_tlv::TlvReader;
7use std::sync::Arc;
8
9#[derive(Clone, Debug)]
11pub struct Certificate {
12 pub name: Arc<Name>,
13 pub public_key: Bytes,
14 pub valid_from: u64,
15 pub valid_until: u64,
16 pub issuer: Option<Arc<Name>>,
19 pub signed_region: Option<Bytes>,
22 pub sig_value: Option<Bytes>,
24}
25
26impl Certificate {
27 pub fn decode(data: &Data) -> Result<Self, TrustError> {
34 let content = data.content().ok_or(TrustError::InvalidKey)?;
35
36 let mut public_key: Option<Bytes> = None;
37 let mut valid_from: u64 = 0;
38 let mut valid_until: u64 = u64::MAX;
39
40 let mut reader = TlvReader::new(content.clone());
41 while !reader.is_empty() {
42 let (typ, value) = reader.read_tlv().map_err(|_| TrustError::InvalidKey)?;
43 match typ {
44 0x00 => {
45 public_key = Some(value);
46 }
47 tlv_type::VALIDITY_PERIOD => {
48 let mut vr = TlvReader::new(value);
49 while !vr.is_empty() {
50 let (vtyp, vval) = vr.read_tlv().map_err(|_| TrustError::InvalidKey)?;
51 match vtyp {
52 tlv_type::NOT_BEFORE => {
53 valid_from = decode_be_u64(&vval);
54 }
55 tlv_type::NOT_AFTER => {
56 valid_until = decode_be_u64(&vval);
57 }
58 _ => {}
59 }
60 }
61 }
62 _ => {}
63 }
64 }
65
66 let public_key = public_key.ok_or(TrustError::InvalidKey)?;
67 if public_key.is_empty() {
68 return Err(TrustError::InvalidKey);
69 }
70
71 let issuer = data
73 .sig_info()
74 .and_then(|si| si.key_locator.as_ref())
75 .map(Arc::clone);
76
77 let signed_region = Some(Bytes::copy_from_slice(data.signed_region()));
79 let sig_value = Some(Bytes::copy_from_slice(data.sig_value()));
80
81 Ok(Certificate {
82 name: Arc::clone(&data.name),
83 public_key,
84 valid_from,
85 valid_until,
86 issuer,
87 signed_region,
88 sig_value,
89 })
90 }
91
92 pub fn is_valid_at(&self, now_ns: u64) -> bool {
95 now_ns >= self.valid_from && now_ns <= self.valid_until
96 }
97}
98
99fn decode_be_u64(bytes: &[u8]) -> u64 {
101 let mut val: u64 = 0;
102 for &b in bytes.iter().take(8) {
103 val = (val << 8) | b as u64;
104 }
105 val
106}
107
108pub struct CertCache {
119 local: DashMap<Arc<Name>, Certificate>,
120 by_digest: DashMap<[u8; 32], Arc<Name>>,
121}
122
123impl CertCache {
124 pub fn new() -> Self {
125 Self {
126 local: DashMap::new(),
127 by_digest: DashMap::new(),
128 }
129 }
130
131 pub fn get(&self, key_name: &Arc<Name>) -> Option<Certificate> {
132 self.local.get(key_name).map(|r| r.clone())
133 }
134
135 pub fn get_by_key_digest(&self, digest: &[u8]) -> Option<Certificate> {
141 let key: &[u8; 32] = digest.try_into().ok()?;
142 let name = self.by_digest.get(key)?.clone();
143 self.local.get(&name).map(|r| r.clone())
144 }
145
146 pub fn insert(&self, cert: Certificate) {
147 use sha2::{Digest, Sha256};
148 let digest = Sha256::digest(&cert.public_key);
149 let digest_arr: [u8; 32] = digest.into();
150 self.by_digest.insert(digest_arr, Arc::clone(&cert.name));
151 self.local.insert(Arc::clone(&cert.name), cert);
152 }
153}
154
155impl Default for CertCache {
156 fn default() -> Self {
157 Self::new()
158 }
159}
160
161#[cfg(test)]
162mod tests {
163 use super::*;
164 use ndn_packet::NameComponent;
165 use ndn_tlv::TlvWriter;
166
167 fn make_cert_data(pk: &[u8], valid_from: u64, valid_until: u64) -> Bytes {
169 let mut signed = TlvWriter::new();
170
171 signed.write_nested(0x07, |w| {
173 w.write_tlv(0x08, b"test");
174 w.write_tlv(0x08, b"KEY");
175 w.write_tlv(0x08, b"k1");
176 });
177
178 signed.write_nested(0x15, |w| {
180 w.write_tlv(0x00, pk);
181 w.write_nested(tlv_type::VALIDITY_PERIOD, |w| {
182 w.write_tlv(tlv_type::NOT_BEFORE, &valid_from.to_be_bytes());
183 w.write_tlv(tlv_type::NOT_AFTER, &valid_until.to_be_bytes());
184 });
185 });
186
187 signed.write_nested(0x16, |w| {
189 w.write_tlv(0x1b, &[5u8]); });
191
192 let signed_region = signed.finish();
193
194 let mut outer = TlvWriter::new();
196 let sig_val = vec![0u8; 64];
197 let mut inner = signed_region.to_vec();
198 {
199 let mut sw = TlvWriter::new();
200 sw.write_tlv(0x17, &sig_val);
201 inner.extend_from_slice(&sw.finish());
202 }
203 outer.write_tlv(0x06, &inner);
204 outer.finish()
205 }
206
207 #[test]
208 fn decode_certificate_from_data() {
209 let pk = vec![1u8; 32];
210 let wire = make_cert_data(&pk, 1000, 2000);
211 let data = Data::decode(wire).unwrap();
212 let cert = Certificate::decode(&data).unwrap();
213
214 assert_eq!(cert.public_key.as_ref(), &pk[..]);
215 assert_eq!(cert.valid_from, 1000);
216 assert_eq!(cert.valid_until, 2000);
217 assert_eq!(cert.name.components().len(), 3);
218 }
219
220 #[test]
221 fn decode_certificate_no_content_fails() {
222 let mut signed = TlvWriter::new();
224 signed.write_nested(0x07, |w| {
225 w.write_tlv(0x08, b"test");
226 });
227 signed.write_nested(0x16, |w| {
228 w.write_tlv(0x1b, &[5u8]);
229 });
230 let signed_region = signed.finish();
231 let mut inner = signed_region.to_vec();
232 {
233 let mut sw = TlvWriter::new();
234 sw.write_tlv(0x17, &[0u8; 64]);
235 inner.extend_from_slice(&sw.finish());
236 }
237 let mut outer = TlvWriter::new();
238 outer.write_tlv(0x06, &inner);
239 let wire = outer.finish();
240
241 let data = Data::decode(wire).unwrap();
242 assert!(Certificate::decode(&data).is_err());
243 }
244
245 #[test]
246 fn decode_certificate_empty_key_fails() {
247 let wire = make_cert_data(&[], 0, u64::MAX);
248 let data = Data::decode(wire).unwrap();
249 assert!(Certificate::decode(&data).is_err());
250 }
251
252 #[test]
253 fn get_by_key_digest_returns_inserted_cert() {
254 let pk = vec![7u8; 32];
255 let cache = CertCache::new();
256 cache.insert(Certificate {
257 name: Arc::new(Name::from_components([NameComponent::generic(
258 Bytes::from_static(b"k1"),
259 )])),
260 public_key: Bytes::copy_from_slice(&pk),
261 valid_from: 0,
262 valid_until: u64::MAX,
263 issuer: None,
264 signed_region: None,
265 sig_value: None,
266 });
267
268 use sha2::{Digest, Sha256};
270 let expected = Sha256::digest(&pk);
271 let cert = cache
272 .get_by_key_digest(expected.as_slice())
273 .expect("digest lookup should hit");
274 assert_eq!(cert.public_key.as_ref(), &pk[..]);
275 }
276
277 #[test]
278 fn get_by_key_digest_misses_for_unknown_digest() {
279 let cache = CertCache::new();
280 cache.insert(Certificate {
281 name: Arc::new(Name::from_components([NameComponent::generic(
282 Bytes::from_static(b"k1"),
283 )])),
284 public_key: Bytes::copy_from_slice(&[1u8; 32]),
285 valid_from: 0,
286 valid_until: u64::MAX,
287 issuer: None,
288 signed_region: None,
289 sig_value: None,
290 });
291 let bogus = [0xFFu8; 32];
292 assert!(cache.get_by_key_digest(&bogus).is_none());
293 }
294
295 #[test]
296 fn get_by_key_digest_rejects_wrong_length() {
297 let cache = CertCache::new();
298 assert!(cache.get_by_key_digest(&[0u8; 31]).is_none());
300 assert!(cache.get_by_key_digest(&[0u8; 33]).is_none());
302 }
303
304 #[test]
305 fn is_valid_at_checks_time_range() {
306 let cert = Certificate {
307 name: Arc::new(Name::from_components([NameComponent::generic(
308 Bytes::from_static(b"k"),
309 )])),
310 public_key: Bytes::from_static(&[1; 32]),
311 valid_from: 1000,
312 valid_until: 2000,
313 issuer: None,
314 signed_region: None,
315 sig_value: None,
316 };
317 assert!(!cert.is_valid_at(999));
318 assert!(cert.is_valid_at(1000));
319 assert!(cert.is_valid_at(1500));
320 assert!(cert.is_valid_at(2000));
321 assert!(!cert.is_valid_at(2001));
322 }
323}