1use std::sync::Arc;
2
3use bytes::Bytes;
4use ndn_packet::{Name, tlv_type};
5use ndn_tlv::TlvWriter;
6
7use crate::{
8 TrustError,
9 cert_cache::{CertCache, Certificate},
10 key_store::MemKeyStore,
11 signer::{Ed25519Signer, Signer},
12};
13
14pub struct SecurityManager {
25 keys: MemKeyStore,
26 cert_cache: CertCache,
27 anchors: dashmap::DashMap<Arc<Name>, Certificate>,
29}
30
31impl SecurityManager {
32 pub fn new() -> Self {
33 Self {
34 keys: MemKeyStore::new(),
35 cert_cache: CertCache::new(),
36 anchors: dashmap::DashMap::new(),
37 }
38 }
39
40 pub fn generate_ed25519(&self, key_name: Name) -> Result<Name, TrustError> {
48 use ring::rand::{SecureRandom, SystemRandom};
49 let rng = SystemRandom::new();
50 let mut seed = [0u8; 32];
51 rng.fill(&mut seed)
52 .map_err(|_| TrustError::KeyStore("system RNG unavailable".into()))?;
53 let signer = Ed25519Signer::from_seed(&seed, key_name.clone());
54 self.keys.add(Arc::new(key_name.clone()), signer);
55 Ok(key_name)
56 }
57
58 pub fn generate_ed25519_from_seed(
60 &self,
61 key_name: Name,
62 seed: &[u8; 32],
63 ) -> Result<Name, TrustError> {
64 let signer = Ed25519Signer::from_seed(seed, key_name.clone());
65 self.keys.add(Arc::new(key_name.clone()), signer);
66 Ok(key_name)
67 }
68
69 pub fn issue_self_signed(
75 &self,
76 key_name: &Name,
77 public_key_bytes: Bytes,
78 validity_ms: u64,
79 ) -> Result<Certificate, TrustError> {
80 let now_ns = now_ns();
81 let valid_until = if validity_ms == u64::MAX {
82 u64::MAX
83 } else {
84 now_ns + validity_ms * 1_000_000
85 };
86 let cert = Certificate {
87 name: Arc::new(key_name.clone()),
88 public_key: public_key_bytes,
89 valid_from: now_ns,
90 valid_until,
91 issuer: None,
92 signed_region: None,
93 sig_value: None,
94 };
95 self.cert_cache.insert(cert.clone());
96 self.anchors
97 .insert(Arc::new(key_name.clone()), cert.clone());
98 Ok(cert)
99 }
100
101 pub async fn certify(
109 &self,
110 subject_key_name: &Name,
111 subject_public_key: Bytes,
112 issuer_key_name: &Name,
113 validity_ms: u64,
114 ) -> Result<Certificate, TrustError> {
115 let issuer_signer = self.keys.get_signer_sync(issuer_key_name)?;
116
117 let now_ns = now_ns();
118 let valid_until = now_ns + validity_ms * 1_000_000;
119
120 let _wire = encode_cert_data(
122 subject_key_name,
123 &subject_public_key,
124 issuer_signer.as_ref(),
125 now_ns,
126 valid_until,
127 )
128 .await?;
129
130 let cert = Certificate {
131 name: Arc::new(subject_key_name.clone()),
132 public_key: subject_public_key,
133 valid_from: now_ns,
134 valid_until,
135 issuer: None,
136 signed_region: None,
137 sig_value: None,
138 };
139 self.cert_cache.insert(cert.clone());
140 Ok(cert)
141 }
142
143 pub fn add_trust_anchor(&self, cert: Certificate) {
145 self.anchors.insert(Arc::clone(&cert.name), cert.clone());
146 self.cert_cache.insert(cert);
147 }
148
149 pub fn trust_anchor(&self, key_name: &Name) -> Option<Certificate> {
151 self.anchors
152 .iter()
153 .find(|r| r.key().as_ref() == key_name)
154 .map(|r| r.value().clone())
155 }
156
157 pub fn trust_anchor_names(&self) -> Vec<Arc<Name>> {
159 self.anchors.iter().map(|r| Arc::clone(r.key())).collect()
160 }
161
162 pub async fn get_signer(&self, key_name: &Name) -> Result<Arc<dyn Signer>, TrustError> {
164 use crate::key_store::KeyStore;
165 self.keys.get_signer(key_name).await
166 }
167
168 pub fn get_signer_sync(&self, key_name: &Name) -> Result<Arc<dyn Signer>, TrustError> {
170 self.keys.get_signer_sync(key_name)
171 }
172
173 pub fn cert_cache(&self) -> &CertCache {
175 &self.cert_cache
176 }
177
178 pub fn from_pib(pib: &crate::pib::FilePib, identity: &Name) -> Result<Self, TrustError> {
187 let mgr = SecurityManager::new();
188
189 let signer = pib.get_signer(identity)?;
191 mgr.keys.add(Arc::new(identity.clone()), signer);
192
193 if let Ok(cert) = pib.get_cert(identity) {
195 mgr.cert_cache.insert(cert);
196 }
197
198 for anchor in pib.trust_anchors()? {
200 mgr.add_trust_anchor(anchor);
201 }
202
203 Ok(mgr)
204 }
205
206 pub fn auto_init(
215 identity: &Name,
216 pib_path: &std::path::Path,
217 ) -> Result<(Self, bool), TrustError> {
218 use crate::pib::FilePib;
219
220 let pib = if pib_path.exists() {
222 FilePib::open(pib_path)?
223 } else {
224 FilePib::new(pib_path)?
225 };
226
227 let existing_keys = pib.list_keys()?;
228 if !existing_keys.is_empty() {
229 let key_name = &existing_keys[0];
231 let mgr = SecurityManager::from_pib(&pib, key_name)?;
232 return Ok((mgr, false));
233 }
234
235 let key_name = append_key_component(identity);
237 let signer = pib.generate_ed25519(&key_name)?;
238
239 let pk = Bytes::copy_from_slice(&signer.public_key_bytes());
241 let now_ns = now_ns();
242 let one_year_ns = 365 * 24 * 3600 * 1_000_000_000u64;
243 let cert = Certificate {
244 name: Arc::new(key_name.clone()),
245 public_key: pk,
246 valid_from: now_ns,
247 valid_until: now_ns.saturating_add(one_year_ns),
248 issuer: Some(Arc::new(key_name.clone())), signed_region: None,
250 sig_value: None,
251 };
252 pib.store_cert(&key_name, &cert)?;
253 pib.add_trust_anchor(&key_name, &cert)?;
254
255 let mgr = SecurityManager::from_pib(&pib, &key_name)?;
256 Ok((mgr, true))
257 }
258}
259
260fn append_key_component(identity: &Name) -> Name {
262 use ndn_packet::NameComponent;
263 let mut components: Vec<NameComponent> = identity.components().to_vec();
264 components.push(NameComponent::generic(Bytes::from_static(b"KEY")));
265 components.push(NameComponent::generic(Bytes::from_static(b"self")));
266 Name::from_components(components)
267}
268
269impl Default for SecurityManager {
270 fn default() -> Self {
271 Self::new()
272 }
273}
274
275async fn encode_cert_data(
287 subject_key_name: &Name,
288 subject_public_key: &[u8],
289 issuer_signer: &dyn Signer,
290 valid_from_ns: u64,
291 valid_until_ns: u64,
292) -> Result<Bytes, TrustError> {
293 let mut signed = TlvWriter::new();
295
296 write_name(&mut signed, subject_key_name);
298
299 signed.write_nested(tlv_type::META_INFO, |w| {
301 w.write_tlv(tlv_type::CONTENT_TYPE, &2u64.to_be_bytes());
302 w.write_tlv(tlv_type::FRESHNESS_PERIOD, &3_600_000u64.to_be_bytes());
303 });
304
305 signed.write_nested(tlv_type::CONTENT, |w| {
307 w.write_tlv(0x00, subject_public_key); w.write_nested(tlv_type::VALIDITY_PERIOD, |w| {
311 w.write_tlv(tlv_type::NOT_BEFORE, &valid_from_ns.to_be_bytes());
312 w.write_tlv(tlv_type::NOT_AFTER, &valid_until_ns.to_be_bytes());
313 });
314 });
315
316 let sig_type_code = issuer_signer.sig_type().code();
318 signed.write_nested(tlv_type::SIGNATURE_INFO, |w| {
319 w.write_tlv(tlv_type::SIGNATURE_TYPE, &[sig_type_code as u8]);
320 w.write_nested(tlv_type::KEY_LOCATOR, |w| {
322 write_name(w, issuer_signer.key_name());
323 });
324 });
325
326 let signed_region = signed.finish();
327
328 let signature = issuer_signer.sign(&signed_region).await?;
330
331 let mut outer = TlvWriter::new();
333 outer.write_nested(tlv_type::DATA, |w| {
334 w.write_raw(&signed_region);
336 w.write_tlv(tlv_type::SIGNATURE_VALUE, &signature);
338 });
339
340 Ok(outer.finish())
341}
342
343fn write_name(w: &mut TlvWriter, name: &Name) {
345 w.write_nested(tlv_type::NAME, |w| {
346 for comp in name.components() {
347 w.write_tlv(comp.typ, &comp.value);
348 }
349 });
350}
351
352fn now_ns() -> u64 {
353 use std::time::{SystemTime, UNIX_EPOCH};
354 SystemTime::now()
355 .duration_since(UNIX_EPOCH)
356 .map(|d| d.as_nanos() as u64)
357 .unwrap_or(0)
358}
359
360#[cfg(test)]
361mod tests {
362 use super::*;
363 use ndn_packet::NameComponent;
364
365 fn key_name(s: &'static str) -> Name {
366 Name::from_components([NameComponent::generic(Bytes::from_static(s.as_bytes()))])
367 }
368
369 #[test]
370 fn generate_ed25519_stores_key() {
371 let mgr = SecurityManager::new();
372 let kn = key_name("mykey");
373 assert!(mgr.generate_ed25519(kn.clone()).is_ok());
374 }
375
376 #[test]
377 fn issue_self_signed_adds_anchor() {
378 let mgr = SecurityManager::new();
379 let kn = key_name("anchor");
380 let pk = Bytes::from_static(&[0xAB; 32]);
381 let cert = mgr.issue_self_signed(&kn, pk, u64::MAX).unwrap();
382 assert_eq!(*cert.name, kn);
383 assert!(mgr.trust_anchor(&kn).is_some());
384 }
385
386 #[test]
387 fn trust_anchor_not_present_returns_none() {
388 let mgr = SecurityManager::new();
389 let kn = key_name("missing");
390 assert!(mgr.trust_anchor(&kn).is_none());
391 }
392
393 #[test]
394 fn add_trust_anchor_inserts_into_cache() {
395 let mgr = SecurityManager::new();
396 let kn = key_name("ta");
397 let cert = Certificate {
398 name: Arc::new(kn.clone()),
399 public_key: Bytes::from_static(&[1u8; 32]),
400 valid_from: 0,
401 valid_until: u64::MAX,
402 issuer: None,
403 signed_region: None,
404 sig_value: None,
405 };
406 mgr.add_trust_anchor(cert.clone());
407 assert!(mgr.trust_anchor(&kn).is_some());
408 assert!(mgr.cert_cache().get(&Arc::new(kn)).is_some());
409 }
410
411 #[test]
412 fn trust_anchor_names_returns_all() {
413 let mgr = SecurityManager::new();
414 let kn1 = key_name("a");
415 let kn2 = key_name("b");
416 for kn in [&kn1, &kn2] {
417 mgr.add_trust_anchor(Certificate {
418 name: Arc::new(kn.clone()),
419 public_key: Bytes::from_static(&[0; 32]),
420 valid_from: 0,
421 valid_until: u64::MAX,
422 issuer: None,
423 signed_region: None,
424 sig_value: None,
425 });
426 }
427 let names = mgr.trust_anchor_names();
428 assert_eq!(names.len(), 2);
429 }
430
431 #[test]
432 fn generate_from_seed_and_retrieve() {
433 let mgr = SecurityManager::new();
434 let kn = key_name("seeded");
435 let seed = [7u8; 32];
436 mgr.generate_ed25519_from_seed(kn.clone(), &seed).unwrap();
437 }
440
441 #[tokio::test]
442 async fn get_signer_after_generate() {
443 let mgr = SecurityManager::new();
444 let kn = key_name("sigkey");
445 let seed = [9u8; 32];
446 mgr.generate_ed25519_from_seed(kn.clone(), &seed).unwrap();
447 let signer = mgr.get_signer(&kn).await.unwrap();
448 assert_eq!(signer.key_name(), &kn);
449 }
450
451 #[tokio::test]
452 async fn certify_produces_signed_cert() {
453 let mgr = SecurityManager::new();
454
455 let ca_name = key_name("ca");
457 let ca_seed = [1u8; 32];
458 mgr.generate_ed25519_from_seed(ca_name.clone(), &ca_seed)
459 .unwrap();
460
461 let subj_name = key_name("subject");
463 let subj_seed = [2u8; 32];
464 mgr.generate_ed25519_from_seed(subj_name.clone(), &subj_seed)
465 .unwrap();
466
467 let subj_pk = Bytes::copy_from_slice(
468 &crate::signer::Ed25519Signer::from_seed(&subj_seed, subj_name.clone())
469 .public_key_bytes(),
470 );
471
472 let cert = mgr
474 .certify(&subj_name, subj_pk.clone(), &ca_name, 60_000)
475 .await
476 .unwrap();
477
478 assert_eq!(*cert.name, subj_name);
479 assert_eq!(cert.public_key, subj_pk);
480 assert!(cert.valid_until > cert.valid_from);
481
482 assert!(mgr.cert_cache().get(&Arc::new(subj_name)).is_some());
484 }
485
486 #[tokio::test]
487 async fn certify_fails_with_unknown_issuer() {
488 let mgr = SecurityManager::new();
489
490 let subj_name = key_name("subj");
491 let ca_name = key_name("unknown_ca");
492 let pk = Bytes::from_static(&[0xAA; 32]);
493
494 let result = mgr.certify(&subj_name, pk, &ca_name, 60_000).await;
495 assert!(result.is_err());
496 }
497
498 #[test]
499 fn auto_init_generates_on_empty_pib() {
500 let dir = tempfile::tempdir().unwrap();
501 let pib_path = dir.path().join("pib");
502 let identity = key_name("router1");
503
504 let (mgr, generated) = SecurityManager::auto_init(&identity, &pib_path).unwrap();
505 assert!(generated);
506 assert!(!mgr.trust_anchor_names().is_empty());
507
508 let (_mgr2, generated2) = SecurityManager::auto_init(&identity, &pib_path).unwrap();
510 assert!(!generated2);
511 }
512}