From 59ebfa06c92a6898c51fa1508bb7154ae7ea9c1b Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Sun, 1 Jan 2023 15:55:34 +0530 Subject: [PATCH 1/3] NOC: Support read attribute for current fabric index --- matter/src/data_model/sdm/noc.rs | 36 ++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/matter/src/data_model/sdm/noc.rs b/matter/src/data_model/sdm/noc.rs index 3812ed6..5a8214e 100644 --- a/matter/src/data_model/sdm/noc.rs +++ b/matter/src/data_model/sdm/noc.rs @@ -78,6 +78,16 @@ pub enum Commands { AddTrustedRootCert = 0x0b, } +#[derive(FromPrimitive)] +enum Attributes { + NOCs = 0, + Fabrics = 1, + SupportedFabrics = 2, + CommissionedFabrics = 3, + TrustedRootCerts = 4, + CurrentFabricIndex = 5, +} + pub struct NocCluster { base: Cluster, dev_att: Box, @@ -106,13 +116,15 @@ impl NocCluster { acl_mgr: Arc, failsafe: Arc, ) -> Result, Error> { - Ok(Box::new(Self { + let mut c = Box::new(Self { dev_att, fabric_mgr, acl_mgr, failsafe, base: Cluster::new(ID)?, - })) + }); + c.base.add_attribute(attr_currfabindex_new()?)?; + Ok(c) } fn add_acl(&self, fab_idx: u8, admin_subject: u64) -> Result<(), Error> { @@ -342,6 +354,15 @@ impl NocCluster { } } +fn attr_currfabindex_new() -> Result { + Attribute::new( + Attributes::CurrentFabricIndex as u16, + AttrValue::Custom, + Access::RV, + Quality::NONE, + ) +} + impl ClusterType for NocCluster { fn base(&self) -> &Cluster { &self.base @@ -367,6 +388,17 @@ impl ClusterType for NocCluster { _ => Err(IMStatusCode::UnsupportedCommand), } } + + fn read_custom_attribute(&self, encoder: &mut dyn Encoder, attr: &AttrDetails) { + match num::FromPrimitive::from_u16(attr.attr_id) { + Some(Attributes::CurrentFabricIndex) => { + encoder.encode(EncodeValue::Value(&attr.fab_idx)) + } + _ => { + error!("Attribute not supported: this shouldn't happen"); + } + } + } } fn add_attestation_element( From 6d19a034d05d20572a87bc77ec990bc10ebb25eb Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Sun, 1 Jan 2023 16:26:17 +0530 Subject: [PATCH 2/3] Fabric: Save vendor id when new Fabric is created --- matter/src/data_model/sdm/noc.rs | 3 ++- matter/src/fabric.rs | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/matter/src/data_model/sdm/noc.rs b/matter/src/data_model/sdm/noc.rs index 5a8214e..63f3d0f 100644 --- a/matter/src/data_model/sdm/noc.rs +++ b/matter/src/data_model/sdm/noc.rs @@ -162,6 +162,7 @@ impl NocCluster { icac_value, noc_value, r.ipk_value.0, + r.vendor_id, ) .map_err(|_| NocStatus::TableFull)?; let fab_idx = self @@ -479,7 +480,7 @@ struct AddNocReq<'a> { icac_value: OctetStr<'a>, ipk_value: OctetStr<'a>, case_admin_subject: u64, - _vendor_id: u16, + vendor_id: u16, } #[derive(FromTLV)] diff --git a/matter/src/fabric.rs b/matter/src/fabric.rs index 8f85504..86919b3 100644 --- a/matter/src/fabric.rs +++ b/matter/src/fabric.rs @@ -39,6 +39,7 @@ macro_rules! fb_key { }; } +const ST_VID: &str = "vid"; const ST_RCA: &str = "rca"; const ST_ICA: &str = "ica"; const ST_NOC: &str = "noc"; @@ -50,6 +51,7 @@ const ST_PRKEY: &str = "privkey"; pub struct Fabric { node_id: u64, fabric_id: u64, + vendor_id: u16, key_pair: Box, pub root_ca: Cert, pub icac: Cert, @@ -66,6 +68,7 @@ impl Fabric { icac: Cert, noc: Cert, ipk: &[u8], + vendor_id: u16, ) -> Result { let node_id = noc.get_node_id()?; let fabric_id = noc.get_fabric_id()?; @@ -73,6 +76,7 @@ impl Fabric { let mut f = Self { node_id, fabric_id, + vendor_id, key_pair: Box::new(key_pair), root_ca, icac, @@ -105,6 +109,7 @@ impl Fabric { Ok(Self { node_id: 0, fabric_id: 0, + vendor_id: 0, key_pair: Box::new(KeyPairDummy::new()?), root_ca: Cert::default(), icac: Cert::default(), @@ -181,6 +186,7 @@ impl Fabric { let key = &key[..len]; psm.set_kv_slice(fb_key!(index, ST_PRKEY), key)?; + psm.set_kv_u64(ST_VID, self.vendor_id.into())?; Ok(()) } @@ -206,7 +212,17 @@ impl Fabric { psm.get_kv_slice(fb_key!(index, ST_PRKEY), &mut priv_key)?; let keypair = KeyPair::new_from_components(pub_key.as_slice(), priv_key.as_slice())?; - Fabric::new(keypair, root_ca, icac, noc, ipk.as_slice()) + let mut vendor_id = 0; + psm.get_kv_u64(ST_VID, &mut vendor_id)?; + + Fabric::new( + keypair, + root_ca, + icac, + noc, + ipk.as_slice(), + vendor_id as u16, + ) } } From 263a0e8d6e0bbe88f3c6aaba84e7b8f5b4c06178 Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Sun, 1 Jan 2023 18:20:34 +0530 Subject: [PATCH 3/3] NOC: Support the read of 'Fabrics' attribute --- matter/src/data_model/sdm/noc.rs | 21 +++++++++++++++++ matter/src/fabric.rs | 39 ++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/matter/src/data_model/sdm/noc.rs b/matter/src/data_model/sdm/noc.rs index 63f3d0f..929809c 100644 --- a/matter/src/data_model/sdm/noc.rs +++ b/matter/src/data_model/sdm/noc.rs @@ -124,6 +124,7 @@ impl NocCluster { base: Cluster::new(ID)?, }); c.base.add_attribute(attr_currfabindex_new()?)?; + c.base.add_attribute(attr_fabrics_new()?)?; Ok(c) } @@ -364,6 +365,15 @@ fn attr_currfabindex_new() -> Result { ) } +fn attr_fabrics_new() -> Result { + Attribute::new( + Attributes::Fabrics as u16, + AttrValue::Custom, + Access::RV | Access::FAB_SCOPED, + Quality::NONE, + ) +} + impl ClusterType for NocCluster { fn base(&self) -> &Cluster { &self.base @@ -395,6 +405,17 @@ impl ClusterType for NocCluster { Some(Attributes::CurrentFabricIndex) => { encoder.encode(EncodeValue::Value(&attr.fab_idx)) } + Some(Attributes::Fabrics) => encoder.encode(EncodeValue::Closure(&|tag, tw| { + let _ = tw.start_array(tag); + let _ = self.fabric_mgr.for_each(|entry, fab_idx| { + if !attr.fab_filter || attr.fab_idx == fab_idx { + let _ = entry + .get_fabric_desc(fab_idx) + .to_tlv(tw, TagType::Anonymous); + } + }); + let _ = tw.end_container(); + })), _ => { error!("Attribute not supported: this shouldn't happen"); } diff --git a/matter/src/fabric.rs b/matter/src/fabric.rs index 86919b3..c9ae240 100644 --- a/matter/src/fabric.rs +++ b/matter/src/fabric.rs @@ -28,6 +28,7 @@ use crate::{ group_keys::KeySet, mdns::{self, Mdns}, sys::{Psm, SysMdnsService}, + tlv::{OctetStr, TLVWriter, TagType, ToTLV, UtfStr}, }; const MAX_CERT_TLV_LEN: usize = 300; @@ -61,6 +62,19 @@ pub struct Fabric { mdns_service: Option, } +#[derive(ToTLV)] +#[tlvargs(lifetime = "'a", start = 1)] +pub struct FabricDescriptor<'a> { + root_public_key: OctetStr<'a>, + vendor_id: u16, + fabric_id: u64, + node_id: u64, + label: UtfStr<'a>, + // TODO: Instead of the direct value, we should consider GlobalElements::FabricIndex + #[tagval(0xFE)] + pub fab_idx: Option, +} + impl Fabric { pub fn new( key_pair: KeyPair, @@ -166,6 +180,17 @@ impl Fabric { self.fabric_id } + pub fn get_fabric_desc(&self, fab_idx: u8) -> FabricDescriptor { + FabricDescriptor { + root_public_key: OctetStr::new(self.root_ca.get_pubkey()), + vendor_id: self.vendor_id, + fabric_id: self.fabric_id, + node_id: self.node_id, + label: UtfStr::new(b""), + fab_idx: Some(fab_idx), + } + } + fn store(&self, index: usize, psm: &MutexGuard) -> Result<(), Error> { let mut key = [0u8; MAX_CERT_TLV_LEN]; let len = self.root_ca.as_tlv(&mut key)?; @@ -312,4 +337,18 @@ impl FabricMgr { } true } + + // Parameters to T are the Fabric and its Fabric Index + pub fn for_each(&self, mut f: T) -> Result<(), Error> + where + T: FnMut(&Fabric, u8), + { + let mgr = self.inner.read().unwrap(); + for i in 1..MAX_SUPPORTED_FABRICS { + if let Some(fabric) = &mgr.fabrics[i] { + f(fabric, i as u8) + } + } + Ok(()) + } }