From 98e0b6cef8f427d1db99d3e1b0ecd1669b6799a7 Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Sat, 21 Jan 2023 17:41:38 +0530 Subject: [PATCH 1/4] Cert: Include support for encoding DN strings So far, only DN Integers were being supported. Include support for strings too --- matter/src/cert/asn1_writer.rs | 11 +- matter/src/cert/mod.rs | 225 ++++++++++++++++++++++++++------- matter/src/cert/printer.rs | 4 + matter/src/error.rs | 11 +- 4 files changed, 201 insertions(+), 50 deletions(-) diff --git a/matter/src/cert/asn1_writer.rs b/matter/src/cert/asn1_writer.rs index cec7e7d..3cb7f47 100644 --- a/matter/src/cert/asn1_writer.rs +++ b/matter/src/cert/asn1_writer.rs @@ -180,13 +180,18 @@ impl<'a> CertConsumer for ASN1Writer<'a> { self.write_str(0x02, i) } + fn printstr(&mut self, _tag: &str, s: &str) -> Result<(), Error> { + // Note: ASN1 has multiple strings, this is PrintableString + self.write_str(0x13, s.as_bytes()) + } + fn utf8str(&mut self, _tag: &str, s: &str) -> Result<(), Error> { - // Note: ASN1 has 3 string, this is UTF8String + // Note: ASN1 has multiple strings, this is UTF8String self.write_str(0x0c, s.as_bytes()) } fn bitstr(&mut self, _tag: &str, truncate: bool, s: &[u8]) -> Result<(), Error> { - // Note: ASN1 has 3 string, this is BIT String + // Note: ASN1 has multiple strings, this is BIT String // Strip off the end zeroes let mut last_byte = s.len() - 1; @@ -208,7 +213,7 @@ impl<'a> CertConsumer for ASN1Writer<'a> { } fn ostr(&mut self, _tag: &str, s: &[u8]) -> Result<(), Error> { - // Note: ASN1 has 3 string, this is Octet String + // Note: ASN1 has multiple strings, this is Octet String self.write_str(0x04, s) } diff --git a/matter/src/cert/mod.rs b/matter/src/cert/mod.rs index e1191d3..879981e 100644 --- a/matter/src/cert/mod.rs +++ b/matter/src/cert/mod.rs @@ -268,6 +268,22 @@ const MAX_DN_ENTRIES: usize = 5; #[derive(FromPrimitive, Copy, Clone)] enum DnTags { + CommonName = 1, + Surname = 2, + SerialNum = 3, + CountryName = 4, + LocalityName = 5, + StateName = 6, + OrgName = 7, + OrgUnitName = 8, + Title = 9, + Name = 10, + GivenName = 11, + Intials = 12, + GenQalifier = 13, + DnQualifier = 14, + Pseudonym = 15, + DomainComponent = 16, NodeId = 17, FirmwareSignId = 18, IcaId = 19, @@ -276,11 +292,17 @@ enum DnTags { NocCat = 22, } +enum DistNameValue { + Uint(u64), + Utf8Str(Vec), + PrintableStr(Vec), +} + #[derive(Default)] struct DistNames { // The order in which the DNs arrive is important, as the signing // requires that the ASN1 notation retains the same order - dn: Vec<(u8, u64)>, + dn: Vec<(u8, DistNameValue)>, } impl DistNames { @@ -288,10 +310,18 @@ impl DistNames { self.dn .iter() .find(|(id, _)| *id == match_id as u8) - .map(|(_, value)| *value) + .and_then(|(_, value)| { + if let DistNameValue::Uint(u) = *value { + Some(u) + } else { + None + } + }) } } +const PRINTABLE_STR_THRESHOLD: u8 = 0x80; + impl<'a> FromTLV<'a> for DistNames { fn from_tlv(t: &TLVElement<'a>) -> Result { let mut d = Self { @@ -300,12 +330,18 @@ impl<'a> FromTLV<'a> for DistNames { let iter = t.confirm_list()?.enter().ok_or(Error::Invalid)?; for t in iter { if let TagType::Context(tag) = t.get_tag() { - let value = t.u64().map_err(|e| { - // Non-integer DNs not yet supported - error!("This DN is not yet supported{}", tag); - e - })?; - d.dn.push((tag, value)); + if let Ok(value) = t.u64() { + d.dn.push((tag, DistNameValue::Uint(value))); + } else if let Ok(value) = t.slice() { + if tag > PRINTABLE_STR_THRESHOLD { + d.dn.push(( + tag - PRINTABLE_STR_THRESHOLD, + DistNameValue::PrintableStr(value.to_vec()), + )); + } else { + d.dn.push((tag, DistNameValue::Utf8Str(value.to_vec()))); + } + } } } Ok(d) @@ -316,7 +352,14 @@ impl ToTLV for DistNames { fn to_tlv(&self, tw: &mut TLVWriter, tag: TagType) -> Result<(), Error> { tw.start_list(tag)?; for (name, value) in &self.dn { - tw.u64(TagType::Context(*name), *value)?; + match value { + DistNameValue::Uint(v) => tw.u64(TagType::Context(*name), *v)?, + DistNameValue::Utf8Str(v) => tw.utf8(TagType::Context(*name), v.as_slice())?, + DistNameValue::PrintableStr(v) => tw.utf8( + TagType::Context(*name + PRINTABLE_STR_THRESHOLD), + v.as_slice(), + )?, + } } tw.end_container() } @@ -324,43 +367,106 @@ impl ToTLV for DistNames { impl DistNames { fn encode(&self, tag: &str, w: &mut dyn CertConsumer) -> Result<(), Error> { - const OID_MATTER_NODE_ID: [u8; 10] = - [0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x01]; - const OID_MATTER_FW_SIGN_ID: [u8; 10] = - [0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x02]; - const OID_MATTER_ICA_ID: [u8; 10] = - [0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x03]; - const OID_MATTER_ROOT_CA_ID: [u8; 10] = - [0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x04]; - const OID_MATTER_FABRIC_ID: [u8; 10] = - [0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x05]; - const OID_MATTER_NOC_CAT_ID: [u8; 10] = - [0x2B, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x06]; - - let dn_encoding = [ - ("Chip Node Id:", &OID_MATTER_NODE_ID), - ("Chip Firmware Signing Id:", &OID_MATTER_FW_SIGN_ID), - ("Chip ICA Id:", &OID_MATTER_ICA_ID), - ("Chip Root CA Id:", &OID_MATTER_ROOT_CA_ID), - ("Chip Fabric Id:", &OID_MATTER_FABRIC_ID), + const OID_COMMON_NAME: [u8; 3] = [0x55_u8, 0x04, 0x03]; + const OID_SURNAME: [u8; 3] = [0x55_u8, 0x04, 0x04]; + const OID_SERIAL_NUMBER: [u8; 3] = [0x55_u8, 0x04, 0x05]; + const OID_COUNTRY_NAME: [u8; 3] = [0x55_u8, 0x04, 0x06]; + const OID_LOCALITY_NAME: [u8; 3] = [0x55_u8, 0x04, 0x07]; + const OID_STATE_NAME: [u8; 3] = [0x55_u8, 0x04, 0x08]; + const OID_ORGANIZATION_NAME: [u8; 3] = [0x55_u8, 0x04, 0x0A]; + const OID_ORGANIZATIONAL_UNIT_NAME: [u8; 3] = [0x55_u8, 0x04, 0x0B]; + const OID_TITLE: [u8; 3] = [0x55_u8, 0x04, 0x0C]; + const OID_NAME: [u8; 3] = [0x55_u8, 0x04, 0x29]; + const OID_GIVEN_NAME: [u8; 3] = [0x55_u8, 0x04, 0x2A]; + const OID_INITIALS: [u8; 3] = [0x55_u8, 0x04, 0x2B]; + const OID_GENERATION_QUALIFIER: [u8; 3] = [0x55_u8, 0x04, 0x2C]; + const OID_DN_QUALIFIER: [u8; 3] = [0x55_u8, 0x04, 0x2E]; + const OID_PSEUDONYM: [u8; 3] = [0x55_u8, 0x04, 0x41]; + const OID_DOMAIN_COMPONENT: [u8; 10] = [ + 0x09_u8, 0x92, 0x26, 0x89, 0x93, 0xF2, 0x2C, 0x64, 0x01, 0x19, + ]; + const OID_MATTER_NODE_ID: [u8; 10] = [ + 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x01, + ]; + const OID_MATTER_FW_SIGNING_ID: [u8; 10] = [ + 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x02, + ]; + const OID_MATTER_ICAC_ID: [u8; 10] = [ + 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x03, + ]; + const OID_MATTER_RCAC_ID: [u8; 10] = [ + 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x04, + ]; + const OID_MATTER_FABRIC_ID: [u8; 10] = [ + 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x05, + ]; + const OID_MATTER_CASE_AUTH_TAG: [u8; 10] = [ + 0x2B_u8, 0x06, 0x01, 0x04, 0x01, 0x82, 0xA2, 0x7C, 0x01, 0x06, + ]; + + const DN_ENCODING: [(&str, &[u8], Option); 22] = [ + ("Common Name:", &OID_COMMON_NAME, None), + ("Surname:", &OID_SURNAME, None), + ("Serial Number", &OID_SERIAL_NUMBER, None), + ("Country Name", &OID_COUNTRY_NAME, None), + ("Locality name", &OID_LOCALITY_NAME, None), + ("State Name", &OID_STATE_NAME, None), + ("Org Name", &OID_ORGANIZATION_NAME, None), + ("OU Name", &OID_ORGANIZATIONAL_UNIT_NAME, None), + ("Title", &OID_TITLE, None), + ("Name", &OID_NAME, None), + ("Given Name", &OID_GIVEN_NAME, None), + ("Initials", &OID_INITIALS, None), + ("Gen Qualifier", &OID_GENERATION_QUALIFIER, None), + ("DN Qualifier", &OID_DN_QUALIFIER, None), + ("Pseudonym", &OID_PSEUDONYM, None), + ("Domain Component", &OID_DOMAIN_COMPONENT, None), + ( + "Chip Node Id:", + &OID_MATTER_NODE_ID, + Some(IntToStringLen::Len16), + ), + ( + "Chip Firmware Signing Id:", + &OID_MATTER_FW_SIGNING_ID, + Some(IntToStringLen::Len16), + ), + ( + "Chip ICA Id:", + &OID_MATTER_ICAC_ID, + Some(IntToStringLen::Len16), + ), + ( + "Chip Root CA Id:", + &OID_MATTER_RCAC_ID, + Some(IntToStringLen::Len16), + ), + ( + "Chip Fabric Id:", + &OID_MATTER_FABRIC_ID, + Some(IntToStringLen::Len16), + ), + ( + "Chip NOC CAT Id:", + &OID_MATTER_CASE_AUTH_TAG, + Some(IntToStringLen::Len8), + ), ]; w.start_seq(tag)?; for (id, value) in &self.dn { - if let Ok(tag) = num::FromPrimitive::from_u8(*id).ok_or(Error::InvalidData) { - if let DnTags::NocCat = tag { - w.start_set("")?; - w.start_seq("")?; - w.oid("Chip NOC CAT Id:", &OID_MATTER_NOC_CAT_ID)?; - w.utf8str("", format!("{:08X}", value).as_str())?; - w.end_seq()?; - w.end_set()?; + let tag: Option = num::FromPrimitive::from_u8(*id); + if tag.is_some() { + let index = (id - 1) as usize; + if index <= DN_ENCODING.len() { + let this = &DN_ENCODING[index]; + encode_dn_value(value, this.0, this.1, w, this.2)?; } else { - let index: usize = (*id as usize) - (DnTags::NodeId as usize); - let this = &dn_encoding[index]; - encode_u64_dn(*value, this.0, this.1, w)?; + // Non Matter DNs are encoded as + error!("Invalid DN, too high {}", id); } } else { + // Non Matter DNs are encoded as error!("Non Matter DNs are not yet supported {}", id); } } @@ -369,16 +475,42 @@ impl DistNames { } } -fn encode_u64_dn( - value: u64, +#[derive(Copy, Clone)] +/// Describes the expected string length while encoding an integer as a string +enum IntToStringLen { + Len16, + Len8, +} + +fn encode_dn_value( + value: &DistNameValue, name: &str, oid: &[u8], w: &mut dyn CertConsumer, + // Only applicable for integer values + expected_len: Option, ) -> Result<(), Error> { w.start_set("")?; w.start_seq("")?; w.oid(name, oid)?; - w.utf8str("", format!("{:016X}", value).as_str())?; + match value { + DistNameValue::Uint(v) => match expected_len { + Some(IntToStringLen::Len16) => w.utf8str("", format!("{:016X}", v).as_str())?, + Some(IntToStringLen::Len8) => w.utf8str("", format!("{:08X}", v).as_str())?, + _ => { + error!("Invalid encoding"); + return Err(Error::Invalid); + } + }, + DistNameValue::Utf8Str(v) => { + let str = String::from_utf8(v.to_vec())?; + w.utf8str("", &str)?; + } + DistNameValue::PrintableStr(v) => { + let str = String::from_utf8(v.to_vec())?; + w.printstr("", &str)?; + } + } w.end_seq()?; w.end_set() } @@ -557,6 +689,7 @@ pub trait CertConsumer { fn start_seq(&mut self, tag: &str) -> Result<(), Error>; fn end_seq(&mut self) -> Result<(), Error>; fn integer(&mut self, tag: &str, i: &[u8]) -> Result<(), Error>; + fn printstr(&mut self, tag: &str, s: &str) -> Result<(), Error>; fn utf8str(&mut self, tag: &str, s: &str) -> Result<(), Error>; fn bitstr(&mut self, tag: &str, truncate: bool, s: &[u8]) -> Result<(), Error>; fn ostr(&mut self, tag: &str, s: &[u8]) -> Result<(), Error>; @@ -589,14 +722,14 @@ mod tests { fn test_asn1_encode_success() { { let mut asn1_buf = [0u8; 1000]; - let c = Cert::new(&test_vectors::ASN1_INPUT1).unwrap(); + let c = Cert::new(&test_vectors::CHIP_CERT_INPUT1).unwrap(); let len = c.as_asn1(&mut asn1_buf).unwrap(); assert_eq!(&test_vectors::ASN1_OUTPUT1, &asn1_buf[..len]); } { let mut asn1_buf = [0u8; 1000]; - let c = Cert::new(&test_vectors::ASN1_INPUT2).unwrap(); + let c = Cert::new(&test_vectors::CHIP_CERT_INPUT2).unwrap(); let len = c.as_asn1(&mut asn1_buf).unwrap(); assert_eq!(&test_vectors::ASN1_OUTPUT2, &asn1_buf[..len]); } @@ -759,7 +892,7 @@ mod tests { 0x93, 0xd3, 0x7c, 0x4, 0x0, 0xe4, 0xc7, 0x78, 0xe9, 0x83, 0x5b, 0xc, 0x33, 0x61, 0x5c, 0x2e, 0x18, ]; - pub const ASN1_INPUT1: [u8; 237] = [ + pub const CHIP_CERT_INPUT1: [u8; 237] = [ 0x15, 0x30, 0x01, 0x01, 0x00, 0x24, 0x02, 0x01, 0x37, 0x03, 0x24, 0x14, 0x00, 0x24, 0x15, 0x03, 0x18, 0x26, 0x04, 0x80, 0x22, 0x81, 0x27, 0x26, 0x05, 0x80, 0x25, 0x4d, 0x3a, 0x37, 0x06, 0x24, 0x13, 0x01, 0x24, 0x15, 0x03, 0x18, 0x24, 0x07, 0x01, 0x24, @@ -778,7 +911,7 @@ mod tests { 0xaa, 0xab, 0xa0, 0xdb, 0xb4, 0x79, 0x63, 0xfc, 0x02, 0x03, 0x27, 0x25, 0xac, 0x21, 0x6f, 0xef, 0x27, 0xab, 0x0f, 0x90, 0x09, 0x99, 0x05, 0xa8, 0x60, 0xd8, 0x18, ]; - pub const ASN1_INPUT2: [u8; 247] = [ + pub const CHIP_CERT_INPUT2: [u8; 247] = [ 0x15, 0x30, 0x01, 0x01, 0x01, 0x24, 0x02, 0x01, 0x37, 0x03, 0x24, 0x13, 0x01, 0x24, 0x15, 0x03, 0x18, 0x26, 0x04, 0x80, 0x22, 0x81, 0x27, 0x26, 0x05, 0x80, 0x25, 0x4d, 0x3a, 0x37, 0x06, 0x26, 0x11, 0x69, 0xb6, 0x01, 0x00, 0x24, 0x15, 0x03, 0x18, 0x24, diff --git a/matter/src/cert/printer.rs b/matter/src/cert/printer.rs index 4b6d4fe..e92dbd4 100644 --- a/matter/src/cert/printer.rs +++ b/matter/src/cert/printer.rs @@ -61,6 +61,10 @@ impl<'a, 'b> CertConsumer for CertPrinter<'a, 'b> { let _ = writeln!(self.f, "{} {} {:x?}", SPACE[self.level], tag, i); Ok(()) } + fn printstr(&mut self, tag: &str, s: &str) -> Result<(), Error> { + let _ = writeln!(self.f, "{} {} {:x?}", SPACE[self.level], tag, s); + Ok(()) + } fn utf8str(&mut self, tag: &str, s: &str) -> Result<(), Error> { let _ = writeln!(self.f, "{} {} {:x?}", SPACE[self.level], tag, s); Ok(()) diff --git a/matter/src/error.rs b/matter/src/error.rs index 60e30a5..ba07d29 100644 --- a/matter/src/error.rs +++ b/matter/src/error.rs @@ -15,7 +15,9 @@ * limitations under the License. */ -use std::{array::TryFromSliceError, fmt, sync::PoisonError, time::SystemTimeError}; +use std::{ + array::TryFromSliceError, fmt, string::FromUtf8Error, sync::PoisonError, time::SystemTimeError, +}; use async_channel::{SendError, TryRecvError}; use log::error; @@ -65,6 +67,7 @@ pub enum Error { TLVNotFound, TLVTypeMismatch, TruncatedPacket, + Utf8Fail, } impl From for Error { @@ -115,6 +118,12 @@ impl From> for Error { } } +impl From for Error { + fn from(_e: FromUtf8Error) -> Self { + Self::Utf8Fail + } +} + impl From for Error { fn from(e: TryRecvError) -> Self { error!("Error in channel try_recv {}", e); From 2d655702348361bfa36901fa78a6d80339e16117 Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Sat, 21 Jan 2023 19:50:07 +0530 Subject: [PATCH 2/4] Cert: Support path-len-constraint in BasicConstraints --- matter/src/cert/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/matter/src/cert/mod.rs b/matter/src/cert/mod.rs index 879981e..74eb93e 100644 --- a/matter/src/cert/mod.rs +++ b/matter/src/cert/mod.rs @@ -180,10 +180,10 @@ impl BasicConstraints { w.start_seq("")?; if self.is_ca { // Encode CA only if true - w.bool("CA:", true)? + w.bool("CA:", true)?; } - if self.path.is_some() { - error!("Path Len is not yet implemented"); + if let Some(len) = self.path { + w.integer("Path Len Constraint", &[len])?; } w.end_seq() } From e6709aab189ea1cd2d40037f181bd236b5bfbb9f Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Sat, 21 Jan 2023 19:58:48 +0530 Subject: [PATCH 3/4] Cert: Update tests for parsing txt fields in DNs --- matter/src/cert/mod.rs | 63 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/matter/src/cert/mod.rs b/matter/src/cert/mod.rs index 74eb93e..61d7bf2 100644 --- a/matter/src/cert/mod.rs +++ b/matter/src/cert/mod.rs @@ -733,6 +733,13 @@ mod tests { let len = c.as_asn1(&mut asn1_buf).unwrap(); assert_eq!(&test_vectors::ASN1_OUTPUT2, &asn1_buf[..len]); } + + { + let mut asn1_buf = [0u8; 1000]; + let c = Cert::new(&test_vectors::CHIP_CERT_TXT_IN_DN).unwrap(); + let len = c.as_asn1(&mut asn1_buf).unwrap(); + assert_eq!(&test_vectors::ASN1_OUTPUT_TXT_IN_DN, &asn1_buf[..len]); + } } #[test] @@ -931,6 +938,29 @@ mod tests { 0xf5, 0x6c, 0x1d, 0x65, 0x6c, 0x0f, 0xd1, 0xe8, 0x55, 0x14, 0x5e, 0x27, 0xfd, 0xa4, 0xac, 0xf9, 0x93, 0xdb, 0x29, 0x49, 0xaa, 0x71, 0x18, ]; + pub const CHIP_CERT_TXT_IN_DN: [u8; 304] = [ + 0x15, 0x30, 0x1, 0x1, 0x1, 0x24, 0x2, 0x1, 0x37, 0x3, 0x2c, 0x84, 0x2, 0x55, 0x53, + 0x2c, 0x7, 0x6, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2c, 0x1, 0xb, 0x4d, 0x61, 0x74, + 0x74, 0x65, 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x27, 0x14, 0x1, 0x0, 0x0, 0x0, 0xfe, + 0xff, 0xff, 0xff, 0x18, 0x26, 0x4, 0x7f, 0xd2, 0x43, 0x29, 0x26, 0x5, 0x7f, 0x94, 0x5b, + 0xe5, 0x37, 0x6, 0x2c, 0x84, 0x2, 0x55, 0x53, 0x2c, 0x7, 0x6, 0x47, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2c, 0x1, 0xb, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x52, 0x6f, 0x6f, + 0x74, 0x27, 0x14, 0x1, 0x0, 0x0, 0x0, 0xfe, 0xff, 0xff, 0xff, 0x18, 0x24, 0x7, 0x1, + 0x24, 0x8, 0x1, 0x30, 0x9, 0x41, 0x4, 0x5b, 0x37, 0xdf, 0x65, 0x49, 0xc2, 0xd, 0xc8, + 0xd7, 0x22, 0xa6, 0xb8, 0xac, 0xb6, 0x60, 0xa8, 0xa7, 0x64, 0xce, 0x7b, 0xaf, 0x6c, + 0x6c, 0x22, 0x4f, 0x7e, 0xe8, 0x43, 0x49, 0x68, 0x4a, 0xd7, 0xd8, 0x9, 0xff, 0x65, 0x0, + 0x33, 0xd1, 0x52, 0x7d, 0xcf, 0x1f, 0xba, 0xac, 0x6a, 0x9c, 0x3a, 0xd8, 0xb4, 0x1e, + 0xda, 0xc9, 0x9, 0xf7, 0xb5, 0xc7, 0x60, 0xfd, 0x54, 0x2c, 0x89, 0x23, 0x75, 0x37, 0xa, + 0x35, 0x1, 0x29, 0x1, 0x24, 0x2, 0x1, 0x18, 0x24, 0x2, 0x60, 0x30, 0x4, 0x14, 0x72, + 0xc2, 0x1, 0xf7, 0x57, 0x19, 0x13, 0xb3, 0x48, 0xca, 0x0, 0xca, 0x7b, 0x45, 0xf4, 0x77, + 0x46, 0x68, 0xc9, 0x7e, 0x30, 0x5, 0x14, 0x72, 0xc2, 0x1, 0xf7, 0x57, 0x19, 0x13, 0xb3, + 0x48, 0xca, 0x0, 0xca, 0x7b, 0x45, 0xf4, 0x77, 0x46, 0x68, 0xc9, 0x7e, 0x18, 0x30, 0xb, + 0x40, 0x65, 0x16, 0x4b, 0x16, 0x6a, 0xdf, 0xf1, 0x8c, 0x15, 0x61, 0xa, 0x8c, 0xe9, + 0x1b, 0xd7, 0x3, 0xe9, 0xc1, 0xf6, 0x77, 0xb7, 0x11, 0xce, 0x13, 0x35, 0x5, 0x15, 0x2d, + 0xf0, 0xda, 0x15, 0x11, 0x16, 0x75, 0xac, 0x55, 0x91, 0xce, 0xe7, 0x86, 0x85, 0x1c, + 0xdd, 0x9e, 0xfd, 0xad, 0x29, 0x66, 0x74, 0xbe, 0xbc, 0xb2, 0xa3, 0xa3, 0x20, 0x9b, + 0xcd, 0xe7, 0xb3, 0x9, 0xdb, 0x55, 0x2c, 0x6f, 0x18, + ]; pub const ASN1_OUTPUT1: [u8; 388] = [ 0x30, 0x82, 0x01, 0x80, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x00, 0x30, 0x0a, @@ -995,5 +1025,38 @@ mod tests { 0xbf, 0x68, 0x18, 0x59, 0x7f, 0xf7, 0xe8, 0xaf, 0x88, 0x91, 0x1c, 0x72, 0x32, 0xf7, 0x52, ]; + pub const ASN1_OUTPUT_TXT_IN_DN: [u8; 427] = [ + 0x30, 0x82, 0x01, 0xa7, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0a, + 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x30, 0x56, 0x31, 0x0b, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, + 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x4d, 0x61, 0x74, + 0x74, 0x65, 0x72, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, + 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, 0xa2, 0x7c, 0x01, 0x04, 0x0c, 0x10, 0x46, 0x46, + 0x46, 0x46, 0x46, 0x46, 0x46, 0x45, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, + 0x30, 0x1e, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x30, 0x38, 0x32, 0x30, 0x33, 0x30, + 0x35, 0x35, 0x5a, 0x17, 0x0d, 0x32, 0x31, 0x31, 0x32, 0x30, 0x38, 0x32, 0x30, 0x33, + 0x30, 0x35, 0x35, 0x5a, 0x30, 0x56, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0f, 0x30, 0x0d, 0x06, 0x03, 0x55, 0x04, 0x0a, + 0x0c, 0x06, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x72, 0x20, 0x52, 0x6f, + 0x6f, 0x74, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, + 0xa2, 0x7c, 0x01, 0x04, 0x0c, 0x10, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x45, + 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, + 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x5b, 0x37, 0xdf, 0x65, 0x49, 0xc2, 0x0d, + 0xc8, 0xd7, 0x22, 0xa6, 0xb8, 0xac, 0xb6, 0x60, 0xa8, 0xa7, 0x64, 0xce, 0x7b, 0xaf, + 0x6c, 0x6c, 0x22, 0x4f, 0x7e, 0xe8, 0x43, 0x49, 0x68, 0x4a, 0xd7, 0xd8, 0x09, 0xff, + 0x65, 0x00, 0x33, 0xd1, 0x52, 0x7d, 0xcf, 0x1f, 0xba, 0xac, 0x6a, 0x9c, 0x3a, 0xd8, + 0xb4, 0x1e, 0xda, 0xc9, 0x09, 0xf7, 0xb5, 0xc7, 0x60, 0xfd, 0x54, 0x2c, 0x89, 0x23, + 0x75, 0xa3, 0x66, 0x30, 0x64, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, + 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x0e, 0x06, + 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x06, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x72, 0xc2, 0x01, 0xf7, + 0x57, 0x19, 0x13, 0xb3, 0x48, 0xca, 0x00, 0xca, 0x7b, 0x45, 0xf4, 0x77, 0x46, 0x68, + 0xc9, 0x7e, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, + 0x14, 0x72, 0xc2, 0x01, 0xf7, 0x57, 0x19, 0x13, 0xb3, 0x48, 0xca, 0x00, 0xca, 0x7b, + 0x45, 0xf4, 0x77, 0x46, 0x68, 0xc9, 0x7e, + ]; } } From cf72862d20b39661d6b3695cd6d5633764c2fe62 Mon Sep 17 00:00:00 2001 From: Kedar Sovani Date: Sat, 21 Jan 2023 19:50:29 +0530 Subject: [PATCH 4/4] tlv_tool: Make provision to dump ASN1 representation of certificates --- tools/tlv_tool/src/main.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/tlv_tool/src/main.rs b/tools/tlv_tool/src/main.rs index 43b2440..821e0d0 100644 --- a/tools/tlv_tool/src/main.rs +++ b/tools/tlv_tool/src/main.rs @@ -47,7 +47,12 @@ fn main() { .arg( Arg::with_name("cert") .long("cert") - .help("The input is a Matter-encoded Certificate"), + .help("Decode a Matter-encoded Certificate"), + ) + .arg( + Arg::with_name("as-asn1") + .long("as-asn1") + .help("Decode a Matter-encoded Certificate and encode as ASN1"), ) .arg(Arg::with_name("tlvs").help("List of TLVs").required(true)) .get_matches(); @@ -88,6 +93,11 @@ fn main() { if m.is_present("cert") { let cert = cert::Cert::new(&tlv_list[..index]).unwrap(); println!("{}", cert); + } else if m.is_present("as-asn1") { + let mut asn1_cert = [0_u8; 1024]; + let cert = cert::Cert::new(&tlv_list[..index]).unwrap(); + let len = cert.as_asn1(&mut asn1_cert).unwrap(); + println!("{:02x?}", &asn1_cert[..len]); } else { tlv::print_tlv_list(&tlv_list[..index]); }