Merge pull request #2 from project-chip/feature/noc_fabrics_attr

Descriptor Cluster: Support attributes CurrentFabricIndex and Fabrics
This commit is contained in:
Kedar Sovani 2023-01-03 08:43:00 +05:30 committed by GitHub
commit ed5949253b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 113 additions and 4 deletions

View file

@ -78,6 +78,16 @@ pub enum Commands {
AddTrustedRootCert = 0x0b, AddTrustedRootCert = 0x0b,
} }
#[derive(FromPrimitive)]
enum Attributes {
NOCs = 0,
Fabrics = 1,
SupportedFabrics = 2,
CommissionedFabrics = 3,
TrustedRootCerts = 4,
CurrentFabricIndex = 5,
}
pub struct NocCluster { pub struct NocCluster {
base: Cluster, base: Cluster,
dev_att: Box<dyn DevAttDataFetcher>, dev_att: Box<dyn DevAttDataFetcher>,
@ -106,13 +116,16 @@ impl NocCluster {
acl_mgr: Arc<AclMgr>, acl_mgr: Arc<AclMgr>,
failsafe: Arc<FailSafe>, failsafe: Arc<FailSafe>,
) -> Result<Box<Self>, Error> { ) -> Result<Box<Self>, Error> {
Ok(Box::new(Self { let mut c = Box::new(Self {
dev_att, dev_att,
fabric_mgr, fabric_mgr,
acl_mgr, acl_mgr,
failsafe, failsafe,
base: Cluster::new(ID)?, base: Cluster::new(ID)?,
})) });
c.base.add_attribute(attr_currfabindex_new()?)?;
c.base.add_attribute(attr_fabrics_new()?)?;
Ok(c)
} }
fn add_acl(&self, fab_idx: u8, admin_subject: u64) -> Result<(), Error> { fn add_acl(&self, fab_idx: u8, admin_subject: u64) -> Result<(), Error> {
@ -155,6 +168,7 @@ impl NocCluster {
icac_value, icac_value,
noc_value, noc_value,
r.ipk_value.0, r.ipk_value.0,
r.vendor_id,
) )
.map_err(|_| NocStatus::TableFull)?; .map_err(|_| NocStatus::TableFull)?;
let fab_idx = self let fab_idx = self
@ -347,6 +361,24 @@ impl NocCluster {
} }
} }
fn attr_currfabindex_new() -> Result<Attribute, Error> {
Attribute::new(
Attributes::CurrentFabricIndex as u16,
AttrValue::Custom,
Access::RV,
Quality::NONE,
)
}
fn attr_fabrics_new() -> Result<Attribute, Error> {
Attribute::new(
Attributes::Fabrics as u16,
AttrValue::Custom,
Access::RV | Access::FAB_SCOPED,
Quality::NONE,
)
}
impl ClusterType for NocCluster { impl ClusterType for NocCluster {
fn base(&self) -> &Cluster { fn base(&self) -> &Cluster {
&self.base &self.base
@ -372,6 +404,28 @@ impl ClusterType for NocCluster {
_ => Err(IMStatusCode::UnsupportedCommand), _ => 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))
}
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");
}
}
}
} }
fn add_attestation_element( fn add_attestation_element(
@ -452,7 +506,7 @@ struct AddNocReq<'a> {
icac_value: OctetStr<'a>, icac_value: OctetStr<'a>,
ipk_value: OctetStr<'a>, ipk_value: OctetStr<'a>,
case_admin_subject: u64, case_admin_subject: u64,
_vendor_id: u16, vendor_id: u16,
} }
#[derive(FromTLV)] #[derive(FromTLV)]

View file

