Just use time-rs in no_std mode
This commit is contained in:
parent
a4b8b53014
commit
592d1ee028
12 changed files with 63 additions and 155 deletions
|
@ -8,5 +8,3 @@ exclude = ["examples/*"]
|
||||||
smol = { git = "https://github.com/esp-rs-compat/smol" }
|
smol = { git = "https://github.com/esp-rs-compat/smol" }
|
||||||
polling = { git = "https://github.com/esp-rs-compat/polling" }
|
polling = { git = "https://github.com/esp-rs-compat/polling" }
|
||||||
socket2 = { git = "https://github.com/esp-rs-compat/socket2" }
|
socket2 = { git = "https://github.com/esp-rs-compat/socket2" }
|
||||||
chrono = { git = "https://github.com/ivmarkov/chrono" }
|
|
||||||
time = { git = "https://github.com/ivmarkov/time", branch = "master" }
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ path = "src/lib.rs"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["std", "crypto_mbedtls", "backtrace"]
|
default = ["std", "crypto_mbedtls", "backtrace"]
|
||||||
std = ["alloc", "env_logger", "chrono", "time", "rand", "qrcode", "libmdns", "simple-mdns", "simple-dns", "async-io", "smol"]
|
std = ["alloc", "env_logger", "rand", "qrcode", "libmdns", "simple-mdns", "simple-dns", "async-io", "smol"]
|
||||||
backtrace = []
|
backtrace = []
|
||||||
alloc = []
|
alloc = []
|
||||||
nightly = []
|
nightly = []
|
||||||
|
@ -38,11 +38,10 @@ no-std-net = "0.6"
|
||||||
subtle = "2.4.1"
|
subtle = "2.4.1"
|
||||||
safemem = "0.3.3"
|
safemem = "0.3.3"
|
||||||
owo-colors = "3"
|
owo-colors = "3"
|
||||||
|
time = { version = "0.3", default-features = false }
|
||||||
verhoeff = { version = "1", default-features = false }
|
verhoeff = { version = "1", default-features = false }
|
||||||
|
|
||||||
# STD-only dependencies
|
# STD-only dependencies
|
||||||
chrono = { version = "=0.4.19", optional = true, default-features = false, features = ["clock", "std"] } # =0.4.19 for compatibility with ESP IDF
|
|
||||||
time = { version = "0.1", optional = true, default-features = false }
|
|
||||||
rand = { version = "0.8.5", optional = true }
|
rand = { version = "0.8.5", optional = true }
|
||||||
qrcode = { version = "0.12", default-features = false, optional = true } # Print QR code
|
qrcode = { version = "0.12", default-features = false, optional = true } # Print QR code
|
||||||
simple-mdns = { version = "0.4", features = ["sync"], optional = true }
|
simple-mdns = { version = "0.4", features = ["sync"], optional = true }
|
||||||
|
|
|
@ -15,12 +15,14 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
use super::{CertConsumer, MAX_DEPTH};
|
use super::{CertConsumer, MAX_DEPTH};
|
||||||
use crate::{
|
use crate::{
|
||||||
error::{Error, ErrorCode},
|
error::{Error, ErrorCode},
|
||||||
utils::epoch::{UtcCalendar, MATTER_EPOCH_SECS},
|
utils::epoch::MATTER_EPOCH_SECS,
|
||||||
};
|
};
|
||||||
use core::{fmt::Write, time::Duration};
|
use core::fmt::Write;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ASN1Writer<'a> {
|
pub struct ASN1Writer<'a> {
|
||||||
|
@ -262,19 +264,24 @@ impl<'a> CertConsumer for ASN1Writer<'a> {
|
||||||
self.write_str(0x06, oid)
|
self.write_str(0x06, oid)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn utctime(&mut self, _tag: &str, epoch: u32, utc_calendar: UtcCalendar) -> Result<(), Error> {
|
fn utctime(&mut self, _tag: &str, epoch: u32) -> Result<(), Error> {
|
||||||
let matter_epoch = MATTER_EPOCH_SECS + epoch as u64;
|
let matter_epoch = MATTER_EPOCH_SECS + epoch as u64;
|
||||||
|
|
||||||
let dt = utc_calendar(Duration::from_secs(matter_epoch as _));
|
let dt = OffsetDateTime::from_unix_timestamp(matter_epoch as _).unwrap();
|
||||||
|
|
||||||
let mut time_str: heapless::String<32> = heapless::String::<32>::new();
|
let mut time_str: heapless::String<32> = heapless::String::<32>::new();
|
||||||
|
|
||||||
if dt.year >= 2050 {
|
if dt.year() >= 2050 {
|
||||||
// If year is >= 2050, ASN.1 requires it to be Generalised Time
|
// If year is >= 2050, ASN.1 requires it to be Generalised Time
|
||||||
write!(
|
write!(
|
||||||
&mut time_str,
|
&mut time_str,
|
||||||
"{:04}{:02}{:02}{:02}{:02}{:02}Z",
|
"{:04}{:02}{:02}{:02}{:02}{:02}Z",
|
||||||
dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second
|
dt.year(),
|
||||||
|
dt.month() as u8,
|
||||||
|
dt.day(),
|
||||||
|
dt.hour(),
|
||||||
|
dt.minute(),
|
||||||
|
dt.second()
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.write_str(0x18, time_str.as_bytes())
|
self.write_str(0x18, time_str.as_bytes())
|
||||||
|
@ -282,12 +289,12 @@ impl<'a> CertConsumer for ASN1Writer<'a> {
|
||||||
write!(
|
write!(
|
||||||
&mut time_str,
|
&mut time_str,
|
||||||
"{:02}{:02}{:02}{:02}{:02}{:02}Z",
|
"{:02}{:02}{:02}{:02}{:02}{:02}Z",
|
||||||
dt.year % 100,
|
dt.year() % 100,
|
||||||
dt.month,
|
dt.month() as u8,
|
||||||
dt.day,
|
dt.day(),
|
||||||
dt.hour,
|
dt.hour(),
|
||||||
dt.minute,
|
dt.minute(),
|
||||||
dt.second
|
dt.second()
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.write_str(0x17, time_str.as_bytes())
|
self.write_str(0x17, time_str.as_bytes())
|
||||||
|
|
|
@ -21,7 +21,7 @@ use crate::{
|
||||||
crypto::KeyPair,
|
crypto::KeyPair,
|
||||||
error::{Error, ErrorCode},
|
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::writebuf::WriteBuf,
|
||||||
};
|
};
|
||||||
use log::error;
|
use log::error;
|
||||||
use num_derive::FromPrimitive;
|
use num_derive::FromPrimitive;
|
||||||
|
@ -621,21 +621,17 @@ impl<'a> Cert<'a> {
|
||||||
Ok(wb.as_slice().len())
|
Ok(wb.as_slice().len())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_asn1(&self, buf: &mut [u8], utc_calendar: UtcCalendar) -> Result<usize, Error> {
|
pub fn as_asn1(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||||
let mut w = ASN1Writer::new(buf);
|
let mut w = ASN1Writer::new(buf);
|
||||||
self.encode(&mut w, Some(utc_calendar))?;
|
self.encode(&mut w)?;
|
||||||
Ok(w.as_slice().len())
|
Ok(w.as_slice().len())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn verify_chain_start(&self, utc_calendar: UtcCalendar) -> CertVerifier {
|
pub fn verify_chain_start(&self) -> CertVerifier {
|
||||||
CertVerifier::new(self, utc_calendar)
|
CertVerifier::new(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn encode(
|
fn encode(&self, w: &mut dyn CertConsumer) -> Result<(), Error> {
|
||||||
&self,
|
|
||||||
w: &mut dyn CertConsumer,
|
|
||||||
utc_calendar: Option<UtcCalendar>,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
w.start_seq("")?;
|
w.start_seq("")?;
|
||||||
|
|
||||||
w.start_ctx("Version:", 0)?;
|
w.start_ctx("Version:", 0)?;
|
||||||
|
@ -654,10 +650,8 @@ impl<'a> Cert<'a> {
|
||||||
self.issuer.encode("Issuer:", w)?;
|
self.issuer.encode("Issuer:", w)?;
|
||||||
|
|
||||||
w.start_seq("Validity:")?;
|
w.start_seq("Validity:")?;
|
||||||
if let Some(utc_calendar) = utc_calendar {
|
w.utctime("Not Before:", self.not_before)?;
|
||||||
w.utctime("Not Before:", self.not_before, utc_calendar)?;
|
w.utctime("Not After:", self.not_after)?;
|
||||||
w.utctime("Not After:", self.not_after, utc_calendar)?;
|
|
||||||
}
|
|
||||||
w.end_seq()?;
|
w.end_seq()?;
|
||||||
|
|
||||||
self.subject.encode("Subject:", w)?;
|
self.subject.encode("Subject:", w)?;
|
||||||
|
@ -689,7 +683,7 @@ impl<'a> fmt::Display for Cert<'a> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let mut printer = CertPrinter::new(f);
|
let mut printer = CertPrinter::new(f);
|
||||||
let _ = self
|
let _ = self
|
||||||
.encode(&mut printer, None)
|
.encode(&mut printer)
|
||||||
.map_err(|e| error!("Error decoding certificate: {}", e));
|
.map_err(|e| error!("Error decoding certificate: {}", e));
|
||||||
// Signature is not encoded by the Cert Decoder
|
// Signature is not encoded by the Cert Decoder
|
||||||
writeln!(f, "Signature: {:x?}", self.get_signature())
|
writeln!(f, "Signature: {:x?}", self.get_signature())
|
||||||
|
@ -698,12 +692,11 @@ impl<'a> fmt::Display for Cert<'a> {
|
||||||
|
|
||||||
pub struct CertVerifier<'a> {
|
pub struct CertVerifier<'a> {
|
||||||
cert: &'a Cert<'a>,
|
cert: &'a Cert<'a>,
|
||||||
utc_calendar: UtcCalendar,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> CertVerifier<'a> {
|
impl<'a> CertVerifier<'a> {
|
||||||
pub fn new(cert: &'a Cert, utc_calendar: UtcCalendar) -> Self {
|
pub fn new(cert: &'a Cert) -> Self {
|
||||||
Self { cert, utc_calendar }
|
Self { cert }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_cert(self, parent: &'a Cert) -> Result<CertVerifier<'a>, Error> {
|
pub fn add_cert(self, parent: &'a Cert) -> Result<CertVerifier<'a>, Error> {
|
||||||
|
@ -711,7 +704,7 @@ impl<'a> CertVerifier<'a> {
|
||||||
Err(ErrorCode::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)?;
|
||||||
let asn1 = &asn1[..len];
|
let asn1 = &asn1[..len];
|
||||||
|
|
||||||
let k = KeyPair::new_from_public(parent.get_pubkey())?;
|
let k = KeyPair::new_from_public(parent.get_pubkey())?;
|
||||||
|
@ -724,7 +717,7 @@ impl<'a> CertVerifier<'a> {
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
// TODO: other validation checks
|
// TODO: other validation checks
|
||||||
Ok(CertVerifier::new(parent, self.utc_calendar))
|
Ok(CertVerifier::new(parent))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn finalise(self) -> Result<(), Error> {
|
pub fn finalise(self) -> Result<(), Error> {
|
||||||
|
@ -751,7 +744,7 @@ pub trait CertConsumer {
|
||||||
fn start_ctx(&mut self, tag: &str, id: u8) -> Result<(), Error>;
|
fn start_ctx(&mut self, tag: &str, id: u8) -> Result<(), Error>;
|
||||||
fn end_ctx(&mut self) -> Result<(), Error>;
|
fn end_ctx(&mut self) -> Result<(), Error>;
|
||||||
fn oid(&mut self, tag: &str, oid: &[u8]) -> Result<(), Error>;
|
fn oid(&mut self, tag: &str, oid: &[u8]) -> Result<(), Error>;
|
||||||
fn utctime(&mut self, tag: &str, epoch: u32, utc_calendar: UtcCalendar) -> Result<(), Error>;
|
fn utctime(&mut self, tag: &str, epoch: u32) -> Result<(), Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const MAX_DEPTH: usize = 10;
|
const MAX_DEPTH: usize = 10;
|
||||||
|
@ -768,44 +761,36 @@ mod tests {
|
||||||
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;
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_asn1_encode_success() {
|
fn test_asn1_encode_success() {
|
||||||
{
|
{
|
||||||
let mut asn1_buf = [0u8; 1000];
|
let mut asn1_buf = [0u8; 1000];
|
||||||
let c = Cert::new(&test_vectors::CHIP_CERT_INPUT1).unwrap();
|
let c = Cert::new(&test_vectors::CHIP_CERT_INPUT1).unwrap();
|
||||||
let len = c
|
let len = c.as_asn1(&mut asn1_buf).unwrap();
|
||||||
.as_asn1(&mut asn1_buf, crate::utils::epoch::sys_utc_calendar)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(&test_vectors::ASN1_OUTPUT1, &asn1_buf[..len]);
|
assert_eq!(&test_vectors::ASN1_OUTPUT1, &asn1_buf[..len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut asn1_buf = [0u8; 1000];
|
let mut asn1_buf = [0u8; 1000];
|
||||||
let c = Cert::new(&test_vectors::CHIP_CERT_INPUT2).unwrap();
|
let c = Cert::new(&test_vectors::CHIP_CERT_INPUT2).unwrap();
|
||||||
let len = c
|
let len = c.as_asn1(&mut asn1_buf).unwrap();
|
||||||
.as_asn1(&mut asn1_buf, crate::utils::epoch::sys_utc_calendar)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(&test_vectors::ASN1_OUTPUT2, &asn1_buf[..len]);
|
assert_eq!(&test_vectors::ASN1_OUTPUT2, &asn1_buf[..len]);
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut asn1_buf = [0u8; 1000];
|
let mut asn1_buf = [0u8; 1000];
|
||||||
let c = Cert::new(&test_vectors::CHIP_CERT_TXT_IN_DN).unwrap();
|
let c = Cert::new(&test_vectors::CHIP_CERT_TXT_IN_DN).unwrap();
|
||||||
let len = c
|
let len = c.as_asn1(&mut asn1_buf).unwrap();
|
||||||
.as_asn1(&mut asn1_buf, crate::utils::epoch::sys_utc_calendar)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(&test_vectors::ASN1_OUTPUT_TXT_IN_DN, &asn1_buf[..len]);
|
assert_eq!(&test_vectors::ASN1_OUTPUT_TXT_IN_DN, &asn1_buf[..len]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_chain_success() {
|
fn test_verify_chain_success() {
|
||||||
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 rca = Cert::new(&test_vectors::RCA1_SUCCESS).unwrap();
|
let rca = Cert::new(&test_vectors::RCA1_SUCCESS).unwrap();
|
||||||
let a = noc.verify_chain_start(crate::utils::epoch::sys_utc_calendar);
|
let a = noc.verify_chain_start();
|
||||||
a.add_cert(&icac)
|
a.add_cert(&icac)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.add_cert(&rca)
|
.add_cert(&rca)
|
||||||
|
@ -814,7 +799,6 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[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
|
||||||
|
@ -822,35 +806,33 @@ mod tests {
|
||||||
use crate::error::ErrorCode;
|
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();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(ErrorCode::InvalidAuthKey),
|
Err(ErrorCode::InvalidAuthKey),
|
||||||
a.add_cert(&icac).unwrap().finalise().map_err(|e| e.code())
|
a.add_cert(&icac).unwrap().finalise().map_err(|e| e.code())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_auth_key_chain_incorrect() {
|
fn test_auth_key_chain_incorrect() {
|
||||||
use crate::error::ErrorCode;
|
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();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(ErrorCode::InvalidAuthKey),
|
Err(ErrorCode::InvalidAuthKey),
|
||||||
a.add_cert(&icac).map(|_| ()).map_err(|e| e.code())
|
a.add_cert(&icac).map(|_| ()).map_err(|e| e.code())
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_cert_corrupted() {
|
fn test_cert_corrupted() {
|
||||||
use crate::error::ErrorCode;
|
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();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Err(ErrorCode::InvalidSignature),
|
Err(ErrorCode::InvalidSignature),
|
||||||
a.add_cert(&icac).map(|_| ()).map_err(|e| e.code())
|
a.add_cert(&icac).map(|_| ()).map_err(|e| e.code())
|
||||||
|
|
|
@ -15,12 +15,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
use super::{CertConsumer, MAX_DEPTH};
|
use super::{CertConsumer, MAX_DEPTH};
|
||||||
use crate::{
|
use crate::{error::Error, utils::epoch::MATTER_EPOCH_SECS};
|
||||||
error::Error,
|
use core::fmt;
|
||||||
utils::epoch::{UtcCalendar, MATTER_EPOCH_SECS},
|
|
||||||
};
|
|
||||||
use core::{fmt, time::Duration};
|
|
||||||
|
|
||||||
pub struct CertPrinter<'a, 'b> {
|
pub struct CertPrinter<'a, 'b> {
|
||||||
level: usize,
|
level: usize,
|
||||||
|
@ -123,10 +122,10 @@ impl<'a, 'b> CertConsumer for CertPrinter<'a, 'b> {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn utctime(&mut self, tag: &str, epoch: u32, utc_calendar: UtcCalendar) -> Result<(), Error> {
|
fn utctime(&mut self, tag: &str, epoch: u32) -> Result<(), Error> {
|
||||||
let matter_epoch = MATTER_EPOCH_SECS + epoch as u64;
|
let matter_epoch = MATTER_EPOCH_SECS + epoch as u64;
|
||||||
|
|
||||||
let dt = utc_calendar(Duration::from_secs(matter_epoch as _));
|
let dt = OffsetDateTime::from_unix_timestamp(matter_epoch as _).unwrap();
|
||||||
|
|
||||||
let _ = writeln!(self.f, "{} {} {:?}", SPACE[self.level], tag, dt);
|
let _ = writeln!(self.f, "{} {} {:?}", SPACE[self.level], tag, dt);
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -25,10 +25,7 @@ use crate::{
|
||||||
mdns::{Mdns, MdnsMgr},
|
mdns::{Mdns, MdnsMgr},
|
||||||
pairing::{print_pairing_code_and_qr, DiscoveryCapabilities},
|
pairing::{print_pairing_code_and_qr, DiscoveryCapabilities},
|
||||||
secure_channel::{pake::PaseMgr, spake2p::VerifierData},
|
secure_channel::{pake::PaseMgr, spake2p::VerifierData},
|
||||||
utils::{
|
utils::{epoch::Epoch, rand::Rand},
|
||||||
epoch::{Epoch, UtcCalendar},
|
|
||||||
rand::Rand,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Device Commissioning Data
|
/// Device Commissioning Data
|
||||||
|
@ -48,17 +45,16 @@ pub struct Matter<'a> {
|
||||||
pub mdns_mgr: RefCell<MdnsMgr<'a>>,
|
pub mdns_mgr: RefCell<MdnsMgr<'a>>,
|
||||||
pub epoch: Epoch,
|
pub epoch: Epoch,
|
||||||
pub rand: Rand,
|
pub rand: Rand,
|
||||||
pub utc_calendar: UtcCalendar,
|
|
||||||
pub dev_det: &'a BasicInfoConfig<'a>,
|
pub dev_det: &'a BasicInfoConfig<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Matter<'a> {
|
impl<'a> Matter<'a> {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn new_default(dev_det: &'a BasicInfoConfig, mdns: &'a mut dyn Mdns, port: u16) -> Self {
|
pub fn new_default(dev_det: &'a BasicInfoConfig, mdns: &'a mut dyn Mdns, port: u16) -> Self {
|
||||||
use crate::utils::epoch::{sys_epoch, sys_utc_calendar};
|
use crate::utils::epoch::sys_epoch;
|
||||||
use crate::utils::rand::sys_rand;
|
use crate::utils::rand::sys_rand;
|
||||||
|
|
||||||
Self::new(dev_det, mdns, sys_epoch, sys_rand, sys_utc_calendar, port)
|
Self::new(dev_det, mdns, sys_epoch, sys_rand, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new Matter object
|
/// Creates a new Matter object
|
||||||
|
@ -72,7 +68,6 @@ impl<'a> Matter<'a> {
|
||||||
mdns: &'a mut dyn Mdns,
|
mdns: &'a mut dyn Mdns,
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
rand: Rand,
|
rand: Rand,
|
||||||
utc_calendar: UtcCalendar,
|
|
||||||
port: u16,
|
port: u16,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
@ -89,7 +84,6 @@ impl<'a> Matter<'a> {
|
||||||
)),
|
)),
|
||||||
epoch,
|
epoch,
|
||||||
rand,
|
rand,
|
||||||
utc_calendar,
|
|
||||||
dev_det,
|
dev_det,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -178,9 +172,3 @@ impl<'a> Borrow<Rand> for Matter<'a> {
|
||||||
&self.rand
|
&self.rand
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Borrow<UtcCalendar> for Matter<'a> {
|
|
||||||
fn borrow(&self) -> &UtcCalendar {
|
|
||||||
&self.utc_calendar
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ use crate::{
|
||||||
proto_ctx::ProtoCtx,
|
proto_ctx::ProtoCtx,
|
||||||
session::{CaseDetails, CloneData, NocCatIds, SessionMode},
|
session::{CaseDetails, CloneData, NocCatIds, SessionMode},
|
||||||
},
|
},
|
||||||
utils::{epoch::UtcCalendar, rand::Rand, writebuf::WriteBuf},
|
utils::{rand::Rand, writebuf::WriteBuf},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -70,16 +70,11 @@ impl CaseSession {
|
||||||
pub struct Case<'a> {
|
pub struct Case<'a> {
|
||||||
fabric_mgr: &'a RefCell<FabricMgr>,
|
fabric_mgr: &'a RefCell<FabricMgr>,
|
||||||
rand: Rand,
|
rand: Rand,
|
||||||
utc_calendar: UtcCalendar,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Case<'a> {
|
impl<'a> Case<'a> {
|
||||||
pub fn new(fabric_mgr: &'a RefCell<FabricMgr>, rand: Rand, utc_calendar: UtcCalendar) -> Self {
|
pub fn new(fabric_mgr: &'a RefCell<FabricMgr>, rand: Rand) -> Self {
|
||||||
Self {
|
Self { fabric_mgr, rand }
|
||||||
fabric_mgr,
|
|
||||||
rand,
|
|
||||||
utc_calendar,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn casesigma3_handler(
|
pub fn casesigma3_handler(
|
||||||
|
@ -133,9 +128,7 @@ impl<'a> Case<'a> {
|
||||||
if let Some(icac) = d.initiator_icac {
|
if let Some(icac) = d.initiator_icac {
|
||||||
initiator_icac = Some(Cert::new(icac.0)?);
|
initiator_icac = Some(Cert::new(icac.0)?);
|
||||||
}
|
}
|
||||||
if let Err(e) =
|
if let Err(e) = Case::validate_certs(fabric, &initiator_noc, &initiator_icac) {
|
||||||
Case::validate_certs(fabric, &initiator_noc, &initiator_icac, self.utc_calendar)
|
|
||||||
{
|
|
||||||
error!("Certificate Chain doesn't match: {}", e);
|
error!("Certificate Chain doesn't match: {}", e);
|
||||||
common::create_sc_status_report(ctx.tx, common::SCStatusCodes::InvalidParameter, None)?;
|
common::create_sc_status_report(ctx.tx, common::SCStatusCodes::InvalidParameter, None)?;
|
||||||
ctx.exch_ctx.exch.close();
|
ctx.exch_ctx.exch.close();
|
||||||
|
@ -339,13 +332,8 @@ impl<'a> Case<'a> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validate_certs(
|
fn validate_certs(fabric: &Fabric, noc: &Cert, icac: &Option<Cert>) -> Result<(), Error> {
|
||||||
fabric: &Fabric,
|
let mut verifier = noc.verify_chain_start();
|
||||||
noc: &Cert,
|
|
||||||
icac: &Option<Cert>,
|
|
||||||
utc_calendar: UtcCalendar,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
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()? {
|
||||||
Err(ErrorCode::Invalid)?;
|
Err(ErrorCode::Invalid)?;
|
||||||
|
|
|
@ -24,7 +24,7 @@ use crate::{
|
||||||
secure_channel::common::*,
|
secure_channel::common::*,
|
||||||
tlv,
|
tlv,
|
||||||
transport::{proto_ctx::ProtoCtx, session::CloneData},
|
transport::{proto_ctx::ProtoCtx, session::CloneData},
|
||||||
utils::{epoch::UtcCalendar, rand::Rand},
|
utils::rand::Rand,
|
||||||
};
|
};
|
||||||
use log::{error, info};
|
use log::{error, info};
|
||||||
use num;
|
use num;
|
||||||
|
@ -46,10 +46,9 @@ impl<'a> SecureChannel<'a> {
|
||||||
fabric_mgr: &'a RefCell<FabricMgr>,
|
fabric_mgr: &'a RefCell<FabricMgr>,
|
||||||
mdns: &'a RefCell<MdnsMgr<'a>>,
|
mdns: &'a RefCell<MdnsMgr<'a>>,
|
||||||
rand: Rand,
|
rand: Rand,
|
||||||
utc_calendar: UtcCalendar,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
SecureChannel {
|
SecureChannel {
|
||||||
case: Case::new(fabric_mgr, rand, utc_calendar),
|
case: Case::new(fabric_mgr, rand),
|
||||||
pase,
|
pase,
|
||||||
mdns,
|
mdns,
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,7 @@ use crate::secure_channel::common::PROTO_ID_SECURE_CHANNEL;
|
||||||
use crate::secure_channel::core::SecureChannel;
|
use crate::secure_channel::core::SecureChannel;
|
||||||
use crate::transport::mrp::ReliableMessage;
|
use crate::transport::mrp::ReliableMessage;
|
||||||
use crate::transport::{exchange, network::Address, packet::Packet};
|
use crate::transport::{exchange, network::Address, packet::Packet};
|
||||||
use crate::utils::epoch::{Epoch, UtcCalendar};
|
use crate::utils::epoch::Epoch;
|
||||||
use crate::utils::rand::Rand;
|
use crate::utils::rand::Rand;
|
||||||
|
|
||||||
use super::proto_ctx::ProtoCtx;
|
use super::proto_ctx::ProtoCtx;
|
||||||
|
@ -210,8 +210,7 @@ impl<'a> TransportMgr<'a> {
|
||||||
+ Borrow<RefCell<PaseMgr>>
|
+ Borrow<RefCell<PaseMgr>>
|
||||||
+ Borrow<RefCell<MdnsMgr<'a>>>
|
+ Borrow<RefCell<MdnsMgr<'a>>>
|
||||||
+ Borrow<Epoch>
|
+ Borrow<Epoch>
|
||||||
+ Borrow<Rand>
|
+ Borrow<Rand>,
|
||||||
+ Borrow<UtcCalendar>,
|
|
||||||
>(
|
>(
|
||||||
matter: &'a T,
|
matter: &'a T,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -221,7 +220,6 @@ impl<'a> TransportMgr<'a> {
|
||||||
matter.borrow(),
|
matter.borrow(),
|
||||||
matter.borrow(),
|
matter.borrow(),
|
||||||
*matter.borrow(),
|
*matter.borrow(),
|
||||||
*matter.borrow(),
|
|
||||||
),
|
),
|
||||||
*matter.borrow(),
|
*matter.borrow(),
|
||||||
*matter.borrow(),
|
*matter.borrow(),
|
||||||
|
|
|
@ -2,60 +2,15 @@ use core::time::Duration;
|
||||||
|
|
||||||
pub type Epoch = fn() -> Duration;
|
pub type Epoch = fn() -> Duration;
|
||||||
|
|
||||||
pub type UtcCalendar = fn(Duration) -> UtcDate;
|
|
||||||
|
|
||||||
pub const MATTER_EPOCH_SECS: u64 = 946684800; // Seconds from 1970/01/01 00:00:00 till 2000/01/01 00:00:00 UTC
|
pub const MATTER_EPOCH_SECS: u64 = 946684800; // Seconds from 1970/01/01 00:00:00 till 2000/01/01 00:00:00 UTC
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, Eq, PartialEq)]
|
|
||||||
pub struct UtcDate {
|
|
||||||
pub year: u16,
|
|
||||||
pub month: u8, // 1 - 12
|
|
||||||
pub day: u8, // 1 - 31
|
|
||||||
pub hour: u8, // 0 - 23
|
|
||||||
pub minute: u8,
|
|
||||||
pub second: u8,
|
|
||||||
pub millis: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn dummy_epoch() -> Duration {
|
pub fn dummy_epoch() -> Duration {
|
||||||
Duration::from_secs(0)
|
Duration::from_secs(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dummy_utc_calendar(_duration: Duration) -> UtcDate {
|
|
||||||
Default::default()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub fn sys_epoch() -> Duration {
|
pub fn sys_epoch() -> Duration {
|
||||||
std::time::SystemTime::now()
|
std::time::SystemTime::now()
|
||||||
.duration_since(std::time::UNIX_EPOCH)
|
.duration_since(std::time::UNIX_EPOCH)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub fn sys_utc_calendar(duration: Duration) -> UtcDate {
|
|
||||||
use chrono::{Datelike, TimeZone, Timelike};
|
|
||||||
use log::warn;
|
|
||||||
|
|
||||||
let dt = match chrono::Utc.timestamp_opt(duration.as_secs() as _, duration.subsec_nanos()) {
|
|
||||||
chrono::LocalResult::None => panic!("Invalid time"),
|
|
||||||
chrono::LocalResult::Single(s) => s,
|
|
||||||
chrono::LocalResult::Ambiguous(_, a) => {
|
|
||||||
warn!(
|
|
||||||
"Ambiguous time for epoch {:?}; returning latest timestamp: {a}",
|
|
||||||
duration
|
|
||||||
);
|
|
||||||
a
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
UtcDate {
|
|
||||||
year: dt.year() as _,
|
|
||||||
month: dt.month() as _,
|
|
||||||
day: dt.day() as _,
|
|
||||||
hour: dt.hour() as _,
|
|
||||||
minute: dt.minute() as _,
|
|
||||||
second: dt.second() as _,
|
|
||||||
millis: (dt.nanosecond() / 1000) as _,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -106,15 +106,11 @@ pub type DmHandler<'a> = handler_chain_type!(OnOffCluster, EchoCluster, Descript
|
||||||
pub fn matter(mdns: &mut dyn Mdns) -> Matter<'_> {
|
pub fn matter(mdns: &mut dyn Mdns) -> Matter<'_> {
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use matter::utils::epoch::sys_epoch as epoch;
|
use matter::utils::epoch::sys_epoch as epoch;
|
||||||
#[cfg(feature = "std")]
|
|
||||||
use matter::utils::epoch::sys_utc_calendar as utc_calendar;
|
|
||||||
|
|
||||||
#[cfg(not(feature = "std"))]
|
#[cfg(not(feature = "std"))]
|
||||||
use matter::utils::epoch::dummy_epoch as epoch;
|
use matter::utils::epoch::dummy_epoch as epoch;
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
use matter::utils::epoch::dummy_utc_calendar as utc_calendar;
|
|
||||||
|
|
||||||
Matter::new(&BASIC_INFO, mdns, epoch, dummy_rand, utc_calendar, 5540)
|
Matter::new(&BASIC_INFO, mdns, epoch, dummy_rand, 5540)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An Interaction Model Engine to facilitate easy testing
|
/// An Interaction Model Engine to facilitate easy testing
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use matter::cert;
|
use matter::cert;
|
||||||
use matter::tlv;
|
use matter::tlv;
|
||||||
use matter::utils::epoch::sys_utc_calendar;
|
|
||||||
use simple_logger::SimpleLogger;
|
use simple_logger::SimpleLogger;
|
||||||
use std::process;
|
use std::process;
|
||||||
|
|
||||||
|
@ -95,7 +94,7 @@ fn main() {
|
||||||
} else if m.is_present("as-asn1") {
|
} else if m.is_present("as-asn1") {
|
||||||
let mut asn1_cert = [0_u8; 1024];
|
let mut asn1_cert = [0_u8; 1024];
|
||||||
let cert = cert::Cert::new(&tlv_list[..index]).unwrap();
|
let cert = cert::Cert::new(&tlv_list[..index]).unwrap();
|
||||||
let len = cert.as_asn1(&mut asn1_cert, sys_utc_calendar).unwrap();
|
let len = cert.as_asn1(&mut asn1_cert).unwrap();
|
||||||
println!("{:02x?}", &asn1_cert[..len]);
|
println!("{:02x?}", &asn1_cert[..len]);
|
||||||
} else {
|
} else {
|
||||||
tlv::print_tlv_list(&tlv_list[..index]);
|
tlv::print_tlv_list(&tlv_list[..index]);
|
||||||
|
|
Loading…
Add table
Reference in a new issue