Skip to content

Commit d2926a4

Browse files
authored
Merge pull request #9 from project-chip/feature/multi-admin
Multi-Admin Support
2 parents 0979c1a + 34e137a commit d2926a4

28 files changed

+678
-215
lines changed

examples/onoff_light/src/main.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,27 @@ mod dev_att;
1919
use matter::core::{self, CommissioningData};
2020
use matter::data_model::cluster_basic_information::BasicInfoConfig;
2121
use matter::data_model::device_types::device_type_add_on_off_light;
22-
use rand::prelude::*;
22+
use matter::secure_channel::spake2p::VerifierData;
2323

2424
fn main() {
2525
env_logger::init();
26-
let mut comm_data = CommissioningData {
26+
let comm_data = CommissioningData {
2727
// TODO: Hard-coded for now
28-
passwd: 123456,
28+
verifier: VerifierData::new_with_pw(123456),
2929
discriminator: 250,
30-
..Default::default()
3130
};
32-
rand::thread_rng().fill_bytes(&mut comm_data.salt);
3331

3432
// vid/pid should match those in the DAC
3533
let dev_info = BasicInfoConfig {
3634
vid: 0xFFF1,
3735
pid: 0x8002,
3836
hw_ver: 2,
3937
sw_ver: 1,
38+
serial_no: "aabbccdd".to_string(),
4039
};
4140
let dev_att = Box::new(dev_att::HardCodedDevAtt::new());
4241

43-
let mut matter = core::Matter::new(&dev_info, dev_att, &comm_data).unwrap();
42+
let mut matter = core::Matter::new(dev_info, dev_att, comm_data).unwrap();
4443
let dm = matter.get_data_model();
4544
{
4645
let mut node = dm.node.write().unwrap();

matter/src/core.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,19 +25,15 @@ use crate::{
2525
fabric::FabricMgr,
2626
interaction_model::InteractionModel,
2727
mdns::Mdns,
28-
secure_channel::core::SecureChannel,
28+
secure_channel::{core::SecureChannel, pake::PaseMgr, spake2p::VerifierData},
2929
transport,
3030
};
3131
use std::sync::Arc;
3232

33-
#[derive(Default)]
3433
/// Device Commissioning Data
3534
pub struct CommissioningData {
36-
/// The commissioning salt
37-
pub salt: [u8; 16],
38-
/// The password for commissioning the device
39-
// TODO: We should replace this with verifier instead of password
40-
pub passwd: u32,
35+
/// The data like password or verifier that is required to authenticate
36+
pub verifier: VerifierData,
4137
/// The 12-bit discriminator used to differentiate between multiple devices
4238
pub discriminator: u16,
4339
}
@@ -57,17 +53,19 @@ impl Matter {
5753
/// requires a set of device attestation certificates and keys. It is the responsibility of
5854
/// this object to return the device attestation details when queried upon.
5955
pub fn new(
60-
dev_det: &BasicInfoConfig,
56+
dev_det: BasicInfoConfig,
6157
dev_att: Box<dyn DevAttDataFetcher>,
62-
dev_comm: &CommissioningData,
58+
dev_comm: CommissioningData,
6359
) -> Result<Box<Matter>, Error> {
6460
let mdns = Mdns::get()?;
65-
mdns.set_values(dev_det.vid, dev_det.pid, dev_comm.discriminator);
61+
mdns.set_values(dev_det.vid, dev_det.pid);
6662

6763
let fabric_mgr = Arc::new(FabricMgr::new()?);
6864
let acl_mgr = Arc::new(AclMgr::new()?);
65+
let mut pase = PaseMgr::new();
6966
let open_comm_window = fabric_mgr.is_empty();
70-
let data_model = DataModel::new(dev_det, dev_att, fabric_mgr.clone(), acl_mgr)?;
67+
let data_model =
68+
DataModel::new(dev_det, dev_att, fabric_mgr.clone(), acl_mgr, pase.clone())?;
7169
let mut matter = Box::new(Matter {
7270
transport_mgr: transport::mgr::Mgr::new()?,
7371
data_model,
@@ -76,11 +74,12 @@ impl Matter {
7674
let interaction_model =
7775
Box::new(InteractionModel::new(Box::new(matter.data_model.clone())));
7876
matter.transport_mgr.register_protocol(interaction_model)?;
79-
let mut secure_channel = Box::new(SecureChannel::new(matter.fabric_mgr.clone()));
77+
8078
if open_comm_window {
81-
secure_channel.open_comm_window(&dev_comm.salt, dev_comm.passwd)?;
79+
pase.enable_pase_session(dev_comm.verifier, dev_comm.discriminator)?;
8280
}
8381

82+
let secure_channel = Box::new(SecureChannel::new(pase, matter.fabric_mgr.clone()));
8483
matter.transport_mgr.register_protocol(secure_channel)?;
8584
Ok(matter)
8685
}

matter/src/data_model/cluster_basic_information.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,35 @@
1717

1818
use super::objects::*;
1919
use crate::error::*;
20+
use num_derive::FromPrimitive;
2021

2122
pub const ID: u32 = 0x0028;
23+
24+
#[derive(FromPrimitive)]
2225
enum Attributes {
26+
DMRevision = 0,
2327
VendorId = 2,
2428
ProductId = 4,
2529
HwVer = 7,
2630
SwVer = 9,
31+
SerialNo = 0x0f,
2732
}
2833

2934
pub struct BasicInfoConfig {
3035
pub vid: u16,
3136
pub pid: u16,
3237
pub hw_ver: u16,
3338
pub sw_ver: u32,
39+
pub serial_no: String,
40+
}
41+
42+
fn attr_dm_rev_new() -> Result<Attribute, Error> {
43+
Attribute::new(
44+
Attributes::DMRevision as u16,
45+
AttrValue::Uint8(1),
46+
Access::RV,
47+
Quality::FIXED,
48+
)
3449
}
3550

3651
fn attr_vid_new(vid: u16) -> Result<Attribute, Error> {
@@ -69,19 +84,31 @@ fn attr_sw_ver_new(sw_ver: u32) -> Result<Attribute, Error> {
6984
)
7085
}
7186

87+
fn attr_serial_no_new(label: String) -> Result<Attribute, Error> {
88+
Attribute::new(
89+
Attributes::SerialNo as u16,
90+
AttrValue::Utf8(label),
91+
Access::RV,
92+
Quality::FIXED,
93+
)
94+
}
7295
pub struct BasicInfoCluster {
7396
base: Cluster,
7497
}
7598

7699
impl BasicInfoCluster {
77-
pub fn new(cfg: &BasicInfoConfig) -> Result<Box<Self>, Error> {
100+
pub fn new(cfg: BasicInfoConfig) -> Result<Box<Self>, Error> {
78101
let mut cluster = Box::new(BasicInfoCluster {
79102
base: Cluster::new(ID)?,
80103
});
104+
cluster.base.add_attribute(attr_dm_rev_new()?)?;
81105
cluster.base.add_attribute(attr_vid_new(cfg.vid)?)?;
82106
cluster.base.add_attribute(attr_pid_new(cfg.pid)?)?;
83107
cluster.base.add_attribute(attr_hw_ver_new(cfg.hw_ver)?)?;
84108
cluster.base.add_attribute(attr_sw_ver_new(cfg.sw_ver)?)?;
109+
cluster
110+
.base
111+
.add_attribute(attr_serial_no_new(cfg.serial_no)?)?;
85112
Ok(cluster)
86113
}
87114
}

matter/src/data_model/core.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ use crate::{
3636
},
3737
InteractionConsumer, Transaction,
3838
},
39+
secure_channel::pake::PaseMgr,
3940
tlv::{TLVArray, TLVWriter, TagType, ToTLV},
4041
transport::session::{Session, SessionMode},
4142
};
@@ -50,10 +51,11 @@ pub struct DataModel {
5051

5152
impl DataModel {
5253
pub fn new(
53-
dev_details: &BasicInfoConfig,
54+
dev_details: BasicInfoConfig,
5455
dev_att: Box<dyn DevAttDataFetcher>,
5556
fabric_mgr: Arc<FabricMgr>,
5657
acl_mgr: Arc<AclMgr>,
58+
pase_mgr: PaseMgr,
5759
) -> Result<Self, Error> {
5860
let dm = DataModel {
5961
node: Arc::new(RwLock::new(Node::new()?)),
@@ -62,7 +64,14 @@ impl DataModel {
6264
{
6365
let mut node = dm.node.write()?;
6466
node.set_changes_cb(Box::new(dm.clone()));
65-
device_type_add_root_node(&mut node, dev_details, dev_att, fabric_mgr, acl_mgr)?;
67+
device_type_add_root_node(
68+
&mut node,
69+
dev_details,
70+
dev_att,
71+
fabric_mgr,
72+
acl_mgr,
73+
pase_mgr,
74+
)?;
6675
}
6776
Ok(dm)
6877
}
@@ -75,7 +84,7 @@ impl DataModel {
7584
) -> Result<AttrValue, IMStatusCode> {
7685
let node = self.node.read().unwrap();
7786
let cluster = node.get_cluster(endpoint, cluster)?;
78-
cluster.base().read_attribute_raw(attr).map(|a| *a)
87+
cluster.base().read_attribute_raw(attr).map(|a| a.clone())
7988
}
8089

8190
// Encode a write attribute from a path that may or may not be wildcard

matter/src/data_model/device_types.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use super::cluster_basic_information::BasicInfoCluster;
1919
use super::cluster_basic_information::BasicInfoConfig;
2020
use super::cluster_on_off::OnOffCluster;
2121
use super::objects::*;
22+
use super::sdm::admin_commissioning::AdminCommCluster;
2223
use super::sdm::dev_att::DevAttDataFetcher;
2324
use super::sdm::general_commissioning::GenCommCluster;
2425
use super::sdm::noc::NocCluster;
@@ -27,20 +28,27 @@ use super::system_model::access_control::AccessControlCluster;
2728
use crate::acl::AclMgr;
2829
use crate::error::*;
2930
use crate::fabric::FabricMgr;
31+
use crate::secure_channel::pake::PaseMgr;
3032
use std::sync::Arc;
3133
use std::sync::RwLockWriteGuard;
3234

35+
pub const DEV_TYPE_ROOT_NODE: DeviceType = DeviceType {
36+
dtype: 0x0016,
37+
drev: 1,
38+
};
39+
3340
type WriteNode<'a> = RwLockWriteGuard<'a, Box<Node>>;
3441

3542
pub fn device_type_add_root_node(
3643
node: &mut WriteNode,
37-
dev_info: &BasicInfoConfig,
44+
dev_info: BasicInfoConfig,
3845
dev_att: Box<dyn DevAttDataFetcher>,
3946
fabric_mgr: Arc<FabricMgr>,
4047
acl_mgr: Arc<AclMgr>,
48+
pase_mgr: PaseMgr,
4149
) -> Result<u32, Error> {
4250
// Add the root endpoint
43-
let endpoint = node.add_endpoint()?;
51+
let endpoint = node.add_endpoint(DEV_TYPE_ROOT_NODE)?;
4452
if endpoint != 0 {
4553
// Somehow endpoint 0 was already added, this shouldn't be the case
4654
return Err(Error::Invalid);
@@ -51,6 +59,7 @@ pub fn device_type_add_root_node(
5159
let failsafe = general_commissioning.failsafe();
5260
node.add_cluster(0, general_commissioning)?;
5361
node.add_cluster(0, NwCommCluster::new()?)?;
62+
node.add_cluster(0, AdminCommCluster::new(pase_mgr)?)?;
5463
node.add_cluster(
5564
0,
5665
NocCluster::new(dev_att, fabric_mgr, acl_mgr.clone(), failsafe)?,
@@ -59,8 +68,13 @@ pub fn device_type_add_root_node(
5968
Ok(endpoint)
6069
}
6170

71+
const DEV_TYPE_ON_OFF_LIGHT: DeviceType = DeviceType {
72+
dtype: 0x0100,
73+
drev: 2,
74+
};
75+
6276
pub fn device_type_add_on_off_light(node: &mut WriteNode) -> Result<u32, Error> {
63-
let endpoint = node.add_endpoint()?;
77+
let endpoint = node.add_endpoint(DEV_TYPE_ON_OFF_LIGHT)?;
6478
node.add_cluster(endpoint, OnOffCluster::new()?)?;
6579
Ok(endpoint)
6680
}

matter/src/data_model/objects/attribute.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,14 +88,15 @@ bitflags! {
8888
* - instead of arrays, can use linked-lists to conserve space and avoid the internal fragmentation
8989
*/
9090

91-
#[derive(PartialEq, Copy, Clone)]
91+
#[derive(PartialEq, Clone)]
9292
pub enum AttrValue {
9393
Int64(i64),
9494
Uint8(u8),
9595
Uint16(u16),
9696
Uint32(u32),
9797
Uint64(u64),
9898
Bool(bool),
99+
Utf8(String),
99100
Custom,
100101
}
101102

@@ -108,6 +109,7 @@ impl Debug for AttrValue {
108109
AttrValue::Uint32(v) => write!(f, "{:?}", *v),
109110
AttrValue::Uint64(v) => write!(f, "{:?}", *v),
110111
AttrValue::Bool(v) => write!(f, "{:?}", *v),
112+
AttrValue::Utf8(v) => write!(f, "{:?}", *v),
111113
AttrValue::Custom => write!(f, "custom-attribute"),
112114
}?;
113115
Ok(())
@@ -123,6 +125,7 @@ impl ToTLV for AttrValue {
123125
AttrValue::Uint16(v) => tw.u16(tag_type, *v),
124126
AttrValue::Uint32(v) => tw.u32(tag_type, *v),
125127
AttrValue::Uint64(v) => tw.u64(tag_type, *v),
128+
AttrValue::Utf8(v) => tw.utf8(tag_type, v.as_bytes()),
126129
_ => {
127130
error!("Attribute type not yet supported");
128131
Err(Error::AttributeNotFound)

matter/src/data_model/objects/cluster.rs

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,6 @@ pub trait ClusterType {
8787
pub struct Cluster {
8888
pub(super) id: u32,
8989
attributes: Vec<Attribute>,
90-
feature_map: Option<u32>,
9190
data_ver: u32,
9291
}
9392

@@ -96,7 +95,6 @@ impl Cluster {
9695
let mut c = Cluster {
9796
id,
9897
attributes: Vec::with_capacity(ATTRS_PER_CLUSTER),
99-
feature_map: None,
10098
data_ver: rand::thread_rng().gen_range(0..0xFFFFFFFF),
10199
};
102100
c.add_default_attributes()?;
@@ -112,22 +110,20 @@ impl Cluster {
112110
}
113111

114112
pub fn set_feature_map(&mut self, map: u32) -> Result<(), Error> {
115-
if self.feature_map.is_none() {
116-
self.add_attribute(Attribute::new(
117-
GlobalElements::FeatureMap as u16,
118-
AttrValue::Uint32(map),
119-
Access::RV,
120-
Quality::NONE,
121-
)?)?;
122-
} else {
123-
self.write_attribute_raw(GlobalElements::FeatureMap as u16, AttrValue::Uint32(map))
124-
.map_err(|_| Error::Invalid)?;
125-
}
126-
self.feature_map = Some(map);
113+
self.write_attribute_raw(GlobalElements::FeatureMap as u16, AttrValue::Uint32(map))
114+
.map_err(|_| Error::Invalid)?;
127115
Ok(())
128116
}
129117

130118
fn add_default_attributes(&mut self) -> Result<(), Error> {
119+
// Default feature map is 0
120+
self.add_attribute(Attribute::new(
121+
GlobalElements::FeatureMap as u16,
122+
AttrValue::Uint32(0),
123+
Access::RV,
124+
Quality::NONE,
125+
)?)?;
126+
131127
self.add_attribute(Attribute::new(
132128
GlobalElements::AttributeList as u16,
133129
AttrValue::Custom,
@@ -233,8 +229,7 @@ impl Cluster {
233229
return;
234230
}
235231
GlobalElements::FeatureMap => {
236-
let val = if let Some(m) = self.feature_map { m } else { 0 };
237-
encoder.encode(EncodeValue::Value(&val));
232+
encoder.encode(EncodeValue::Value(&attr.value));
238233
return;
239234
}
240235
_ => {
@@ -284,7 +279,7 @@ impl Cluster {
284279
) -> Result<(), IMStatusCode> {
285280
let a = self.get_attribute_mut(attr_id)?;
286281
if a.value != AttrValue::Custom {
287-
let mut value = a.value;
282+
let mut value = a.value.clone();
288283
value
289284
.update_from_tlv(data)
290285
.map_err(|_| IMStatusCode::Failure)?;

matter/src/data_model/objects/encoder.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,9 @@ pub trait Encoder {
115115
/// Encode a status report
116116
fn encode_status(&mut self, status: IMStatusCode, cluster_status: u16);
117117
}
118+
119+
#[derive(ToTLV, Copy, Clone)]
120+
pub struct DeviceType {
121+
pub dtype: u16,
122+
pub drev: u16,
123+
}

0 commit comments

Comments
 (0)