Optional feature to capture stacktrace on error

This commit is contained in:
imarkov 2023-04-29 19:38:01 +03:00 committed by ivmarkov
parent 0677a5938a
commit 2a2bdab9c5
58 changed files with 531 additions and 384 deletions

View file

@ -16,7 +16,7 @@
*/ */
use matter::data_model::sdm::dev_att::{DataType, DevAttDataFetcher}; use matter::data_model::sdm::dev_att::{DataType, DevAttDataFetcher};
use matter::error::Error; use matter::error::{Error, ErrorCode};
pub struct HardCodedDevAtt {} pub struct HardCodedDevAtt {}
@ -159,7 +159,7 @@ impl DevAttDataFetcher for HardCodedDevAtt {
data.copy_from_slice(src); data.copy_from_slice(src);
Ok(src.len()) Ok(src.len())
} else { } else {
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
} }
} }

View file

@ -16,7 +16,9 @@
*/ */
use std::borrow::Borrow; use std::borrow::Borrow;
use std::error::Error;
use log::info;
use matter::core::{CommissioningData, Matter}; use matter::core::{CommissioningData, Matter};
use matter::data_model::cluster_basic_information::BasicInfoConfig; use matter::data_model::cluster_basic_information::BasicInfoConfig;
use matter::data_model::cluster_on_off; use matter::data_model::cluster_on_off;
@ -36,8 +38,10 @@ use matter::transport::{
mod dev_att; mod dev_att;
fn main() { fn main() -> Result<(), impl Error> {
env_logger::init(); env_logger::init_from_env(
env_logger::Env::default().filter_or(env_logger::DEFAULT_FILTER_ENV, "info"),
);
// vid/pid should match those in the DAC // vid/pid should match those in the DAC
let dev_info = BasicInfoConfig { let dev_info = BasicInfoConfig {
@ -50,35 +54,37 @@ fn main() {
device_name: "OnOff Light", device_name: "OnOff Light",
}; };
//let mut mdns = matter::mdns::astro::AstroMdns::new().unwrap(); let mut mdns = matter::mdns::astro::AstroMdns::new()?;
let mut mdns = matter::mdns::libmdns::LibMdns::new().unwrap(); //let mut mdns = matter::mdns::libmdns::LibMdns::new()?;
//let mut mdns = matter::mdns::DummyMdns {};
let matter = Matter::new_default(&dev_info, &mut mdns, matter::transport::udp::MATTER_PORT); let matter = Matter::new_default(&dev_info, &mut mdns, matter::transport::udp::MATTER_PORT);
let dev_att = dev_att::HardCodedDevAtt::new(); let dev_att = dev_att::HardCodedDevAtt::new();
let psm = persist::FilePsm::new(std::env::temp_dir().join("matter-iot")).unwrap(); let psm_path = std::env::temp_dir().join("matter-iot");
info!("Persisting from/to {}", psm_path.display());
let psm = persist::FilePsm::new(psm_path)?;
let mut buf = [0; 4096]; let mut buf = [0; 4096];
if let Some(data) = psm.load("fabrics", &mut buf).unwrap() { if let Some(data) = psm.load("acls", &mut buf)? {
matter.load_fabrics(data).unwrap(); matter.load_acls(data)?;
} }
if let Some(data) = psm.load("acls", &mut buf).unwrap() { if let Some(data) = psm.load("fabrics", &mut buf)? {
matter.load_acls(data).unwrap(); matter.load_fabrics(data)?;
} }
matter matter.start::<4096>(
.start::<4096>( CommissioningData {
CommissioningData { // TODO: Hard-coded for now
// TODO: Hard-coded for now verifier: VerifierData::new_with_pw(123456, *matter.borrow()),
verifier: VerifierData::new_with_pw(123456, *matter.borrow()), discriminator: 250,
discriminator: 250, },
}, &mut buf,
&mut buf, )?;
)
.unwrap();
let matter = &matter; let matter = &matter;
let dev_att = &dev_att; let dev_att = &dev_att;
@ -86,20 +92,20 @@ fn main() {
let mut transport = TransportMgr::new(matter); let mut transport = TransportMgr::new(matter);
smol::block_on(async move { smol::block_on(async move {
let udp = UdpListener::new().await.unwrap(); let udp = UdpListener::new().await?;
loop { loop {
let mut rx_buf = [0; MAX_RX_BUF_SIZE]; let mut rx_buf = [0; MAX_RX_BUF_SIZE];
let mut tx_buf = [0; MAX_TX_BUF_SIZE]; let mut tx_buf = [0; MAX_TX_BUF_SIZE];
let (len, addr) = udp.recv(&mut rx_buf).await.unwrap(); let (len, addr) = udp.recv(&mut rx_buf).await?;
let mut completion = transport.recv(addr, &mut rx_buf[..len], &mut tx_buf); let mut completion = transport.recv(addr, &mut rx_buf[..len], &mut tx_buf);
while let Some(action) = completion.next_action().unwrap() { while let Some(action) = completion.next_action()? {
match action { match action {
RecvAction::Send(addr, buf) => { RecvAction::Send(addr, buf) => {
udp.send(addr, buf).await.unwrap(); udp.send(addr, buf).await?;
} }
RecvAction::Interact(mut ctx) => { RecvAction::Interact(mut ctx) => {
let node = Node { let node = Node {
@ -119,24 +125,29 @@ fn main() {
let mut im = let mut im =
InteractionModel(DataModel::new(matter.borrow(), &node, &mut handler)); InteractionModel(DataModel::new(matter.borrow(), &node, &mut handler));
if im.handle(&mut ctx).unwrap() { if im.handle(&mut ctx)? {
if ctx.send().unwrap() { if ctx.send()? {
udp.send(ctx.tx.peer, ctx.tx.as_slice()).await.unwrap(); udp.send(ctx.tx.peer, ctx.tx.as_slice()).await?;
} }
} }
} }
} }
} }
if let Some(data) = matter.store_fabrics(&mut buf).unwrap() { if let Some(data) = matter.store_fabrics(&mut buf)? {
psm.store("fabrics", data).unwrap(); psm.store("fabrics", data)?;
} }
if let Some(data) = matter.store_acls(&mut buf).unwrap() { if let Some(data) = matter.store_acls(&mut buf)? {
psm.store("acls", data).unwrap(); psm.store("acls", data)?;
} }
} }
});
#[allow(unreachable_code)]
Ok::<_, matter::error::Error>(())
})?;
Ok::<_, matter::error::Error>(())
} }
fn handler<'a>(matter: &'a Matter<'a>, dev_att: &'a dyn DevAttDataFetcher) -> impl Handler + 'a { fn handler<'a>(matter: &'a Matter<'a>, dev_att: &'a dyn DevAttDataFetcher) -> impl Handler + 'a {

View file

@ -159,7 +159,7 @@ impl DevAttDataFetcher for HardCodedDevAtt {
data.copy_from_slice(src); data.copy_from_slice(src);
Ok(src.len()) Ok(src.len())
} else { } else {
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
} }
} }

View file

@ -15,8 +15,9 @@ name = "matter"
path = "src/lib.rs" path = "src/lib.rs"
[features] [features]
default = ["std", "crypto_mbedtls"] default = ["std", "crypto_mbedtls", "backtrace"]
std = ["alloc", "env_logger", "chrono", "rand", "qrcode", "libmdns", "simple-mdns", "simple-dns", "smol"] std = ["alloc", "env_logger", "chrono", "rand", "qrcode", "libmdns", "simple-mdns", "simple-dns", "smol"]
backtrace = []
alloc = [] alloc = []
nightly = [] nightly = []
crypto_openssl = ["openssl", "foreign-types", "hmac", "sha2"] crypto_openssl = ["openssl", "foreign-types", "hmac", "sha2"]
@ -32,7 +33,7 @@ heapless = "0.7.16"
num = "0.4" num = "0.4"
num-derive = "0.3.3" num-derive = "0.3.3"
num-traits = "0.2.15" num-traits = "0.2.15"
strum = { version = "0.24", features = ["derive"], default-features = false, no-default-feature = true } strum = { version = "0.24", features = ["derive"], default-features = false }
log = { version = "0.4.17", features = ["max_level_debug", "release_max_level_debug"] } log = { version = "0.4.17", features = ["max_level_debug", "release_max_level_debug"] }
no-std-net = "0.6" no-std-net = "0.6"
subtle = "2.4.1" subtle = "2.4.1"

View file

@ -19,7 +19,7 @@ use core::{cell::RefCell, fmt::Display};
use crate::{ use crate::{
data_model::objects::{Access, ClusterId, EndptId, Privilege}, data_model::objects::{Access, ClusterId, EndptId, Privilege},
error::Error, error::{Error, ErrorCode},
fabric, fabric,
interaction_model::messages::GenericPath, interaction_model::messages::GenericPath,
tlv::{FromTLV, TLVElement, TLVList, TLVWriter, TagType, ToTLV}, tlv::{FromTLV, TLVElement, TLVList, TLVWriter, TagType, ToTLV},
@ -50,7 +50,7 @@ impl FromTLV<'_> for AuthMode {
{ {
num::FromPrimitive::from_u32(t.u32()?) num::FromPrimitive::from_u32(t.u32()?)
.filter(|a| *a != AuthMode::Invalid) .filter(|a| *a != AuthMode::Invalid)
.ok_or(Error::Invalid) .ok_or_else(|| ErrorCode::Invalid.into())
} }
} }
@ -112,7 +112,7 @@ impl AccessorSubjects {
return Ok(()); return Ok(());
} }
} }
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
/// Match the match_subject with any of the current subjects /// Match the match_subject with any of the current subjects
@ -314,7 +314,7 @@ impl AclEntry {
.subjects .subjects
.iter() .iter()
.position(|s| s.is_none()) .position(|s| s.is_none())
.ok_or(Error::NoSpace)?; .ok_or(ErrorCode::NoSpace)?;
self.subjects[index] = Some(subject); self.subjects[index] = Some(subject);
Ok(()) Ok(())
} }
@ -328,7 +328,7 @@ impl AclEntry {
.targets .targets
.iter() .iter()
.position(|s| s.is_none()) .position(|s| s.is_none())
.ok_or(Error::NoSpace)?; .ok_or(ErrorCode::NoSpace)?;
self.targets[index] = Some(target); self.targets[index] = Some(target);
Ok(()) Ok(())
} }
@ -425,13 +425,13 @@ impl AclMgr {
.filter(|a| a.fab_idx == entry.fab_idx) .filter(|a| a.fab_idx == entry.fab_idx)
.count(); .count();
if cnt >= ENTRIES_PER_FABRIC { if cnt >= ENTRIES_PER_FABRIC {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
let index = self let index = self
.entries .entries
.iter() .iter()
.position(|a| a.is_none()) .position(|a| a.is_none())
.ok_or(Error::NoSpace)?; .ok_or(ErrorCode::NoSpace)?;
self.entries[index] = Some(entry); self.entries[index] = Some(entry);
self.changed = true; self.changed = true;
@ -503,7 +503,7 @@ impl AclMgr {
} }
pub fn load(&mut self, data: &[u8]) -> Result<(), Error> { pub fn load(&mut self, data: &[u8]) -> Result<(), Error> {
let root = TLVList::new(data).iter().next().ok_or(Error::Invalid)?; let root = TLVList::new(data).iter().next().ok_or(ErrorCode::Invalid)?;
self.entries = AclEntries::from_tlv(&root)?; self.entries = AclEntries::from_tlv(&root)?;
self.changed = false; self.changed = false;
@ -547,7 +547,7 @@ impl AclMgr {
return Ok(entry); return Ok(entry);
} }
} }
Err(Error::NotFound) Err(ErrorCode::NotFound.into())
} }
} }

View file

