From 13b9963ed561c8716ec177c683befe46997976b4 Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Fri, 22 May 2026 18:35:02 +0000 Subject: [PATCH 1/2] Do not use NotBefore=0 in certs validity periods --- rs-matter/src/cert/builder.rs | 61 +++++++++---- .../src/commissioner/fabric_credentials.rs | 54 ++++++------ rs-matter/src/commissioner/noc_generator.rs | 86 +++++++++++-------- rs-matter/tests/case.rs | 4 +- 4 files changed, 128 insertions(+), 77 deletions(-) diff --git a/rs-matter/src/cert/builder.rs b/rs-matter/src/cert/builder.rs index a8093963..51b83b1a 100644 --- a/rs-matter/src/cert/builder.rs +++ b/rs-matter/src/cert/builder.rs @@ -263,20 +263,21 @@ impl<'a> CertBuilderCore<'a> { subject_key_id: &KeyId, authority_key_id: &KeyId, ) -> Result<(), Error> { - // 1. Basic Constraints + // 1. Basic Constraints — per Matter Spec: + // RCAC: cA = TRUE, pathLenConstraint shall NOT be present + // ICAC: cA = TRUE, pathLenConstraint = 0 + // NOC: cA = FALSE, pathLenConstraint shall NOT be present tw.start_struct(&TLVTag::Context(1))?; match cert_type { CertType::Rcac => { - tw.bool(&TLVTag::Context(1), true)?; // is_ca = true - tw.u8(&TLVTag::Context(2), 1)?; // path_len = 1 + tw.bool(&TLVTag::Context(1), true)?; } CertType::Icac => { - tw.bool(&TLVTag::Context(1), true)?; // is_ca = true + tw.bool(&TLVTag::Context(1), true)?; tw.u8(&TLVTag::Context(2), 0)?; // path_len = 0 } CertType::Noc => { - tw.bool(&TLVTag::Context(1), false)?; // is_ca = false - // No path_len for end entity + tw.bool(&TLVTag::Context(1), false)?; } } tw.end_container()?; @@ -581,12 +582,14 @@ impl<'a> RcacBuilder<'a> { #[cfg(test)] mod tests { - use super::*; use crate::{ cert::{MAX_CERT_TLV_AND_ASN1_LEN, MAX_CERT_TLV_LEN}, + commissioner::noc_generator::DEFAULT_VALIDITY, crypto::{test_only_crypto, CanonPkcPublicKey, PublicKey, SigningSecretKey}, }; + use super::*; + #[test] fn test_validate_cat_id_valid() { // Version = 1, identifier = 0x1234 @@ -659,6 +662,41 @@ mod tests { assert!(len < MAX_CERT_TLV_LEN); } + #[test] + fn test_rcac_self_verify() { + let crypto = test_only_crypto(); + let rcac_secret_key = unwrap!(crypto.generate_secret_key()); + let rcac_pubkey = rcac_secret_key.pub_key().unwrap(); + + let subject = SubjectDN { + node_id: None, + fabric_id: Some(0x0000_0000_0000_0001), + cat_ids: &[], + ca_id: Some(0x1122_3344_5566_7788), + }; + let mut cert_buf = [0u8; MAX_CERT_TLV_AND_ASN1_LEN]; + let mut builder = RcacBuilder::new(&mut cert_buf); + let len = unwrap!(builder.build( + &crypto, + subject, + DEFAULT_VALIDITY, + &rcac_pubkey, + &rcac_secret_key, + &[0x01], + )); + + // Re-parse the just-built RCAC and self-verify. + let cert = CertRef::new(crate::tlv::TLVElement::new(&cert_buf[..len])); + let mut scratch = [0u8; MAX_CERT_TLV_AND_ASN1_LEN]; + let res = cert + .verify_chain_start(&crypto, DEFAULT_VALIDITY.not_before as _) + .finalise(&mut scratch); + assert!( + res.is_ok(), + "RCAC built by RcacBuilder failed self-verification: {res:?}" + ); + } + /// Test building an ICAC signed by RCAC #[test] fn test_build_icac() { @@ -676,8 +714,6 @@ mod tests { let icac_id = 0x1234u64; let rcac_id = 0x5678u64; let fabric_id = 0x0000000000000001u64; - let not_before = 0u32; - let not_after = 0u32; let subject = SubjectDN { node_id: None, @@ -686,11 +722,6 @@ mod tests { ca_id: Some(icac_id), }; - let validity = Validity { - not_before, - not_after, - }; - let issuer = IssuerDN { ca_id: Some(rcac_id), fabric_id: Some(fabric_id), @@ -703,7 +734,7 @@ mod tests { let len = unwrap!(builder.build( &crypto, subject, - validity, + DEFAULT_VALIDITY, &icac_pubkey, &rcac_pubkey, &rcac_secret_key, diff --git a/rs-matter/src/commissioner/fabric_credentials.rs b/rs-matter/src/commissioner/fabric_credentials.rs index 75249fe0..eee70aa9 100644 --- a/rs-matter/src/commissioner/fabric_credentials.rs +++ b/rs-matter/src/commissioner/fabric_credentials.rs @@ -21,6 +21,7 @@ //! during commissioning. It combines NOC generation with IPK management //! and node ID assignment. +use crate::cert::builder::Validity; use crate::cert::MAX_CERT_TLV_LEN; use crate::crypto::{CanonAeadKey, CanonAeadKeyRef, Crypto, RngCore, AEAD_CANON_KEY_LEN}; use crate::error::Error; @@ -90,8 +91,9 @@ impl FabricCredentials { /// # Arguments /// * `crypto` - Cryptographic backend /// * `fabric_id` - The fabric identifier - pub fn new(crypto: &C, fabric_id: u64) -> Result { - let noc_generator = NocGenerator::new(crypto, fabric_id)?; + /// * `validity` - Validity period for generated certificates + pub fn new(crypto: &C, fabric_id: u64, validity: Validity) -> Result { + let noc_generator = NocGenerator::new(crypto, fabric_id, validity)?; let mut ipk = CanonAeadKey::new(); let mut ipk_bytes = [0u8; AEAD_CANON_KEY_LEN]; crypto.rand()?.fill_bytes(&mut ipk_bytes); @@ -110,15 +112,17 @@ impl FabricCredentials { /// * `crypto` - Cryptographic backend /// * `fabric_id` - The fabric identifier /// * `starting_node_id` - The first node ID to assign + /// * `validity` - Validity period for generated certificates pub fn with_starting_node_id( crypto: &C, fabric_id: u64, starting_node_id: u64, + validity: Validity, ) -> Result { if starting_node_id < 1 { return Err(crate::error::ErrorCode::InvalidData.into()); } - let mut creds = Self::new(crypto, fabric_id)?; + let mut creds = Self::new(crypto, fabric_id, validity)?; creds.next_node_id = starting_node_id; Ok(creds) } @@ -267,6 +271,7 @@ impl FabricCredentials { mod tests { use super::*; use crate::cert::CertRef; + use crate::commissioner::noc_generator::DEFAULT_VALIDITY; use crate::crypto::{test_only_crypto, AEAD_KEY_ZEROED}; use crate::tlv::TLVElement; @@ -318,7 +323,7 @@ mod tests { let crypto = test_only_crypto(); let fabric_id = 0x1234567890ABCDEFu64; - let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); // Should have root cert assert!(!creds.root_cert().is_empty()); @@ -339,7 +344,8 @@ mod tests { let creds = unwrap!(FabricCredentials::with_starting_node_id( &crypto, fabric_id, - starting_node_id + starting_node_id, + DEFAULT_VALIDITY, )); assert_eq!(creds.peek_next_node_id(), starting_node_id); @@ -349,7 +355,7 @@ mod tests { fn test_node_id_auto_increment() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); @@ -370,7 +376,7 @@ mod tests { fn test_peek_next_node_id_doesnt_increment() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let id1 = creds.peek_next_node_id(); let id2 = creds.peek_next_node_id(); @@ -385,7 +391,7 @@ mod tests { fn test_custom_node_id_doesnt_affect_counter() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); @@ -406,7 +412,7 @@ mod tests { fn test_generate_device_credentials_basic() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); @@ -428,7 +434,7 @@ mod tests { fn test_device_credentials_with_cat_ids() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); let cat_ids = &[0x00011111u32, 0x00022222u32]; @@ -443,7 +449,7 @@ mod tests { fn test_enable_icac() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); // Initially no ICAC assert!(creds.icac_cert().is_none()); @@ -459,7 +465,7 @@ mod tests { fn test_device_credentials_includes_icac_when_enabled() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); @@ -477,7 +483,7 @@ mod tests { fn test_icac_cert_available_after_enable() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); assert!(creds.icac_cert().is_none()); @@ -491,7 +497,7 @@ mod tests { fn test_noc_signed_by_icac_when_enabled() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); @@ -511,7 +517,7 @@ mod tests { fn test_ipk_is_generated() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let ipk = creds.ipk(); @@ -524,7 +530,7 @@ mod tests { fn test_set_custom_ipk() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let custom_ipk = [0x42u8; AEAD_CANON_KEY_LEN]; creds.set_ipk(CanonAeadKeyRef::new(&custom_ipk)); @@ -536,7 +542,7 @@ mod tests { fn test_root_cert_available() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let root_cert = creds.root_cert(); assert!(!root_cert.is_empty()); @@ -547,7 +553,7 @@ mod tests { fn test_root_cert_consistent() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); @@ -568,7 +574,7 @@ mod tests { fn test_verify_noc_and_rcac_parse() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); @@ -587,7 +593,7 @@ mod tests { fn test_generated_noc_contains_correct_node_id() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); @@ -605,7 +611,7 @@ mod tests { fn test_generated_noc_contains_correct_fabric_id() { let crypto = test_only_crypto(); let fabric_id = 0xABCDEF123456u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); @@ -622,7 +628,7 @@ mod tests { fn test_cat_ids_present_in_noc_when_specified() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); let cat_ids = &[0x00011111u32, 0x00022222u32, 0x00033333u32]; @@ -642,7 +648,7 @@ mod tests { fn test_invalid_csr_fails() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let invalid_csr = &[0x01, 0x02, 0x03, 0x04]; @@ -655,7 +661,7 @@ mod tests { fn test_four_cat_ids_fails() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let csr = generate_test_csr(); let too_many_cat_ids = &[0x00011111u32, 0x00022222u32, 0x00033333u32, 0x00044444u32]; diff --git a/rs-matter/src/commissioner/noc_generator.rs b/rs-matter/src/commissioner/noc_generator.rs index 2563a860..60eaa99e 100644 --- a/rs-matter/src/commissioner/noc_generator.rs +++ b/rs-matter/src/commissioner/noc_generator.rs @@ -23,7 +23,7 @@ //! - Optional Intermediate CA Certificate (ICAC) //! - Node Operational Certificate (NOC) -use crate::cert::builder::{IcacBuilder, IssuerDN, NocBuilder, RcacBuilder}; +use crate::cert::builder::{IcacBuilder, IssuerDN, NocBuilder, RcacBuilder, Validity}; use crate::cert::x509::csr::CsrRef; use crate::cert::{MAX_CERT_TLV_AND_ASN1_LEN, MAX_CERT_TLV_LEN}; use crate::crypto::{ @@ -32,6 +32,24 @@ use crate::crypto::{ }; use crate::error::{Error, ErrorCode}; +// NotBefore MUST NOT be 0 (Matter epoch start, 2000-01-01). +// CHIP's ChipEpochToASN1Time treats epoch=0 as the "no +// well-defined expiration date" sentinel and re-emits it as +// GeneralizedTime "99991231235959Z" regardless of which field +// it appears in (see CHIPCert.cpp:1076-1106 and the +// explanatory comment about CHIP epoch 0 NotBefore producing +// an invalid TBS signature on round-trip). +// +// We sign over UTCTime "000101000000Z" (Matter epoch); CHIP +// would reconstruct GeneralizedTime "99991231235959Z" and the +// hash would mismatch. Using 1 second past the Matter epoch +// avoids the sentinel collision while keeping the cert +// effectively unbounded on the lower end. +pub const DEFAULT_VALIDITY: Validity = Validity { + not_before: 1, // 2000-01-01 00:00:01 — past CHIP's epoch=0 sentinel + not_after: 0, // no expiry (NotAfter sentinel is legitimate) +}; + /// Generated NOC credentials for a device. #[derive(Debug)] pub struct NocCredentials { @@ -77,6 +95,8 @@ pub struct NocGenerator { icac_id: Option, /// Next serial number for certificates next_serial: u64, + /// Validity period for certificates + validity: Validity, } impl NocGenerator { @@ -88,10 +108,11 @@ impl NocGenerator { /// # Arguments /// * `crypto` - Cryptographic backend /// * `fabric_id` - The fabric identifier for this CA + /// * `validity` - Validity period for generated certificates /// /// # Returns /// A new `NocGenerator` ready to issue NOCs. - pub fn new(crypto: &C, fabric_id: u64) -> Result { + pub fn new(crypto: &C, fabric_id: u64, validity: Validity) -> Result { // Generate a random RCAC ID let mut rcac_id_bytes = [0u8; 8]; crypto.rand()?.fill_bytes(&mut rcac_id_bytes); @@ -123,11 +144,6 @@ impl NocGenerator { ca_id: Some(rcac_id), }; - let validity = crate::cert::builder::Validity { - not_before: 0, // epoch start - not_after: 0, // no expiry - }; - let cert_len = RcacBuilder::new(&mut cert_buf).build( crypto, subject, @@ -153,6 +169,7 @@ impl NocGenerator { rcac_id, icac_id: None, next_serial: 1, + validity, }) } @@ -164,12 +181,14 @@ impl NocGenerator { /// * `root_cert` - The Root CA certificate (TLV encoded) /// * `fabric_id` - The fabric identifier /// * `rcac_id` - The RCAC identifier + /// * `validity` - Validity period for generated certificates pub fn from_root_ca( crypto: &C, root_privkey: CanonPkcSecretKey, root_cert: &[u8], fabric_id: u64, rcac_id: u64, + validity: Validity, ) -> Result { // Derive public key from private key let root_key = crypto.secret_key(root_privkey.reference())?; @@ -192,6 +211,7 @@ impl NocGenerator { rcac_id, icac_id: None, next_serial: 1, + validity, }) } @@ -234,11 +254,6 @@ impl NocGenerator { ca_id: Some(icac_id), }; - let validity = crate::cert::builder::Validity { - not_before: 0, // epoch start - not_after: 0, // no expiry - }; - let issuer = crate::cert::builder::IssuerDN { ca_id: Some(self.rcac_id), fabric_id: Some(self.fabric_id), @@ -248,7 +263,7 @@ impl NocGenerator { let cert_len = IcacBuilder::new(&mut cert_buf).build( crypto, subject, - validity, + self.validity, &icac_key.pub_key()?, &root_signing_key.pub_key()?, &root_signing_key, @@ -330,15 +345,10 @@ impl NocGenerator { ca_id: None, }; - let validity = crate::cert::builder::Validity { - not_before: 0, // epoch start - not_after: 0, // no expiry - }; - let cert_len = NocBuilder::new(&mut cert_buf).build( crypto, subject, - validity, + self.validity, &crypto.pub_key(CanonPkcPublicKeyRef::try_new(&device_pubkey)?)?, &crypto.pub_key(issuer_pubkey.reference())?, &signing_key, @@ -418,11 +428,12 @@ impl NocGenerator { #[cfg(test)] mod tests { - use super::*; use crate::cert::CertRef; use crate::crypto::test_only_crypto; use crate::tlv::TLVElement; + use super::*; + /// Known valid CSR from C++ test vectors (TestChipCryptoPAL.cpp) /// This CSR has a valid signature and can be verified. const GOOD_CSR: &[u8] = &[ @@ -466,7 +477,7 @@ mod tests { let crypto = test_only_crypto(); let fabric_id = 0x1234_5678_9ABC_DEF0; - let generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); // Verify fabric_id is stored assert_eq!(generator.fabric_id(), fabric_id); @@ -490,7 +501,7 @@ mod tests { let crypto = test_only_crypto(); let fabric_id = 0xABCD; - let gen1 = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let gen1 = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let root_cert = gen1.root_cert(); let rcac_id = gen1.rcac_id(); @@ -504,7 +515,8 @@ mod tests { root_privkey, &root_cert_copy, fabric_id, - rcac_id + rcac_id, + DEFAULT_VALIDITY, )); // Verify credentials match @@ -517,7 +529,7 @@ mod tests { fn test_generate_icac_creates_certificate() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let icac = unwrap!(generator.generate_icac(&crypto)); @@ -532,7 +544,7 @@ mod tests { fn test_icac_cert_available_after_generation() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); // Before generation, icac_cert() should return None assert!(generator.icac_cert().is_none()); @@ -555,7 +567,7 @@ mod tests { fn test_multiple_icac_calls_replace_previous() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); // Generate first ICAC unwrap!(generator.generate_icac(&crypto)); @@ -581,7 +593,7 @@ mod tests { fn test_generate_noc_basic() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let node_id = 0x1234; let creds = unwrap!(generator.generate_noc(&crypto, GOOD_CSR, node_id, &[])); @@ -600,7 +612,7 @@ mod tests { fn test_generate_noc_with_icac() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); // Generate ICAC first unwrap!(generator.generate_icac(&crypto)); @@ -620,7 +632,7 @@ mod tests { fn test_generate_noc_with_cat_ids() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let node_id = 0xABCD; let cat_ids = [0x0001_0001, 0x0001_0002, 0x0001_0003]; @@ -642,7 +654,7 @@ mod tests { fn test_generate_noc_increments_serial() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); // Initial serial should be 1 assert_eq!(generator.next_serial, 1); @@ -664,7 +676,7 @@ mod tests { fn test_noc_contains_correct_node_id() { let crypto = test_only_crypto(); let fabric_id = 0x9999; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let node_id = 0xDEAD_BEEF_CAFE_BABE; let creds = unwrap!(generator.generate_noc(&crypto, GOOD_CSR, node_id, &[])); @@ -680,7 +692,7 @@ mod tests { fn test_noc_contains_device_pubkey_from_csr() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let creds = unwrap!(generator.generate_noc(&crypto, GOOD_CSR, 1, &[])); @@ -742,7 +754,7 @@ mod tests { fn test_generate_noc_bad_signature_fails() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); // CSR with bad signature should fail verification let result = generator.generate_noc(&crypto, BAD_SIGNATURE_CSR, 1, &[]); @@ -753,7 +765,7 @@ mod tests { fn test_generate_noc_too_many_cat_ids_fails() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); // More than 3 CAT IDs should fail let too_many_cat_ids = [0x0001_0001, 0x0001_0002, 0x0001_0003, 0x0001_0004]; @@ -766,7 +778,7 @@ mod tests { fn test_generated_rcac_can_be_parsed() { let crypto = test_only_crypto(); let fabric_id = 0x1234; - let generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let rcac = generator.root_cert(); @@ -782,7 +794,7 @@ mod tests { fn test_generated_icac_can_be_parsed() { let crypto = test_only_crypto(); let fabric_id = 0x5678; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let icac = unwrap!(generator.generate_icac(&crypto)); @@ -798,7 +810,7 @@ mod tests { fn test_generated_noc_can_be_parsed() { let crypto = test_only_crypto(); let fabric_id = 0xABCD; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); let node_id = 0x9999; let creds = unwrap!(generator.generate_noc(&crypto, GOOD_CSR, node_id, &[])); diff --git a/rs-matter/tests/case.rs b/rs-matter/tests/case.rs index fa8cb5e6..5978f39f 100644 --- a/rs-matter/tests/case.rs +++ b/rs-matter/tests/case.rs @@ -27,6 +27,7 @@ use embassy_time::{Duration, Timer}; use log::info; use rs_matter::commissioner::fabric_credentials::FabricCredentials; +use rs_matter::commissioner::noc_generator::DEFAULT_VALIDITY; use rs_matter::crypto::{test_only_crypto, CanonPkcSecretKey, Crypto, SecretKey, SigningSecretKey}; use rs_matter::dm::devices::test::{TEST_DEV_ATT, TEST_DEV_COMM, TEST_DEV_DET}; use rs_matter::error::Error; @@ -62,7 +63,8 @@ fn test_case_handshake() { // ---- 1. Generate credentials using FabricCredentials ---- - let mut fabric_creds = FabricCredentials::new(&crypto, TEST_FABRIC_ID).unwrap(); + let mut fabric_creds = + FabricCredentials::new(&crypto, TEST_FABRIC_ID, DEFAULT_VALIDITY).unwrap(); // Generate controller credentials (keypair + CSR + NOC) let controller_secret_key = crypto.generate_secret_key().unwrap(); From 44e62ab4a5ccd1fdd30d018f435b990971547a5c Mon Sep 17 00:00:00 2001 From: ivmarkov Date: Fri, 22 May 2026 19:15:46 +0000 Subject: [PATCH 2/2] Address code review feedback --- rs-matter/src/cert/builder.rs | 48 ++++++++++++----- .../src/commissioner/fabric_credentials.rs | 47 ++++++++-------- rs-matter/src/commissioner/noc_generator.rs | 53 +++++++------------ rs-matter/tests/case.rs | 11 ++-- 4 files changed, 83 insertions(+), 76 deletions(-) diff --git a/rs-matter/src/cert/builder.rs b/rs-matter/src/cert/builder.rs index 51b83b1a..c7c63e88 100644 --- a/rs-matter/src/cert/builder.rs +++ b/rs-matter/src/cert/builder.rs @@ -43,13 +43,6 @@ enum CertType { Noc, } -/// Internal shared certificate builder implementation. -/// -/// Contains all the common logic for building Noc, Icac, and Rcac certificates. -struct CertBuilderCore<'a> { - buf: &'a mut [u8], -} - pub struct IssuerDN { pub(crate) ca_id: Option, pub(crate) fabric_id: Option, @@ -64,10 +57,40 @@ pub struct SubjectDN<'a> { pub(crate) ca_id: Option, } +/// Validity period for certificates, represented as seconds since the Matter epoch (2000-01-01T00:00:00Z). #[derive(Clone, Copy)] pub struct Validity { - pub(crate) not_before: u32, - pub(crate) not_after: u32, + /// NotBefore time (seconds since Matter epoch) + /// + /// This must not be 0 (the Matter epoch start) to avoid collision with CHIP's epoch=0 sentinel in ASN.1 time encoding. + pub not_before: u32, + /// NotAfter time (seconds since Matter epoch, 0 = no expiry) + pub not_after: u32, +} + +// NotBefore MUST NOT be 0 (Matter epoch start, 2000-01-01). +// CHIP's ChipEpochToASN1Time treats epoch=0 as the "no +// well-defined expiration date" sentinel and re-emits it as +// GeneralizedTime "99991231235959Z" regardless of which field +// it appears in (see CHIPCert.cpp:1076-1106 and the +// explanatory comment about CHIP epoch 0 NotBefore producing +// an invalid TBS signature on round-trip). +// +// We sign over UTCTime "000101000000Z" (Matter epoch); CHIP +// would reconstruct GeneralizedTime "99991231235959Z" and the +// hash would mismatch. Using 1 second past the Matter epoch +// avoids the sentinel collision while keeping the cert +// effectively unbounded on the lower end. +pub const VALID_FOREVER: Validity = Validity { + not_before: 1, // 2000-01-01 00:00:01 — past CHIP's epoch=0 sentinel + not_after: 0, // no expiry (NotAfter sentinel is legitimate) +}; + +/// Internal shared certificate builder implementation. +/// +/// Contains all the common logic for building Noc, Icac, and Rcac certificates. +struct CertBuilderCore<'a> { + buf: &'a mut [u8], } impl<'a> CertBuilderCore<'a> { @@ -584,7 +607,6 @@ impl<'a> RcacBuilder<'a> { mod tests { use crate::{ cert::{MAX_CERT_TLV_AND_ASN1_LEN, MAX_CERT_TLV_LEN}, - commissioner::noc_generator::DEFAULT_VALIDITY, crypto::{test_only_crypto, CanonPkcPublicKey, PublicKey, SigningSecretKey}, }; @@ -679,7 +701,7 @@ mod tests { let len = unwrap!(builder.build( &crypto, subject, - DEFAULT_VALIDITY, + VALID_FOREVER, &rcac_pubkey, &rcac_secret_key, &[0x01], @@ -689,7 +711,7 @@ mod tests { let cert = CertRef::new(crate::tlv::TLVElement::new(&cert_buf[..len])); let mut scratch = [0u8; MAX_CERT_TLV_AND_ASN1_LEN]; let res = cert - .verify_chain_start(&crypto, DEFAULT_VALIDITY.not_before as _) + .verify_chain_start(&crypto, VALID_FOREVER.not_before as _) .finalise(&mut scratch); assert!( res.is_ok(), @@ -734,7 +756,7 @@ mod tests { let len = unwrap!(builder.build( &crypto, subject, - DEFAULT_VALIDITY, + VALID_FOREVER, &icac_pubkey, &rcac_pubkey, &rcac_secret_key, diff --git a/rs-matter/src/commissioner/fabric_credentials.rs b/rs-matter/src/commissioner/fabric_credentials.rs index eee70aa9..78cb6a55 100644 --- a/rs-matter/src/commissioner/fabric_credentials.rs +++ b/rs-matter/src/commissioner/fabric_credentials.rs @@ -269,12 +269,13 @@ impl FabricCredentials { #[cfg(test)] mod tests { - use super::*; + use crate::cert::builder::VALID_FOREVER; use crate::cert::CertRef; - use crate::commissioner::noc_generator::DEFAULT_VALIDITY; use crate::crypto::{test_only_crypto, AEAD_KEY_ZEROED}; use crate::tlv::TLVElement; + use super::*; + /// Valid CSR from C++ test (TestChipCryptoPAL.cpp) /// This CSR has a valid signature and can be verified. const GOOD_CSR: &[u8] = &[ @@ -323,7 +324,7 @@ mod tests { let crypto = test_only_crypto(); let fabric_id = 0x1234567890ABCDEFu64; - let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); // Should have root cert assert!(!creds.root_cert().is_empty()); @@ -345,7 +346,7 @@ mod tests { &crypto, fabric_id, starting_node_id, - DEFAULT_VALIDITY, + VALID_FOREVER, )); assert_eq!(creds.peek_next_node_id(), starting_node_id); @@ -355,7 +356,7 @@ mod tests { fn test_node_id_auto_increment() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); @@ -376,7 +377,7 @@ mod tests { fn test_peek_next_node_id_doesnt_increment() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let id1 = creds.peek_next_node_id(); let id2 = creds.peek_next_node_id(); @@ -391,7 +392,7 @@ mod tests { fn test_custom_node_id_doesnt_affect_counter() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); @@ -412,7 +413,7 @@ mod tests { fn test_generate_device_credentials_basic() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); @@ -434,7 +435,7 @@ mod tests { fn test_device_credentials_with_cat_ids() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); let cat_ids = &[0x00011111u32, 0x00022222u32]; @@ -449,7 +450,7 @@ mod tests { fn test_enable_icac() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); // Initially no ICAC assert!(creds.icac_cert().is_none()); @@ -465,7 +466,7 @@ mod tests { fn test_device_credentials_includes_icac_when_enabled() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); @@ -483,7 +484,7 @@ mod tests { fn test_icac_cert_available_after_enable() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); assert!(creds.icac_cert().is_none()); @@ -497,7 +498,7 @@ mod tests { fn test_noc_signed_by_icac_when_enabled() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); @@ -517,7 +518,7 @@ mod tests { fn test_ipk_is_generated() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let ipk = creds.ipk(); @@ -530,7 +531,7 @@ mod tests { fn test_set_custom_ipk() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let custom_ipk = [0x42u8; AEAD_CANON_KEY_LEN]; creds.set_ipk(CanonAeadKeyRef::new(&custom_ipk)); @@ -542,7 +543,7 @@ mod tests { fn test_root_cert_available() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let root_cert = creds.root_cert(); assert!(!root_cert.is_empty()); @@ -553,7 +554,7 @@ mod tests { fn test_root_cert_consistent() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); @@ -574,7 +575,7 @@ mod tests { fn test_verify_noc_and_rcac_parse() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); @@ -593,7 +594,7 @@ mod tests { fn test_generated_noc_contains_correct_node_id() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); @@ -611,7 +612,7 @@ mod tests { fn test_generated_noc_contains_correct_fabric_id() { let crypto = test_only_crypto(); let fabric_id = 0xABCDEF123456u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); @@ -628,7 +629,7 @@ mod tests { fn test_cat_ids_present_in_noc_when_specified() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); let cat_ids = &[0x00011111u32, 0x00022222u32, 0x00033333u32]; @@ -648,7 +649,7 @@ mod tests { fn test_invalid_csr_fails() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let invalid_csr = &[0x01, 0x02, 0x03, 0x04]; @@ -661,7 +662,7 @@ mod tests { fn test_four_cat_ids_fails() { let crypto = test_only_crypto(); let fabric_id = 0x1u64; - let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut creds = unwrap!(FabricCredentials::new(&crypto, fabric_id, VALID_FOREVER)); let csr = generate_test_csr(); let too_many_cat_ids = &[0x00011111u32, 0x00022222u32, 0x00033333u32, 0x00044444u32]; diff --git a/rs-matter/src/commissioner/noc_generator.rs b/rs-matter/src/commissioner/noc_generator.rs index 60eaa99e..b0c80abc 100644 --- a/rs-matter/src/commissioner/noc_generator.rs +++ b/rs-matter/src/commissioner/noc_generator.rs @@ -32,24 +32,6 @@ use crate::crypto::{ }; use crate::error::{Error, ErrorCode}; -// NotBefore MUST NOT be 0 (Matter epoch start, 2000-01-01). -// CHIP's ChipEpochToASN1Time treats epoch=0 as the "no -// well-defined expiration date" sentinel and re-emits it as -// GeneralizedTime "99991231235959Z" regardless of which field -// it appears in (see CHIPCert.cpp:1076-1106 and the -// explanatory comment about CHIP epoch 0 NotBefore producing -// an invalid TBS signature on round-trip). -// -// We sign over UTCTime "000101000000Z" (Matter epoch); CHIP -// would reconstruct GeneralizedTime "99991231235959Z" and the -// hash would mismatch. Using 1 second past the Matter epoch -// avoids the sentinel collision while keeping the cert -// effectively unbounded on the lower end. -pub const DEFAULT_VALIDITY: Validity = Validity { - not_before: 1, // 2000-01-01 00:00:01 — past CHIP's epoch=0 sentinel - not_after: 0, // no expiry (NotAfter sentinel is legitimate) -}; - /// Generated NOC credentials for a device. #[derive(Debug)] pub struct NocCredentials { @@ -428,6 +410,7 @@ impl NocGenerator { #[cfg(test)] mod tests { + use crate::cert::builder::VALID_FOREVER; use crate::cert::CertRef; use crate::crypto::test_only_crypto; use crate::tlv::TLVElement; @@ -477,7 +460,7 @@ mod tests { let crypto = test_only_crypto(); let fabric_id = 0x1234_5678_9ABC_DEF0; - let generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); // Verify fabric_id is stored assert_eq!(generator.fabric_id(), fabric_id); @@ -501,7 +484,7 @@ mod tests { let crypto = test_only_crypto(); let fabric_id = 0xABCD; - let gen1 = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let gen1 = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); let root_cert = gen1.root_cert(); let rcac_id = gen1.rcac_id(); @@ -516,7 +499,7 @@ mod tests { &root_cert_copy, fabric_id, rcac_id, - DEFAULT_VALIDITY, + VALID_FOREVER, )); // Verify credentials match @@ -529,7 +512,7 @@ mod tests { fn test_generate_icac_creates_certificate() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); let icac = unwrap!(generator.generate_icac(&crypto)); @@ -544,7 +527,7 @@ mod tests { fn test_icac_cert_available_after_generation() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); // Before generation, icac_cert() should return None assert!(generator.icac_cert().is_none()); @@ -567,7 +550,7 @@ mod tests { fn test_multiple_icac_calls_replace_previous() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); // Generate first ICAC unwrap!(generator.generate_icac(&crypto)); @@ -593,7 +576,7 @@ mod tests { fn test_generate_noc_basic() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); let node_id = 0x1234; let creds = unwrap!(generator.generate_noc(&crypto, GOOD_CSR, node_id, &[])); @@ -612,7 +595,7 @@ mod tests { fn test_generate_noc_with_icac() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); // Generate ICAC first unwrap!(generator.generate_icac(&crypto)); @@ -632,7 +615,7 @@ mod tests { fn test_generate_noc_with_cat_ids() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); let node_id = 0xABCD; let cat_ids = [0x0001_0001, 0x0001_0002, 0x0001_0003]; @@ -654,7 +637,7 @@ mod tests { fn test_generate_noc_increments_serial() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); // Initial serial should be 1 assert_eq!(generator.next_serial, 1); @@ -676,7 +659,7 @@ mod tests { fn test_noc_contains_correct_node_id() { let crypto = test_only_crypto(); let fabric_id = 0x9999; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); let node_id = 0xDEAD_BEEF_CAFE_BABE; let creds = unwrap!(generator.generate_noc(&crypto, GOOD_CSR, node_id, &[])); @@ -692,7 +675,7 @@ mod tests { fn test_noc_contains_device_pubkey_from_csr() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); let creds = unwrap!(generator.generate_noc(&crypto, GOOD_CSR, 1, &[])); @@ -754,7 +737,7 @@ mod tests { fn test_generate_noc_bad_signature_fails() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); // CSR with bad signature should fail verification let result = generator.generate_noc(&crypto, BAD_SIGNATURE_CSR, 1, &[]); @@ -765,7 +748,7 @@ mod tests { fn test_generate_noc_too_many_cat_ids_fails() { let crypto = test_only_crypto(); let fabric_id = 0x1; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); // More than 3 CAT IDs should fail let too_many_cat_ids = [0x0001_0001, 0x0001_0002, 0x0001_0003, 0x0001_0004]; @@ -778,7 +761,7 @@ mod tests { fn test_generated_rcac_can_be_parsed() { let crypto = test_only_crypto(); let fabric_id = 0x1234; - let generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); let rcac = generator.root_cert(); @@ -794,7 +777,7 @@ mod tests { fn test_generated_icac_can_be_parsed() { let crypto = test_only_crypto(); let fabric_id = 0x5678; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); let icac = unwrap!(generator.generate_icac(&crypto)); @@ -810,7 +793,7 @@ mod tests { fn test_generated_noc_can_be_parsed() { let crypto = test_only_crypto(); let fabric_id = 0xABCD; - let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, DEFAULT_VALIDITY)); + let mut generator = unwrap!(NocGenerator::new(&crypto, fabric_id, VALID_FOREVER)); let node_id = 0x9999; let creds = unwrap!(generator.generate_noc(&crypto, GOOD_CSR, node_id, &[])); diff --git a/rs-matter/tests/case.rs b/rs-matter/tests/case.rs index 5978f39f..e48d7f02 100644 --- a/rs-matter/tests/case.rs +++ b/rs-matter/tests/case.rs @@ -17,17 +17,15 @@ #![cfg(all(feature = "std", feature = "async-io"))] -#[allow(dead_code)] -mod common; - use core::pin::pin; use embassy_futures::select::{select, Either}; use embassy_time::{Duration, Timer}; + use log::info; +use rs_matter::cert::builder::VALID_FOREVER; use rs_matter::commissioner::fabric_credentials::FabricCredentials; -use rs_matter::commissioner::noc_generator::DEFAULT_VALIDITY; use rs_matter::crypto::{test_only_crypto, CanonPkcSecretKey, Crypto, SecretKey, SigningSecretKey}; use rs_matter::dm::devices::test::{TEST_DEV_ATT, TEST_DEV_COMM, TEST_DEV_DET}; use rs_matter::error::Error; @@ -42,6 +40,9 @@ use rs_matter::Matter; use crate::common::{create_localhost_socket_pair, init_env_logger, run_device_controller}; +#[allow(dead_code)] +mod common; + const TEST_FABRIC_ID: u64 = 1; const CONTROLLER_NODE_ID: u64 = 100; const DEVICE_NODE_ID: u64 = 200; @@ -64,7 +65,7 @@ fn test_case_handshake() { // ---- 1. Generate credentials using FabricCredentials ---- let mut fabric_creds = - FabricCredentials::new(&crypto, TEST_FABRIC_ID, DEFAULT_VALIDITY).unwrap(); + FabricCredentials::new(&crypto, TEST_FABRIC_ID, VALID_FOREVER).unwrap(); // Generate controller credentials (keypair + CSR + NOC) let controller_secret_key = crypto.generate_secret_key().unwrap();