cleanup, show tlv errors

This commit is contained in:
Alex Janka 2024-02-22 10:38:42 +11:00
parent 3b9bc6c959
commit 7a49efe6f6
4 changed files with 129 additions and 40 deletions

View file

@ -159,12 +159,6 @@ impl AccessorySocket {
} }
send_data.extend_from_slice("\r\n".as_bytes()); send_data.extend_from_slice("\r\n".as_bytes());
send_data.extend_from_slice(&body); send_data.extend_from_slice(&body);
let mut visible = String::new();
for b in &send_data {
let part: Vec<u8> = 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() { if let Some(encryption) = self.socket_encryption.as_mut() {
let mut packets = Vec::new(); let mut packets = Vec::new();
@ -201,9 +195,6 @@ impl AccessorySocket {
log::info!("encrypted {i} chunks!"); log::info!("encrypted {i} chunks!");
} }
log::info!("data: {send_data:X?}");
log::info!("data len: {}", send_data.len());
self.socket.write_all(&send_data)?; self.socket.write_all(&send_data)?;
let mut buf = [0; 1024]; let mut buf = [0; 1024];

View file

@ -4,14 +4,14 @@ use hkdf::Hkdf;
use sha2::Sha512; use sha2::Sha512;
use std::{collections::HashMap, path::PathBuf}; use std::{collections::HashMap, path::PathBuf};
use thiserror::Error; use thiserror::Error;
use tlv8::{TlvEncode, TlvType}; use tlv8::{HomekitState, TlvEncode, TlvType};
use x25519_dalek::{EphemeralSecret, PublicKey}; use x25519_dalek::{EphemeralSecret, PublicKey};
use pairing_data::DevicePairingData; use pairing_data::DevicePairingData;
use crate::{ use crate::{
homekit_http::AccessorySocket, homekit_http::AccessorySocket,
tlv8::{decode, FormatTlv, TlvEncodableData}, tlv8::{decode, TlvEncodableData},
}; };
mod pairing_data; mod pairing_data;
@ -198,8 +198,6 @@ impl DevicePairingData {
return Err(HomekitError::StateMismatch); return Err(HomekitError::StateMismatch);
} }
log::info!("step3 response: {}", step3_response.as_tlv_string());
// 5.7.4 M4: Accessory -> iOS Device Verify Finish Responseʼ // 5.7.4 M4: Accessory -> iOS Device Verify Finish Responseʼ
// When the accessory receives <M3>, it must perform the following steps: // When the accessory receives <M3>, it must perform the following steps:
// //
@ -233,14 +231,12 @@ impl DevicePairingData {
b"Control-Write-Encryption-Key", b"Control-Write-Encryption-Key",
&mut controller_to_accessory_key, &mut controller_to_accessory_key,
)?; )?;
log::info!("c2a key: {controller_to_accessory_key:?}");
let mut accessory_to_controller_key = [0; 32]; let mut accessory_to_controller_key = [0; 32];
Hkdf::<Sha512>::new(Some(b"Control-Salt"), shared_secret.as_bytes()).expand( Hkdf::<Sha512>::new(Some(b"Control-Salt"), shared_secret.as_bytes()).expand(
b"Control-Read-Encryption-Key", b"Control-Read-Encryption-Key",
&mut accessory_to_controller_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); 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)] #[derive(Debug, Error)]
pub enum HomekitError { pub enum HomekitError {
#[error("io")] #[error("io")]
@ -283,7 +270,7 @@ pub enum HomekitError {
#[error("no device pairing data stored")] #[error("no device pairing data stored")]
NoPairingData, NoPairingData,
#[error("tlv error")] #[error("tlv error")]
Tlv(#[from] tlv8::TlvError), Tlv(#[from] tlv8::TlvCodecError),
#[error("mismatch with state response")] #[error("mismatch with state response")]
StateMismatch, StateMismatch,
#[error("Tlv not found")] #[error("Tlv not found")]

View file

@ -70,3 +70,79 @@ impl TryFrom<u8> for TlvType {
} }
} }
} }
#[derive(Debug)]
pub enum TlvError {
Reserved,
Unknown,
Authentication,
Backoff,
MaxPeers,
MaxTries,
Unavailable,
Busy,
}
impl From<TlvError> 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<u8> for TlvError {
type Error = TlvErrorDecodeError;
fn try_from(value: u8) -> Result<Self, Self::Error> {
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<u8> for HomekitState {
type Error = HomekitStateDecodeError;
fn try_from(value: u8) -> Result<Self, Self::Error> {
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)),
}
}
}