@ -17,7 +17,7 @@
use super::{CertConsumer, MAX_DEPTH}; use super::{CertConsumer, MAX_DEPTH};
use crate::{ use crate::{
error::Error, error::{Error, ErrorCode},
utils::epoch::{UtcCalendar, MATTER_EPOCH_SECS}, utils::epoch::{UtcCalendar, MATTER_EPOCH_SECS},
}; };
use core::{fmt::Write, time::Duration}; use core::{fmt::Write, time::Duration};
@ -54,7 +54,7 @@ impl<'a> ASN1Writer<'a> {
self.offset += size; self.offset += size;
return Ok(()); return Ok(());
} }
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
pub fn append_tlv<F>(&mut self, tag: u8, len: usize, f: F) -> Result<(), Error> pub fn append_tlv<F>(&mut self, tag: u8, len: usize, f: F) -> Result<(), Error>
@ -70,7 +70,7 @@ impl<'a> ASN1Writer<'a> {
self.offset += len; self.offset += len;
return Ok(()); return Ok(());
} }
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
fn add_compound(&mut self, val: u8) -> Result<(), Error> { fn add_compound(&mut self, val: u8) -> Result<(), Error> {
@ -80,7 +80,7 @@ impl<'a> ASN1Writer<'a> {
self.depth[self.current_depth] = self.offset; self.depth[self.current_depth] = self.offset;
self.current_depth += 1; self.current_depth += 1;
if self.current_depth >= MAX_DEPTH { if self.current_depth >= MAX_DEPTH {
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} else { } else {
Ok(()) Ok(())
} }
@ -113,7 +113,7 @@ impl<'a> ASN1Writer<'a> {
fn end_compound(&mut self) -> Result<(), Error> { fn end_compound(&mut self) -> Result<(), Error> {
if self.current_depth == 0 { if self.current_depth == 0 {
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
let seq_len = self.get_compound_len(); let seq_len = self.get_compound_len();
let write_offset = self.get_length_encoding_offset(); let write_offset = self.get_length_encoding_offset();
@ -148,7 +148,7 @@ impl<'a> ASN1Writer<'a> {
// This is done with an 0xA2 followed by 2 bytes of actual len // This is done with an 0xA2 followed by 2 bytes of actual len
3 3
} else { } else {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?
}; };
Ok(len) Ok(len)
} }

View file

@ -19,7 +19,7 @@ use core::fmt::{self, Write};
use crate::{ use crate::{
crypto::KeyPair, crypto::KeyPair,
error::Error, error::{Error, ErrorCode},
tlv::{self, FromTLV, OctetStr, TLVArray, TLVElement, TLVWriter, TagType, ToTLV}, tlv::{self, FromTLV, OctetStr, TLVArray, TLVElement, TLVWriter, TagType, ToTLV},
utils::{epoch::UtcCalendar, writebuf::WriteBuf}, utils::{epoch::UtcCalendar, writebuf::WriteBuf},
}; };
@ -349,22 +349,22 @@ impl<'a> FromTLV<'a> for DistNames<'a> {
let mut d = Self { let mut d = Self {
dn: heapless::Vec::new(), dn: heapless::Vec::new(),
}; };
let iter = t.confirm_list()?.enter().ok_or(Error::Invalid)?; let iter = t.confirm_list()?.enter().ok_or(ErrorCode::Invalid)?;
for t in iter { for t in iter {
if let TagType::Context(tag) = t.get_tag() { if let TagType::Context(tag) = t.get_tag() {
if let Ok(value) = t.u64() { if let Ok(value) = t.u64() {
d.dn.push((tag, DistNameValue::Uint(value))) d.dn.push((tag, DistNameValue::Uint(value)))
.map_err(|_| Error::BufferTooSmall)?; .map_err(|_| ErrorCode::BufferTooSmall)?;
} else if let Ok(value) = t.slice() { } else if let Ok(value) = t.slice() {
if tag > PRINTABLE_STR_THRESHOLD { if tag > PRINTABLE_STR_THRESHOLD {
d.dn.push(( d.dn.push((
tag - PRINTABLE_STR_THRESHOLD, tag - PRINTABLE_STR_THRESHOLD,
DistNameValue::PrintableStr(value), DistNameValue::PrintableStr(value),
)) ))
.map_err(|_| Error::BufferTooSmall)?; .map_err(|_| ErrorCode::BufferTooSmall)?;
} else { } else {
d.dn.push((tag, DistNameValue::Utf8Str(value))) d.dn.push((tag, DistNameValue::Utf8Str(value)))
.map_err(|_| Error::BufferTooSmall)?; .map_err(|_| ErrorCode::BufferTooSmall)?;
} }
} }
} }
@ -531,7 +531,7 @@ fn encode_dn_value(
} }
_ => { _ => {
error!("Invalid encoding"); error!("Invalid encoding");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?
} }
}, },
DistNameValue::Utf8Str(v) => { DistNameValue::Utf8Str(v) => {
@ -570,7 +570,9 @@ impl<'a> Cert<'a> {
} }
pub fn get_node_id(&self) -> Result<u64, Error> { pub fn get_node_id(&self) -> Result<u64, Error> {
self.subject.u64(DnTags::NodeId).ok_or(Error::NoNodeId) self.subject
.u64(DnTags::NodeId)
.ok_or_else(|| Error::from(ErrorCode::NoNodeId))
} }
pub fn get_cat_ids(&self, output: &mut [u32]) { pub fn get_cat_ids(&self, output: &mut [u32]) {
@ -578,7 +580,9 @@ impl<'a> Cert<'a> {
} }
pub fn get_fabric_id(&self) -> Result<u64, Error> { pub fn get_fabric_id(&self) -> Result<u64, Error> {
self.subject.u64(DnTags::FabricId).ok_or(Error::NoFabricId) self.subject
.u64(DnTags::FabricId)
.ok_or_else(|| Error::from(ErrorCode::NoFabricId))
} }
pub fn get_pubkey(&self) -> &[u8] { pub fn get_pubkey(&self) -> &[u8] {
@ -589,7 +593,7 @@ impl<'a> Cert<'a> {
if let Some(id) = self.extensions.subj_key_id.as_ref() { if let Some(id) = self.extensions.subj_key_id.as_ref() {
Ok(id.0) Ok(id.0)
} else { } else {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }
@ -641,7 +645,7 @@ impl<'a> Cert<'a> {
w.integer("Serial Num:", self.serial_no.0)?; w.integer("Serial Num:", self.serial_no.0)?;
w.start_seq("Signature Algorithm:")?; w.start_seq("Signature Algorithm:")?;
let (str, oid) = match get_sign_algo(self.sign_algo).ok_or(Error::Invalid)? { let (str, oid) = match get_sign_algo(self.sign_algo).ok_or(ErrorCode::Invalid)? {
SignAlgoValue::ECDSAWithSHA256 => ("ECDSA with SHA256", OID_ECDSA_WITH_SHA256), SignAlgoValue::ECDSAWithSHA256 => ("ECDSA with SHA256", OID_ECDSA_WITH_SHA256),
}; };
w.oid(str, &oid)?; w.oid(str, &oid)?;
@ -660,11 +664,11 @@ impl<'a> Cert<'a> {
w.start_seq("")?; w.start_seq("")?;
w.start_seq("Public Key Algorithm")?; w.start_seq("Public Key Algorithm")?;
let (str, pub_key) = match get_pubkey_algo(self.pubkey_algo).ok_or(Error::Invalid)? { let (str, pub_key) = match get_pubkey_algo(self.pubkey_algo).ok_or(ErrorCode::Invalid)? {
PubKeyAlgoValue::EcPubKey => ("ECPubKey", OID_PUB_KEY_ECPUBKEY), PubKeyAlgoValue::EcPubKey => ("ECPubKey", OID_PUB_KEY_ECPUBKEY),
}; };
w.oid(str, &pub_key)?; w.oid(str, &pub_key)?;
let (str, curve_id) = match get_ec_curve_id(self.ec_curve_id).ok_or(Error::Invalid)? { let (str, curve_id) = match get_ec_curve_id(self.ec_curve_id).ok_or(ErrorCode::Invalid)? {
EcCurveIdValue::Prime256V1 => ("Prime256v1", OID_EC_TYPE_PRIME256V1), EcCurveIdValue::Prime256V1 => ("Prime256v1", OID_EC_TYPE_PRIME256V1),
}; };
w.oid(str, &curve_id)?; w.oid(str, &curve_id)?;
@ -704,7 +708,7 @@ impl<'a> CertVerifier<'a> {
pub fn add_cert(self, parent: &'a Cert) -> Result<CertVerifier<'a>, Error> { pub fn add_cert(self, parent: &'a Cert) -> Result<CertVerifier<'a>, Error> {
if !self.cert.is_authority(parent)? { if !self.cert.is_authority(parent)? {
return Err(Error::InvalidAuthKey); Err(ErrorCode::InvalidAuthKey)?;
} }
let mut asn1 = [0u8; MAX_ASN1_CERT_SIZE]; let mut asn1 = [0u8; MAX_ASN1_CERT_SIZE];
let len = self.cert.as_asn1(&mut asn1, self.utc_calendar)?; let len = self.cert.as_asn1(&mut asn1, self.utc_calendar)?;
@ -761,7 +765,6 @@ mod tests {
use log::info; use log::info;
use crate::cert::Cert; use crate::cert::Cert;
use crate::error::Error;
use crate::tlv::{self, FromTLV, TLVWriter, TagType, ToTLV}; use crate::tlv::{self, FromTLV, TLVWriter, TagType, ToTLV};
use crate::utils::writebuf::WriteBuf; use crate::utils::writebuf::WriteBuf;
@ -815,31 +818,43 @@ mod tests {
#[test] #[test]
fn test_verify_chain_incomplete() { fn test_verify_chain_incomplete() {
// The chain doesn't lead up to a self-signed certificate // The chain doesn't lead up to a self-signed certificate
use crate::error::ErrorCode;
let noc = Cert::new(&test_vectors::NOC1_SUCCESS).unwrap(); let noc = Cert::new(&test_vectors::NOC1_SUCCESS).unwrap();
let icac = Cert::new(&test_vectors::ICAC1_SUCCESS).unwrap(); let icac = Cert::new(&test_vectors::ICAC1_SUCCESS).unwrap();
let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar); let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar);
assert_eq!( assert_eq!(
Err(Error::InvalidAuthKey), Err(ErrorCode::InvalidAuthKey),
a.add_cert(&icac).unwrap().finalise() a.add_cert(&icac).unwrap().finalise().map_err(|e| e.code())
); );
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[test] #[test]
fn test_auth_key_chain_incorrect() { fn test_auth_key_chain_incorrect() {
use crate::error::ErrorCode;
let noc = Cert::new(&test_vectors::NOC1_AUTH_KEY_FAIL).unwrap(); let noc = Cert::new(&test_vectors::NOC1_AUTH_KEY_FAIL).unwrap();
let icac = Cert::new(&test_vectors::ICAC1_SUCCESS).unwrap(); let icac = Cert::new(&test_vectors::ICAC1_SUCCESS).unwrap();
let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar); let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar);
assert_eq!(Err(Error::InvalidAuthKey), a.add_cert(&icac).map(|_| ())); assert_eq!(
Err(ErrorCode::InvalidAuthKey),
a.add_cert(&icac).map(|_| ()).map_err(|e| e.code())
);
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
#[test] #[test]
fn test_cert_corrupted() { fn test_cert_corrupted() {
use crate::error::ErrorCode;
let noc = Cert::new(&test_vectors::NOC1_CORRUPT_CERT).unwrap(); let noc = Cert::new(&test_vectors::NOC1_CORRUPT_CERT).unwrap();
let icac = Cert::new(&test_vectors::ICAC1_SUCCESS).unwrap(); let icac = Cert::new(&test_vectors::ICAC1_SUCCESS).unwrap();
let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar); let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar);
assert_eq!(Err(Error::InvalidSignature), a.add_cert(&icac).map(|_| ())); assert_eq!(
Err(ErrorCode::InvalidSignature),
a.add_cert(&icac).map(|_| ()).map_err(|e| e.code())
);
} }
#[test] #[test]

View file

@ -17,7 +17,7 @@
//! Base38 encoding and decoding functions. //! Base38 encoding and decoding functions.
use crate::error::Error; use crate::error::{Error, ErrorCode};
const BASE38_CHARS: [char; 38] = [ const BASE38_CHARS: [char; 38] = [
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I',
@ -86,7 +86,7 @@ const RADIX: u32 = BASE38_CHARS.len() as u32;
pub fn encode_string<const N: usize>(bytes: &[u8]) -> Result<heapless::String<N>, Error> { pub fn encode_string<const N: usize>(bytes: &[u8]) -> Result<heapless::String<N>, Error> {
let mut string = heapless::String::new(); let mut string = heapless::String::new();
for c in encode(bytes) { for c in encode(bytes) {
string.push(c).map_err(|_| Error::NoSpace)?; string.push(c).map_err(|_| ErrorCode::NoSpace)?;
} }
Ok(string) Ok(string)
@ -135,7 +135,7 @@ pub fn decode_vec<const N: usize>(base38_str: &str) -> Result<heapless::Vec<u8,
let mut vec = heapless::Vec::new(); let mut vec = heapless::Vec::new();
for byte in decode(base38_str) { for byte in decode(base38_str) {
vec.push(byte?).map_err(|_| Error::NoSpace)?; vec.push(byte?).map_err(|_| ErrorCode::NoSpace)?;
} }
Ok(vec) Ok(vec)
@ -179,19 +179,19 @@ fn decode_base38(chars: &[u8]) -> impl Iterator<Item = Result<u8, Error>> {
match decode_char(*c) { match decode_char(*c) {
Ok(v) => value = value * RADIX + v as u32, Ok(v) => value = value * RADIX + v as u32,
Err(err) => { Err(err) => {
cerr = Some(err); cerr = Some(err.code());
break; break;
} }
} }
} }
} else { } else {
cerr = Some(Error::InvalidData) cerr = Some(ErrorCode::InvalidData)
} }
(0..repeat) (0..repeat)
.map(move |_| { .map(move |_| {
if let Some(err) = cerr { if let Some(err) = cerr {
Err(err) Err(err.into())
} else { } else {
let byte = (value & 0xff) as u8; let byte = (value & 0xff) as u8;
@ -205,12 +205,12 @@ fn decode_base38(chars: &[u8]) -> impl Iterator<Item = Result<u8, Error>> {
fn decode_char(c: u8) -> Result<u8, Error> { fn decode_char(c: u8) -> Result<u8, Error> {
if !(45..=90).contains(&c) { if !(45..=90).contains(&c) {
return Err(Error::InvalidData); Err(ErrorCode::InvalidData)?;
} }
let c = DECODE_BASE38[c as usize - 45]; let c = DECODE_BASE38[c as usize - 45];
if c == UNUSED { if c == UNUSED {
return Err(Error::InvalidData); Err(ErrorCode::InvalidData)?;
} }
Ok(c) Ok(c)

View file

@ -17,7 +17,7 @@
use log::error; use log::error;
use crate::error::Error; use crate::error::{Error, ErrorCode};
pub fn hkdf_sha256(_salt: &[u8], _ikm: &[u8], _info: &[u8], _key: &mut [u8]) -> Result<(), Error> { pub fn hkdf_sha256(_salt: &[u8], _ikm: &[u8], _info: &[u8], _key: &mut [u8]) -> Result<(), Error> {
error!("This API should never get called"); error!("This API should never get called");
@ -79,7 +79,7 @@ impl KeyPair {
pub fn get_csr<'a>(&self, _out_csr: &'a mut [u8]) -> Result<&'a [u8], Error> { pub fn get_csr<'a>(&self, _out_csr: &'a mut [u8]) -> Result<&'a [u8], Error> {
error!("This API should never get called"); error!("This API should never get called");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
pub fn get_public_key(&self, _pub_key: &mut [u8]) -> Result<usize, Error> { pub fn get_public_key(&self, _pub_key: &mut [u8]) -> Result<usize, Error> {
@ -92,17 +92,17 @@ impl KeyPair {
pub fn derive_secret(self, _peer_pub_key: &[u8], _secret: &mut [u8]) -> Result<usize, Error> { pub fn derive_secret(self, _peer_pub_key: &[u8], _secret: &mut [u8]) -> Result<usize, Error> {
error!("This API should never get called"); error!("This API should never get called");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
pub fn sign_msg(&self, _msg: &[u8], _signature: &mut [u8]) -> Result<usize, Error> { pub fn sign_msg(&self, _msg: &[u8], _signature: &mut [u8]) -> Result<usize, Error> {
error!("This API should never get called"); error!("This API should never get called");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
pub fn verify_msg(&self, _msg: &[u8], _signature: &[u8]) -> Result<(), Error> { pub fn verify_msg(&self, _msg: &[u8], _signature: &[u8]) -> Result<(), Error> {
error!("This API should never get called"); error!("This API should never get called");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }

View file

@ -17,7 +17,7 @@
use log::error; use log::error;
use crate::error::Error; use crate::error::{Error, ErrorCode};
pub fn hkdf_sha256(_salt: &[u8], _ikm: &[u8], _info: &[u8], _key: &mut [u8]) -> Result<(), Error> { pub fn hkdf_sha256(_salt: &[u8], _ikm: &[u8], _info: &[u8], _key: &mut [u8]) -> Result<(), Error> {
error!("This API should never get called"); error!("This API should never get called");
@ -81,7 +81,7 @@ impl KeyPair {
pub fn get_csr<'a>(&self, _out_csr: &'a mut [u8]) -> Result<&'a [u8], Error> { pub fn get_csr<'a>(&self, _out_csr: &'a mut [u8]) -> Result<&'a [u8], Error> {
error!("This API should never get called"); error!("This API should never get called");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
pub fn get_public_key(&self, _pub_key: &mut [u8]) -> Result<usize, Error> { pub fn get_public_key(&self, _pub_key: &mut [u8]) -> Result<usize, Error> {
@ -94,17 +94,17 @@ impl KeyPair {
pub fn derive_secret(self, _peer_pub_key: &[u8], _secret: &mut [u8]) -> Result<usize, Error> { pub fn derive_secret(self, _peer_pub_key: &[u8], _secret: &mut [u8]) -> Result<usize, Error> {
error!("This API should never get called"); error!("This API should never get called");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
pub fn sign_msg(&self, _msg: &[u8], _signature: &mut [u8]) -> Result<usize, Error> { pub fn sign_msg(&self, _msg: &[u8], _signature: &mut [u8]) -> Result<usize, Error> {
error!("This API should never get called"); error!("This API should never get called");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
pub fn verify_msg(&self, _msg: &[u8], _signature: &[u8]) -> Result<(), Error> { pub fn verify_msg(&self, _msg: &[u8], _signature: &[u8]) -> Result<(), Error> {
error!("This API should never get called"); error!("This API should never get called");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }

View file

@ -34,7 +34,7 @@ use crate::{
// TODO: We should move ASN1Writer out of Cert, // TODO: We should move ASN1Writer out of Cert,
// so Crypto doesn't have to depend on Cert // so Crypto doesn't have to depend on Cert
cert::{ASN1Writer, CertConsumer}, cert::{ASN1Writer, CertConsumer},
error::Error, error::{Error, ErrorCode},
}; };
pub struct HmacSha256 { pub struct HmacSha256 {
@ -49,11 +49,13 @@ impl HmacSha256 {
} }
pub fn update(&mut self, data: &[u8]) -> Result<(), Error> { pub fn update(&mut self, data: &[u8]) -> Result<(), Error> {
self.inner.update(data).map_err(|_| Error::TLSStack) self.inner
.update(data)
.map_err(|_| ErrorCode::TLSStack.into())
} }
pub fn finish(self, out: &mut [u8]) -> Result<(), Error> { pub fn finish(self, out: &mut [u8]) -> Result<(), Error> {
self.inner.finish(out).map_err(|_| Error::TLSStack)?; self.inner.finish(out).map_err(|_| ErrorCode::TLSStack)?;
Ok(()) Ok(())
} }
} }
@ -102,11 +104,11 @@ impl KeyPair {
Ok(Some(a)) => Ok(a), Ok(Some(a)) => Ok(a),
Ok(None) => { Ok(None) => {
error!("Error in writing CSR: None received"); error!("Error in writing CSR: None received");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
Err(e) => { Err(e) => {
error!("Error in writing CSR {}", e); error!("Error in writing CSR {}", e);
Err(Error::TLSStack) Err(ErrorCode::TLSStack.into())
} }
} }
} }
@ -161,7 +163,7 @@ impl KeyPair {
let mut ctr_drbg = CtrDrbg::new(Arc::new(OsEntropy::new()), None)?; let mut ctr_drbg = CtrDrbg::new(Arc::new(OsEntropy::new()), None)?;
if signature.len() < super::EC_SIGNATURE_LEN_BYTES { if signature.len() < super::EC_SIGNATURE_LEN_BYTES {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
safemem::write_bytes(signature, 0); safemem::write_bytes(signature, 0);
@ -192,7 +194,7 @@ impl KeyPair {
if let Err(e) = tmp_key.verify(hash::Type::Sha256, &msg_hash, mbedtls_sign) { if let Err(e) = tmp_key.verify(hash::Type::Sha256, &msg_hash, mbedtls_sign) {
info!("The error is {}", e); info!("The error is {}", e);
Err(Error::InvalidSignature) Err(ErrorCode::InvalidSignature.into())
} else { } else {
Ok(()) Ok(())
} }
@ -229,7 +231,7 @@ fn convert_asn1_sign_to_r_s(signature: &mut [u8]) -> Result<usize, Error> {
// Type 0x2 is Integer (first integer is r) // Type 0x2 is Integer (first integer is r)
if signature[offset] != 2 { if signature[offset] != 2 {
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
offset += 1; offset += 1;
@ -254,7 +256,7 @@ fn convert_asn1_sign_to_r_s(signature: &mut [u8]) -> Result<usize, Error> {
// Type 0x2 is Integer (this integer is s) // Type 0x2 is Integer (this integer is s)
if signature[offset] != 2 { if signature[offset] != 2 {
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
offset += 1; offset += 1;
@ -273,17 +275,17 @@ fn convert_asn1_sign_to_r_s(signature: &mut [u8]) -> Result<usize, Error> {
Ok(64) Ok(64)
} else { } else {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }
pub fn pbkdf2_hmac(pass: &[u8], iter: usize, salt: &[u8], key: &mut [u8]) -> Result<(), Error> { pub fn pbkdf2_hmac(pass: &[u8], iter: usize, salt: &[u8], key: &mut [u8]) -> Result<(), Error> {
mbedtls::hash::pbkdf2_hmac(Type::Sha256, pass, salt, iter as u32, key) mbedtls::hash::pbkdf2_hmac(Type::Sha256, pass, salt, iter as u32, key)
.map_err(|_e| Error::TLSStack) .map_err(|_e| ErrorCode::TLSStack.into())
} }
pub fn hkdf_sha256(salt: &[u8], ikm: &[u8], info: &[u8], key: &mut [u8]) -> Result<(), Error> { pub fn hkdf_sha256(salt: &[u8], ikm: &[u8], info: &[u8], key: &mut [u8]) -> Result<(), Error> {
Hkdf::hkdf(Type::Sha256, salt, ikm, info, key).map_err(|_e| Error::TLSStack) Hkdf::hkdf(Type::Sha256, salt, ikm, info, key).map_err(|_e| ErrorCode::TLSStack.into())
} }
pub fn encrypt_in_place( pub fn encrypt_in_place(
@ -304,7 +306,7 @@ pub fn encrypt_in_place(
cipher cipher
.encrypt_auth_inplace(ad, data, tag) .encrypt_auth_inplace(ad, data, tag)
.map(|(len, _)| len) .map(|(len, _)| len)
.map_err(|_e| Error::TLSStack) .map_err(|_e| ErrorCode::TLSStack.into())
} }
pub fn decrypt_in_place( pub fn decrypt_in_place(
@ -326,7 +328,7 @@ pub fn decrypt_in_place(
.map(|(len, _)| len) .map(|(len, _)| len)
.map_err(|e| { .map_err(|e| {
error!("Error during decryption: {:?}", e); error!("Error during decryption: {:?}", e);
Error::TLSStack ErrorCode::TLSStack.into()
}) })
} }
@ -343,12 +345,12 @@ impl Sha256 {
} }
pub fn update(&mut self, data: &[u8]) -> Result<(), Error> { pub fn update(&mut self, data: &[u8]) -> Result<(), Error> {
self.ctx.update(data).map_err(|_| Error::TLSStack)?; self.ctx.update(data).map_err(|_| ErrorCode::TLSStack)?;
Ok(()) Ok(())
} }
pub fn finish(self, digest: &mut [u8]) -> Result<(), Error> { pub fn finish(self, digest: &mut [u8]) -> Result<(), Error> {
self.ctx.finish(digest).map_err(|_| Error::TLSStack)?; self.ctx.finish(digest).map_err(|_| ErrorCode::TLSStack)?;
Ok(()) Ok(())
} }
} }

View file

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::error::Error; use crate::error::{Error, ErrorCode};
use foreign_types::ForeignTypeRef; use foreign_types::ForeignTypeRef;
use log::error; use log::error;
@ -46,7 +46,8 @@ pub struct HmacSha256 {
impl HmacSha256 { impl HmacSha256 {
pub fn new(key: &[u8]) -> Result<Self, Error> { pub fn new(key: &[u8]) -> Result<Self, Error> {
Ok(Self { Ok(Self {
ctx: Hmac::<sha2::Sha256>::new_from_slice(key).map_err(|_x| Error::InvalidKeyLength)?, ctx: Hmac::<sha2::Sha256>::new_from_slice(key)
.map_err(|_x| ErrorCode::InvalidKeyLength)?,
}) })
} }
@ -107,7 +108,7 @@ impl KeyPair {
fn private_key(&self) -> Result<&EcKey<Private>, Error> { fn private_key(&self) -> Result<&EcKey<Private>, Error> {
match &self.key { match &self.key {
KeyType::Public(_) => Err(Error::Invalid), KeyType::Public(_) => Err(ErrorCode::Invalid.into()),
KeyType::Private(k) => Ok(&k), KeyType::Private(k) => Ok(&k),
} }
} }
@ -167,7 +168,7 @@ impl KeyPair {
a.copy_from_slice(csr); a.copy_from_slice(csr);
Ok(a) Ok(a)
} else { } else {
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
} }
@ -178,7 +179,7 @@ impl KeyPair {
let msg = h.finish()?; let msg = h.finish()?;
if signature.len() < super::EC_SIGNATURE_LEN_BYTES { if signature.len() < super::EC_SIGNATURE_LEN_BYTES {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
safemem::write_bytes(signature, 0); safemem::write_bytes(signature, 0);
@ -205,11 +206,11 @@ impl KeyPair {
KeyType::Public(key) => key, KeyType::Public(key) => key,
_ => { _ => {
error!("Not yet supported"); error!("Not yet supported");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
}; };
if !sig.verify(&msg, k)? { if !sig.verify(&msg, k)? {
Err(Error::InvalidSignature) Err(ErrorCode::InvalidSignature.into())
} else { } else {
Ok(()) Ok(())
} }
@ -220,7 +221,7 @@ const P256_KEY_LEN: usize = 256 / 8;
pub fn pubkey_from_der<'a>(der: &'a [u8], out_key: &mut [u8]) -> Result<(), Error> { pub fn pubkey_from_der<'a>(der: &'a [u8], out_key: &mut [u8]) -> Result<(), Error> {
if out_key.len() != P256_KEY_LEN { if out_key.len() != P256_KEY_LEN {
error!("Insufficient length"); error!("Insufficient length");
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} else { } else {
let key = X509::from_der(der)?.public_key()?.public_key_to_der()?; let key = X509::from_der(der)?.public_key()?.public_key_to_der()?;
let len = key.len(); let len = key.len();
@ -232,7 +233,7 @@ pub fn pubkey_from_der<'a>(der: &'a [u8], out_key: &mut [u8]) -> Result<(), Erro
pub fn pbkdf2_hmac(pass: &[u8], iter: usize, salt: &[u8], key: &mut [u8]) -> Result<(), Error> { pub fn pbkdf2_hmac(pass: &[u8], iter: usize, salt: &[u8], key: &mut [u8]) -> Result<(), Error> {
openssl::pkcs5::pbkdf2_hmac(pass, salt, iter, MessageDigest::sha256(), key) openssl::pkcs5::pbkdf2_hmac(pass, salt, iter, MessageDigest::sha256(), key)
.map_err(|_e| Error::TLSStack) .map_err(|_e| ErrorCode::TLSStack.into())
} }
pub fn hkdf_sha256(salt: &[u8], ikm: &[u8], info: &[u8], key: &mut [u8]) -> Result<(), Error> { pub fn hkdf_sha256(salt: &[u8], ikm: &[u8], info: &[u8], key: &mut [u8]) -> Result<(), Error> {
@ -372,7 +373,9 @@ impl Sha256 {
} }
pub fn update(&mut self, data: &[u8]) -> Result<(), Error> { pub fn update(&mut self, data: &[u8]) -> Result<(), Error> {
self.hasher.update(data).map_err(|_| Error::TLSStack) self.hasher
.update(data)
.map_err(|_| ErrorCode::TLSStack.into())
} }
pub fn finish(mut self, data: &mut [u8]) -> Result<(), Error> { pub fn finish(mut self, data: &mut [u8]) -> Result<(), Error> {

View file

@ -39,7 +39,7 @@ use x509_cert::{
spki::{AlgorithmIdentifier, SubjectPublicKeyInfoOwned}, spki::{AlgorithmIdentifier, SubjectPublicKeyInfoOwned},
}; };
use crate::error::Error; use crate::error::{Error, ErrorCode};
use super::CryptoKeyPair; use super::CryptoKeyPair;
@ -79,7 +79,7 @@ impl HmacSha256 {
Ok(Self { Ok(Self {
inner: HmacSha256I::new_from_slice(key).map_err(|e| { inner: HmacSha256I::new_from_slice(key).map_err(|e| {
error!("Error creating HmacSha256 {:?}", e); error!("Error creating HmacSha256 {:?}", e);
Error::TLSStack ErrorCode::TLSStack
})?, })?,
}) })
} }
@ -143,7 +143,7 @@ impl KeyPair {
fn private_key(&self) -> Result<&SecretKey, Error> { fn private_key(&self) -> Result<&SecretKey, Error> {
match &self.key { match &self.key {
KeyType::Private(key) => Ok(key), KeyType::Private(key) => Ok(key),
KeyType::Public(_) => Err(Error::Crypto), KeyType::Public(_) => Err(ErrorCode::Crypto.into()),
} }
} }
} }
@ -158,7 +158,7 @@ impl CryptoKeyPair for KeyPair {
priv_key[..slice.len()].copy_from_slice(slice); priv_key[..slice.len()].copy_from_slice(slice);
Ok(len) Ok(len)
} }
KeyType::Public(_) => Err(Error::Crypto), KeyType::Public(_) => Err(ErrorCode::Crypto.into()),
} }
} }
fn get_csr<'a>(&self, out_csr: &'a mut [u8]) -> Result<&'a [u8], Error> { fn get_csr<'a>(&self, out_csr: &'a mut [u8]) -> Result<&'a [u8], Error> {
@ -251,7 +251,7 @@ impl CryptoKeyPair for KeyPair {
use p256::ecdsa::signature::Signer; use p256::ecdsa::signature::Signer;
if signature.len() < super::EC_SIGNATURE_LEN_BYTES { if signature.len() < super::EC_SIGNATURE_LEN_BYTES {
return Err(Error::NoSpace); return Err(ErrorCode::NoSpace.into());
} }
match &self.key { match &self.key {
@ -274,7 +274,7 @@ impl CryptoKeyPair for KeyPair {
verifying_key verifying_key
.verify(msg, &signature) .verify(msg, &signature)
.map_err(|_| Error::InvalidSignature)?; .map_err(|_| ErrorCode::InvalidSignature)?;
Ok(()) Ok(())
} }
@ -291,7 +291,7 @@ pub fn hkdf_sha256(salt: &[u8], ikm: &[u8], info: &[u8], key: &mut [u8]) -> Resu
.expand(info, key) .expand(info, key)
.map_err(|e| { .map_err(|e| {
error!("Error with hkdf_sha256 {:?}", e); error!("Error with hkdf_sha256 {:?}", e);
Error::TLSStack ErrorCode::TLSStack.into()
}) })
} }

View file

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::{ use crate::{
error::Error, error::{Error, ErrorCode},
tlv::{FromTLV, TLVWriter, TagType, ToTLV}, tlv::{FromTLV, TLVWriter, TagType, ToTLV},
}; };
@ -80,12 +80,12 @@ impl<'a> FromTLV<'a> for KeyPair {
t.confirm_array()?.enter(); t.confirm_array()?.enter();
if let Some(mut array) = t.enter() { if let Some(mut array) = t.enter() {
let pub_key = array.next().ok_or(Error::Invalid)?.slice()?; let pub_key = array.next().ok_or(ErrorCode::Invalid)?.slice()?;
let priv_key = array.next().ok_or(Error::Invalid)?.slice()?; let priv_key = array.next().ok_or(ErrorCode::Invalid)?.slice()?;
KeyPair::new_from_components(pub_key, priv_key) KeyPair::new_from_components(pub_key, priv_key)
} else { } else {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }
} }
@ -108,7 +108,7 @@ impl ToTLV for KeyPair {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::error::Error; use crate::error::ErrorCode;
use super::KeyPair; use super::KeyPair;
@ -122,8 +122,9 @@ mod tests {
fn test_verify_msg_fail() { fn test_verify_msg_fail() {
let key = KeyPair::new_from_public(&test_vectors::PUB_KEY1).unwrap(); let key = KeyPair::new_from_public(&test_vectors::PUB_KEY1).unwrap();
assert_eq!( assert_eq!(
key.verify_msg(&test_vectors::MSG1_FAIL, &test_vectors::SIGNATURE1), key.verify_msg(&test_vectors::MSG1_FAIL, &test_vectors::SIGNATURE1)
Err(Error::InvalidSignature) .map_err(|e| e.code()),
Err(ErrorCode::InvalidSignature)
); );
} }

View file

@ -17,7 +17,7 @@
use crate::{ use crate::{
data_model::objects::{Cluster, Handler}, data_model::objects::{Cluster, Handler},
error::Error, error::{Error, ErrorCode},
utils::rand::Rand, utils::rand::Rand,
}; };
@ -51,7 +51,7 @@ impl TemplateCluster {
if attr.is_system() { if attr.is_system() {
CLUSTER.read(attr.attr_id, writer) CLUSTER.read(attr.attr_id, writer)
} else { } else {
Err(Error::AttributeNotFound) Err(ErrorCode::AttributeNotFound.into())
} }
} else { } else {
Ok(()) Ok(())

View file

@ -22,7 +22,7 @@ use crate::{
acl::{AccessReq, Accessor}, acl::{AccessReq, Accessor},
attribute_enum, attribute_enum,
data_model::objects::*, data_model::objects::*,
error::Error, error::{Error, ErrorCode},
interaction_model::{ interaction_model::{
core::IMStatusCode, core::IMStatusCode,
messages::{ messages::{
@ -320,7 +320,7 @@ impl<'a> Cluster<'a> {
GlobalElements::FeatureMap => writer.set(self.feature_map), GlobalElements::FeatureMap => writer.set(self.feature_map),
other => { other => {
error!("This attribute is not yet handled {:?}", other); error!("This attribute is not yet handled {:?}", other);
Err(Error::AttributeNotFound) Err(ErrorCode::AttributeNotFound.into())
} }
} }
} }

View file

@ -26,7 +26,7 @@ use crate::interaction_model::messages::ib::{
use crate::interaction_model::messages::GenericPath; use crate::interaction_model::messages::GenericPath;
use crate::tlv::UtfStr; use crate::tlv::UtfStr;
use crate::{ use crate::{
error::Error, error::{Error, ErrorCode},
interaction_model::messages::ib::{AttrDataTag, AttrRespTag}, interaction_model::messages::ib::{AttrDataTag, AttrRespTag},
tlv::{FromTLV, TLVElement, TLVWriter, TagType, ToTLV}, tlv::{FromTLV, TLVElement, TLVWriter, TagType, ToTLV},
}; };
@ -135,8 +135,13 @@ impl<'a, 'b, 'c> AttrDataEncoder<'a, 'b, 'c> {
match handler.read(&attr, encoder) { match handler.read(&attr, encoder) {
Ok(()) => None, Ok(()) => None,
Err(Error::NoSpace) => return Ok(Some(attr.path().to_gp())), Err(e) => {
Err(error) => attr.status(error.into())?, if e.code() == ErrorCode::NoSpace {
return Ok(Some(attr.path().to_gp()));
} else {
attr.status(e.into())?
}
}
} }
} }
Err(status) => Some(status), Err(status) => Some(status),
@ -181,8 +186,13 @@ impl<'a, 'b, 'c> AttrDataEncoder<'a, 'b, 'c> {
match handler.read(&attr, encoder).await { match handler.read(&attr, encoder).await {
Ok(()) => None, Ok(()) => None,
Err(Error::NoSpace) => return Ok(Some(attr.path().to_gp())), Err(e) => {
Err(error) => attr.status(error.into())?, if e.code() == ErrorCode::NoSpace {
return Ok(Some(attr.path().to_gp()));
} else {
attr.status(e.into())?
}
}
} }
} }
Err(status) => Some(status), Err(status) => Some(status),
@ -321,7 +331,7 @@ impl<'a> AttrData<'a> {
pub fn with_dataver(self, dataver: u32) -> Result<&'a TLVElement<'a>, Error> { pub fn with_dataver(self, dataver: u32) -> Result<&'a TLVElement<'a>, Error> {
if let Some(req_dataver) = self.for_dataver { if let Some(req_dataver) = self.for_dataver {
if req_dataver != dataver { if req_dataver != dataver {
return Err(Error::DataVersionMismatch); Err(ErrorCode::DataVersionMismatch)?;
} }
} }
@ -557,7 +567,8 @@ macro_rules! attribute_enum {
type Error = $crate::error::Error; type Error = $crate::error::Error;
fn try_from(id: $crate::data_model::objects::AttrId) -> Result<Self, Self::Error> { fn try_from(id: $crate::data_model::objects::AttrId) -> Result<Self, Self::Error> {
<$en>::from_repr(id).ok_or($crate::error::Error::AttributeNotFound) <$en>::from_repr(id)
.ok_or_else(|| $crate::error::ErrorCode::AttributeNotFound.into())
} }
} }
}; };
@ -571,7 +582,7 @@ macro_rules! command_enum {
type Error = $crate::error::Error; type Error = $crate::error::Error;
fn try_from(id: $crate::data_model::objects::CmdId) -> Result<Self, Self::Error> { fn try_from(id: $crate::data_model::objects::CmdId) -> Result<Self, Self::Error> {
<$en>::from_repr(id).ok_or($crate::error::Error::CommandNotFound) <$en>::from_repr(id).ok_or_else(|| $crate::error::ErrorCode::CommandNotFound.into())
} }
} }
}; };

View file

@ -15,7 +15,11 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::{error::Error, interaction_model::core::Transaction, tlv::TLVElement}; use crate::{
error::{Error, ErrorCode},
interaction_model::core::Transaction,
tlv::TLVElement,
};
use super::{AttrData, AttrDataEncoder, AttrDetails, CmdDataEncoder, CmdDetails}; use super::{AttrData, AttrDataEncoder, AttrDetails, CmdDataEncoder, CmdDetails};
@ -27,7 +31,7 @@ pub trait Handler {
fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error>; fn read(&self, attr: &AttrDetails, encoder: AttrDataEncoder) -> Result<(), Error>;
fn write(&mut self, _attr: &AttrDetails, _data: AttrData) -> Result<(), Error> { fn write(&mut self, _attr: &AttrDetails, _data: AttrData) -> Result<(), Error> {
Err(Error::AttributeNotFound) Err(ErrorCode::AttributeNotFound.into())
} }
fn invoke( fn invoke(
@ -37,7 +41,7 @@ pub trait Handler {
_data: &TLVElement, _data: &TLVElement,
_encoder: CmdDataEncoder, _encoder: CmdDataEncoder,
) -> Result<(), Error> { ) -> Result<(), Error> {
Err(Error::CommandNotFound) Err(ErrorCode::CommandNotFound.into())
} }
} }
@ -88,7 +92,7 @@ impl EmptyHandler {
impl Handler for EmptyHandler { impl Handler for EmptyHandler {
fn read(&self, _attr: &AttrDetails, _encoder: AttrDataEncoder) -> Result<(), Error> { fn read(&self, _attr: &AttrDetails, _encoder: AttrDataEncoder) -> Result<(), Error> {
Err(Error::AttributeNotFound) Err(ErrorCode::AttributeNotFound.into())
} }
} }
@ -202,7 +206,7 @@ macro_rules! handler_chain_type {
pub mod asynch { pub mod asynch {
use crate::{ use crate::{
data_model::objects::{AttrData, AttrDataEncoder, AttrDetails, CmdDataEncoder, CmdDetails}, data_model::objects::{AttrData, AttrDataEncoder, AttrDetails, CmdDataEncoder, CmdDetails},
error::Error, error::{Error, ErrorCode},
interaction_model::core::Transaction, interaction_model::core::Transaction,
tlv::TLVElement, tlv::TLVElement,
}; };
@ -221,7 +225,7 @@ pub mod asynch {
_attr: &'a AttrDetails<'_>, _attr: &'a AttrDetails<'_>,
_data: AttrData<'a>, _data: AttrData<'a>,
) -> Result<(), Error> { ) -> Result<(), Error> {
Err(Error::AttributeNotFound) Err(ErrorCode::AttributeNotFound.into())
} }
async fn invoke<'a>( async fn invoke<'a>(
@ -231,7 +235,7 @@ pub mod asynch {
_data: &'a TLVElement<'_>, _data: &'a TLVElement<'_>,
_encoder: CmdDataEncoder<'a, '_, '_>, _encoder: CmdDataEncoder<'a, '_, '_>,
) -> Result<(), Error> { ) -> Result<(), Error> {
Err(Error::CommandNotFound) Err(ErrorCode::CommandNotFound.into())
} }
} }
@ -305,7 +309,7 @@ pub mod asynch {
_attr: &'a AttrDetails<'_>, _attr: &'a AttrDetails<'_>,
_encoder: AttrDataEncoder<'a, '_, '_>, _encoder: AttrDataEncoder<'a, '_, '_>,
) -> Result<(), Error> { ) -> Result<(), Error> {
Err(Error::AttributeNotFound) Err(ErrorCode::AttributeNotFound.into())
} }
} }

View file

@ -16,7 +16,7 @@
*/ */
use crate::{ use crate::{
error::Error, error::{Error, ErrorCode},
tlv::{FromTLV, TLVElement, ToTLV}, tlv::{FromTLV, TLVElement, ToTLV},
}; };
use log::error; use log::error;
@ -47,12 +47,12 @@ impl FromTLV<'_> for Privilege {
1 => Ok(Privilege::VIEW), 1 => Ok(Privilege::VIEW),
2 => { 2 => {
error!("ProxyView privilege not yet supporteds"); error!("ProxyView privilege not yet supporteds");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
3 => Ok(Privilege::OPERATE), 3 => Ok(Privilege::OPERATE),
4 => Ok(Privilege::MANAGE), 4 => Ok(Privilege::MANAGE),
5 => Ok(Privilege::ADMIN), 5 => Ok(Privilege::ADMIN),
_ => Err(Error::Invalid), _ => Err(ErrorCode::Invalid.into()),
} }
} }
} }

View file

@ -144,7 +144,7 @@ impl<'a> AdminCommCluster<'a> {
) -> Result<(), Error> { ) -> Result<(), Error> {
match cmd.cmd_id.try_into()? { match cmd.cmd_id.try_into()? {
Commands::OpenCommWindow => self.handle_command_opencomm_win(data)?, Commands::OpenCommWindow => self.handle_command_opencomm_win(data)?,
_ => Err(Error::CommandNotFound)?, _ => Err(ErrorCode::CommandNotFound)?,
} }
self.data_ver.changed(); self.data_ver.changed();

View file

@ -15,7 +15,10 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::{error::Error, transport::session::SessionMode}; use crate::{
error::{Error, ErrorCode},
transport::session::SessionMode,
};
use log::error; use log::error;
#[derive(PartialEq)] #[derive(PartialEq)]
@ -62,7 +65,7 @@ impl FailSafe {
State::Armed(c) => { State::Armed(c) => {
if c.session_mode != session_mode { if c.session_mode != session_mode {
error!("Received Fail-Safe Arm with different session modes; current {:?}, incoming {:?}", c.session_mode, session_mode); error!("Received Fail-Safe Arm with different session modes; current {:?}, incoming {:?}", c.session_mode, session_mode);
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
// re-arm // re-arm
c.timeout = timeout; c.timeout = timeout;
@ -75,22 +78,22 @@ impl FailSafe {
match &mut self.state { match &mut self.state {
State::Idle => { State::Idle => {
error!("Received Fail-Safe Disarm without it being armed"); error!("Received Fail-Safe Disarm without it being armed");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
State::Armed(c) => { State::Armed(c) => {
match c.noc_state { match c.noc_state {
NocState::NocNotRecvd => return Err(Error::Invalid), NocState::NocNotRecvd => Err(ErrorCode::Invalid)?,
NocState::AddNocRecvd(idx) | NocState::UpdateNocRecvd(idx) => { NocState::AddNocRecvd(idx) | NocState::UpdateNocRecvd(idx) => {
if let SessionMode::Case(c) = session_mode { if let SessionMode::Case(c) = session_mode {
if c.fab_idx != idx { if c.fab_idx != idx {
error!( error!(
"Received disarm in separate session from previous Add/Update NOC" "Received disarm in separate session from previous Add/Update NOC"
); );
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
} else { } else {
error!("Received disarm in a non-CASE session"); error!("Received disarm in a non-CASE session");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
} }
} }
@ -106,13 +109,13 @@ impl FailSafe {
pub fn record_add_noc(&mut self, fabric_index: u8) -> Result<(), Error> { pub fn record_add_noc(&mut self, fabric_index: u8) -> Result<(), Error> {
match &mut self.state { match &mut self.state {
State::Idle => Err(Error::Invalid), State::Idle => Err(ErrorCode::Invalid.into()),
State::Armed(c) => { State::Armed(c) => {
if c.noc_state == NocState::NocNotRecvd { if c.noc_state == NocState::NocNotRecvd {
c.noc_state = NocState::AddNocRecvd(fabric_index); c.noc_state = NocState::AddNocRecvd(fabric_index);
Ok(()) Ok(())
} else { } else {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }
} }

View file

@ -235,9 +235,9 @@ impl<'a> GenCommCluster<'a> {
cmd_enter!("Set Regulatory Config"); cmd_enter!("Set Regulatory Config");
let country_code = data let country_code = data
.find_tag(1) .find_tag(1)
.map_err(|_| Error::InvalidCommand)? .map_err(|_| ErrorCode::InvalidCommand)?
.slice() .slice()
.map_err(|_| Error::InvalidCommand)?; .map_err(|_| ErrorCode::InvalidCommand)?;
info!("Received country code: {:?}", country_code); info!("Received country code: {:?}", country_code);
let cmd_data = CommonResponse { let cmd_data = CommonResponse {

View file

@ -277,7 +277,7 @@ impl<'a> NocCluster<'a> {
} }
_ => { _ => {
error!("Attribute not supported: this shouldn't happen"); error!("Attribute not supported: this shouldn't happen");
Err(Error::AttributeNotFound) Err(ErrorCode::AttributeNotFound.into())
} }
} }
} }
@ -563,7 +563,7 @@ impl<'a> NocCluster<'a> {
info!("Received CSR Nonce:{:?}", req.str); info!("Received CSR Nonce:{:?}", req.str);
if !self.failsafe.borrow().is_armed() { if !self.failsafe.borrow().is_armed() {
return Err(Error::UnsupportedAccess); Err(ErrorCode::UnsupportedAccess)?;
} }
let noc_keypair = KeyPair::new()?; let noc_keypair = KeyPair::new()?;
@ -602,7 +602,7 @@ impl<'a> NocCluster<'a> {
) -> Result<(), Error> { ) -> Result<(), Error> {
cmd_enter!("AddTrustedRootCert"); cmd_enter!("AddTrustedRootCert");
if !self.failsafe.borrow().is_armed() { if !self.failsafe.borrow().is_armed() {
return Err(Error::UnsupportedAccess); Err(ErrorCode::UnsupportedAccess)?;
} }
// This may happen on CASE or PASE. For PASE, the existence of NOC Data is necessary // This may happen on CASE or PASE. For PASE, the existence of NOC Data is necessary
@ -612,13 +612,13 @@ impl<'a> NocCluster<'a> {
let noc_data = transaction let noc_data = transaction
.session_mut() .session_mut()
.get_noc_data::<NocData>() .get_noc_data::<NocData>()
.ok_or(Error::NoSession)?; .ok_or(ErrorCode::NoSession)?;
let req = CommonReq::from_tlv(data).map_err(Error::map_invalid_command)?; let req = CommonReq::from_tlv(data).map_err(Error::map_invalid_command)?;
info!("Received Trusted Cert:{:x?}", req.str); info!("Received Trusted Cert:{:x?}", req.str);
noc_data.root_ca = noc_data.root_ca =
heapless::Vec::from_slice(req.str.0).map_err(|_| Error::BufferTooSmall)?; heapless::Vec::from_slice(req.str.0).map_err(|_| ErrorCode::BufferTooSmall)?;
// TODO // TODO
} }
_ => (), _ => (),
@ -720,6 +720,6 @@ fn get_certchainrequest_params(data: &TLVElement) -> Result<DataType, Error> {
match cert_type { match cert_type {
CERT_TYPE_DAC => Ok(dev_att::DataType::DAC), CERT_TYPE_DAC => Ok(dev_att::DataType::DAC),
CERT_TYPE_PAI => Ok(dev_att::DataType::PAI), CERT_TYPE_PAI => Ok(dev_att::DataType::PAI),
_ => Err(Error::Invalid), _ => Err(ErrorCode::Invalid.into()),
} }
} }

View file

@ -20,7 +20,7 @@ use crate::{
AttrDataEncoder, AttrDetails, ChangeNotifier, Cluster, Dataver, Handler, AttrDataEncoder, AttrDetails, ChangeNotifier, Cluster, Dataver, Handler,
NonBlockingHandler, ATTRIBUTE_LIST, FEATURE_MAP, NonBlockingHandler, ATTRIBUTE_LIST, FEATURE_MAP,
}, },
error::Error, error::{Error, ErrorCode},
utils::rand::Rand, utils::rand::Rand,
}; };
@ -57,7 +57,7 @@ impl Handler for NwCommCluster {
if attr.is_system() { if attr.is_system() {
CLUSTER.read(attr.attr_id, writer) CLUSTER.read(attr.attr_id, writer)
} else { } else {
Err(Error::AttributeNotFound) Err(ErrorCode::AttributeNotFound.into())
} }
} else { } else {
Ok(()) Ok(())

View file

@ -141,7 +141,7 @@ impl<'a> AccessControlCluster<'a> {
} }
_ => { _ => {
error!("Attribute not yet supported: this shouldn't happen"); error!("Attribute not yet supported: this shouldn't happen");
Err(Error::AttributeNotFound) Err(ErrorCode::AttributeNotFound.into())
} }
} }
} }
@ -229,7 +229,7 @@ mod tests {
// Test, ACL has fabric index 2, but the accessing fabric is 1 // Test, ACL has fabric index 2, but the accessing fabric is 1
// the fabric index in the TLV should be ignored and the ACL should be created with entry 1 // the fabric index in the TLV should be ignored and the ACL should be created with entry 1
let result = acl.write_acl_attr(&ListOperation::AddItem, &data, 1); let result = acl.write_acl_attr(&ListOperation::AddItem, &data, 1);
assert_eq!(result, Ok(())); assert!(result.is_ok());
let verifier = AclEntry::new(1, Privilege::VIEW, AuthMode::Case); let verifier = AclEntry::new(1, Privilege::VIEW, AuthMode::Case);
acl_mgr acl_mgr
@ -268,7 +268,7 @@ mod tests {
let result = acl.write_acl_attr(&ListOperation::EditItem(1), &data, 2); let result = acl.write_acl_attr(&ListOperation::EditItem(1), &data, 2);
// Fabric 2's index 1, is actually our index 2, update the verifier // Fabric 2's index 1, is actually our index 2, update the verifier
verifier[2] = new; verifier[2] = new;
assert_eq!(result, Ok(())); assert!(result.is_ok());
// Also validate in the acl_mgr that the entries are in the right order // Also validate in the acl_mgr that the entries are in the right order
let mut index = 0; let mut index = 0;
@ -301,7 +301,7 @@ mod tests {
// Test , Delete Fabric 1's index 0 // Test , Delete Fabric 1's index 0
let result = acl.write_acl_attr(&ListOperation::DeleteItem(0), &data, 1); let result = acl.write_acl_attr(&ListOperation::DeleteItem(0), &data, 1);
assert_eq!(result, Ok(())); assert!(result.is_ok());
let verifier = [input[0], input[2]]; let verifier = [input[0], input[2]];
// Also validate in the acl_mgr that the entries are in the right order // Also validate in the acl_mgr that the entries are in the right order

View file

@ -17,8 +17,8 @@
use core::{array::TryFromSliceError, fmt, str::Utf8Error}; use core::{array::TryFromSliceError, fmt, str::Utf8Error};
#[derive(Debug, PartialEq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Error { pub enum ErrorCode {
AttributeNotFound, AttributeNotFound,
AttributeIsCustom, AttributeIsCustom,
BufferTooSmall, BufferTooSmall,
@ -73,7 +73,36 @@ pub enum Error {
Utf8Fail, Utf8Fail,
} }
impl From<ErrorCode> for Error {
fn from(code: ErrorCode) -> Self {
Self::new(code)
}
}
pub struct Error {
code: ErrorCode,
#[cfg(all(feature = "std", feature = "backtrace"))]
backtrace: std::backtrace::Backtrace,
}
impl Error { impl Error {
pub fn new(code: ErrorCode) -> Self {
Self {
code,
#[cfg(all(feature = "std", feature = "backtrace"))]
backtrace: std::backtrace::Backtrace::capture(),
}
}
pub const fn code(&self) -> ErrorCode {
self.code
}
#[cfg(all(feature = "std", feature = "backtrace"))]
pub const fn backtrace(&self) -> &std::backtrace::Backtrace {
&self.backtrace
}
pub fn remap<F>(self, matcher: F, to: Self) -> Self pub fn remap<F>(self, matcher: F, to: Self) -> Self
where where
F: FnOnce(&Self) -> bool, F: FnOnce(&Self) -> bool,
@ -86,19 +115,22 @@ impl Error {
} }
pub fn map_invalid(self, to: Self) -> Self { pub fn map_invalid(self, to: Self) -> Self {
self.remap(|e| matches!(e, Self::Invalid | Self::InvalidData), to) self.remap(
|e| matches!(e.code(), ErrorCode::Invalid | ErrorCode::InvalidData),
to,
)
} }
pub fn map_invalid_command(self) -> Self { pub fn map_invalid_command(self) -> Self {
self.map_invalid(Error::InvalidCommand) self.map_invalid(Error::new(ErrorCode::InvalidCommand))
} }
pub fn map_invalid_action(self) -> Self { pub fn map_invalid_action(self) -> Self {
self.map_invalid(Error::InvalidAction) self.map_invalid(Error::new(ErrorCode::InvalidAction))
} }
pub fn map_invalid_data_type(self) -> Self { pub fn map_invalid_data_type(self) -> Self {
self.map_invalid(Error::InvalidDataType) self.map_invalid(Error::new(ErrorCode::InvalidDataType))
} }
} }
@ -106,14 +138,14 @@ impl Error {
impl From<std::io::Error> for Error { impl From<std::io::Error> for Error {
fn from(_e: std::io::Error) -> Self { fn from(_e: std::io::Error) -> Self {
// Keep things simple for now // Keep things simple for now
Self::StdIoError Self::new(ErrorCode::StdIoError)
} }
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl<T> From<std::sync::PoisonError<T>> for Error { impl<T> From<std::sync::PoisonError<T>> for Error {
fn from(_e: std::sync::PoisonError<T>) -> Self { fn from(_e: std::sync::PoisonError<T>) -> Self {
Self::RwLock Self::new(ErrorCode::RwLock)
} }
} }
@ -121,7 +153,7 @@ impl<T> From<std::sync::PoisonError<T>> for Error {
impl From<openssl::error::ErrorStack> for Error { impl From<openssl::error::ErrorStack> for Error {
fn from(e: openssl::error::ErrorStack) -> Self { fn from(e: openssl::error::ErrorStack) -> Self {
::log::error!("Error in TLS: {}", e); ::log::error!("Error in TLS: {}", e);
Self::TLSStack Self::new(ErrorCode::TLSStack)
} }
} }
@ -129,39 +161,57 @@ impl From<openssl::error::ErrorStack> for Error {
impl From<mbedtls::Error> for Error { impl From<mbedtls::Error> for Error {
fn from(e: mbedtls::Error) -> Self { fn from(e: mbedtls::Error) -> Self {
::log::error!("Error in TLS: {}", e); ::log::error!("Error in TLS: {}", e);
Self::TLSStack Self::new(ErrorCode::TLSStack)
} }
} }
#[cfg(feature = "crypto_rustcrypto")] #[cfg(feature = "crypto_rustcrypto")]
impl From<ccm::aead::Error> for Error { impl From<ccm::aead::Error> for Error {
fn from(_e: ccm::aead::Error) -> Self { fn from(_e: ccm::aead::Error) -> Self {
Self::Crypto Self::new(ErrorCode::Crypto)
} }
} }
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl From<std::time::SystemTimeError> for Error { impl From<std::time::SystemTimeError> for Error {
fn from(_e: std::time::SystemTimeError) -> Self { fn from(_e: std::time::SystemTimeError) -> Self {
Self::SysTimeFail Error::new(ErrorCode::SysTimeFail)
} }
} }
impl From<TryFromSliceError> for Error { impl From<TryFromSliceError> for Error {
fn from(_e: TryFromSliceError) -> Self { fn from(_e: TryFromSliceError) -> Self {
Self::Invalid Self::new(ErrorCode::Invalid)
} }
} }
impl From<Utf8Error> for Error { impl From<Utf8Error> for Error {
fn from(_e: Utf8Error) -> Self { fn from(_e: Utf8Error) -> Self {
Self::Utf8Fail Self::new(ErrorCode::Utf8Fail)
}
}
impl fmt::Debug for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
#[cfg(not(all(feature = "std", feature = "backtrace")))]
{
write!(f, "Error::{}", self)?;
}
#[cfg(all(feature = "std", feature = "backtrace"))]
{
write!(f, "Error::{} {{\n", self)?;
write!(f, "{}", self.backtrace())?;
write!(f, "}}\n")?;
}
Ok(())
} }
} }
impl fmt::Display for Error { impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self) write!(f, "{:?}", self.code())
} }
} }

View file

@ -24,10 +24,10 @@ use log::info;
use crate::{ use crate::{
cert::{Cert, MAX_CERT_TLV_LEN}, cert::{Cert, MAX_CERT_TLV_LEN},
crypto::{self, hkdf_sha256, HmacSha256, KeyPair}, crypto::{self, hkdf_sha256, HmacSha256, KeyPair},
error::Error, error::{Error, ErrorCode},
group_keys::KeySet, group_keys::KeySet,
mdns::{MdnsMgr, ServiceMode}, mdns::{MdnsMgr, ServiceMode},
tlv::{FromTLV, OctetStr, TLVElement, TLVList, TLVWriter, TagType, ToTLV, UtfStr}, tlv::{FromTLV, OctetStr, TLVList, TLVWriter, TagType, ToTLV, UtfStr},
utils::writebuf::WriteBuf, utils::writebuf::WriteBuf,
}; };
@ -123,7 +123,7 @@ impl Fabric {
0x69, 0x63, 0x69, 0x63,
]; ];
hkdf_sha256(&fabric_id_be, root_pubkey, &COMPRESSED_FABRIC_ID_INFO, out) hkdf_sha256(&fabric_id_be, root_pubkey, &COMPRESSED_FABRIC_ID_INFO, out)
.map_err(|_| Error::NoSpace) .map_err(|_| Error::from(ErrorCode::NoSpace))
} }
pub fn match_dest_id(&self, random: &[u8], target: &[u8]) -> Result<(), Error> { pub fn match_dest_id(&self, random: &[u8], target: &[u8]) -> Result<(), Error> {
@ -144,7 +144,7 @@ impl Fabric {
if id.as_slice() == target { if id.as_slice() == target {
Ok(()) Ok(())
} else { } else {
Err(Error::NotFound) Err(ErrorCode::NotFound.into())
} }
} }
@ -208,7 +208,7 @@ impl FabricMgr {
} }
} }
let root = TLVList::new(data).iter().next().ok_or(Error::Invalid)?; let root = TLVList::new(data).iter().next().ok_or(ErrorCode::Invalid)?;
self.fabrics = FabricEntries::from_tlv(&root)?; self.fabrics = FabricEntries::from_tlv(&root)?;
@ -227,6 +227,7 @@ impl FabricMgr {
if self.changed { if self.changed {
let mut wb = WriteBuf::new(buf); let mut wb = WriteBuf::new(buf);
let mut tw = TLVWriter::new(&mut wb); let mut tw = TLVWriter::new(&mut wb);
self.fabrics.to_tlv(&mut tw, TagType::Anonymous)?; self.fabrics.to_tlv(&mut tw, TagType::Anonymous)?;
self.changed = false; self.changed = false;
@ -252,7 +253,7 @@ impl FabricMgr {
} }
} }
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
pub fn remove(&mut self, fab_idx: u8, mdns_mgr: &mut MdnsMgr) -> Result<(), Error> { pub fn remove(&mut self, fab_idx: u8, mdns_mgr: &mut MdnsMgr) -> Result<(), Error> {
@ -262,10 +263,10 @@ impl FabricMgr {
self.changed = true; self.changed = true;
Ok(()) Ok(())
} else { } else {
Err(Error::NotFound) Err(ErrorCode::NotFound.into())
} }
} else { } else {
Err(Error::NotFound) Err(ErrorCode::NotFound.into())
} }
} }
@ -277,7 +278,7 @@ impl FabricMgr {
} }
} }
} }
Err(Error::NotFound) Err(ErrorCode::NotFound.into())
} }
pub fn get_fabric(&self, idx: usize) -> Result<Option<&Fabric>, Error> { pub fn get_fabric(&self, idx: usize) -> Result<Option<&Fabric>, Error> {
@ -317,7 +318,7 @@ impl FabricMgr {
.filter_map(|f| f.as_ref()) .filter_map(|f| f.as_ref())
.any(|f| f.label == label) .any(|f| f.label == label)
{ {
return Err(Error::Invalid); return Err(ErrorCode::Invalid.into());
} }
} }

View file

@ -17,8 +17,8 @@
use crate::{ use crate::{
crypto::{self, SYMM_KEY_LEN_BYTES}, crypto::{self, SYMM_KEY_LEN_BYTES},
error::Error, error::{Error, ErrorCode},
tlv::{FromTLV, TLVElement, TLVWriter, TagType, ToTLV}, tlv::{FromTLV, TLVWriter, TagType, ToTLV},
}; };
type KeySetKey = [u8; SYMM_KEY_LEN_BYTES]; type KeySetKey = [u8; SYMM_KEY_LEN_BYTES];
@ -42,7 +42,8 @@ impl KeySet {
0x47, 0x72, 0x6f, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x20, 0x76, 0x31, 0x2e, 0x30, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x4b, 0x65, 0x79, 0x20, 0x76, 0x31, 0x2e, 0x30,
]; ];
crypto::hkdf_sha256(compressed_id, ipk, &GRP_KEY_INFO, opkey).map_err(|_| Error::NoSpace) crypto::hkdf_sha256(compressed_id, ipk, &GRP_KEY_INFO, opkey)
.map_err(|_| ErrorCode::NoSpace.into())
} }
pub fn op_key(&self) -> &[u8] { pub fn op_key(&self) -> &[u8] {

View file

@ -78,27 +78,33 @@ pub enum IMStatusCode {
FailSafeRequired = 0xca, FailSafeRequired = 0xca,
} }
impl From<Error> for IMStatusCode { impl From<ErrorCode> for IMStatusCode {
fn from(e: Error) -> Self { fn from(e: ErrorCode) -> Self {
match e { match e {
Error::EndpointNotFound => IMStatusCode::UnsupportedEndpoint, ErrorCode::EndpointNotFound => IMStatusCode::UnsupportedEndpoint,
Error::ClusterNotFound => IMStatusCode::UnsupportedCluster, ErrorCode::ClusterNotFound => IMStatusCode::UnsupportedCluster,
Error::AttributeNotFound => IMStatusCode::UnsupportedAttribute, ErrorCode::AttributeNotFound => IMStatusCode::UnsupportedAttribute,
Error::CommandNotFound => IMStatusCode::UnsupportedCommand, ErrorCode::CommandNotFound => IMStatusCode::UnsupportedCommand,
Error::InvalidAction => IMStatusCode::InvalidAction, ErrorCode::InvalidAction => IMStatusCode::InvalidAction,
Error::InvalidCommand => IMStatusCode::InvalidCommand, ErrorCode::InvalidCommand => IMStatusCode::InvalidCommand,
Error::UnsupportedAccess => IMStatusCode::UnsupportedAccess, ErrorCode::UnsupportedAccess => IMStatusCode::UnsupportedAccess,
Error::Busy => IMStatusCode::Busy, ErrorCode::Busy => IMStatusCode::Busy,
Error::DataVersionMismatch => IMStatusCode::DataVersionMismatch, ErrorCode::DataVersionMismatch => IMStatusCode::DataVersionMismatch,
Error::ResourceExhausted => IMStatusCode::ResourceExhausted, ErrorCode::ResourceExhausted => IMStatusCode::ResourceExhausted,
_ => IMStatusCode::Failure, _ => IMStatusCode::Failure,
} }
} }
} }
impl From<Error> for IMStatusCode {
fn from(value: Error) -> Self {
Self::from(value.code())
}
}
impl FromTLV<'_> for IMStatusCode { impl FromTLV<'_> for IMStatusCode {
fn from_tlv(t: &TLVElement) -> Result<Self, Error> { fn from_tlv(t: &TLVElement) -> Result<Self, Error> {
num::FromPrimitive::from_u16(t.u16()?).ok_or(Error::Invalid) num::FromPrimitive::from_u16(t.u16()?).ok_or_else(|| ErrorCode::Invalid.into())
} }
} }
@ -223,7 +229,7 @@ pub enum Interaction<'a> {
impl<'a> Interaction<'a> { impl<'a> Interaction<'a> {
fn new(rx: &'a Packet, transaction: &mut Transaction) -> Result<Option<Self>, Error> { fn new(rx: &'a Packet, transaction: &mut Transaction) -> Result<Option<Self>, Error> {
let opcode: OpCode = let opcode: OpCode =
num::FromPrimitive::from_u8(rx.get_proto_opcode()).ok_or(Error::Invalid)?; num::FromPrimitive::from_u8(rx.get_proto_opcode()).ok_or(ErrorCode::Invalid)?;
let rx_data = rx.as_slice(); let rx_data = rx.as_slice();
@ -264,7 +270,7 @@ impl<'a> Interaction<'a> {
)?))), )?))),
_ => { _ => {
error!("Opcode not handled: {:?}", opcode); error!("Opcode not handled: {:?}", opcode);
Err(Error::InvalidOpcode) Err(ErrorCode::InvalidOpcode.into())
} }
} }
} }

View file

@ -17,8 +17,8 @@
use crate::{ use crate::{
data_model::objects::{ClusterId, EndptId}, data_model::objects::{ClusterId, EndptId},
error::Error, error::{Error, ErrorCode},
tlv::{FromTLV, TLVElement, TLVWriter, TagType, ToTLV}, tlv::{FromTLV, TLVWriter, TagType, ToTLV},
}; };
// A generic path with endpoint, clusters, and a leaf // A generic path with endpoint, clusters, and a leaf
@ -48,7 +48,7 @@ impl GenericPath {
cluster: Some(c), cluster: Some(c),
leaf: Some(l), leaf: Some(l),
} => Ok((e, c, l)), } => Ok((e, c, l)),
_ => Err(Error::Invalid), _ => Err(ErrorCode::Invalid.into()),
} }
} }
/// Returns true, if the path is wildcard /// Returns true, if the path is wildcard
@ -69,7 +69,7 @@ pub mod msg {
use crate::{ use crate::{
error::Error, error::Error,
interaction_model::core::IMStatusCode, interaction_model::core::IMStatusCode,
tlv::{FromTLV, TLVArray, TLVElement, TLVWriter, TagType, ToTLV}, tlv::{FromTLV, TLVArray, TLVWriter, TagType, ToTLV},
}; };
use super::ib::{ use super::ib::{
@ -259,7 +259,7 @@ pub mod ib {
use crate::{ use crate::{
data_model::objects::{AttrDetails, AttrId, ClusterId, CmdId, EncodeValue, EndptId}, data_model::objects::{AttrDetails, AttrId, ClusterId, CmdId, EncodeValue, EndptId},
error::Error, error::{Error, ErrorCode},
interaction_model::core::IMStatusCode, interaction_model::core::IMStatusCode,
tlv::{FromTLV, Nullable, TLVElement, TLVWriter, TagType, ToTLV}, tlv::{FromTLV, Nullable, TLVElement, TLVWriter, TagType, ToTLV},
}; };
@ -447,7 +447,7 @@ pub mod ib {
f(ListOperation::DeleteList, data)?; f(ListOperation::DeleteList, data)?;
// Now the data must be a list, that should be added item by item // Now the data must be a list, that should be added item by item
let container = data.enter().ok_or(Error::Invalid)?; let container = data.enter().ok_or(ErrorCode::Invalid)?;
for d in container { for d in container {
f(ListOperation::AddItem, &d)?; f(ListOperation::AddItem, &d)?;
} }
@ -544,7 +544,7 @@ pub mod ib {
if c.path.leaf.is_none() { if c.path.leaf.is_none() {
error!("Wildcard command parameter not supported"); error!("Wildcard command parameter not supported");
Err(Error::CommandNotFound) Err(ErrorCode::CommandNotFound.into())
} else { } else {
Ok(c) Ok(c)
} }

View file

@ -217,7 +217,7 @@ pub mod astro {
use std::collections::HashMap; use std::collections::HashMap;
use super::Mdns; use super::Mdns;
use crate::error::Error; use crate::error::{Error, ErrorCode};
use astro_dnssd::{DNSServiceBuilder, RegisteredDnsService}; use astro_dnssd::{DNSServiceBuilder, RegisteredDnsService};
use log::info; use log::info;
@ -269,7 +269,7 @@ pub mod astro {
builder = builder.with_key_value(kvs.0.to_string(), kvs.1.to_string()); builder = builder.with_key_value(kvs.0.to_string(), kvs.1.to_string());
} }
let svc = builder.register().map_err(|_| Error::MdnsError)?; let svc = builder.register().map_err(|_| ErrorCode::MdnsError)?;
self.services.insert( self.services.insert(
ServiceId { ServiceId {
@ -348,7 +348,7 @@ pub mod astro {
// use std::collections::HashMap; // use std::collections::HashMap;
// use super::Mdns; // use super::Mdns;
// use crate::error::Error; // use crate::error::{Error, ErrorCode};
// use log::info; // use log::info;
// use zeroconf::prelude::*; // use zeroconf::prelude::*;
// use zeroconf::{MdnsService, ServiceType, TxtRecord}; // use zeroconf::{MdnsService, ServiceType, TxtRecord};
@ -402,7 +402,7 @@ pub mod astro {
// svc.set_txt_record(txt); // svc.set_txt_record(txt);
// //let event_loop = svc.register().map_err(|_| Error::MdnsError)?; // //let event_loop = svc.register().map_err(|_| ErrorCode::MdnsError)?;
// self.services.insert( // self.services.insert(
// ServiceId { // ServiceId {
@ -604,7 +604,7 @@ pub mod libmdns {
// pub mod simplemdns { // pub mod simplemdns {
// use std::net::Ipv4Addr; // use std::net::Ipv4Addr;
// use crate::error::Error; // use crate::error::{Error, ErrorCode};
// use super::Mdns; // use super::Mdns;
// use log::info; // use log::info;
// use simple_dns::{ // use simple_dns::{

View file

@ -16,6 +16,7 @@
*/ */
use crate::{ use crate::{
error::ErrorCode,
tlv::{TLVWriter, TagType}, tlv::{TLVWriter, TagType},
utils::writebuf::WriteBuf, utils::writebuf::WriteBuf,
}; };
@ -134,7 +135,7 @@ impl<'data> QrSetupPayload<'data> {
if is_vendor_tag(tag) { if is_vendor_tag(tag) {
self.add_optional_data(tag, data) self.add_optional_data(tag, data)
} else { } else {
Err(Error::InvalidArgument) Err(ErrorCode::InvalidArgument.into())
} }
} }
@ -150,7 +151,7 @@ impl<'data> QrSetupPayload<'data> {
if is_common_tag(tag) { if is_common_tag(tag) {
self.add_optional_data(tag, data) self.add_optional_data(tag, data)
} else { } else {
Err(Error::InvalidArgument) Err(ErrorCode::InvalidArgument.into())
} }
} }
@ -163,7 +164,7 @@ impl<'data> QrSetupPayload<'data> {
} else { } else {
self.optional_data.push(item) self.optional_data.push(item)
} }
.map_err(|_| Error::NoSpace) .map_err(|_| ErrorCode::NoSpace.into())
} }
pub fn get_all_optional_data(&self) -> &[OptionalQRCodeInfo] { pub fn get_all_optional_data(&self) -> &[OptionalQRCodeInfo] {
@ -267,7 +268,7 @@ pub(super) fn payload_base38_representation<const N: usize>(
payload_base38_representation_with_tlv(payload, bits_buf, tlv_buf) payload_base38_representation_with_tlv(payload, bits_buf, tlv_buf)
} else { } else {
Err(Error::InvalidArgument) Err(ErrorCode::InvalidArgument.into())
} }
} }
@ -299,7 +300,7 @@ pub fn estimate_buffer_size(payload: &QrSetupPayload) -> Result<usize, Error> {
estimate = estimate_struct_overhead(estimate); estimate = estimate_struct_overhead(estimate);
if estimate > u32::MAX as usize { if estimate > u32::MAX as usize {
return Err(Error::NoMemory); Err(ErrorCode::NoMemory)?;
} }
Ok(estimate) Ok(estimate)
@ -352,11 +353,11 @@ fn populate_bits(
total_payload_data_size_in_bits: usize, total_payload_data_size_in_bits: usize,
) -> Result<(), Error> { ) -> Result<(), Error> {
if *offset + number_of_bits > total_payload_data_size_in_bits { if *offset + number_of_bits > total_payload_data_size_in_bits {
return Err(Error::InvalidArgument); Err(ErrorCode::InvalidArgument)?;
} }
if input >= 1u64 << number_of_bits { if input >= 1u64 << number_of_bits {
return Err(Error::InvalidArgument); Err(ErrorCode::InvalidArgument)?;
} }
let mut index = *offset; let mut index = *offset;
@ -390,7 +391,7 @@ fn payload_base38_representation_with_tlv<const N: usize>(
let mut base38_encoded: heapless::String<N> = "MT:".into(); let mut base38_encoded: heapless::String<N> = "MT:".into();
for c in base38::encode(bits) { for c in base38::encode(bits) {
base38_encoded.push(c).map_err(|_| Error::NoSpace)?; base38_encoded.push(c).map_err(|_| ErrorCode::NoSpace)?;
} }
Ok(base38_encoded) Ok(base38_encoded)
@ -431,7 +432,7 @@ fn generate_bit_set<'a>(
TOTAL_PAYLOAD_DATA_SIZE_IN_BITS + tlv_data.map(|tlv_data| tlv_data.len() * 8).unwrap_or(0); TOTAL_PAYLOAD_DATA_SIZE_IN_BITS + tlv_data.map(|tlv_data| tlv_data.len() * 8).unwrap_or(0);
if bits_buf.len() * 8 < total_payload_size_in_bits { if bits_buf.len() * 8 < total_payload_size_in_bits {
return Err(Error::BufferTooSmall); Err(ErrorCode::BufferTooSmall)?;
}; };
let passwd = passwd_from_comm_data(payload.comm_data); let passwd = passwd_from_comm_data(payload.comm_data);

View file

@ -25,7 +25,7 @@ mod file_psm {
use log::info; use log::info;
use crate::error::Error; use crate::error::{Error, ErrorCode};
pub struct FilePsm { pub struct FilePsm {
dir: PathBuf, dir: PathBuf,
@ -47,7 +47,7 @@ mod file_psm {
loop { loop {
if offset == buf.len() { if offset == buf.len() {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
let len = file.read(&mut buf[offset..])?; let len = file.read(&mut buf[offset..])?;

View file

@ -22,11 +22,11 @@ use log::{error, trace};
use crate::{ use crate::{
cert::Cert, cert::Cert,
crypto::{self, KeyPair, Sha256}, crypto::{self, KeyPair, Sha256},
error::Error, error::{Error, ErrorCode},
fabric::{Fabric, FabricMgr}, fabric::{Fabric, FabricMgr},
secure_channel::common::SCStatusCodes, secure_channel::common::SCStatusCodes,
secure_channel::common::{self, OpCode}, secure_channel::common::{self, OpCode},
tlv::{get_root_node_struct, FromTLV, OctetStr, TLVElement, TLVWriter, TagType}, tlv::{get_root_node_struct, FromTLV, OctetStr, TLVWriter, TagType},
transport::{ transport::{
network::Address, network::Address,
proto_ctx::ProtoCtx, proto_ctx::ProtoCtx,
@ -90,9 +90,9 @@ impl<'a> Case<'a> {
.exch_ctx .exch_ctx
.exch .exch
.take_case_session::<CaseSession>() .take_case_session::<CaseSession>()
.ok_or(Error::InvalidState)?; .ok_or(ErrorCode::InvalidState)?;
if case_session.state != State::Sigma1Rx { if case_session.state != State::Sigma1Rx {
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
case_session.state = State::Sigma3Rx; case_session.state = State::Sigma3Rx;
@ -117,7 +117,7 @@ impl<'a> Case<'a> {
let mut decrypted: [u8; 800] = [0; 800]; let mut decrypted: [u8; 800] = [0; 800];
if encrypted.len() > decrypted.len() { if encrypted.len() > decrypted.len() {
error!("Data too large"); error!("Data too large");
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
let decrypted = &mut decrypted[..encrypted.len()]; let decrypted = &mut decrypted[..encrypted.len()];
decrypted.copy_from_slice(encrypted); decrypted.copy_from_slice(encrypted);
@ -204,7 +204,7 @@ impl<'a> Case<'a> {
case_session.local_fabric_idx = local_fabric_idx?; case_session.local_fabric_idx = local_fabric_idx?;
if r.peer_pub_key.0.len() != crypto::EC_POINT_LEN_BYTES { if r.peer_pub_key.0.len() != crypto::EC_POINT_LEN_BYTES {
error!("Invalid public key length"); error!("Invalid public key length");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
case_session.peer_pub_key.copy_from_slice(r.peer_pub_key.0); case_session.peer_pub_key.copy_from_slice(r.peer_pub_key.0);
trace!( trace!(
@ -220,7 +220,7 @@ impl<'a> Case<'a> {
let len = key_pair.derive_secret(r.peer_pub_key.0, &mut case_session.shared_secret)?; let len = key_pair.derive_secret(r.peer_pub_key.0, &mut case_session.shared_secret)?;
if len != 32 { if len != 32 {
error!("Derived secret length incorrect"); error!("Derived secret length incorrect");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
// println!("Derived secret: {:x?} len: {}", secret, len); // println!("Derived secret: {:x?} len: {}", secret, len);
@ -348,14 +348,14 @@ impl<'a> Case<'a> {
let mut verifier = noc.verify_chain_start(utc_calendar); let mut verifier = noc.verify_chain_start(utc_calendar);
if fabric.get_fabric_id() != noc.get_fabric_id()? { if fabric.get_fabric_id() != noc.get_fabric_id()? {
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
if let Some(icac) = icac { if let Some(icac) = icac {
// If ICAC is present handle it // If ICAC is present handle it
if let Ok(fid) = icac.get_fabric_id() { if let Ok(fid) = icac.get_fabric_id() {
if fid != fabric.get_fabric_id() { if fid != fabric.get_fabric_id() {
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
} }
verifier = verifier.add_cert(icac)?; verifier = verifier.add_cert(icac)?;
@ -377,7 +377,7 @@ impl<'a> Case<'a> {
0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x4b, 0x65, 0x79, 0x73,
]; ];
if key.len() < 48 { if key.len() < 48 {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
let mut salt = heapless::Vec::<u8, 256>::new(); let mut salt = heapless::Vec::<u8, 256>::new();
salt.extend_from_slice(ipk).unwrap(); salt.extend_from_slice(ipk).unwrap();
@ -388,7 +388,7 @@ impl<'a> Case<'a> {
// println!("Session Key: salt: {:x?}, len: {}", salt, salt.len()); // println!("Session Key: salt: {:x?}, len: {}", salt, salt.len());
crypto::hkdf_sha256(salt.as_slice(), shared_secret, &SEKEYS_INFO, key) crypto::hkdf_sha256(salt.as_slice(), shared_secret, &SEKEYS_INFO, key)
.map_err(|_x| Error::NoSpace)?; .map_err(|_x| ErrorCode::NoSpace)?;
// println!("Session Key: key: {:x?}", key); // println!("Session Key: key: {:x?}", key);
Ok(()) Ok(())
@ -425,7 +425,7 @@ impl<'a> Case<'a> {
) -> Result<(), Error> { ) -> Result<(), Error> {
const S3K_INFO: [u8; 6] = [0x53, 0x69, 0x67, 0x6d, 0x61, 0x33]; const S3K_INFO: [u8; 6] = [0x53, 0x69, 0x67, 0x6d, 0x61, 0x33];
if key.len() < 16 { if key.len() < 16 {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
let mut salt = heapless::Vec::<u8, 256>::new(); let mut salt = heapless::Vec::<u8, 256>::new();
salt.extend_from_slice(ipk).unwrap(); salt.extend_from_slice(ipk).unwrap();
@ -438,7 +438,7 @@ impl<'a> Case<'a> {
// println!("Sigma3Key: salt: {:x?}, len: {}", salt, salt.len()); // println!("Sigma3Key: salt: {:x?}, len: {}", salt, salt.len());
crypto::hkdf_sha256(salt.as_slice(), shared_secret, &S3K_INFO, key) crypto::hkdf_sha256(salt.as_slice(), shared_secret, &S3K_INFO, key)
.map_err(|_x| Error::NoSpace)?; .map_err(|_x| ErrorCode::NoSpace)?;
// println!("Sigma3Key: key: {:x?}", key); // println!("Sigma3Key: key: {:x?}", key);
Ok(()) Ok(())
@ -452,7 +452,7 @@ impl<'a> Case<'a> {
) -> Result<(), Error> { ) -> Result<(), Error> {
const S2K_INFO: [u8; 6] = [0x53, 0x69, 0x67, 0x6d, 0x61, 0x32]; const S2K_INFO: [u8; 6] = [0x53, 0x69, 0x67, 0x6d, 0x61, 0x32];
if key.len() < 16 { if key.len() < 16 {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
let mut salt = heapless::Vec::<u8, 256>::new(); let mut salt = heapless::Vec::<u8, 256>::new();
salt.extend_from_slice(ipk).unwrap(); salt.extend_from_slice(ipk).unwrap();
@ -467,7 +467,7 @@ impl<'a> Case<'a> {
// println!("Sigma2Key: salt: {:x?}, len: {}", salt, salt.len()); // println!("Sigma2Key: salt: {:x?}, len: {}", salt, salt.len());
crypto::hkdf_sha256(salt.as_slice(), &case_session.shared_secret, &S2K_INFO, key) crypto::hkdf_sha256(salt.as_slice(), &case_session.shared_secret, &S2K_INFO, key)
.map_err(|_x| Error::NoSpace)?; .map_err(|_x| ErrorCode::NoSpace)?;
// println!("Sigma2Key: key: {:x?}", key); // println!("Sigma2Key: key: {:x?}", key);
Ok(()) Ok(())

View file

@ -57,7 +57,7 @@ impl<'a> SecureChannel<'a> {
pub fn handle(&mut self, ctx: &mut ProtoCtx) -> Result<(bool, Option<CloneData>), Error> { pub fn handle(&mut self, ctx: &mut ProtoCtx) -> Result<(bool, Option<CloneData>), Error> {
let proto_opcode: OpCode = let proto_opcode: OpCode =
num::FromPrimitive::from_u8(ctx.rx.get_proto_opcode()).ok_or(Error::Invalid)?; num::FromPrimitive::from_u8(ctx.rx.get_proto_opcode()).ok_or(ErrorCode::Invalid)?;
ctx.tx.set_proto_id(PROTO_ID_SECURE_CHANNEL); ctx.tx.set_proto_id(PROTO_ID_SECURE_CHANNEL);
info!("Received Opcode: {:?}", proto_opcode); info!("Received Opcode: {:?}", proto_opcode);
info!("Received Data:"); info!("Received Data:");
@ -82,7 +82,7 @@ impl<'a> SecureChannel<'a> {
OpCode::CASESigma3 => self.case.casesigma3_handler(ctx), OpCode::CASESigma3 => self.case.casesigma3_handler(ctx),
_ => { _ => {
error!("OpCode Not Handled: {:?}", proto_opcode); error!("OpCode Not Handled: {:?}", proto_opcode);
Err(Error::InvalidOpcode) Err(ErrorCode::InvalidOpcode.into())
} }
}?; }?;

View file

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::error::Error; use crate::error::{Error, ErrorCode};
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -29,35 +29,35 @@ impl CryptoSpake2 {
// Computes w0 from w0s respectively // Computes w0 from w0s respectively
pub fn set_w0_from_w0s(&mut self, _w0s: &[u8]) -> Result<(), Error> { pub fn set_w0_from_w0s(&mut self, _w0s: &[u8]) -> Result<(), Error> {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
pub fn set_w1_from_w1s(&mut self, _w1s: &[u8]) -> Result<(), Error> { pub fn set_w1_from_w1s(&mut self, _w1s: &[u8]) -> Result<(), Error> {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
pub fn set_w0(&mut self, _w0: &[u8]) -> Result<(), Error> { pub fn set_w0(&mut self, _w0: &[u8]) -> Result<(), Error> {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
pub fn set_w1(&mut self, _w1: &[u8]) -> Result<(), Error> { pub fn set_w1(&mut self, _w1: &[u8]) -> Result<(), Error> {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn set_L(&mut self, _l: &[u8]) -> Result<(), Error> { pub fn set_L(&mut self, _l: &[u8]) -> Result<(), Error> {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[allow(dead_code)] #[allow(dead_code)]
pub fn set_L_from_w1s(&mut self, _w1s: &[u8]) -> Result<(), Error> { pub fn set_L_from_w1s(&mut self, _w1s: &[u8]) -> Result<(), Error> {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn get_pB(&mut self, _pB: &mut [u8]) -> Result<(), Error> { pub fn get_pB(&mut self, _pB: &mut [u8]) -> Result<(), Error> {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
#[allow(non_snake_case)] #[allow(non_snake_case)]
@ -68,6 +68,6 @@ impl CryptoSpake2 {
_pB: &[u8], _pB: &[u8],
_out: &mut [u8], _out: &mut [u8],
) -> Result<(), Error> { ) -> Result<(), Error> {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }

View file

@ -18,7 +18,7 @@
use alloc::sync::Arc; use alloc::sync::Arc;
use core::ops::{Mul, Sub}; use core::ops::{Mul, Sub};
use crate::error::Error; use crate::error::{Error, ErrorCode};
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
use log::error; use log::error;
@ -150,7 +150,7 @@ impl CryptoSpake2 {
let pB_internal = pB_internal.as_slice(); let pB_internal = pB_internal.as_slice();
if pB_internal.len() != pB.len() { if pB_internal.len() != pB.len() {
error!("pB length mismatch"); error!("pB length mismatch");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
pB.copy_from_slice(pB_internal); pB.copy_from_slice(pB_internal);
Ok(()) Ok(())

View file

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::error::Error; use crate::error::{Error, ErrorCode};
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
use log::error; use log::error;
@ -158,7 +158,7 @@ impl CryptoSpake2 {
let pB_internal = pB_internal.as_slice(); let pB_internal = pB_internal.as_slice();
if pB_internal.len() != pB.len() { if pB_internal.len() != pB.len() {
error!("pB length mismatch"); error!("pB length mismatch");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
pB.copy_from_slice(pB_internal); pB.copy_from_slice(pB_internal);
Ok(()) Ok(())

View file

@ -23,10 +23,10 @@ use super::{
}; };
use crate::{ use crate::{
crypto, crypto,
error::Error, error::{Error, ErrorCode},
mdns::{MdnsMgr, ServiceMode}, mdns::{MdnsMgr, ServiceMode},
secure_channel::common::OpCode, secure_channel::common::OpCode,
tlv::{self, get_root_node_struct, FromTLV, OctetStr, TLVElement, TLVWriter, TagType, ToTLV}, tlv::{self, get_root_node_struct, FromTLV, OctetStr, TLVWriter, TagType, ToTLV},
transport::{ transport::{
exchange::ExchangeCtx, exchange::ExchangeCtx,
network::Address, network::Address,
@ -176,7 +176,7 @@ impl PakeState {
if let PakeState::InProgress(s) = new { if let PakeState::InProgress(s) = new {
Ok(s) Ok(s)
} else { } else {
Err(Error::InvalidSignature) Err(ErrorCode::InvalidSignature.into())
} }
} }
@ -187,7 +187,7 @@ impl PakeState {
fn take_sess_data(&mut self, exch_ctx: &ExchangeCtx) -> Result<SessionData, Error> { fn take_sess_data(&mut self, exch_ctx: &ExchangeCtx) -> Result<SessionData, Error> {
let sd = self.take()?; let sd = self.take()?;
if sd.exch_id != exch_ctx.exch.get_id() || sd.peer_addr != exch_ctx.sess.get_peer_addr() { if sd.exch_id != exch_ctx.exch.get_id() || sd.peer_addr != exch_ctx.sess.get_peer_addr() {
Err(Error::InvalidState) Err(ErrorCode::InvalidState.into())
} else { } else {
Ok(sd) Ok(sd)
} }
@ -240,10 +240,10 @@ impl Pake {
let clone_data = if status_code == SCStatusCodes::SessionEstablishmentSuccess { let clone_data = if status_code == SCStatusCodes::SessionEstablishmentSuccess {
// Get the keys // Get the keys
let ke = ke.ok_or(Error::Invalid)?; let ke = ke.ok_or(ErrorCode::Invalid)?;
let mut session_keys: [u8; 48] = [0; 48]; let mut session_keys: [u8; 48] = [0; 48];
crypto::hkdf_sha256(&[], ke, &SPAKE2_SESSION_KEYS_INFO, &mut session_keys) crypto::hkdf_sha256(&[], ke, &SPAKE2_SESSION_KEYS_INFO, &mut session_keys)
.map_err(|_x| Error::NoSpace)?; .map_err(|_x| ErrorCode::NoSpace)?;
// Create a session // Create a session
let data = sd.spake2p.get_app_data(); let data = sd.spake2p.get_app_data();
@ -314,7 +314,7 @@ impl Pake {
let a = PBKDFParamReq::from_tlv(&root)?; let a = PBKDFParamReq::from_tlv(&root)?;
if a.passcode_id != 0 { if a.passcode_id != 0 {
error!("Can't yet handle passcode_id != 0"); error!("Can't yet handle passcode_id != 0");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
let mut our_random: [u8; 32] = [0; 32]; let mut our_random: [u8; 32] = [0; 32];

View file

@ -25,7 +25,7 @@ use subtle::ConstantTimeEq;
use crate::{ use crate::{
crypto::{pbkdf2_hmac, Sha256}, crypto::{pbkdf2_hmac, Sha256},
error::Error, error::{Error, ErrorCode},
}; };
use super::{common::SCStatusCodes, crypto::CryptoSpake2}; use super::{common::SCStatusCodes, crypto::CryptoSpake2};
@ -198,7 +198,7 @@ impl Spake2P {
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub fn handle_pA(&mut self, pA: &[u8], pB: &mut [u8], cB: &mut [u8]) -> Result<(), Error> { pub fn handle_pA(&mut self, pA: &[u8], pB: &mut [u8], cB: &mut [u8]) -> Result<(), Error> {
if self.mode != Spake2Mode::Verifier(Spake2VerifierState::Init) { if self.mode != Spake2Mode::Verifier(Spake2VerifierState::Init) {
return Err(Error::InvalidState); Err(ErrorCode::InvalidState)?;
} }
if let Some(crypto_spake2) = &mut self.crypto_spake2 { if let Some(crypto_spake2) = &mut self.crypto_spake2 {
@ -251,13 +251,13 @@ impl Spake2P {
if ke_internal.len() == Ke.len() { if ke_internal.len() == Ke.len() {
Ke.copy_from_slice(ke_internal); Ke.copy_from_slice(ke_internal);
} else { } else {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
// Step 2: KcA || KcB = KDF(nil, Ka, "ConfirmationKeys") // Step 2: KcA || KcB = KDF(nil, Ka, "ConfirmationKeys")
let mut KcAKcB: [u8; 32] = [0; 32]; let mut KcAKcB: [u8; 32] = [0; 32];
crypto::hkdf_sha256(&[], Ka, &SPAKE2P_KEY_CONFIRM_INFO, &mut KcAKcB) crypto::hkdf_sha256(&[], Ka, &SPAKE2P_KEY_CONFIRM_INFO, &mut KcAKcB)
.map_err(|_x| Error::NoSpace)?; .map_err(|_x| ErrorCode::NoSpace)?;
let KcA = &KcAKcB[0..(KcAKcB.len() / 2)]; let KcA = &KcAKcB[0..(KcAKcB.len() / 2)];
let KcB = &KcAKcB[(KcAKcB.len() / 2)..]; let KcB = &KcAKcB[(KcAKcB.len() / 2)..];

View file

@ -46,6 +46,7 @@ pub fn create_status_report(
proto_code: u16, proto_code: u16,
proto_data: Option<&[u8]>, proto_data: Option<&[u8]>,
) -> Result<(), Error> { ) -> Result<(), Error> {
proto_tx.reset();
proto_tx.set_proto_id(PROTO_ID_SECURE_CHANNEL); proto_tx.set_proto_id(PROTO_ID_SECURE_CHANNEL);
proto_tx.set_proto_opcode(OpCode::StatusReport as u8); proto_tx.set_proto_opcode(OpCode::StatusReport as u8);
let wb = proto_tx.get_writebuf()?; let wb = proto_tx.get_writebuf()?;

View file

@ -15,7 +15,7 @@
* limitations under the License. * limitations under the License.
*/ */
use crate::error::Error; use crate::error::{Error, ErrorCode};
use byteorder::{ByteOrder, LittleEndian}; use byteorder::{ByteOrder, LittleEndian};
use core::fmt; use core::fmt;
@ -284,7 +284,7 @@ fn read_length_value<'a>(
// We'll consume the current offset (len) + the entire string // We'll consume the current offset (len) + the entire string
if length + size_of_length_field > t.left { if length + size_of_length_field > t.left {
// Return Error // Return Error
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} else { } else {
Ok(( Ok((
// return the additional size only // return the additional size only
@ -390,14 +390,14 @@ impl<'a> TLVElement<'a> {
pub fn i8(&self) -> Result<i8, Error> { pub fn i8(&self) -> Result<i8, Error> {
match self.element_type { match self.element_type {
ElementType::S8(a) => Ok(a), ElementType::S8(a) => Ok(a),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
pub fn u8(&self) -> Result<u8, Error> { pub fn u8(&self) -> Result<u8, Error> {
match self.element_type { match self.element_type {
ElementType::U8(a) => Ok(a), ElementType::U8(a) => Ok(a),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
@ -405,7 +405,7 @@ impl<'a> TLVElement<'a> {
match self.element_type { match self.element_type {
ElementType::U8(a) => Ok(a.into()), ElementType::U8(a) => Ok(a.into()),
ElementType::U16(a) => Ok(a), ElementType::U16(a) => Ok(a),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
@ -414,7 +414,7 @@ impl<'a> TLVElement<'a> {
ElementType::U8(a) => Ok(a.into()), ElementType::U8(a) => Ok(a.into()),
ElementType::U16(a) => Ok(a.into()), ElementType::U16(a) => Ok(a.into()),
ElementType::U32(a) => Ok(a), ElementType::U32(a) => Ok(a),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
@ -424,7 +424,7 @@ impl<'a> TLVElement<'a> {
ElementType::U16(a) => Ok(a.into()), ElementType::U16(a) => Ok(a.into()),
ElementType::U32(a) => Ok(a.into()), ElementType::U32(a) => Ok(a.into()),
ElementType::U64(a) => Ok(a), ElementType::U64(a) => Ok(a),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
@ -434,7 +434,7 @@ impl<'a> TLVElement<'a> {
| ElementType::Utf8l(s) | ElementType::Utf8l(s)
| ElementType::Str16l(s) | ElementType::Str16l(s)
| ElementType::Utf16l(s) => Ok(s), | ElementType::Utf16l(s) => Ok(s),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
@ -444,9 +444,9 @@ impl<'a> TLVElement<'a> {
| ElementType::Utf8l(s) | ElementType::Utf8l(s)
| ElementType::Str16l(s) | ElementType::Str16l(s)
| ElementType::Utf16l(s) => { | ElementType::Utf16l(s) => {
Ok(core::str::from_utf8(s).map_err(|_| Error::InvalidData)?) Ok(core::str::from_utf8(s).map_err(|_| Error::from(ErrorCode::InvalidData))?)
} }
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
@ -454,48 +454,48 @@ impl<'a> TLVElement<'a> {
match self.element_type { match self.element_type {
ElementType::False => Ok(false), ElementType::False => Ok(false),
ElementType::True => Ok(true), ElementType::True => Ok(true),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
pub fn null(&self) -> Result<(), Error> { pub fn null(&self) -> Result<(), Error> {
match self.element_type { match self.element_type {
ElementType::Null => Ok(()), ElementType::Null => Ok(()),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
pub fn confirm_struct(&self) -> Result<TLVElement<'a>, Error> { pub fn confirm_struct(&self) -> Result<TLVElement<'a>, Error> {
match self.element_type { match self.element_type {
ElementType::Struct(_) => Ok(*self), ElementType::Struct(_) => Ok(*self),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
pub fn confirm_array(&self) -> Result<TLVElement<'a>, Error> { pub fn confirm_array(&self) -> Result<TLVElement<'a>, Error> {
match self.element_type { match self.element_type {
ElementType::Array(_) => Ok(*self), ElementType::Array(_) => Ok(*self),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
pub fn confirm_list(&self) -> Result<TLVElement<'a>, Error> { pub fn confirm_list(&self) -> Result<TLVElement<'a>, Error> {
match self.element_type { match self.element_type {
ElementType::List(_) => Ok(*self), ElementType::List(_) => Ok(*self),
_ => Err(Error::TLVTypeMismatch), _ => Err(ErrorCode::TLVTypeMismatch.into()),
} }
} }
pub fn find_tag(&self, tag: u32) -> Result<TLVElement<'a>, Error> { pub fn find_tag(&self, tag: u32) -> Result<TLVElement<'a>, Error> {
let match_tag: TagType = TagType::Context(tag as u8); let match_tag: TagType = TagType::Context(tag as u8);
let iter = self.enter().ok_or(Error::TLVTypeMismatch)?; let iter = self.enter().ok_or(ErrorCode::TLVTypeMismatch)?;
for a in iter { for a in iter {
if match_tag == a.tag_type { if match_tag == a.tag_type {
return Ok(a); return Ok(a);
} }
} }
Err(Error::NoTagFound) Err(ErrorCode::NoTagFound.into())
} }
pub fn get_tag(&self) -> TagType { pub fn get_tag(&self) -> TagType {
@ -721,14 +721,17 @@ impl<'a> Iterator for TLVContainerIterator<'a> {
} }
pub fn get_root_node(b: &[u8]) -> Result<TLVElement, Error> { pub fn get_root_node(b: &[u8]) -> Result<TLVElement, Error> {
TLVList::new(b).iter().next().ok_or(Error::InvalidData) Ok(TLVList::new(b)
.iter()
.next()
.ok_or(ErrorCode::InvalidData)?)
} }
pub fn get_root_node_struct(b: &[u8]) -> Result<TLVElement, Error> { pub fn get_root_node_struct(b: &[u8]) -> Result<TLVElement, Error> {
TLVList::new(b) TLVList::new(b)
.iter() .iter()
.next() .next()
.ok_or(Error::InvalidData)? .ok_or(ErrorCode::InvalidData)?
.confirm_struct() .confirm_struct()
} }
@ -736,7 +739,7 @@ pub fn get_root_node_list(b: &[u8]) -> Result<TLVElement, Error> {
TLVList::new(b) TLVList::new(b)
.iter() .iter()
.next() .next()
.ok_or(Error::InvalidData)? .ok_or(ErrorCode::InvalidData)?
.confirm_list() .confirm_list()
} }
@ -802,7 +805,7 @@ mod tests {
get_root_node_list, get_root_node_struct, ElementType, Pointer, TLVElement, TLVList, get_root_node_list, get_root_node_struct, ElementType, Pointer, TLVElement, TLVList,
TagType, TagType,
}; };
use crate::error::Error; use crate::error::ErrorCode;
#[test] #[test]
fn test_short_length_tag() { fn test_short_length_tag() {
@ -1146,7 +1149,10 @@ mod tests {
element_type: ElementType::U32(1), element_type: ElementType::U32(1),
} }
); );
assert_eq!(cmd_path.find_tag(3), Err(Error::NoTagFound)); assert_eq!(
cmd_path.find_tag(3).map_err(|e| e.code()),
Err(ErrorCode::NoTagFound)
);
// This is the variable of the invoke command // This is the variable of the invoke command
assert_eq!( assert_eq!(

View file

@ -16,7 +16,7 @@
*/ */
use super::{ElementType, TLVContainerIterator, TLVElement, TLVWriter, TagType}; use super::{ElementType, TLVContainerIterator, TLVElement, TLVWriter, TagType};
use crate::error::Error; use crate::error::{Error, ErrorCode};
use core::fmt::Debug; use core::fmt::Debug;
use core::slice::Iter; use core::slice::Iter;
use log::error; use log::error;
@ -31,7 +31,7 @@ pub trait FromTLV<'a> {
where where
Self: Sized, Self: Sized,
{ {
Err(Error::TLVNotFound) Err(ErrorCode::TLVNotFound.into())
} }
} }
@ -45,7 +45,8 @@ impl<'a, T: FromTLV<'a> + Default, const N: usize> FromTLV<'a> for [T; N] {
let mut a = heapless::Vec::<T, N>::new(); let mut a = heapless::Vec::<T, N>::new();
if let Some(tlv_iter) = t.enter() { if let Some(tlv_iter) = t.enter() {
for element in tlv_iter { for element in tlv_iter {
a.push(T::from_tlv(&element)?).map_err(|_| Error::NoSpace)?; a.push(T::from_tlv(&element)?)
.map_err(|_| ErrorCode::NoSpace)?;
} }
} }
@ -53,10 +54,10 @@ impl<'a, T: FromTLV<'a> + Default, const N: usize> FromTLV<'a> for [T; N] {
// implementation on top of heapless::Vec (to avoid requiring Copy) // implementation on top of heapless::Vec (to avoid requiring Copy)
// Not sure why we actually need that yet, but without it unit tests fail // Not sure why we actually need that yet, but without it unit tests fail
while a.len() < N { while a.len() < N {
a.push(Default::default()).map_err(|_| Error::NoSpace)?; a.push(Default::default()).map_err(|_| ErrorCode::NoSpace)?;
} }
a.into_array().map_err(|_| Error::Invalid) a.into_array().map_err(|_| ErrorCode::Invalid.into())
} }
} }
@ -131,7 +132,7 @@ impl<'a> UtfStr<'a> {
} }
pub fn as_str(&self) -> Result<&str, Error> { pub fn as_str(&self) -> Result<&str, Error> {
core::str::from_utf8(self.0).map_err(|_| Error::Invalid) core::str::from_utf8(self.0).map_err(|_| ErrorCode::Invalid.into())
} }
} }
@ -172,7 +173,7 @@ impl<'a> ToTLV for OctetStr<'a> {
/// Implements the Owned version of Octet String /// Implements the Owned version of Octet String
impl<const N: usize> FromTLV<'_> for heapless::Vec<u8, N> { impl<const N: usize> FromTLV<'_> for heapless::Vec<u8, N> {
fn from_tlv(t: &TLVElement) -> Result<heapless::Vec<u8, N>, Error> { fn from_tlv(t: &TLVElement) -> Result<heapless::Vec<u8, N>, Error> {
heapless::Vec::from_slice(t.slice()?).map_err(|_| Error::NoSpace) heapless::Vec::from_slice(t.slice()?).map_err(|_| ErrorCode::NoSpace.into())
} }
} }
@ -189,7 +190,7 @@ impl<const N: usize> FromTLV<'_> for heapless::String<N> {
string string
.push_str(core::str::from_utf8(t.slice()?)?) .push_str(core::str::from_utf8(t.slice()?)?)
.map_err(|_| Error::NoSpace)?; .map_err(|_| ErrorCode::NoSpace)?;
Ok(string) Ok(string)
} }
@ -411,7 +412,7 @@ impl<'a> ToTLV for TLVElement<'a> {
ElementType::EndCnt => tw.end_container(), ElementType::EndCnt => tw.end_container(),
_ => { _ => {
error!("ToTLV Not supported"); error!("ToTLV Not supported");
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }
} }
@ -419,7 +420,7 @@ impl<'a> ToTLV for TLVElement<'a> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{FromTLV, OctetStr, TLVElement, TLVWriter, TagType, ToTLV}; use super::{FromTLV, OctetStr, TLVWriter, TagType, ToTLV};
use crate::{error::Error, tlv::TLVList, utils::writebuf::WriteBuf}; use crate::{error::Error, tlv::TLVList, utils::writebuf::WriteBuf};
use matter_macro_derive::{FromTLV, ToTLV}; use matter_macro_derive::{FromTLV, ToTLV};

View file

@ -164,7 +164,7 @@ impl<'a, 'b> TLVWriter<'a, 'b> {
pub fn str8(&mut self, tag_type: TagType, data: &[u8]) -> Result<(), Error> { pub fn str8(&mut self, tag_type: TagType, data: &[u8]) -> Result<(), Error> {
if data.len() > 256 { if data.len() > 256 {
error!("use str16() instead"); error!("use str16() instead");
return Err(Error::Invalid); return Err(ErrorCode::Invalid.into());
} }
self.put_control_tag(tag_type, WriteElementType::Str8l)?; self.put_control_tag(tag_type, WriteElementType::Str8l)?;
self.buf.le_u8(data.len() as u8)?; self.buf.le_u8(data.len() as u8)?;

View file

@ -21,11 +21,10 @@ use core::fmt;
use core::time::Duration; use core::time::Duration;
use log::{error, info, trace}; use log::{error, info, trace};
use crate::error::Error; use crate::error::{Error, ErrorCode};
use crate::interaction_model::core::{ResumeReadReq, ResumeSubscribeReq}; use crate::interaction_model::core::{ResumeReadReq, ResumeSubscribeReq};
use crate::secure_channel; use crate::secure_channel;
use crate::secure_channel::case::CaseSession; use crate::secure_channel::case::CaseSession;
use crate::tlv::print_tlv_list;
use crate::utils::epoch::Epoch; use crate::utils::epoch::Epoch;
use crate::utils::rand::Rand; use crate::utils::rand::Rand;
@ -227,7 +226,8 @@ impl Exchange {
tx.get_proto_id(), tx.get_proto_id(),
tx.get_proto_opcode(), tx.get_proto_opcode(),
); );
print_tlv_list(tx.as_slice());
//print_tlv_list(tx.as_slice());
tx.proto.exch_id = self.id; tx.proto.exch_id = self.id;
if self.role == Role::Initiator { if self.role == Role::Initiator {
@ -317,10 +317,10 @@ impl ExchangeMgr {
info!("Creating new exchange"); info!("Creating new exchange");
let e = Exchange::new(id, sess_idx, role); let e = Exchange::new(id, sess_idx, role);
if exchanges.insert(id, e).is_err() { if exchanges.insert(id, e).is_err() {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
} else { } else {
return Err(Error::NoSpace); Err(ErrorCode::NoSpace)?;
} }
} }
@ -330,11 +330,11 @@ impl ExchangeMgr {
if result.get_role() == role && sess_idx == result.sess_idx { if result.get_role() == role && sess_idx == result.sess_idx {
Ok(result) Ok(result)
} else { } else {
Err(Error::NoExchange) Err(ErrorCode::NoExchange.into())
} }
} else { } else {
error!("This should never happen"); error!("This should never happen");
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
} }
@ -375,7 +375,7 @@ impl ExchangeMgr {
pub fn send(&mut self, exch_id: u16, tx: &mut Packet) -> Result<bool, Error> { pub fn send(&mut self, exch_id: u16, tx: &mut Packet) -> Result<bool, Error> {
let exchange = let exchange =
ExchangeMgr::_get_with_id(&mut self.exchanges, exch_id).ok_or(Error::NoExchange)?; ExchangeMgr::_get_with_id(&mut self.exchanges, exch_id).ok_or(ErrorCode::NoExchange)?;
let mut session = self.sess_mgr.get_session_handle(exchange.sess_idx); let mut session = self.sess_mgr.get_session_handle(exchange.sess_idx);
exchange.send(tx, &mut session) exchange.send(tx, &mut session)
} }
@ -474,7 +474,7 @@ impl fmt::Display for ExchangeMgr {
#[allow(clippy::bool_assert_comparison)] #[allow(clippy::bool_assert_comparison)]
mod tests { mod tests {
use crate::{ use crate::{
error::Error, error::ErrorCode,
transport::{ transport::{
network::Address, network::Address,
session::{CloneData, SessionMode}, session::{CloneData, SessionMode},
@ -532,9 +532,12 @@ mod tests {
let clone_data = get_clone_data(peer_sess_id, local_sess_id); let clone_data = get_clone_data(peer_sess_id, local_sess_id);
match mgr.add_session(&clone_data) { match mgr.add_session(&clone_data) {
Ok(s) => assert_eq!(peer_sess_id, s.get_peer_sess_id()), Ok(s) => assert_eq!(peer_sess_id, s.get_peer_sess_id()),
Err(Error::NoSpace) => break, Err(e) => {
_ => { if e.code() == ErrorCode::NoSpace {
panic!("Couldn't, create session"); break;
} else {
panic!("Could not create sessions");
}
} }
} }
local_sess_id += 1; local_sess_id += 1;
@ -576,7 +579,10 @@ mod tests {
for i in 1..(MAX_SESSIONS + 1) { for i in 1..(MAX_SESSIONS + 1) {
// Now purposefully overflow the sessions by adding another session // Now purposefully overflow the sessions by adding another session
let result = mgr.add_session(&get_clone_data(new_peer_sess_id, new_local_sess_id)); let result = mgr.add_session(&get_clone_data(new_peer_sess_id, new_local_sess_id));
assert!(matches!(result, Err(Error::NoSpace))); assert!(matches!(
result.map_err(|e| e.code()),
Err(ErrorCode::NoSpace)
));
let mut buf = [0; MAX_TX_BUF_SIZE]; let mut buf = [0; MAX_TX_BUF_SIZE];
let tx = &mut Packet::new_tx(&mut buf); let tx = &mut Packet::new_tx(&mut buf);

View file

@ -109,14 +109,18 @@ impl<'r, 'a, 'p> RecvCompletion<'r, 'a, 'p> {
} }
} }
Ok(None) => (RecvState::Ack, None), Ok(None) => (RecvState::Ack, None),
Err(Error::Duplicate) => (RecvState::Ack, None), Err(e) => match e.code() {
Err(Error::NoSpace) => (RecvState::EvictSession, None), ErrorCode::Duplicate => (RecvState::Ack, None),
Err(err) => Err(err)?, ErrorCode::NoSpace => (RecvState::EvictSession, None),
_ => Err(e)?,
},
}, },
RecvState::AddSession(clone_data) => match self.mgr.exch_mgr.add_session(&clone_data) { RecvState::AddSession(clone_data) => match self.mgr.exch_mgr.add_session(&clone_data) {
Ok(_) => (RecvState::Ack, None), Ok(_) => (RecvState::Ack, None),
Err(Error::NoSpace) => (RecvState::EvictSession2(clone_data), None), Err(e) => match e.code() {
Err(err) => Err(err)?, ErrorCode::NoSpace => (RecvState::EvictSession2(clone_data), None),
_ => Err(e)?,
},
}, },
RecvState::EvictSession => { RecvState::EvictSession => {
if self.mgr.exch_mgr.evict_session(&mut self.tx)? { if self.mgr.exch_mgr.evict_session(&mut self.tx)? {

View file

@ -59,7 +59,7 @@ impl AckEntry {
ack_timeout, ack_timeout,
}) })
} else { } else {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }
@ -120,7 +120,7 @@ impl ReliableMessage {
if self.retrans.is_some() { if self.retrans.is_some() {
// This indicates there was some existing entry for same sess-id/exch-id, which shouldnt happen // This indicates there was some existing entry for same sess-id/exch-id, which shouldnt happen
error!("Previous retrans entry for this exchange already exists"); error!("Previous retrans entry for this exchange already exists");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
self.retrans = Some(RetransEntry::new(proto_tx.plain.ctr)); self.retrans = Some(RetransEntry::new(proto_tx.plain.ctr));
@ -135,7 +135,7 @@ impl ReliableMessage {
pub fn recv(&mut self, proto_rx: &Packet, epoch: Epoch) -> Result<(), Error> { pub fn recv(&mut self, proto_rx: &Packet, epoch: Epoch) -> Result<(), Error> {
if proto_rx.proto.is_ack() { if proto_rx.proto.is_ack() {
// Handle received Acks // Handle received Acks
let ack_msg_ctr = proto_rx.proto.get_ack_msg_ctr().ok_or(Error::Invalid)?; let ack_msg_ctr = proto_rx.proto.get_ack_msg_ctr().ok_or(ErrorCode::Invalid)?;
if let Some(entry) = &self.retrans { if let Some(entry) = &self.retrans {
if entry.get_msg_ctr() != ack_msg_ctr { if entry.get_msg_ctr() != ack_msg_ctr {
// TODO: XXX Fix this // TODO: XXX Fix this
@ -150,7 +150,7 @@ impl ReliableMessage {
// This indicates there was some existing entry for same sess-id/exch-id, which shouldnt happen // This indicates there was some existing entry for same sess-id/exch-id, which shouldnt happen
// TODO: As per the spec if this happens, we need to send out the previous ACK and note this new ACK // TODO: As per the spec if this happens, we need to send out the previous ACK and note this new ACK
error!("Previous ACK entry for this exchange already exists"); error!("Previous ACK entry for this exchange already exists");
return Err(Error::Invalid); Err(ErrorCode::Invalid)?;
} }
self.ack = Some(AckEntry::new(proto_rx.plain.ctr, epoch)?); self.ack = Some(AckEntry::new(proto_rx.plain.ctr, epoch)?);

View file

@ -18,7 +18,7 @@
use log::error; use log::error;
use crate::{ use crate::{
error::Error, error::{Error, ErrorCode},
utils::{parsebuf::ParseBuf, writebuf::WriteBuf}, utils::{parsebuf::ParseBuf, writebuf::WriteBuf},
}; };
@ -109,7 +109,7 @@ impl<'a> Packet<'a> {
if let Direction::Rx(pbuf, _) = &mut self.data { if let Direction::Rx(pbuf, _) = &mut self.data {
Ok(pbuf) Ok(pbuf)
} else { } else {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }
@ -117,7 +117,7 @@ impl<'a> Packet<'a> {
if let Direction::Tx(wbuf) = &mut self.data { if let Direction::Tx(wbuf) = &mut self.data {
Ok(wbuf) Ok(wbuf)
} else { } else {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} }
} }
@ -158,10 +158,10 @@ impl<'a> Packet<'a> {
.decrypt_and_decode(&self.plain, pb, peer_nodeid, dec_key) .decrypt_and_decode(&self.plain, pb, peer_nodeid, dec_key)
} else { } else {
error!("Invalid state for proto_decode"); error!("Invalid state for proto_decode");
Err(Error::InvalidState) Err(ErrorCode::InvalidState.into())
} }
} }
_ => Err(Error::InvalidState), _ => Err(ErrorCode::InvalidState.into()),
} }
} }
@ -171,7 +171,7 @@ impl<'a> Packet<'a> {
RxState::Uninit => Ok(false), RxState::Uninit => Ok(false),
_ => Ok(true), _ => Ok(true),
}, },
_ => Err(Error::InvalidState), _ => Err(ErrorCode::InvalidState.into()),
} }
} }
@ -183,10 +183,10 @@ impl<'a> Packet<'a> {
self.plain.decode(pb) self.plain.decode(pb)
} else { } else {
error!("Invalid state for plain_decode"); error!("Invalid state for plain_decode");
Err(Error::InvalidState) Err(ErrorCode::InvalidState.into())
} }
} }
_ => Err(Error::InvalidState), _ => Err(ErrorCode::InvalidState.into()),
} }
} }
} }

View file

@ -65,7 +65,7 @@ impl PlainHdr {
impl PlainHdr { impl PlainHdr {
// it will have an additional 'message length' field first // it will have an additional 'message length' field first
pub fn decode(&mut self, msg: &mut ParseBuf) -> Result<(), Error> { pub fn decode(&mut self, msg: &mut ParseBuf) -> Result<(), Error> {
self.flags = MsgFlags::from_bits(msg.le_u8()?).ok_or(Error::Invalid)?; self.flags = MsgFlags::from_bits(msg.le_u8()?).ok_or(ErrorCode::Invalid)?;
self.sess_id = msg.le_u16()?; self.sess_id = msg.le_u16()?;
let _sec_flags = msg.le_u8()?; let _sec_flags = msg.le_u8()?;
self.sess_type = if self.sess_id != 0 { self.sess_type = if self.sess_id != 0 {

View file

@ -105,7 +105,7 @@ impl ProtoHdr {
decrypt_in_place(plain_hdr.ctr, peer_nodeid, parsebuf, d)?; decrypt_in_place(plain_hdr.ctr, peer_nodeid, parsebuf, d)?;
} }
self.exch_flags = ExchFlags::from_bits(parsebuf.le_u8()?).ok_or(Error::Invalid)?; self.exch_flags = ExchFlags::from_bits(parsebuf.le_u8()?).ok_or(ErrorCode::Invalid)?;
self.proto_opcode = parsebuf.le_u8()?; self.proto_opcode = parsebuf.le_u8()?;
self.exch_id = parsebuf.le_u16()?; self.exch_id = parsebuf.le_u16()?;
self.proto_id = parsebuf.le_u16()?; self.proto_id = parsebuf.le_u16()?;
@ -128,10 +128,10 @@ impl ProtoHdr {
resp_buf.le_u16(self.exch_id)?; resp_buf.le_u16(self.exch_id)?;
resp_buf.le_u16(self.proto_id)?; resp_buf.le_u16(self.proto_id)?;
if self.is_vendor() { if self.is_vendor() {
resp_buf.le_u16(self.proto_vendor_id.ok_or(Error::Invalid)?)?; resp_buf.le_u16(self.proto_vendor_id.ok_or(ErrorCode::Invalid)?)?;
} }
if self.is_ack() { if self.is_ack() {
resp_buf.le_u32(self.ack_msg_ctr.ok_or(Error::Invalid)?)?; resp_buf.le_u32(self.ack_msg_ctr.ok_or(ErrorCode::Invalid)?)?;
} }
Ok(()) Ok(())
} }
@ -216,7 +216,7 @@ fn decrypt_in_place(
// If so, we need to handle it cleanly here. // If so, we need to handle it cleanly here.
aad.copy_from_slice(parsed_slice); aad.copy_from_slice(parsed_slice);
} else { } else {
return Err(Error::InvalidAAD); Err(ErrorCode::InvalidAAD)?;
} }
// IV: // IV:

View file

@ -410,7 +410,7 @@ impl SessionMgr {
self.sessions[index] = Some(session); self.sessions[index] = Some(session);
Ok(index) Ok(index)
} else { } else {
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
} }
@ -465,7 +465,7 @@ impl SessionMgr {
info!("Creating new session"); info!("Creating new session");
self.add(peer_addr, peer_nodeid) self.add(peer_addr, peer_nodeid)
} else { } else {
Err(Error::NotFound) Err(ErrorCode::NotFound.into())
} }
} }
@ -484,14 +484,14 @@ impl SessionMgr {
let duplicate = session.rx_ctr_state.recv(rx.plain.ctr, is_encrypted); let duplicate = session.rx_ctr_state.recv(rx.plain.ctr, is_encrypted);
if duplicate { if duplicate {
info!("Dropping duplicate packet"); info!("Dropping duplicate packet");
Err(Error::Duplicate) Err(ErrorCode::Duplicate.into())
} else { } else {
Ok(sess_index) Ok(sess_index)
} }
} }
pub fn decode(&mut self, rx: &mut Packet) -> Result<(), Error> { pub fn decode(&mut self, rx: &mut Packet) -> Result<(), Error> {
// let network = self.network.as_ref().ok_or(Error::NoNetworkInterface)?; // let network = self.network.as_ref().ok_or(ErrorCode::NoNetworkInterface)?;
// let (len, src) = network.recv(rx.as_borrow_slice()).await?; // let (len, src) = network.recv(rx.as_borrow_slice()).await?;
// rx.get_parsebuf()?.set_len(len); // rx.get_parsebuf()?.set_len(len);
@ -507,7 +507,7 @@ impl SessionMgr {
pub fn send(&mut self, sess_idx: usize, tx: &mut Packet) -> Result<(), Error> { pub fn send(&mut self, sess_idx: usize, tx: &mut Packet) -> Result<(), Error> {
self.sessions[sess_idx] self.sessions[sess_idx]
.as_mut() .as_mut()
.ok_or(Error::NoSession)? .ok_or(ErrorCode::NoSession)?
.do_send(self.epoch, tx)?; .do_send(self.epoch, tx)?;
// let network = self.network.as_ref().ok_or(Error::NoNetworkInterface)?; // let network = self.network.as_ref().ok_or(Error::NoNetworkInterface)?;

View file

@ -53,7 +53,7 @@ impl UdpListener {
let (size, addr) = self.socket.recv_from(in_buf).await.map_err(|e| { let (size, addr) = self.socket.recv_from(in_buf).await.map_err(|e| {
warn!("Error on the network: {:?}", e); warn!("Error on the network: {:?}", e);
Error::Network ErrorCode::Network
})?; })?;
info!("Got packet: {:?} from addr {:?}", &in_buf[..size], addr); info!("Got packet: {:?} from addr {:?}", &in_buf[..size], addr);
@ -66,7 +66,7 @@ impl UdpListener {
Address::Udp(addr) => { Address::Udp(addr) => {
let len = self.socket.send_to(out_buf, addr).await.map_err(|e| { let len = self.socket.send_to(out_buf, addr).await.map_err(|e| {
warn!("Error on the network: {:?}", e); warn!("Error on the network: {:?}", e);
Error::Network ErrorCode::Network
})?; })?;
info!( info!(

View file

@ -65,7 +65,7 @@ impl<'a> ParseBuf<'a> {
self.left -= size; self.left -= size;
return Ok(tail); return Ok(tail);
} }
Err(Error::TruncatedPacket) Err(ErrorCode::TruncatedPacket.into())
} }
fn advance(&mut self, len: usize) { fn advance(&mut self, len: usize) {
@ -82,7 +82,7 @@ impl<'a> ParseBuf<'a> {
self.advance(size); self.advance(size);
return Ok(data); return Ok(data);
} }
Err(Error::TruncatedPacket) Err(ErrorCode::TruncatedPacket.into())
} }
pub fn le_u8(&mut self) -> Result<u8, Error> { pub fn le_u8(&mut self) -> Result<u8, Error> {

View file

@ -70,9 +70,9 @@ impl<'a> WriteBuf<'a> {
pub fn reserve(&mut self, reserve: usize) -> Result<(), Error> { pub fn reserve(&mut self, reserve: usize) -> Result<(), Error> {
if self.end != 0 || self.start != 0 || self.buf_size != self.buf.len() { if self.end != 0 || self.start != 0 || self.buf_size != self.buf.len() {
Err(Error::Invalid) Err(ErrorCode::Invalid.into())
} else if reserve > self.buf_size { } else if reserve > self.buf_size {
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} else { } else {
self.start = reserve; self.start = reserve;
self.end = reserve; self.end = reserve;
@ -85,7 +85,7 @@ impl<'a> WriteBuf<'a> {
self.buf_size -= with; self.buf_size -= with;
Ok(()) Ok(())
} else { } else {
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
} }
@ -94,7 +94,7 @@ impl<'a> WriteBuf<'a> {
self.buf_size += by; self.buf_size += by;
Ok(()) Ok(())
} else { } else {
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
} }
@ -107,7 +107,7 @@ impl<'a> WriteBuf<'a> {
self.start -= size; self.start -= size;
return Ok(()); return Ok(());
} }
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
pub fn prepend(&mut self, src: &[u8]) -> Result<(), Error> { pub fn prepend(&mut self, src: &[u8]) -> Result<(), Error> {
@ -126,7 +126,7 @@ impl<'a> WriteBuf<'a> {
self.end += size; self.end += size;
return Ok(()); return Ok(());
} }
Err(Error::NoSpace) Err(ErrorCode::NoSpace.into())
} }
pub fn append(&mut self, src: &[u8]) -> Result<(), Error> { pub fn append(&mut self, src: &[u8]) -> Result<(), Error> {

View file

@ -27,7 +27,7 @@ use matter::{
Cluster, CmdDataEncoder, CmdDataWriter, CmdDetails, Dataver, Handler, Quality, Cluster, CmdDataEncoder, CmdDataWriter, CmdDetails, Dataver, Handler, Quality,
ATTRIBUTE_LIST, FEATURE_MAP, ATTRIBUTE_LIST, FEATURE_MAP,
}, },
error::Error, error::{Error, ErrorCode},
interaction_model::{ interaction_model::{
core::Transaction, core::Transaction,
messages::ib::{attr_list_write, ListOperation}, messages::ib::{attr_list_write, ListOperation},
@ -122,7 +122,7 @@ impl TestChecker {
INIT.call_once(|| { INIT.call_once(|| {
G_TEST_CHECKER = Some(Arc::new(Mutex::new(Self::new()))); G_TEST_CHECKER = Some(Arc::new(Mutex::new(Self::new())));
}); });
Ok(G_TEST_CHECKER.as_ref().ok_or(Error::Invalid)?.clone()) Ok(G_TEST_CHECKER.as_ref().ok_or(ErrorCode::Invalid)?.clone())
} }
} }
} }
@ -235,7 +235,7 @@ impl EchoCluster {
} }
} }
Err(Error::ResourceExhausted) Err(ErrorCode::ResourceExhausted.into())
} }
ListOperation::EditItem(index) => { ListOperation::EditItem(index) => {
let data = data.u16()?; let data = data.u16()?;
@ -243,7 +243,7 @@ impl EchoCluster {
tc.write_list[*index as usize] = Some(data); tc.write_list[*index as usize] = Some(data);
Ok(()) Ok(())
} else { } else {
Err(Error::InvalidAction) Err(ErrorCode::InvalidAction.into())
} }
} }
ListOperation::DeleteItem(index) => { ListOperation::DeleteItem(index) => {
@ -251,7 +251,7 @@ impl EchoCluster {
tc.write_list[*index as usize] = None; tc.write_list[*index as usize] = None;
Ok(()) Ok(())
} else { } else {
Err(Error::InvalidAction) Err(ErrorCode::InvalidAction.into())
} }
} }
ListOperation::DeleteList => { ListOperation::DeleteList => {

View file

@ -216,7 +216,7 @@ impl<'a> ImEngine<'a> {
epoch: *self.matter.borrow(), epoch: *self.matter.borrow(),
}; };
let mut rx_buf = [0; MAX_RX_BUF_SIZE]; let mut rx_buf = [0; MAX_RX_BUF_SIZE];
let mut tx_buf = [0; 1450]; // For the long read tests to run unchanged let mut tx_buf = [0; 1440]; // For the long read tests to run unchanged
let mut rx = Packet::new_rx(&mut rx_buf); let mut rx = Packet::new_rx(&mut rx_buf);
let mut tx = Packet::new_tx(&mut tx_buf); let mut tx = Packet::new_tx(&mut tx_buf);
// Create fake rx packet // Create fake rx packet

View file

@ -11,3 +11,4 @@ proc-macro = true
syn = { version = "1", features = ["extra-traits"]} syn = { version = "1", features = ["extra-traits"]}
quote = "1" quote = "1"
proc-macro2 = "1" proc-macro2 = "1"
proc-macro-crate = "1.3"

View file

@ -16,7 +16,7 @@
*/ */
use proc_macro::TokenStream; use proc_macro::TokenStream;
use proc_macro2::Span; use proc_macro2::{Ident, Span};
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use syn::Lit::{Int, Str}; use syn::Lit::{Int, Str};
use syn::NestedMeta::{Lit, Meta}; use syn::NestedMeta::{Lit, Meta};
@ -106,6 +106,18 @@ fn parse_tag_val(field: &syn::Field) -> Option<u8> {
None None
} }
fn get_crate_name() -> String {
let found_crate = proc_macro_crate::crate_name("matter-iot").unwrap_or_else(|err| {
eprintln!("Warning: defaulting to `crate` {err}");
proc_macro_crate::FoundCrate::Itself
});
match found_crate {
proc_macro_crate::FoundCrate::Itself => String::from("crate"),
proc_macro_crate::FoundCrate::Name(name) => name,
}
}
/// Generate a ToTlv implementation for a structure /// Generate a ToTlv implementation for a structure
fn gen_totlv_for_struct( fn gen_totlv_for_struct(
fields: &syn::FieldsNamed, fields: &syn::FieldsNamed,
@ -187,16 +199,18 @@ fn gen_totlv_for_enum(
tag_start += 1; tag_start += 1;
} }
let krate = Ident::new(&get_crate_name(), Span::call_site());
let expanded = quote! { let expanded = quote! {
impl #generics ToTLV for #enum_name #generics { impl #generics #krate::tlv::ToTLV for #enum_name #generics {
fn to_tlv(&self, tw: &mut TLVWriter, tag_type: TagType) -> Result<(), Error> { fn to_tlv(&self, tw: &mut #krate::tlv::TLVWriter, tag_type: #krate::tlv::TagType) -> Result<(), #krate::error::Error> {
let anchor = tw.get_tail(); let anchor = tw.get_tail();
if let Err(err) = (|| { if let Err(err) = (|| {
tw.start_struct(tag_type)?; tw.start_struct(tag_type)?;
match self { match self {
#( #(
Self::#variant_names(c) => { c.to_tlv(tw, TagType::Context(#tags))?; }, Self::#variant_names(c) => { c.to_tlv(tw, #krate::tlv::TagType::Context(#tags))?; },
)* )*
} }
tw.end_container() tw.end_container()
@ -297,14 +311,16 @@ fn gen_fromtlv_for_struct(
} }
} }
let krate = Ident::new(&get_crate_name(), Span::call_site());
// Currently we don't use find_tag() because the tags come in sequential // Currently we don't use find_tag() because the tags come in sequential
// order. If ever the tags start coming out of order, we can use find_tag() // order. If ever the tags start coming out of order, we can use find_tag()
// instead // instead
let expanded = if !tlvargs.unordered { let expanded = if !tlvargs.unordered {
quote! { quote! {
impl #generics FromTLV <#lifetime> for #struct_name #generics { impl #generics #krate::tlv::FromTLV <#lifetime> for #struct_name #generics {
fn from_tlv(t: &TLVElement<#lifetime>) -> Result<Self, Error> { fn from_tlv(t: &#krate::tlv::TLVElement<#lifetime>) -> Result<Self, #krate::error::Error> {
let mut t_iter = t.#datatype ()?.enter().ok_or(Error::Invalid)?; let mut t_iter = t.#datatype ()?.enter().ok_or_else(|| #krate::error::Error::new(#krate::error::ErrorCode::Invalid))?;
let mut item = t_iter.next(); let mut item = t_iter.next();
#( #(
let #idents = if Some(true) == item.map(|x| x.check_ctx_tag(#tags)) { let #idents = if Some(true) == item.map(|x| x.check_ctx_tag(#tags)) {
@ -324,8 +340,8 @@ fn gen_fromtlv_for_struct(
} }
} else { } else {
quote! { quote! {
impl #generics FromTLV <#lifetime> for #struct_name #generics { impl #generics #krate::tlv::FromTLV <#lifetime> for #struct_name #generics {
fn from_tlv(t: &TLVElement<#lifetime>) -> Result<Self, Error> { fn from_tlv(t: &#krate::tlv::TLVElement<#lifetime>) -> Result<Self, #krate::error::Error> {
#( #(
let #idents = if let Ok(s) = t.find_tag(#tags as u32) { let #idents = if let Ok(s) = t.find_tag(#tags as u32) {
#types::from_tlv(&s) #types::from_tlv(&s)
@ -375,20 +391,22 @@ fn gen_fromtlv_for_enum(
tag_start += 1; tag_start += 1;
} }
let krate = Ident::new(&get_crate_name(), Span::call_site());
let expanded = quote! { let expanded = quote! {
impl #generics FromTLV <#lifetime> for #enum_name #generics { impl #generics #krate::tlv::FromTLV <#lifetime> for #enum_name #generics {
fn from_tlv(t: &TLVElement<#lifetime>) -> Result<Self, Error> { fn from_tlv(t: &#krate::tlv::TLVElement<#lifetime>) -> Result<Self, #krate::error::Error> {
let mut t_iter = t.confirm_struct()?.enter().ok_or(Error::Invalid)?; let mut t_iter = t.confirm_struct()?.enter().ok_or_else(|| #krate::error::Error::new(#krate::error::ErrorCode::Invalid))?;
let mut item = t_iter.next().ok_or(Error::Invalid)?; let mut item = t_iter.next().ok_or_else(|| Error::new(#krate::error::ErrorCode::Invalid))?;
if let TagType::Context(tag) = item.get_tag() { if let TagType::Context(tag) = item.get_tag() {
match tag { match tag {
#( #(
#tags => Ok(Self::#variant_names(#types::from_tlv(&item)?)), #tags => Ok(Self::#variant_names(#types::from_tlv(&item)?)),
)* )*
_ => Err(Error::Invalid), _ => Err(#krate::error::Error::new(#krate::error::ErrorCode::Invalid)),
} }
} else { } else {
Err(Error::TLVTypeMismatch) Err(#krate::error::Error::new(#krate::error::ErrorCode::TLVTypeMismatch))
} }
} }
} }