2023-01-07 21:47:33 +05:30
|
|
|
/*
|
|
|
|
*
|
|
|
|
* Copyright (c) 2023 Project CHIP Authors
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
use crate::cmd_enter;
|
|
|
|
use crate::data_model::objects::*;
|
|
|
|
use crate::interaction_model::core::IMStatusCode;
|
2023-01-10 18:40:52 +05:30
|
|
|
use crate::secure_channel::pake::PaseMgr;
|
|
|
|
use crate::secure_channel::spake2p::VerifierData;
|
2023-01-07 21:47:33 +05:30
|
|
|
use crate::tlv::{FromTLV, Nullable, OctetStr, TLVElement};
|
|
|
|
use crate::{error::*, interaction_model::command::CommandReq};
|
|
|
|
use log::{error, info};
|
|
|
|
use num_derive::FromPrimitive;
|
|
|
|
|
|
|
|
pub const ID: u32 = 0x003C;
|
|
|
|
|
|
|
|
#[derive(FromPrimitive, Debug, Copy, Clone, PartialEq)]
|
|
|
|
pub enum WindowStatus {
|
|
|
|
WindowNotOpen = 0,
|
|
|
|
EnhancedWindowOpen = 1,
|
|
|
|
BasicWindowOpen = 2,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(FromPrimitive)]
|
|
|
|
pub enum Attributes {
|
|
|
|
WindowStatus = 0,
|
|
|
|
AdminFabricIndex = 1,
|
|
|
|
AdminVendorId = 2,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(FromPrimitive)]
|
|
|
|
pub enum Commands {
|
|
|
|
OpenCommWindow = 0x00,
|
|
|
|
OpenBasicCommWindow = 0x01,
|
|
|
|
RevokeComm = 0x02,
|
|
|
|
}
|
|
|
|
|
|
|
|
fn attr_window_status_new() -> Result<Attribute, Error> {
|
|
|
|
Attribute::new(
|
|
|
|
Attributes::WindowStatus as u16,
|
|
|
|
AttrValue::Custom,
|
|
|
|
Access::RV,
|
|
|
|
Quality::NONE,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn attr_admin_fabid_new() -> Result<Attribute, Error> {
|
|
|
|
Attribute::new(
|
|
|
|
Attributes::AdminFabricIndex as u16,
|
|
|
|
AttrValue::Custom,
|
|
|
|
Access::RV,
|
|
|
|
Quality::NULLABLE,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn attr_admin_vid_new() -> Result<Attribute, Error> {
|
|
|
|
Attribute::new(
|
|
|
|
Attributes::AdminVendorId as u16,
|
|
|
|
AttrValue::Custom,
|
|
|
|
Access::RV,
|
|
|
|
Quality::NULLABLE,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct AdminCommCluster {
|
2023-01-10 18:40:52 +05:30
|
|
|
pase_mgr: PaseMgr,
|
2023-01-07 21:47:33 +05:30
|
|
|
base: Cluster,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ClusterType for AdminCommCluster {
|
|
|
|
fn base(&self) -> &Cluster {
|
|
|
|
&self.base
|
|
|
|
}
|
|
|
|
fn base_mut(&mut self) -> &mut Cluster {
|
|
|
|
&mut self.base
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_custom_attribute(&self, encoder: &mut dyn Encoder, attr: &AttrDetails) {
|
|
|
|
match num::FromPrimitive::from_u16(attr.attr_id) {
|
|
|
|
Some(Attributes::WindowStatus) => {
|
2023-01-10 18:40:52 +05:30
|
|
|
let status = 1_u8;
|
2023-01-07 21:47:33 +05:30
|
|
|
encoder.encode(EncodeValue::Value(&status))
|
|
|
|
}
|
|
|
|
Some(Attributes::AdminVendorId) => {
|
2023-01-10 18:40:52 +05:30
|
|
|
let vid = Nullable::NotNull(1_u8);
|
|
|
|
|
2023-01-07 21:47:33 +05:30
|
|
|
encoder.encode(EncodeValue::Value(&vid))
|
|
|
|
}
|
|
|
|
Some(Attributes::AdminFabricIndex) => {
|
2023-01-10 18:40:52 +05:30
|
|
|
let vid = Nullable::NotNull(1_u8);
|
2023-01-07 21:47:33 +05:30
|
|
|
encoder.encode(EncodeValue::Value(&vid))
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
error!("Unsupported Attribute: this shouldn't happen");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn handle_command(&mut self, cmd_req: &mut CommandReq) -> Result<(), IMStatusCode> {
|
|
|
|
let cmd = cmd_req
|
|
|
|
.cmd
|
|
|
|
.path
|
|
|
|
.leaf
|
|
|
|
.map(num::FromPrimitive::from_u32)
|
|
|
|
.ok_or(IMStatusCode::UnsupportedCommand)?
|
|
|
|
.ok_or(IMStatusCode::UnsupportedCommand)?;
|
|
|
|
match cmd {
|
|
|
|
Commands::OpenCommWindow => self.handle_command_opencomm_win(cmd_req),
|
|
|
|
_ => Err(IMStatusCode::UnsupportedCommand),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl AdminCommCluster {
|
2023-01-10 18:40:52 +05:30
|
|
|
pub fn new(pase_mgr: PaseMgr) -> Result<Box<Self>, Error> {
|
2023-01-07 21:47:33 +05:30
|
|
|
let mut c = Box::new(AdminCommCluster {
|
2023-01-10 18:40:52 +05:30
|
|
|
pase_mgr,
|
2023-01-07 21:47:33 +05:30
|
|
|
base: Cluster::new(ID)?,
|
|
|
|
});
|
|
|
|
c.base.add_attribute(attr_window_status_new()?)?;
|
|
|
|
c.base.add_attribute(attr_admin_fabid_new()?)?;
|
|
|
|
c.base.add_attribute(attr_admin_vid_new()?)?;
|
|
|
|
Ok(c)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn handle_command_opencomm_win(
|
|
|
|
&mut self,
|
|
|
|
cmd_req: &mut CommandReq,
|
|
|
|
) -> Result<(), IMStatusCode> {
|
|
|
|
cmd_enter!("Open Commissioning Window");
|
2023-01-10 18:40:52 +05:30
|
|
|
let req =
|
2023-01-07 21:47:33 +05:30
|
|
|
OpenCommWindowReq::from_tlv(&cmd_req.data).map_err(|_| IMStatusCode::InvalidCommand)?;
|
2023-01-10 18:40:52 +05:30
|
|
|
let verifier = VerifierData::new(req.verifier.0, req.iterations, req.salt.0);
|
|
|
|
self.pase_mgr
|
|
|
|
.enable_pase_session(verifier, req.discriminator)?;
|
2023-01-07 21:47:33 +05:30
|
|
|
Err(IMStatusCode::Sucess)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(FromTLV)]
|
|
|
|
#[tlvargs(lifetime = "'a")]
|
|
|
|
pub struct OpenCommWindowReq<'a> {
|
|
|
|
_timeout: u16,
|
2023-01-10 18:40:52 +05:30
|
|
|
verifier: OctetStr<'a>,
|
|
|
|
discriminator: u16,
|
|
|
|
iterations: u32,
|
|
|
|
salt: OctetStr<'a>,
|
2023-01-07 21:47:33 +05:30
|
|
|
}
|