Merge pull request #1 from project-chip/feature/ios_support

Commissioning Complete from iOS
This commit is contained in:
Kedar Sovani 2023-01-03 08:42:44 +05:30 committed by GitHub
commit aed39f716c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 84 additions and 31 deletions

View file

@ -141,8 +141,13 @@ impl NocCluster {
let noc_value = Cert::new(r.noc_value.0).map_err(|_| NocStatus::InvalidNOC)?; let noc_value = Cert::new(r.noc_value.0).map_err(|_| NocStatus::InvalidNOC)?;
info!("Received NOC as: {}", noc_value); info!("Received NOC as: {}", noc_value);
let icac_value = Cert::new(r.icac_value.0).map_err(|_| NocStatus::InvalidNOC)?; let icac_value = if r.icac_value.0.len() != 0 {
info!("Received ICAC as: {}", icac_value); let cert = Cert::new(r.icac_value.0).map_err(|_| NocStatus::InvalidNOC)?;
info!("Received ICAC as: {}", cert);
Some(cert)
} else {
None
};
let fabric = Fabric::new( let fabric = Fabric::new(
noc_data.key_pair, noc_data.key_pair,

View file

@ -36,9 +36,9 @@ impl ClusterType for NwCommCluster {
} }
enum FeatureMap { enum FeatureMap {
_Wifi = 0, _Wifi = 0x01,
_Thread = 1, _Thread = 0x02,
Ethernet = 2, Ethernet = 0x04,
} }
impl NwCommCluster { impl NwCommCluster {

View file

@ -48,6 +48,7 @@ impl DescriptorCluster {
base: Cluster::new(ID)?, base: Cluster::new(ID)?,
}); });
c.base.add_attribute(attr_serverlist_new()?)?; c.base.add_attribute(attr_serverlist_new()?)?;
c.base.add_attribute(attr_partslist_new()?)?;
Ok(c) Ok(c)
} }
@ -65,6 +66,12 @@ impl DescriptorCluster {
}); });
let _ = tw.end_container(); let _ = tw.end_container();
} }
fn encode_parts_list(&self, tag: TagType, tw: &mut TLVWriter) {
// TODO: Support Partslist
let _ = tw.start_array(tag);
let _ = tw.end_container();
}
} }
impl ClusterType for DescriptorCluster { impl ClusterType for DescriptorCluster {
@ -80,7 +87,9 @@ impl ClusterType for DescriptorCluster {
Some(Attributes::ServerList) => encoder.encode(EncodeValue::Closure(&|tag, tw| { Some(Attributes::ServerList) => encoder.encode(EncodeValue::Closure(&|tag, tw| {
self.encode_server_list(tag, tw) self.encode_server_list(tag, tw)
})), })),
Some(Attributes::PartsList) => encoder.encode(EncodeValue::Closure(&|tag, tw| {
self.encode_parts_list(tag, tw)
})),
_ => { _ => {
error!("Attribute not supported: this shouldn't happen"); error!("Attribute not supported: this shouldn't happen");
} }
@ -96,3 +105,12 @@ fn attr_serverlist_new() -> Result<Attribute, Error> {
Quality::NONE, Quality::NONE,
) )
} }
fn attr_partslist_new() -> Result<Attribute, Error> {
Attribute::new(
Attributes::PartsList as u16,
AttrValue::Custom,
Access::RV,
Quality::NONE,
)
}

View file

