diff --git a/tools/tlv_tool/Cargo.toml b/tools/tlv_tool/Cargo.toml index f8c1e23..4ae0088 100644 --- a/tools/tlv_tool/Cargo.toml +++ b/tools/tlv_tool/Cargo.toml @@ -10,3 +10,4 @@ matter-iot = { path = "../../matter" } log = {version = "0.4.14", features = ["max_level_trace", "release_max_level_warn"]} simple_logger = "1.16.0" clap = "2.34" +hex = "0.4" diff --git a/tools/tlv_tool/README.md b/tools/tlv_tool/README.md index de81c13..cbc647f 100644 --- a/tools/tlv_tool/README.md +++ b/tools/tlv_tool/README.md @@ -1,10 +1,14 @@ # TLV Tool + A simple tool for printing Matter TLVs or Matter-encoded certificates. ``` $ # For printing a Matter TLV List $ tlv_tool --hex "15, 24, 0, 1, 18" +$ # For printing a Matter TLV List in hexstring +$ tlv_tool --hexstring "1524000118" + $ # For printing a Matter encoded certificate $ tlv_tool --cert "0x15, 0x00" ``` diff --git a/tools/tlv_tool/src/main.rs b/tools/tlv_tool/src/main.rs index 54e5374..0b75ba0 100644 --- a/tools/tlv_tool/src/main.rs +++ b/tools/tlv_tool/src/main.rs @@ -21,6 +21,41 @@ use matter::tlv; use simple_logger::SimpleLogger; use std::process; +fn decode_to_slice_radix>(data: T, out: &mut [u8], radix: u32) -> &[u8] { + let data = data.as_ref(); + + let list = data.split(','); + let mut index = 0; + for byte in list { + let byte = byte.strip_prefix("0x").unwrap_or(byte); + if let Ok(b) = u8::from_str_radix(byte, radix) { + out[index] = b; + index += 1; + } else { + eprintln!("Skipping unknown byte: {}", byte); + } + if index >= out.len() { + eprintln!("Input too long"); + process::exit(1); + } + } + &out[..index] +} + +fn print_tlv(matches: &clap::ArgMatches<'_>, tlv_list: &[u8]) { + if matches.is_present("cert") { + let cert = cert::Cert::new(tlv_list).unwrap(); + println!("{}", cert); + } else if matches.is_present("as-asn1") { + let mut asn1_cert = [0_u8; 1024]; + let cert = cert::Cert::new(tlv_list).unwrap(); + let len = cert.as_asn1(&mut asn1_cert).unwrap(); + println!("{:02x?}", &asn1_cert[..len]); + } else { + tlv::print_tlv_list(tlv_list); + } +} + fn main() { SimpleLogger::new() .with_level(log::LevelFilter::Trace) @@ -42,6 +77,12 @@ fn main() { .long("dec") .help("The input is in Decimal"), ) + .arg( + Arg::with_name("hexstring") + .short("H") + .long("hexstring") + .help("The input is in Hexadecimal String"), + ) .arg( Arg::with_name("cert") .long("cert") @@ -55,14 +96,12 @@ fn main() { .arg(Arg::with_name("tlvs").help("List of TLVs").required(true)) .get_matches(); - // Assume hexadecimal by-default - let base = if m.is_present("hex") { - 16 - } else if m.is_present("dec") { - 10 - } else { - 16 - }; + if m.is_present("hex") || m.is_present("dec") { + if m.is_present("hexstring") { + eprintln!("Cannot use --hexstring with --hex or --dec"); + process::exit(1); + } + } let list: String = m .value_of("tlvs") @@ -70,33 +109,24 @@ fn main() { .chars() .filter(|c| !c.is_whitespace()) .collect(); - let list = list.split(','); - let mut tlv_list: [u8; 1024] = [0; 1024]; - let mut index = 0; - for byte in list { - let byte = byte.strip_prefix("0x").unwrap_or(byte); - if let Ok(b) = u8::from_str_radix(byte, base) { - tlv_list[index] = b; - index += 1; - } else { - eprintln!("Skipping unknown byte: {}", byte); - } - if index >= 1024 { - eprintln!("Input too long"); - process::exit(1); - } - } - // println!("Decoding: {:x?}", &tlv_list[..index]); - if m.is_present("cert") { - let cert = cert::Cert::new(&tlv_list[..index]).unwrap(); - println!("{}", cert); - } else if m.is_present("as-asn1") { - let mut asn1_cert = [0_u8; 1024]; - let cert = cert::Cert::new(&tlv_list[..index]).unwrap(); - let len = cert.as_asn1(&mut asn1_cert).unwrap(); - println!("{:02x?}", &asn1_cert[..len]); + if m.is_present("hexstring") { + let tlv_list = hex::decode(list).unwrap(); + print_tlv(&m, &tlv_list); } else { - tlv::print_tlv_list(&tlv_list[..index]); + // Assume hexadecimal by-default + let base = if m.is_present("hex") { + 16 + } else if m.is_present("dec") { + 10 + } else { + 16 + }; + + let mut tlv_list: [u8; 1024] = [0; 1024]; + let tlv_list = decode_to_slice_radix(list, &mut tlv_list, base); + + // println!("Decoding: {:x?}", &tlv_list[..index]); + print_tlv(&m, tlv_list); } }