View file

@ -1,11 +1,11 @@
mod data_types; use self::data_types::TlvError;
use std::collections::HashMap; use std::collections::HashMap;
pub use data_types::TlvType;
use thiserror::Error; use thiserror::Error;
pub use data_types::{HomekitState, TlvType};
mod data_types;
pub trait FormatTlv { pub trait FormatTlv {
fn as_tlv_string(&self) -> String; fn as_tlv_string(&self) -> String;
} }
@ -20,11 +20,38 @@ impl FormatTlv for (u8, Vec<u8>) {
impl FormatTlv for (&u8, &Vec<u8>) { impl FormatTlv for (&u8, &Vec<u8>) {
fn as_tlv_string(&self) -> String { fn as_tlv_string(&self) -> String {
let (tlv_type, data) = self; let (tlv_type, data) = self;
let tlv_type = TlvType::try_from(**tlv_type).map_or_else( let tlv_type =
|e| format!("Unknown TLV type: {}", e.0), TlvType::try_from(**tlv_type).map_err(|e| format!("Unknown TLV type: {}", e.0));
|v| format!("{v:?}"), match tlv_type {
); Ok(tlv_type) => match tlv_type {
format!("{tlv_type}: {data:?} (length: {})", data.len()) 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<u8, Vec<u8>> {
} }
} }
pub fn decode(data: &[u8]) -> Result<HashMap<u8, Vec<u8>>, TlvError> { impl FormatTlv for Vec<(u8, Vec<u8>)> {
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<HashMap<u8, Vec<u8>>, TlvCodecError> {
let mut tlvs = HashMap::new(); let mut tlvs = HashMap::new();
let mut data = data; let mut data = data;
@ -43,17 +77,17 @@ pub fn decode(data: &[u8]) -> Result<HashMap<u8, Vec<u8>>, TlvError> {
let tlv_len = (data[1] as usize) + 2; let tlv_len = (data[1] as usize) + 2;
let current; let current;
if tlv_len > data.len() { if tlv_len > data.len() {
return Err(TlvError::WrongLength); return Err(TlvCodecError::WrongLength);
} }
(current, data) = data.split_at(tlv_len); (current, data) = data.split_at(tlv_len);
if current.len() < 2 { if current.len() < 2 {
return Err(TlvError::TooShort); return Err(TlvCodecError::TooShort);
} }
if current.len() < tlv_len { if current.len() < tlv_len {
return Err(TlvError::WrongLength); return Err(TlvCodecError::WrongLength);
} }
let tlv_type = current[0]; let tlv_type = current[0];
@ -64,11 +98,12 @@ pub fn decode(data: &[u8]) -> Result<HashMap<u8, Vec<u8>>, TlvError> {
}; };
tlvs.insert(tlv_type, tlv_data); tlvs.insert(tlv_type, tlv_data);
} }
log::info!("{}", tlvs.as_tlv_string());
Ok(tlvs) Ok(tlvs)
} }
#[derive(Debug, Error)] #[derive(Debug, Error)]
pub enum TlvError { pub enum TlvCodecError {
#[error("too short")] #[error("too short")]
TooShort, TooShort,
#[error("wrong length")] #[error("wrong length")]