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(&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() {
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];

View file

@ -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 <M3>, 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::<Sha512>::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")]

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;
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<u8>) {
impl FormatTlv for (&u8, &Vec<u8>) {
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<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 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 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<HashMap<u8, Vec<u8>>, 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")]