From 7a49efe6f6735294db784fbac6e918875a1c477d Mon Sep 17 00:00:00 2001 From: Alex Janka Date: Thu, 22 Feb 2024 10:38:42 +1100 Subject: [PATCH] cleanup, show tlv errors --- homekit-controller/src/homekit_http.rs | 9 --- homekit-controller/src/lib.rs | 19 +----- homekit-controller/src/tlv8/data_types.rs | 76 +++++++++++++++++++++++ homekit-controller/src/tlv8/mod.rs | 65 ++++++++++++++----- 4 files changed, 129 insertions(+), 40 deletions(-) diff --git a/homekit-controller/src/homekit_http.rs b/homekit-controller/src/homekit_http.rs index 2bf9019..a868b3d 100644 --- a/homekit-controller/src/homekit_http.rs +++ b/homekit-controller/src/homekit_http.rs @@ -159,12 +159,6 @@ impl AccessorySocket { } send_data.extend_from_slice("\r\n".as_bytes()); send_data.extend_from_slice(&body); - let mut visible = String::new(); - for b in &send_data { - let part: Vec = std::ascii::escape_default(*b).collect(); - visible.push_str(std::str::from_utf8(&part).unwrap()); - } - log::info!("data as string: {visible}"); if let Some(encryption) = self.socket_encryption.as_mut() { let mut packets = Vec::new(); @@ -201,9 +195,6 @@ impl AccessorySocket { log::info!("encrypted {i} chunks!"); } - log::info!("data: {send_data:X?}"); - log::info!("data len: {}", send_data.len()); - self.socket.write_all(&send_data)?; let mut buf = [0; 1024]; diff --git a/homekit-controller/src/lib.rs b/homekit-controller/src/lib.rs index 5208c61..3452452 100644 --- a/homekit-controller/src/lib.rs +++ b/homekit-controller/src/lib.rs @@ -4,14 +4,14 @@ use hkdf::Hkdf; use sha2::Sha512; use std::{collections::HashMap, path::PathBuf}; use thiserror::Error; -use tlv8::{TlvEncode, TlvType}; +use tlv8::{HomekitState, TlvEncode, TlvType}; use x25519_dalek::{EphemeralSecret, PublicKey}; use pairing_data::DevicePairingData; use crate::{ homekit_http::AccessorySocket, - tlv8::{decode, FormatTlv, TlvEncodableData}, + tlv8::{decode, TlvEncodableData}, }; mod pairing_data; @@ -198,8 +198,6 @@ impl DevicePairingData { return Err(HomekitError::StateMismatch); } - log::info!("step3 response: {}", step3_response.as_tlv_string()); - // 5.7.4 M4: Accessory -> iOS Device – ‘Verify Finish Responseʼ // When the accessory receives , it must perform the following steps: // @@ -233,14 +231,12 @@ impl DevicePairingData { b"Control-Write-Encryption-Key", &mut controller_to_accessory_key, )?; - log::info!("c2a key: {controller_to_accessory_key:?}"); let mut accessory_to_controller_key = [0; 32]; Hkdf::::new(Some(b"Control-Salt"), shared_secret.as_bytes()).expand( b"Control-Read-Encryption-Key", &mut accessory_to_controller_key, )?; - log::info!("a2c key: {accessory_to_controller_key:?}"); socket.set_encryption(controller_to_accessory_key, accessory_to_controller_key); @@ -265,15 +261,6 @@ impl DevicePairingData { } } -pub enum HomekitState { - M1 = 1, - M2 = 2, - M3 = 3, - M4 = 4, - M5 = 5, - M6 = 6, -} - #[derive(Debug, Error)] pub enum HomekitError { #[error("io")] @@ -283,7 +270,7 @@ pub enum HomekitError { #[error("no device pairing data stored")] NoPairingData, #[error("tlv error")] - Tlv(#[from] tlv8::TlvError), + Tlv(#[from] tlv8::TlvCodecError), #[error("mismatch with state response")] StateMismatch, #[error("Tlv not found")] diff --git a/homekit-controller/src/tlv8/data_types.rs b/homekit-controller/src/tlv8/data_types.rs index 96d7c05..41b0cdb 100644 --- a/homekit-controller/src/tlv8/data_types.rs +++ b/homekit-controller/src/tlv8/data_types.rs @@ -70,3 +70,79 @@ impl TryFrom for TlvType { } } } + +#[derive(Debug)] +pub enum TlvError { + Reserved, + Unknown, + Authentication, + Backoff, + MaxPeers, + MaxTries, + Unavailable, + Busy, +} + +impl From for u8 { + fn from(value: TlvError) -> Self { + match value { + TlvError::Reserved => 0x00, + TlvError::Unknown => 0x01, + TlvError::Authentication => 0x02, + TlvError::Backoff => 0x03, + TlvError::MaxPeers => 0x04, + TlvError::MaxTries => 0x05, + TlvError::Unavailable => 0x06, + TlvError::Busy => 0x07, + } + } +} + +#[derive(Debug)] +pub struct TlvErrorDecodeError(pub u8); + +impl TryFrom for TlvError { + type Error = TlvErrorDecodeError; + + fn try_from(value: u8) -> Result { + match value { + 0x00 => Ok(TlvError::Reserved), + 0x01 => Ok(TlvError::Unknown), + 0x02 => Ok(TlvError::Authentication), + 0x03 => Ok(TlvError::Backoff), + 0x04 => Ok(TlvError::MaxPeers), + 0x05 => Ok(TlvError::MaxTries), + 0x06 => Ok(TlvError::Unavailable), + 0x07 => Ok(TlvError::Busy), + _ => Err(TlvErrorDecodeError(value)), + } + } +} + +#[derive(Debug)] +pub enum HomekitState { + M1 = 1, + M2 = 2, + M3 = 3, + M4 = 4, + M5 = 5, + M6 = 6, +} + +pub struct HomekitStateDecodeError(pub u8); + +impl TryFrom for HomekitState { + type Error = HomekitStateDecodeError; + + fn try_from(value: u8) -> Result { + match value { + 1 => Ok(Self::M1), + 2 => Ok(Self::M2), + 3 => Ok(Self::M3), + 4 => Ok(Self::M4), + 5 => Ok(Self::M5), + 6 => Ok(Self::M6), + _ => Err(HomekitStateDecodeError(value)), + } + } +} diff --git a/homekit-controller/src/tlv8/mod.rs b/homekit-controller/src/tlv8/mod.rs index 928c65f..bc04c69 100644 --- a/homekit-controller/src/tlv8/mod.rs +++ b/homekit-controller/src/tlv8/mod.rs @@ -1,11 +1,11 @@ -mod data_types; - +use self::data_types::TlvError; use std::collections::HashMap; - -pub use data_types::TlvType; - use thiserror::Error; +pub use data_types::{HomekitState, TlvType}; + +mod data_types; + pub trait FormatTlv { fn as_tlv_string(&self) -> String; } @@ -20,11 +20,38 @@ impl FormatTlv for (u8, Vec) { impl FormatTlv for (&u8, &Vec) { fn as_tlv_string(&self) -> String { let (tlv_type, data) = self; - let tlv_type = TlvType::try_from(**tlv_type).map_or_else( - |e| format!("Unknown TLV type: {}", e.0), - |v| format!("{v:?}"), - ); - format!("{tlv_type}: {data:?} (length: {})", data.len()) + let tlv_type = + TlvType::try_from(**tlv_type).map_err(|e| format!("Unknown TLV type: {}", e.0)); + match tlv_type { + Ok(tlv_type) => match tlv_type { + TlvType::Error => data + .first() + .map(|v| { + format!( + "Error: {}", + TlvError::try_from(*v).map_or_else( + |e| format!("Unknown error {:02X}", e.0), + |v| format!("{v:?}"), + ) + ) + }) + .unwrap_or(String::from("TLV error type with no data!")), + TlvType::State => data + .first() + .map(|v| { + format!( + "State: {}", + HomekitState::try_from(*v).map_or_else( + |e| format!("Unknown state {:02X}", e.0), + |v| format!("{v:?}"), + ) + ) + }) + .unwrap_or(String::from("TLV error type with no data!")), + _ => format!("{tlv_type:?}: {data:?} (length: {})", data.len()), + }, + Err(tlv_type) => format!("{tlv_type}: {data:?} (length: {})", data.len()), + } } } @@ -35,7 +62,14 @@ impl FormatTlv for HashMap> { } } -pub fn decode(data: &[u8]) -> Result>, TlvError> { +impl FormatTlv for Vec<(u8, Vec)> { + fn as_tlv_string(&self) -> String { + self.iter() + .fold(String::new(), |a, v| format!("{a}\n{}", v.as_tlv_string())) + } +} + +pub fn decode(data: &[u8]) -> Result>, TlvCodecError> { let mut tlvs = HashMap::new(); let mut data = data; @@ -43,17 +77,17 @@ pub fn decode(data: &[u8]) -> Result>, TlvError> { let tlv_len = (data[1] as usize) + 2; let current; if tlv_len > data.len() { - return Err(TlvError::WrongLength); + return Err(TlvCodecError::WrongLength); } (current, data) = data.split_at(tlv_len); if current.len() < 2 { - return Err(TlvError::TooShort); + return Err(TlvCodecError::TooShort); } if current.len() < tlv_len { - return Err(TlvError::WrongLength); + return Err(TlvCodecError::WrongLength); } let tlv_type = current[0]; @@ -64,11 +98,12 @@ pub fn decode(data: &[u8]) -> Result>, TlvError> { }; tlvs.insert(tlv_type, tlv_data); } + log::info!("{}", tlvs.as_tlv_string()); Ok(tlvs) } #[derive(Debug, Error)] -pub enum TlvError { +pub enum TlvCodecError { #[error("too short")] TooShort, #[error("wrong length")]