1use crate::attest::trust_store::{compute_key_id, KeyId};
28use crate::cert::CertRef;
29use crate::crypto::{CanonPkcPublicKeyRef, CanonPkcSignature, Crypto, PKC_CANON_PUBLIC_KEY_LEN};
30use crate::error::{Error, ErrorCode};
31use crate::tlv::{TLVElement, TLVTag, TLVWrite};
32use crate::utils::storage::WriteBuf;
33
34use super::{x509::key_usage_tlv, CertTag, DNTag};
35
36#[derive(Debug, Clone, Copy, PartialEq, Eq)]
38pub enum CertType {
39 Rcac,
41 Icac,
43 Noc,
45}
46
47pub struct IssuerDN {
48 pub(crate) ca_id: Option<u64>,
49 pub(crate) fabric_id: Option<u64>,
50 pub(crate) is_rcac: bool,
51}
52
53#[derive(Clone, Copy)]
54pub struct SubjectDN<'a> {
55 pub(crate) node_id: Option<u64>,
56 pub(crate) fabric_id: Option<u64>,
57 pub(crate) cat_ids: &'a [u32],
58 pub(crate) ca_id: Option<u64>,
59}
60
61#[derive(Clone, Copy)]
63pub struct Validity {
64 pub not_before: u32,
68 pub not_after: u32,
70}
71
72pub const VALID_FOREVER: Validity = Validity {
86 not_before: 1, not_after: 0, };
89
90pub struct CertGenerator<'a> {
101 buf: &'a mut [u8],
102}
103
104impl<'a> CertGenerator<'a> {
105 pub const fn new(buf: &'a mut [u8]) -> Self {
107 Self { buf }
108 }
109
110 #[allow(clippy::too_many_arguments)]
118 pub fn generate<C: Crypto>(
119 &mut self,
120 crypto: C,
121 cert_type: CertType,
122 serial_number: &[u8],
123 validity: Validity,
124 subject: SubjectDN,
125 issuer: IssuerDN,
126 subject_pubkey: CanonPkcPublicKeyRef<'_>,
127 issuer_pubkey: Option<CanonPkcPublicKeyRef<'_>>,
128 signing_key: &C::SecretKey<'_>,
129 ) -> Result<usize, Error> {
130 Self::validate_serial_number(serial_number)?;
131
132 let subject_key_id = compute_key_id(&crypto, subject_pubkey)?;
133
134 let authority_key_id = if let Some(issuer_pk) = issuer_pubkey {
135 compute_key_id(&crypto, issuer_pk)?
136 } else {
137 subject_key_id
139 };
140
141 let tbs_len = self.write_tbs_certificate(
143 serial_number,
144 validity,
145 subject_pubkey.access(),
146 &subject_key_id,
147 &authority_key_id,
148 cert_type,
149 subject,
150 issuer,
151 )?;
152
153 let (tlv_buf, asn1_buf) = self.buf.split_at_mut(tbs_len);
157 let tbs_cert_ref = CertRef::new(TLVElement::new(tlv_buf));
158 let asn1_len = tbs_cert_ref.as_asn1(asn1_buf)?;
159
160 let signature = Self::sign_tbs::<C>(&asn1_buf[..asn1_len], signing_key)?;
162
163 self.append_signature(&signature, tbs_len)
165 }
166
167 #[allow(clippy::too_many_arguments)]
171 fn write_tbs_certificate(
172 &mut self,
173 serial_number: &[u8],
174 validity: Validity,
175 pubkey: &[u8; PKC_CANON_PUBLIC_KEY_LEN],
176 subject_key_id: &KeyId,
177 authority_key_id: &KeyId,
178 cert_type: CertType,
179 subject: SubjectDN,
180 issuer: IssuerDN,
181 ) -> Result<usize, Error> {
182 let mut tw = WriteBuf::new(self.buf);
183
184 tw.start_struct(&TLVTag::Anonymous)?;
185
186 tw.str(&TLVTag::Context(CertTag::SerialNum as _), serial_number)?;
188
189 tw.u8(&TLVTag::Context(CertTag::SignAlgo as _), 1)?;
191
192 tw.start_list(&TLVTag::Context(CertTag::Issuer as _))?;
194 match cert_type {
195 CertType::Rcac => {
196 if let Some(id) = subject.ca_id {
198 tw.u64(&TLVTag::Context(DNTag::RootCaId as u8), id)?;
199 }
200 if let Some(fid) = subject.fabric_id {
201 tw.u64(&TLVTag::Context(DNTag::FabricId as u8), fid)?; }
203 }
204 CertType::Icac | CertType::Noc => {
205 if let Some(id) = issuer.ca_id {
207 let tag = if issuer.is_rcac {
208 DNTag::RootCaId as u8
209 } else {
210 DNTag::IcaId as u8
211 };
212 tw.u64(&TLVTag::Context(tag), id)?;
213 }
214 if let Some(fid) = issuer.fabric_id {
215 tw.u64(&TLVTag::Context(DNTag::FabricId as u8), fid)?;
216 }
217 }
218 }
219 tw.end_container()?;
220
221 tw.u32(
223 &TLVTag::Context(CertTag::NotBefore as u8),
224 validity.not_before,
225 )?;
226
227 tw.u32(
229 &TLVTag::Context(CertTag::NotAfter as u8),
230 validity.not_after,
231 )?;
232
233 tw.start_list(&TLVTag::Context(CertTag::Subject as u8))?;
235 match cert_type {
236 CertType::Noc => {
237 if let Some(nid) = subject.node_id {
239 tw.u64(&TLVTag::Context(DNTag::NodeId as u8), nid)?;
240 }
241 if let Some(fid) = subject.fabric_id {
242 tw.u64(&TLVTag::Context(DNTag::FabricId as u8), fid)?
243 }
244 for cat_id in subject.cat_ids {
245 tw.u64(&TLVTag::Context(DNTag::NocCat as u8), *cat_id as u64)?;
246 }
247 }
248 CertType::Icac => {
249 if let Some(id) = subject.ca_id {
251 tw.u64(&TLVTag::Context(DNTag::IcaId as u8), id)?;
252 }
253 if let Some(fid) = subject.fabric_id {
254 tw.u64(&TLVTag::Context(DNTag::FabricId as u8), fid)?;
255 }
256 }
257 CertType::Rcac => {
258 if let Some(id) = subject.ca_id {
260 tw.u64(&TLVTag::Context(DNTag::RootCaId as u8), id)?;
261 }
262 if let Some(fid) = subject.fabric_id {
263 tw.u64(&TLVTag::Context(DNTag::FabricId as u8), fid)?;
264 }
265 }
266 }
267 tw.end_container()?;
268
269 tw.u8(&TLVTag::Context(CertTag::PubKeyAlgo as u8), 1)?;
271
272 tw.u8(&TLVTag::Context(CertTag::EcCurveId as u8), 1)?;
274
275 tw.str(&TLVTag::Context(CertTag::EcPubKey as u8), pubkey)?;
277
278 tw.start_list(&TLVTag::Context(CertTag::Extensions as u8))?;
280 Self::write_extensions(&mut tw, cert_type, subject_key_id, authority_key_id)?;
281 tw.end_container()?;
282
283 tw.end_container()?;
284
285 Ok(tw.get_tail())
286 }
287
288 fn write_extensions(
290 tw: &mut impl TLVWrite,
291 cert_type: CertType,
292 subject_key_id: &KeyId,
293 authority_key_id: &KeyId,
294 ) -> Result<(), Error> {
295 tw.start_struct(&TLVTag::Context(1))?;
300 match cert_type {
301 CertType::Rcac => {
302 tw.bool(&TLVTag::Context(1), true)?;
303 }
304 CertType::Icac => {
305 tw.bool(&TLVTag::Context(1), true)?;
306 tw.u8(&TLVTag::Context(2), 0)?; }
308 CertType::Noc => {
309 tw.bool(&TLVTag::Context(1), false)?;
310 }
311 }
312 tw.end_container()?;
313
314 let key_usage = match cert_type {
316 CertType::Rcac | CertType::Icac => {
317 key_usage_tlv::KEY_CERT_SIGN | key_usage_tlv::CRL_SIGN
318 }
319 CertType::Noc => key_usage_tlv::DIGITAL_SIGNATURE,
320 };
321 tw.u16(&TLVTag::Context(2), key_usage)?;
322
323 if cert_type == CertType::Noc {
325 tw.start_array(&TLVTag::Context(3))?;
326 tw.u8(&TLVTag::Anonymous, 1)?; tw.u8(&TLVTag::Anonymous, 2)?; tw.end_container()?;
329 }
330
331 tw.str(&TLVTag::Context(4), subject_key_id)?;
333
334 tw.str(&TLVTag::Context(5), authority_key_id)?;
337
338 Ok(())
339 }
340
341 fn sign_tbs<C: Crypto>(
343 tbs_data: &[u8],
344 signing_key: &C::SecretKey<'_>,
345 ) -> Result<CanonPkcSignature, Error> {
346 use crate::crypto::SigningSecretKey;
347
348 let mut signature = CanonPkcSignature::new();
349 signing_key.sign(tbs_data, &mut signature)?;
350 Ok(signature)
351 }
352
353 fn append_signature(
358 &mut self,
359 signature: &CanonPkcSignature,
360 tbs_len: usize,
361 ) -> Result<usize, Error> {
362 if tbs_len == 0 || self.buf[tbs_len - 1] != 0x18 {
363 return Err(ErrorCode::InvalidData.into());
364 }
365
366 let insert_pos = tbs_len - 1;
367
368 let mut tw = WriteBuf::new(&mut self.buf[insert_pos..]);
370 tw.str(
371 &TLVTag::Context(CertTag::Signature as u8),
372 signature.access(),
373 )?;
374 tw.end_container()?;
375
376 Ok(insert_pos + tw.get_tail())
377 }
378
379 fn validate_serial_number(serial: &[u8]) -> Result<(), Error> {
381 if serial.is_empty() {
382 return Err(ErrorCode::InvalidData.into());
383 }
384 if serial.len() > 1 && serial[0] == 0 && (serial[1] & 0x80) == 0 {
386 return Err(ErrorCode::InvalidData.into());
387 }
388 Ok(())
389 }
390}
391
392#[cfg(test)]
393mod tests {
394 use crate::{
395 cert::{MAX_CERT_TLV_AND_ASN1_LEN, MAX_CERT_TLV_LEN},
396 crypto::{test_only_crypto, CanonPkcPublicKey, PublicKey, SigningSecretKey},
397 dm::clusters::time_sync::UtcTime,
398 };
399
400 use super::*;
401
402 const RCAC_ISSUER_DN_UNUSED: IssuerDN = IssuerDN {
406 ca_id: None,
407 fabric_id: None,
408 is_rcac: false,
409 };
410
411 #[test]
412 fn test_validate_serial_number_valid() {
413 assert!(CertGenerator::validate_serial_number(&[0x01]).is_ok());
414 assert!(CertGenerator::validate_serial_number(&[0x00, 0x80]).is_ok()); assert!(CertGenerator::validate_serial_number(&[0x7F]).is_ok());
416 }
417
418 #[test]
419 fn test_validate_serial_number_invalid() {
420 assert!(CertGenerator::validate_serial_number(&[]).is_err()); assert!(CertGenerator::validate_serial_number(&[0x00, 0x01]).is_err());
422 }
424
425 #[test]
427 fn test_build_rcac() {
428 let crypto = test_only_crypto();
429
430 let rcac_secret_key = unwrap!(crypto.generate_secret_key());
431 let rcac_pubkey = rcac_secret_key.pub_key().unwrap();
432
433 let mut rcac_pubkey_canon = CanonPkcPublicKey::new();
434 rcac_pubkey.write_canon(&mut rcac_pubkey_canon).unwrap();
435
436 let serial_number = &[0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF];
437 let rcac_id = 0x1234567890u64;
438 let fabric_id = 0x0000000000000001u64;
439 let not_before = 0u32; let not_after = 0u32; let subject = SubjectDN {
443 node_id: None,
444 fabric_id: Some(fabric_id),
445 cat_ids: &[],
446 ca_id: Some(rcac_id),
447 };
448
449 let validity = Validity {
450 not_before,
451 not_after,
452 };
453
454 let mut cert_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
455 let len = unwrap!(CertGenerator::new(&mut cert_buf).generate(
456 &crypto,
457 CertType::Rcac,
458 serial_number,
459 validity,
460 subject,
461 RCAC_ISSUER_DN_UNUSED,
462 rcac_pubkey_canon.reference(),
463 None,
464 &rcac_secret_key,
465 ));
466
467 assert!(len > 100);
468 assert!(len < MAX_CERT_TLV_LEN);
469 }
470
471 #[test]
472 fn test_rcac_self_verify() {
473 let crypto = test_only_crypto();
474
475 let rcac_secret_key = unwrap!(crypto.generate_secret_key());
476 let rcac_pubkey = rcac_secret_key.pub_key().unwrap();
477
478 let mut rcac_pubkey_canon = CanonPkcPublicKey::new();
479 rcac_pubkey.write_canon(&mut rcac_pubkey_canon).unwrap();
480
481 let subject = SubjectDN {
482 node_id: None,
483 fabric_id: Some(0x0000_0000_0000_0001),
484 cat_ids: &[],
485 ca_id: Some(0x1122_3344_5566_7788),
486 };
487
488 let mut cert_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
489 let len = unwrap!(CertGenerator::new(&mut cert_buf).generate(
490 &crypto,
491 CertType::Rcac,
492 &[0x01],
493 VALID_FOREVER,
494 subject,
495 RCAC_ISSUER_DN_UNUSED,
496 rcac_pubkey_canon.reference(),
497 None,
498 &rcac_secret_key,
499 ));
500
501 let cert = CertRef::new(crate::tlv::TLVElement::new(&cert_buf[..len]));
503 let mut scratch = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
504 let res = cert
505 .verify_chain_start(
506 &crypto,
507 UtcTime::Reliable(VALID_FOREVER.not_before as u64 * 1_000_000),
508 )
509 .finalise(&mut scratch);
510 assert!(
511 res.is_ok(),
512 "RCAC built by CertGenerator failed self-verification: {res:?}"
513 );
514 }
515
516 #[test]
518 fn test_build_icac() {
519 let crypto = test_only_crypto();
520
521 let rcac_secret_key = unwrap!(crypto.generate_secret_key());
522
523 let rcac_pubkey = rcac_secret_key.pub_key().unwrap();
524 let mut rcac_pubkey_canon = CanonPkcPublicKey::new();
525 rcac_pubkey.write_canon(&mut rcac_pubkey_canon).unwrap();
526
527 let icac_secret_key = unwrap!(crypto.generate_secret_key());
528
529 let icac_pubkey = icac_secret_key.pub_key().unwrap();
530 let mut icac_pubkey_canon = CanonPkcPublicKey::new();
531 icac_pubkey.write_canon(&mut icac_pubkey_canon).unwrap();
532
533 let serial_number = &[0x01, 0x02, 0x03, 0x04];
534 let icac_id = 0x1234u64;
535 let rcac_id = 0x5678u64;
536 let fabric_id = 0x0000000000000001u64;
537
538 let subject = SubjectDN {
539 node_id: None,
540 fabric_id: Some(fabric_id),
541 cat_ids: &[],
542 ca_id: Some(icac_id),
543 };
544
545 let issuer = IssuerDN {
546 ca_id: Some(rcac_id),
547 fabric_id: Some(fabric_id),
548 is_rcac: true,
549 };
550
551 let mut cert_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
552 let len = unwrap!(CertGenerator::new(&mut cert_buf).generate(
553 &crypto,
554 CertType::Icac,
555 serial_number,
556 VALID_FOREVER,
557 subject,
558 issuer,
559 icac_pubkey_canon.reference(),
560 Some(rcac_pubkey_canon.reference()),
561 &rcac_secret_key,
562 ));
563
564 assert!(len > 100);
565 assert!(len < MAX_CERT_TLV_LEN);
566 }
567
568 #[test]
570 fn test_build_noc_signed_by_rcac() {
571 let crypto = test_only_crypto();
572
573 let rcac_secret_key = unwrap!(crypto.generate_secret_key());
574
575 let rcac_pubkey = rcac_secret_key.pub_key().unwrap();
576 let mut rcac_pubkey_canon = CanonPkcPublicKey::new();
577 rcac_pubkey.write_canon(&mut rcac_pubkey_canon).unwrap();
578
579 let noc_secret_key = unwrap!(crypto.generate_secret_key());
580
581 let noc_pubkey = noc_secret_key.pub_key().unwrap();
582 let mut noc_pubkey_canon = CanonPkcPublicKey::new();
583 noc_pubkey.write_canon(&mut noc_pubkey_canon).unwrap();
584
585 let serial_number = &[0xAA, 0xBB, 0xCC];
586 let node_id = 0x1122334455667788u64;
587 let fabric_id = 0x0000000000000001u64;
588 let rcac_id = 0x9999u64;
589 let not_before = 0u32;
590 let not_after = 0u32;
591
592 let subject = SubjectDN {
593 node_id: Some(node_id),
594 fabric_id: Some(fabric_id),
595 cat_ids: &[], ca_id: None,
597 };
598
599 let validity = Validity {
600 not_before,
601 not_after,
602 };
603
604 let issuer = IssuerDN {
605 ca_id: Some(rcac_id),
606 fabric_id: Some(fabric_id),
607 is_rcac: true, };
609
610 let mut cert_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
611 let len = unwrap!(CertGenerator::new(&mut cert_buf).generate(
612 &crypto,
613 CertType::Noc,
614 serial_number,
615 validity,
616 subject,
617 issuer,
618 noc_pubkey_canon.reference(),
619 Some(rcac_pubkey_canon.reference()),
620 &rcac_secret_key,
621 ));
622
623 assert!(len > 100);
624 assert!(len < MAX_CERT_TLV_LEN);
625 }
626
627 #[test]
629 fn test_build_noc_with_cat_ids() {
630 let crypto = test_only_crypto();
631
632 let rcac_secret_key = unwrap!(crypto.generate_secret_key());
633
634 let rcac_pubkey = rcac_secret_key.pub_key().unwrap();
635 let mut rcac_pubkey_canon = CanonPkcPublicKey::new();
636 rcac_pubkey.write_canon(&mut rcac_pubkey_canon).unwrap();
637
638 let noc_secret_key = unwrap!(crypto.generate_secret_key());
639
640 let noc_pubkey = noc_secret_key.pub_key().unwrap();
641 let mut noc_pubkey_canon = CanonPkcPublicKey::new();
642 noc_pubkey.write_canon(&mut noc_pubkey_canon).unwrap();
643
644 let serial_number = &[0x01];
645 let node_id = 0x0000000000000001u64;
646 let fabric_id = 0x0000000000000001u64;
647 let rcac_id = 0x1000u64;
648 let cat_ids = &[0x00011111u32, 0x00022222u32, 0x00033333u32]; let not_before = 0u32;
650 let not_after = 0u32;
651
652 let subject = SubjectDN {
653 node_id: Some(node_id),
654 fabric_id: Some(fabric_id),
655 cat_ids,
656 ca_id: None,
657 };
658
659 let validity = Validity {
660 not_before,
661 not_after,
662 };
663
664 let issuer = IssuerDN {
665 ca_id: Some(rcac_id),
666 fabric_id: Some(fabric_id),
667 is_rcac: true,
668 };
669
670 let mut cert_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
671 let len = unwrap!(CertGenerator::new(&mut cert_buf).generate(
672 &crypto,
673 CertType::Noc,
674 serial_number,
675 validity,
676 subject,
677 issuer,
678 noc_pubkey_canon.reference(),
679 Some(rcac_pubkey_canon.reference()),
680 &rcac_secret_key,
681 ));
682
683 assert!(len > 100);
684 assert!(len < MAX_CERT_TLV_LEN);
685 }
686
687 #[test]
689 fn test_build_noc_signed_by_icac() {
690 let crypto = test_only_crypto();
691
692 let icac_secret_key = unwrap!(crypto.generate_secret_key());
693
694 let icac_pubkey = icac_secret_key.pub_key().unwrap();
695 let mut icac_pubkey_canon = CanonPkcPublicKey::new();
696 icac_pubkey.write_canon(&mut icac_pubkey_canon).unwrap();
697
698 let noc_secret_key = unwrap!(crypto.generate_secret_key());
699
700 let noc_pubkey = noc_secret_key.pub_key().unwrap();
701 let mut noc_pubkey_canon = CanonPkcPublicKey::new();
702 noc_pubkey.write_canon(&mut noc_pubkey_canon).unwrap();
703
704 let serial_number = &[0xFF];
705 let node_id = 0xDEADBEEFu64;
706 let fabric_id = 0x0000000000000001u64;
707 let icac_id = 0x2468u64;
708 let not_before = 0u32;
709 let not_after = 0u32;
710
711 let subject = SubjectDN {
712 node_id: Some(node_id),
713 fabric_id: Some(fabric_id),
714 cat_ids: &[], ca_id: None,
716 };
717
718 let validity = Validity {
719 not_before,
720 not_after,
721 };
722
723 let issuer = IssuerDN {
724 ca_id: Some(icac_id),
725 fabric_id: Some(fabric_id),
726 is_rcac: false, };
728
729 let mut cert_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
730 let len = unwrap!(CertGenerator::new(&mut cert_buf).generate(
731 &crypto,
732 CertType::Noc,
733 serial_number,
734 validity,
735 subject,
736 issuer,
737 noc_pubkey_canon.reference(),
738 Some(icac_pubkey_canon.reference()),
739 &icac_secret_key,
740 ));
741
742 assert!(len > 100);
743 assert!(len < MAX_CERT_TLV_LEN);
744 }
745
746 #[test]
748 fn test_build_complete_cert_chain() {
749 let crypto = test_only_crypto();
750
751 let fabric_id = 0x0000000000000001u64;
752 let rcac_id = 0x1111111111u64;
753 let icac_id = 0x2222u64;
754 let node_id = 0x3333333333333333u64;
755 let not_before = 0u32;
756 let not_after = 0u32;
757
758 let rcac_secret_key = unwrap!(crypto.generate_secret_key());
759
760 let rcac_pubkey = rcac_secret_key.pub_key().unwrap();
761 let mut rcac_pubkey_canon = CanonPkcPublicKey::new();
762 rcac_pubkey.write_canon(&mut rcac_pubkey_canon).unwrap();
763
764 let rcac_subject = SubjectDN {
765 node_id: None,
766 fabric_id: Some(fabric_id),
767 cat_ids: &[],
768 ca_id: Some(rcac_id),
769 };
770
771 let validity = Validity {
772 not_before,
773 not_after,
774 };
775
776 let mut rcac_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
777 let rcac_len = unwrap!(CertGenerator::new(&mut rcac_buf).generate(
778 &crypto,
779 CertType::Rcac,
780 &[0x01],
781 validity,
782 rcac_subject,
783 RCAC_ISSUER_DN_UNUSED,
784 rcac_pubkey_canon.reference(),
785 None,
786 &rcac_secret_key,
787 ));
788 assert!(rcac_len > 0);
789
790 let icac_secret_key = unwrap!(crypto.generate_secret_key());
791
792 let icac_pubkey = icac_secret_key.pub_key().unwrap();
793 let mut icac_pubkey_canon = CanonPkcPublicKey::new();
794 icac_pubkey.write_canon(&mut icac_pubkey_canon).unwrap();
795
796 let icac_subject = SubjectDN {
797 node_id: None,
798 fabric_id: Some(fabric_id),
799 cat_ids: &[],
800 ca_id: Some(icac_id),
801 };
802
803 let icac_issuer = IssuerDN {
804 ca_id: Some(rcac_id),
805 fabric_id: Some(fabric_id),
806 is_rcac: true,
807 };
808
809 let mut icac_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
810 let icac_len = unwrap!(CertGenerator::new(&mut icac_buf).generate(
811 &crypto,
812 CertType::Icac,
813 &[0x02],
814 validity,
815 icac_subject,
816 icac_issuer,
817 icac_pubkey_canon.reference(),
818 Some(rcac_pubkey_canon.reference()),
819 &rcac_secret_key,
820 ));
821 assert!(icac_len > 0);
822
823 let noc_secret_key = unwrap!(crypto.generate_secret_key());
824
825 let noc_pubkey = noc_secret_key.pub_key().unwrap();
826 let mut noc_pubkey_canon = CanonPkcPublicKey::new();
827 noc_pubkey.write_canon(&mut noc_pubkey_canon).unwrap();
828
829 let noc_subject = SubjectDN {
830 node_id: Some(node_id),
831 fabric_id: Some(fabric_id),
832 cat_ids: &[],
833 ca_id: None,
834 };
835
836 let noc_issuer = IssuerDN {
837 ca_id: Some(icac_id),
838 fabric_id: Some(fabric_id),
839 is_rcac: false, };
841
842 let mut noc_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
843 let noc_len = unwrap!(CertGenerator::new(&mut noc_buf).generate(
844 &crypto,
845 CertType::Noc,
846 &[0x03],
847 validity,
848 noc_subject,
849 noc_issuer,
850 noc_pubkey_canon.reference(),
851 Some(icac_pubkey_canon.reference()),
852 &icac_secret_key,
853 ));
854 assert!(noc_len > 0);
855
856 assert!(rcac_len > 100 && rcac_len < MAX_CERT_TLV_LEN);
858 assert!(icac_len > 100 && icac_len < MAX_CERT_TLV_LEN);
859 assert!(noc_len > 100 && noc_len < MAX_CERT_TLV_LEN);
860 }
861
862 #[test]
864 fn test_build_cert_with_validity() {
865 let crypto = test_only_crypto();
866
867 let rcac_secret_key = unwrap!(crypto.generate_secret_key());
868
869 let rcac_pubkey = rcac_secret_key.pub_key().unwrap();
870 let mut rcac_pubkey_canon = CanonPkcPublicKey::new();
871 rcac_pubkey.write_canon(&mut rcac_pubkey_canon).unwrap();
872
873 let not_before = 662688000u32;
876 let not_after = not_before + (10 * 365 * 24 * 60 * 60);
878
879 let subject = SubjectDN {
880 node_id: None,
881 fabric_id: Some(0x0000000000000001u64),
882 cat_ids: &[],
883 ca_id: Some(0x1234567890u64),
884 };
885
886 let validity = Validity {
887 not_before,
888 not_after,
889 };
890
891 let mut cert_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN];
892 let len = unwrap!(CertGenerator::new(&mut cert_buf).generate(
893 &crypto,
894 CertType::Rcac,
895 &[0x01],
896 validity,
897 subject,
898 RCAC_ISSUER_DN_UNUSED,
899 rcac_pubkey_canon.reference(),
900 None,
901 &rcac_secret_key,
902 ));
903
904 assert!(len > 100);
905 assert!(len < MAX_CERT_TLV_LEN);
906 }
907
908 #[test]
910 fn test_compute_key_id() {
911 let crypto = test_only_crypto();
912
913 let secret_key = unwrap!(crypto.generate_secret_key());
914
915 let mut pubkey = CanonPkcPublicKey::new();
916 unwrap!(secret_key.pub_key().unwrap().write_canon(&mut pubkey));
917
918 let key_id = unwrap!(compute_key_id(&crypto, pubkey.reference()));
919
920 let key_id2 = unwrap!(compute_key_id(&crypto, pubkey.reference()));
922 assert_eq!(key_id, key_id2);
923 }
924
925 #[test]
927 fn test_different_keys_different_ids() {
928 let crypto = test_only_crypto();
929
930 let secret_key1 = unwrap!(crypto.generate_secret_key());
931 let mut pubkey1 = CanonPkcPublicKey::new();
932 unwrap!(secret_key1.pub_key().unwrap().write_canon(&mut pubkey1));
933
934 let secret_key2 = unwrap!(crypto.generate_secret_key());
935 let mut pubkey2 = CanonPkcPublicKey::new();
936 unwrap!(secret_key2.pub_key().unwrap().write_canon(&mut pubkey2));
937
938 let key_id1 = unwrap!(compute_key_id(&crypto, pubkey1.reference()));
939 let key_id2 = unwrap!(compute_key_id(&crypto, pubkey2.reference()));
940
941 assert_ne!(key_id1, key_id2);
943 }
944}