@ -28,6 +28,7 @@ use crate::{
group_keys::KeySet, group_keys::KeySet,
mdns::{self, Mdns}, mdns::{self, Mdns},
sys::{Psm, SysMdnsService}, sys::{Psm, SysMdnsService},
tlv::{OctetStr, TLVWriter, TagType, ToTLV, UtfStr},
}; };
const MAX_CERT_TLV_LEN: usize = 300; const MAX_CERT_TLV_LEN: usize = 300;
@ -39,6 +40,7 @@ macro_rules! fb_key {
}; };
} }
const ST_VID: &str = "vid";
const ST_RCA: &str = "rca"; const ST_RCA: &str = "rca";
const ST_ICA: &str = "ica"; const ST_ICA: &str = "ica";
const ST_NOC: &str = "noc"; const ST_NOC: &str = "noc";
@ -50,6 +52,7 @@ const ST_PRKEY: &str = "privkey";
pub struct Fabric { pub struct Fabric {
node_id: u64, node_id: u64,
fabric_id: u64, fabric_id: u64,
vendor_id: u16,
key_pair: Box<dyn CryptoKeyPair>, key_pair: Box<dyn CryptoKeyPair>,
pub root_ca: Cert, pub root_ca: Cert,
pub icac: Option<Cert>, pub icac: Option<Cert>,
@ -59,6 +62,19 @@ pub struct Fabric {
mdns_service: Option<SysMdnsService>, mdns_service: Option<SysMdnsService>,
} }
#[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<u8>,
}
impl Fabric { impl Fabric {
pub fn new( pub fn new(
key_pair: KeyPair, key_pair: KeyPair,
@ -66,6 +82,7 @@ impl Fabric {
icac: Option<Cert>, icac: Option<Cert>,
noc: Cert, noc: Cert,
ipk: &[u8], ipk: &[u8],
vendor_id: u16,
) -> Result<Self, Error> { ) -> Result<Self, Error> {
let node_id = noc.get_node_id()?; let node_id = noc.get_node_id()?;
let fabric_id = noc.get_fabric_id()?; let fabric_id = noc.get_fabric_id()?;
@ -73,6 +90,7 @@ impl Fabric {
let mut f = Self { let mut f = Self {
node_id, node_id,
fabric_id, fabric_id,
vendor_id,
key_pair: Box::new(key_pair), key_pair: Box::new(key_pair),
root_ca, root_ca,
icac, icac,
@ -105,6 +123,7 @@ impl Fabric {
Ok(Self { Ok(Self {
node_id: 0, node_id: 0,
fabric_id: 0, fabric_id: 0,
vendor_id: 0,
key_pair: Box::new(KeyPairDummy::new()?), key_pair: Box::new(KeyPairDummy::new()?),
root_ca: Cert::default(), root_ca: Cert::default(),
icac: Some(Cert::default()), icac: Some(Cert::default()),
@ -161,6 +180,17 @@ impl Fabric {
self.fabric_id 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<Psm>) -> Result<(), Error> { fn store(&self, index: usize, psm: &MutexGuard<Psm>) -> Result<(), Error> {
let mut key = [0u8; MAX_CERT_TLV_LEN]; let mut key = [0u8; MAX_CERT_TLV_LEN];
let len = self.root_ca.as_tlv(&mut key)?; let len = self.root_ca.as_tlv(&mut key)?;
@ -187,6 +217,7 @@ impl Fabric {
let key = &key[..len]; let key = &key[..len];
psm.set_kv_slice(fb_key!(index, ST_PRKEY), key)?; psm.set_kv_slice(fb_key!(index, ST_PRKEY), key)?;
psm.set_kv_u64(ST_VID, self.vendor_id.into())?;
Ok(()) Ok(())
} }
@ -216,7 +247,17 @@ impl Fabric {
psm.get_kv_slice(fb_key!(index, ST_PRKEY), &mut priv_key)?; 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())?; 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,
)
} }
} }
@ -306,4 +347,18 @@ impl FabricMgr {
} }
true true
} }
// Parameters to T are the Fabric and its Fabric Index
pub fn for_each<T>(&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(())
}
} }