noc: Support UpdateFabricLabel command

This commit is contained in:
Kedar Sovani 2023-01-11 13:34:59 +05:30
parent 40b6b0c505
commit e6238ee2e6
3 changed files with 108 additions and 23 deletions

View file

@ -27,7 +27,7 @@ use crate::fabric::{Fabric, FabricMgr};
use crate::interaction_model::command::CommandReq; use crate::interaction_model::command::CommandReq;
use crate::interaction_model::core::IMStatusCode; use crate::interaction_model::core::IMStatusCode;
use crate::interaction_model::messages::ib; use crate::interaction_model::messages::ib;
use crate::tlv::{FromTLV, OctetStr, TLVElement, TLVWriter, TagType, ToTLV}; use crate::tlv::{FromTLV, OctetStr, TLVElement, TLVWriter, TagType, ToTLV, UtfStr};
use crate::transport::session::SessionMode; use crate::transport::session::SessionMode;
use crate::utils::writebuf::WriteBuf; use crate::utils::writebuf::WriteBuf;
use crate::{cmd_enter, error::*}; use crate::{cmd_enter, error::*};
@ -75,6 +75,8 @@ pub enum Commands {
CSRResp = 0x05, CSRResp = 0x05,
AddNOC = 0x06, AddNOC = 0x06,
NOCResp = 0x08, NOCResp = 0x08,
UpdateFabricLabel = 0x09,
RemoveFabric = 0x0a,
AddTrustedRootCert = 0x0b, AddTrustedRootCert = 0x0b,
} }
@ -183,19 +185,55 @@ impl NocCluster {
if self.failsafe.record_add_noc(fab_idx).is_err() { if self.failsafe.record_add_noc(fab_idx).is_err() {
error!("Failed to record NoC in the FailSafe, what to do?"); error!("Failed to record NoC in the FailSafe, what to do?");
} }
NocCluster::create_nocresponse(cmd_req.resp, NocStatus::Ok, fab_idx, "".to_owned());
cmd_req.trans.complete();
Ok(())
}
fn create_nocresponse(
tw: &mut TLVWriter,
status_code: NocStatus,
fab_idx: u8,
debug_txt: String,
) {
let cmd_data = NocResp { let cmd_data = NocResp {
status_code: NocStatus::Ok as u8, status_code: status_code as u8,
fab_idx, fab_idx,
debug_txt: "".to_owned(), debug_txt,
}; };
let resp = ib::InvResp::cmd_new( let invoke_resp = ib::InvResp::cmd_new(
0, 0,
ID, ID,
Commands::NOCResp as u16, Commands::NOCResp as u16,
EncodeValue::Value(&cmd_data), EncodeValue::Value(&cmd_data),
); );
let _ = resp.to_tlv(cmd_req.resp, TagType::Anonymous); let _ = invoke_resp.to_tlv(tw, TagType::Anonymous);
}
fn handle_command_updatefablabel(
&mut self,
cmd_req: &mut CommandReq,
) -> Result<(), IMStatusCode> {
cmd_enter!("Update Fabric Label");
let req = UpdateFabricLabelReq::from_tlv(&cmd_req.data)
.map_err(|_| IMStatusCode::InvalidDataType)?;
let label = req
.label
.to_string()
.map_err(|_| IMStatusCode::InvalidDataType)?;
let (result, fab_idx) =
if let SessionMode::Case(fab_idx) = cmd_req.trans.session.get_session_mode() {
if self.fabric_mgr.set_label(fab_idx, label).is_err() {
(NocStatus::LabelConflict, fab_idx)
} else {
(NocStatus::Ok, fab_idx)
}
} else {
// Update Fabric Label not allowed
(NocStatus::InvalidFabricIndex, 0)
};
NocCluster::create_nocresponse(cmd_req.resp, result, fab_idx, "".to_string());
cmd_req.trans.complete(); cmd_req.trans.complete();
Ok(()) Ok(())
} }
@ -203,18 +241,8 @@ impl NocCluster {
fn handle_command_addnoc(&mut self, cmd_req: &mut CommandReq) -> Result<(), IMStatusCode> { fn handle_command_addnoc(&mut self, cmd_req: &mut CommandReq) -> Result<(), IMStatusCode> {
cmd_enter!("AddNOC"); cmd_enter!("AddNOC");
if let Err(e) = self._handle_command_addnoc(cmd_req) { if let Err(e) = self._handle_command_addnoc(cmd_req) {
let cmd_data = NocResp { //TODO: Fab-idx 0?
status_code: e as u8, NocCluster::create_nocresponse(cmd_req.resp, e, 0, "".to_owned());
fab_idx: 0,
debug_txt: "".to_owned(),
};
let invoke_resp = ib::InvResp::cmd_new(
0,
ID,
Commands::NOCResp as u16,
EncodeValue::Value(&cmd_data),
);
let _ = invoke_resp.to_tlv(cmd_req.resp, TagType::Anonymous);
cmd_req.trans.complete(); cmd_req.trans.complete();
} }
Ok(()) Ok(())
@ -401,6 +429,7 @@ impl ClusterType for NocCluster {
Commands::AddTrustedRootCert => self.handle_command_addtrustedrootcert(cmd_req), Commands::AddTrustedRootCert => self.handle_command_addtrustedrootcert(cmd_req),
Commands::AttReq => self.handle_command_attrequest(cmd_req), Commands::AttReq => self.handle_command_attrequest(cmd_req),
Commands::CertChainReq => self.handle_command_certchainrequest(cmd_req), Commands::CertChainReq => self.handle_command_certchainrequest(cmd_req),
Commands::UpdateFabricLabel => self.handle_command_updatefablabel(cmd_req),
_ => Err(IMStatusCode::UnsupportedCommand), _ => Err(IMStatusCode::UnsupportedCommand),
} }
} }
@ -515,6 +544,12 @@ struct CommonReq<'a> {
str: OctetStr<'a>, str: OctetStr<'a>,
} }
#[derive(FromTLV)]
#[tlvargs(lifetime = "'a")]
struct UpdateFabricLabelReq<'a> {
label: UtfStr<'a>,
}
#[derive(FromTLV)] #[derive(FromTLV)]
struct CertChainReq { struct CertChainReq {
cert_type: u8, cert_type: u8,

View file

@ -18,7 +18,7 @@
use std::sync::{Arc, Mutex, MutexGuard, RwLock}; use std::sync::{Arc, Mutex, MutexGuard, RwLock};
use byteorder::{BigEndian, ByteOrder, LittleEndian}; use byteorder::{BigEndian, ByteOrder, LittleEndian};
use log::info; use log::{error, info};
use owning_ref::RwLockReadGuardRef; use owning_ref::RwLockReadGuardRef;
use crate::{ use crate::{
@ -45,6 +45,7 @@ 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";
const ST_IPK: &str = "ipk"; const ST_IPK: &str = "ipk";
const ST_LBL: &str = "label";
const ST_PBKEY: &str = "pubkey"; const ST_PBKEY: &str = "pubkey";
const ST_PRKEY: &str = "privkey"; const ST_PRKEY: &str = "privkey";
@ -58,6 +59,7 @@ pub struct Fabric {
pub icac: Option<Cert>, pub icac: Option<Cert>,
pub noc: Cert, pub noc: Cert,
pub ipk: KeySet, pub ipk: KeySet,
label: String,
compressed_id: [u8; COMPRESSED_FABRIC_ID_LEN], compressed_id: [u8; COMPRESSED_FABRIC_ID_LEN],
mdns_service: Option<SysMdnsService>, mdns_service: Option<SysMdnsService>,
} }
@ -97,6 +99,7 @@ impl Fabric {
noc, noc,
ipk: KeySet::default(), ipk: KeySet::default(),
compressed_id: [0; COMPRESSED_FABRIC_ID_LEN], compressed_id: [0; COMPRESSED_FABRIC_ID_LEN],
label: "".into(),
mdns_service: None, mdns_service: None,
}; };
Fabric::get_compressed_id(f.root_ca.get_pubkey(), fabric_id, &mut f.compressed_id)?; Fabric::get_compressed_id(f.root_ca.get_pubkey(), fabric_id, &mut f.compressed_id)?;
@ -129,6 +132,7 @@ impl Fabric {
icac: Some(Cert::default()), icac: Some(Cert::default()),
noc: Cert::default(), noc: Cert::default(),
ipk: KeySet::default(), ipk: KeySet::default(),
label: "".into(),
compressed_id: [0; COMPRESSED_FABRIC_ID_LEN], compressed_id: [0; COMPRESSED_FABRIC_ID_LEN],
mdns_service: None, mdns_service: None,
}) })
@ -186,7 +190,7 @@ impl Fabric {
vendor_id: self.vendor_id, vendor_id: self.vendor_id,
fabric_id: self.fabric_id, fabric_id: self.fabric_id,
node_id: self.node_id, node_id: self.node_id,
label: UtfStr::new(b""), label: UtfStr(self.label.as_bytes()),
fab_idx: Some(fab_idx), fab_idx: Some(fab_idx),
} }
} }
@ -206,6 +210,7 @@ impl Fabric {
let len = self.noc.as_tlv(&mut key)?; let len = self.noc.as_tlv(&mut key)?;
psm.set_kv_slice(fb_key!(index, ST_NOC), &key[..len])?; psm.set_kv_slice(fb_key!(index, ST_NOC), &key[..len])?;
psm.set_kv_slice(fb_key!(index, ST_IPK), self.ipk.epoch_key())?; psm.set_kv_slice(fb_key!(index, ST_IPK), self.ipk.epoch_key())?;
psm.set_kv_slice(fb_key!(index, ST_LBL), self.label.as_bytes())?;
let mut key = [0_u8; crypto::EC_POINT_LEN_BYTES]; let mut key = [0_u8; crypto::EC_POINT_LEN_BYTES];
let len = self.key_pair.get_public_key(&mut key)?; let len = self.key_pair.get_public_key(&mut key)?;
@ -217,7 +222,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())?; psm.set_kv_u64(fb_key!(index, ST_VID), self.vendor_id.into())?;
Ok(()) Ok(())
} }
@ -241,6 +246,13 @@ impl Fabric {
let mut ipk = Vec::new(); let mut ipk = Vec::new();
psm.get_kv_slice(fb_key!(index, ST_IPK), &mut ipk)?; psm.get_kv_slice(fb_key!(index, ST_IPK), &mut ipk)?;
let mut label = Vec::new();
psm.get_kv_slice(fb_key!(index, ST_LBL), &mut label)?;
let label = String::from_utf8(label).map_err(|_| {
error!("Couldn't read label");
Error::Invalid
})?;
let mut pub_key = Vec::new(); let mut pub_key = Vec::new();
psm.get_kv_slice(fb_key!(index, ST_PBKEY), &mut pub_key)?; psm.get_kv_slice(fb_key!(index, ST_PBKEY), &mut pub_key)?;
let mut priv_key = Vec::new(); let mut priv_key = Vec::new();
@ -248,16 +260,20 @@ impl Fabric {
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())?;
let mut vendor_id = 0; let mut vendor_id = 0;
psm.get_kv_u64(ST_VID, &mut vendor_id)?; psm.get_kv_u64(fb_key!(index, ST_VID), &mut vendor_id)?;
Fabric::new( let f = Fabric::new(
keypair, keypair,
root_ca, root_ca,
icac, icac,
noc, noc,
ipk.as_slice(), ipk.as_slice(),
vendor_id as u16, vendor_id as u16,
) );
f.map(|mut f| {
f.label = label;
f
})
} }
} }
@ -361,4 +377,28 @@ impl FabricMgr {
} }
Ok(()) Ok(())
} }
pub fn set_label(&self, index: u8, label: String) -> Result<(), Error> {
let index = index as usize;
let mut mgr = self.inner.write()?;
if label != "" {
for i in 1..MAX_SUPPORTED_FABRICS {
if let Some(fabric) = &mgr.fabrics[i] {
if fabric.label == label {
return Err(Error::Invalid);
}
}
}
}
if let Some(fabric) = &mut mgr.fabrics[index] {
let old = fabric.label.clone();
fabric.label = label;
let psm = self.psm.lock().unwrap();
if fabric.store(index, &psm).is_err() {
fabric.label = old;
return Err(Error::StdIoError);
}
}
Ok(())
}
} }

View file

@ -119,6 +119,10 @@ impl<'a> UtfStr<'a> {
pub fn new(str: &'a [u8]) -> Self { pub fn new(str: &'a [u8]) -> Self {
Self(str) Self(str)
} }
pub fn to_string(self) -> Result<String, Error> {
String::from_utf8(self.0.to_vec()).map_err(|_| Error::Invalid)
}
} }
impl<'a> ToTLV for UtfStr<'a> { impl<'a> ToTLV for UtfStr<'a> {
@ -127,6 +131,12 @@ impl<'a> ToTLV for UtfStr<'a> {
} }
} }
impl<'a> FromTLV<'a> for UtfStr<'a> {
fn from_tlv(t: &TLVElement<'a>) -> Result<UtfStr<'a>, Error> {
t.slice().map(UtfStr)
}
}
/// Implements OctetString from the spec /// Implements OctetString from the spec
#[derive(Debug, Copy, Clone, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
pub struct OctetStr<'a>(pub &'a [u8]); pub struct OctetStr<'a>(pub &'a [u8]);