@ -52,7 +52,7 @@ pub struct Fabric {
fabric_id: u64, fabric_id: u64,
key_pair: Box<dyn CryptoKeyPair>, key_pair: Box<dyn CryptoKeyPair>,
pub root_ca: Cert, pub root_ca: Cert,
pub icac: Cert, pub icac: Option<Cert>,
pub noc: Cert, pub noc: Cert,
pub ipk: KeySet, pub ipk: KeySet,
compressed_id: [u8; COMPRESSED_FABRIC_ID_LEN], compressed_id: [u8; COMPRESSED_FABRIC_ID_LEN],
@ -63,7 +63,7 @@ impl Fabric {
pub fn new( pub fn new(
key_pair: KeyPair, key_pair: KeyPair,
root_ca: Cert, root_ca: Cert,
icac: Cert, icac: Option<Cert>,
noc: Cert, noc: Cert,
ipk: &[u8], ipk: &[u8],
) -> Result<Self, Error> { ) -> Result<Self, Error> {
@ -107,7 +107,7 @@ impl Fabric {
fabric_id: 0, fabric_id: 0,
key_pair: Box::new(KeyPairDummy::new()?), key_pair: Box::new(KeyPairDummy::new()?),
root_ca: Cert::default(), root_ca: Cert::default(),
icac: Cert::default(), icac: Some(Cert::default()),
noc: Cert::default(), noc: Cert::default(),
ipk: KeySet::default(), ipk: KeySet::default(),
compressed_id: [0; COMPRESSED_FABRIC_ID_LEN], compressed_id: [0; COMPRESSED_FABRIC_ID_LEN],
@ -165,8 +165,14 @@ impl Fabric {
let mut key = [0u8; MAX_CERT_TLV_LEN]; let mut key = [0u8; MAX_CERT_TLV_LEN];
let len = self.root_ca.as_tlv(&mut key)?; let len = self.root_ca.as_tlv(&mut key)?;
psm.set_kv_slice(fb_key!(index, ST_RCA), &key[..len])?; psm.set_kv_slice(fb_key!(index, ST_RCA), &key[..len])?;
let len = self.icac.as_tlv(&mut key)?;
let len = if let Some(icac) = &self.icac {
icac.as_tlv(&mut key)?
} else {
0
};
psm.set_kv_slice(fb_key!(index, ST_ICA), &key[..len])?; psm.set_kv_slice(fb_key!(index, ST_ICA), &key[..len])?;
let len = self.noc.as_tlv(&mut key)?; let len = self.noc.as_tlv(&mut key)?;
psm.set_kv_slice(fb_key!(index, ST_NOC), &key[..len])?; psm.set_kv_slice(fb_key!(index, ST_NOC), &key[..len])?;
psm.set_kv_slice(fb_key!(index, ST_IPK), self.ipk.epoch_key())?; psm.set_kv_slice(fb_key!(index, ST_IPK), self.ipk.epoch_key())?;
@ -191,7 +197,11 @@ impl Fabric {
let mut icac = Vec::new(); let mut icac = Vec::new();
psm.get_kv_slice(fb_key!(index, ST_ICA), &mut icac)?; psm.get_kv_slice(fb_key!(index, ST_ICA), &mut icac)?;
let icac = Cert::new(icac.as_slice())?; let icac = if icac.len() != 0 {
Some(Cert::new(icac.as_slice())?)
} else {
None
};
let mut noc = Vec::new(); let mut noc = Vec::new();
psm.get_kv_slice(fb_key!(index, ST_NOC), &mut noc)?; psm.get_kv_slice(fb_key!(index, ST_NOC), &mut noc)?;

View file

@ -120,7 +120,10 @@ impl Case {
let d = Sigma3Decrypt::from_tlv(&root)?; let d = Sigma3Decrypt::from_tlv(&root)?;
let initiator_noc = Cert::new(d.initiator_noc.0)?; let initiator_noc = Cert::new(d.initiator_noc.0)?;
let initiator_icac = Cert::new(d.initiator_icac.0)?; let mut initiator_icac = None;
if let Some(icac) = d.initiator_icac {
initiator_icac = Some(Cert::new(icac.0)?);
}
if let Err(e) = Case::validate_certs(fabric, &initiator_noc, &initiator_icac) { if let Err(e) = Case::validate_certs(fabric, &initiator_noc, &initiator_icac) {
error!("Certificate Chain doesn't match: {}", e); error!("Certificate Chain doesn't match: {}", e);
common::create_sc_status_report( common::create_sc_status_report(
@ -134,7 +137,7 @@ impl Case {
if Case::validate_sigma3_sign( if Case::validate_sigma3_sign(
d.initiator_noc.0, d.initiator_noc.0,
d.initiator_icac.0, d.initiator_icac.map(|a| a.0),
&initiator_noc, &initiator_noc,
d.signature.0, d.signature.0,
&case_session, &case_session,
@ -304,7 +307,7 @@ impl Case {
fn validate_sigma3_sign( fn validate_sigma3_sign(
initiator_noc: &[u8], initiator_noc: &[u8],
initiator_icac: &[u8], initiator_icac: Option<&[u8]>,
initiator_noc_cert: &Cert, initiator_noc_cert: &Cert,
sign: &[u8], sign: &[u8],
case_session: &CaseSession, case_session: &CaseSession,
@ -314,8 +317,10 @@ impl Case {
let mut write_buf = WriteBuf::new(&mut buf, MAX_TBS_SIZE); let mut write_buf = WriteBuf::new(&mut buf, MAX_TBS_SIZE);
let mut tw = TLVWriter::new(&mut write_buf); let mut tw = TLVWriter::new(&mut write_buf);
tw.start_struct(TagType::Anonymous)?; tw.start_struct(TagType::Anonymous)?;
tw.str8(TagType::Context(1), initiator_noc)?; tw.str16(TagType::Context(1), initiator_noc)?;
tw.str8(TagType::Context(2), initiator_icac)?; if let Some(icac) = initiator_icac {
tw.str16(TagType::Context(2), icac)?;
}
tw.str8(TagType::Context(3), &case_session.peer_pub_key)?; tw.str8(TagType::Context(3), &case_session.peer_pub_key)?;
tw.str8(TagType::Context(4), &case_session.our_pub_key)?; tw.str8(TagType::Context(4), &case_session.our_pub_key)?;
tw.end_container()?; tw.end_container()?;
@ -325,22 +330,24 @@ impl Case {
Ok(()) Ok(())
} }
fn validate_certs(fabric: &Fabric, noc: &Cert, icac: &Cert) -> Result<(), Error> { fn validate_certs(fabric: &Fabric, noc: &Cert, icac: &Option<Cert>) -> Result<(), Error> {
if let Ok(fid) = icac.get_fabric_id() { let mut verifier = noc.verify_chain_start();
if fid != fabric.get_fabric_id() {
return Err(Error::Invalid);
}
}
if fabric.get_fabric_id() != noc.get_fabric_id()? { if fabric.get_fabric_id() != noc.get_fabric_id()? {
return Err(Error::Invalid); return Err(Error::Invalid);
} }
noc.verify_chain_start() if let Some(icac) = icac {
.add_cert(icac)? // If ICAC is present handle it
.add_cert(&fabric.root_ca)? if let Ok(fid) = icac.get_fabric_id() {
.finalise()?; if fid != fabric.get_fabric_id() {
return Err(Error::Invalid);
}
}
verifier = verifier.add_cert(icac)?;
}
verifier.add_cert(&fabric.root_ca)?.finalise()?;
Ok(()) Ok(())
} }
@ -475,7 +482,10 @@ impl Case {
let mut tw = TLVWriter::new(&mut write_buf); let mut tw = TLVWriter::new(&mut write_buf);
tw.start_struct(TagType::Anonymous)?; tw.start_struct(TagType::Anonymous)?;
tw.str16_as(TagType::Context(1), |buf| fabric.noc.as_tlv(buf))?; tw.str16_as(TagType::Context(1), |buf| fabric.noc.as_tlv(buf))?;
tw.str16_as(TagType::Context(2), |buf| fabric.icac.as_tlv(buf))?; if let Some(icac_cert) = &fabric.icac {
tw.str16_as(TagType::Context(2), |buf| icac_cert.as_tlv(buf))?
};
tw.str8(TagType::Context(3), signature)?; tw.str8(TagType::Context(3), signature)?;
tw.str8(TagType::Context(4), &resumption_id)?; tw.str8(TagType::Context(4), &resumption_id)?;
tw.end_container()?; tw.end_container()?;
@ -515,7 +525,9 @@ impl Case {
let mut tw = TLVWriter::new(&mut write_buf); let mut tw = TLVWriter::new(&mut write_buf);
tw.start_struct(TagType::Anonymous)?; tw.start_struct(TagType::Anonymous)?;
tw.str16_as(TagType::Context(1), |buf| fabric.noc.as_tlv(buf))?; tw.str16_as(TagType::Context(1), |buf| fabric.noc.as_tlv(buf))?;
tw.str16_as(TagType::Context(2), |buf| fabric.icac.as_tlv(buf))?; if let Some(icac_cert) = &fabric.icac {
tw.str16_as(TagType::Context(2), |buf| icac_cert.as_tlv(buf))?;
}
tw.str8(TagType::Context(3), our_pub_key)?; tw.str8(TagType::Context(3), our_pub_key)?;
tw.str8(TagType::Context(4), peer_pub_key)?; tw.str8(TagType::Context(4), peer_pub_key)?;
tw.end_container()?; tw.end_container()?;
@ -537,6 +549,6 @@ struct Sigma1Req<'a> {
#[tlvargs(start = 1, lifetime = "'a")] #[tlvargs(start = 1, lifetime = "'a")]
struct Sigma3Decrypt<'a> { struct Sigma3Decrypt<'a> {
initiator_noc: OctetStr<'a>, initiator_noc: OctetStr<'a>,
initiator_icac: OctetStr<'a>, initiator_icac: Option<OctetStr<'a>>,
signature: OctetStr<'a>, signature: OctetStr<'a>,
} }

View file

@ -23,6 +23,7 @@ use crate::{
mdns::{self, Mdns}, mdns::{self, Mdns},
secure_channel::{common::*, pake::PAKE}, secure_channel::{common::*, pake::PAKE},
sys::SysMdnsService, sys::SysMdnsService,
tlv,
transport::proto_demux::{self, ProtoCtx, ResponseRequired}, transport::proto_demux::{self, ProtoCtx, ResponseRequired},
}; };
use log::{error, info}; use log::{error, info};
@ -120,7 +121,9 @@ impl proto_demux::HandleProto for SecureChannel {
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(Error::Invalid)?;
ctx.tx.set_proto_id(PROTO_ID_SECURE_CHANNEL as u16); ctx.tx.set_proto_id(PROTO_ID_SECURE_CHANNEL as u16);
match proto_opcode { info!("Received Data");
tlv::print_tlv_list(ctx.rx.as_borrow_slice());
let result = match proto_opcode {
OpCode::MRPStandAloneAck => self.mrpstandaloneack_handler(ctx), OpCode::MRPStandAloneAck => self.mrpstandaloneack_handler(ctx),
OpCode::PBKDFParamRequest => self.pbkdfparamreq_handler(ctx), OpCode::PBKDFParamRequest => self.pbkdfparamreq_handler(ctx),
OpCode::PASEPake1 => self.pasepake1_handler(ctx), OpCode::PASEPake1 => self.pasepake1_handler(ctx),
@ -131,7 +134,12 @@ impl proto_demux::HandleProto for SecureChannel {
error!("OpCode Not Handled: {:?}", proto_opcode); error!("OpCode Not Handled: {:?}", proto_opcode);
Err(Error::InvalidOpcode) Err(Error::InvalidOpcode)
} }
};
if result == Ok(ResponseRequired::Yes) {
info!("Sending response");
tlv::print_tlv_list(ctx.tx.as_borrow_slice());
} }
result
} }
fn get_proto_id(&self) -> usize { fn get_proto_id(&self) -> usize {

View file

@ -130,7 +130,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 put_str16() instead"); error!("use str16() instead");
return Err(Error::Invalid); return Err(Error::Invalid);
} }
self.put_control_tag(tag_type, WriteElementType::Str8l)?; self.put_control_tag(tag_type, WriteElementType::Str8l)?;