use std::fmt::UpperHex;
#[allow(unused)]
#[derive(Debug, Clone)]
pub struct TLV {
pub t: u16,
pub l: u16,
pub v: Vec<u8>,
pub subs: Vec<TLV>,
}
#[allow(unused)]
impl TLV {
pub fn get_t(&self) -> u16 {
self.t
}
pub fn get_l(&self) -> u16 {
self.l
}
pub fn get_v(&self) -> &[u8] {
&self.v[..]
}
pub fn if_recursive(&self) -> bool {
if self.subs.len() == 0 {
false
} else {
true
}
}
pub fn find_tag(&self, tag: u16) -> Option<TLV> {
if self.t == tag {
return Some(self.clone());
} else if self.if_recursive() {
for tlv in &self.subs {
let res = tlv.find_tag(tag);
match res {
Some(res) => return Some(res),
_ => (),
}
}
}
None
}
pub fn get_aid(&self) -> Option<Vec<u8>> {
let tlv = self.find_tag(0x4F_u16)?;
Some(tlv.v.clone())
}
pub fn get_historical_bytes(&self) -> Option<Vec<u8>> {
let tlv = self.find_tag(0x5F52)?;
Some(tlv.v.clone())
}
pub fn get_fingerprints(&self) -> Option<Vec<u8>> {
let tlv = self.find_tag(0xC5)?;
Some(tlv.v.clone())
}
pub fn get_key_information(&self) -> Option<Vec<u8>> {
let tlv = self.find_tag(0xDE)?;
Some(tlv.v.clone())
}
pub fn get_name(&self) -> Option<Vec<u8>> {
let tlv = self.find_tag(0x5B)?;
Some(tlv.v.clone())
}
pub fn get_signature_algo_attributes(&self) -> Option<Vec<u8>> {
let tlv = self.find_tag(0xC1)?;
Some(tlv.v.clone())
}
pub fn get_encryption_algo_attributes(&self) -> Option<Vec<u8>> {
let tlv = self.find_tag(0xC2)?;
Some(tlv.v.clone())
}
pub fn get_authentication_algo_attributes(&self) -> Option<Vec<u8>> {
let tlv = self.find_tag(0xC3)?;
Some(tlv.v.clone())
}
pub fn get_number_of_signatures(&self) -> Option<Vec<u8>> {
let tlv = self.find_tag(0x93)?;
Some(tlv.v.clone())
}
pub fn get_pin_tries(&self) -> Option<Vec<u8>> {
let tlv = self.find_tag(0xC4)?;
Some(tlv.v.clone())
}
}
fn get(mut data: Vec<u8>) -> (u8, Vec<u8>) {
let res: Vec<u8> = data.drain(0..1).collect();
(res[0], data)
}
#[allow(unused)]
pub fn hex<T: UpperHex>(value: T) -> String {
format!("0x{:X}", value)
}
pub fn hexify(value: Vec<u8>) -> String {
let mut res = String::new();
for v in value.iter() {
let hvalue = hex(v);
res.push_str(" ");
res.push_str(&hvalue);
}
res
}
#[allow(unused_assignments)]
pub fn read_single(orig_data: Vec<u8>, recursive: bool) -> Result<(TLV, Vec<u8>), String> {
let mut subs: Vec<TLV> = Vec::new();
let data = orig_data.clone();
let (t, mut data) = get(data);
let mut t: u16 = (t & 0xff) as u16;
let mut t2: u16 = 0;
let composite: bool = (t & 0x20) == 0x20;
if (t & 0x1f) == 0x1f {
let p = get(data);
t2 = p.0 as u16;
data = p.1;
t2 = t2 & 0xff;
if (t2 & 0x1f) == 0x1f {
return Err(String::from("Only two bytes for tags"));
}
let internal_t: u16 = t << 8;
t = internal_t | (t2 & 0x7f);
}
let p = get(data);
let mut l: u16 = p.0 as u16;
let mut data = p.1;
if l == 0x81 {
let p = get(data);
l = p.0 as u16;
data = p.1;
l = l & 0xff;
} else if l == 0x82 {
let p = get(data);
l = p.0 as u16;
data = p.1;
l = l & 0xff;
let p = get(data);
let second_l = p.0 as u16;
data = p.1;
let internal_l: u16 = l << 8_u8;
l = internal_l | (second_l & 0xff);
} else if l >= 0x80 {
return Err(String::from("Invalid length field!"));
}
let len: usize = l.clone() as usize;
let v = if composite == true {
data[..len].iter().cloned().collect()
} else {
data.drain(0..len).into_iter().collect()
};
if recursive && composite {
subs = read_list(data, true);
return Ok((TLV { t, l, v, subs }, vec![]));
}
Ok((TLV { t, l, v, subs }, data))
}
pub fn read_list(orig_data: Vec<u8>, recursive: bool) -> Vec<TLV> {
let mut result: Vec<TLV> = Vec::new();
let mut data = orig_data.clone();
while data.len() > 0 {
if data[0] == 0xff || data[0] == 0x00 {
let p = get(data);
data = p.1
}
let tmp = read_single(data, recursive).unwrap();
data = tmp.1;
result.push(tmp.0);
}
result
}
pub fn parse_fingerprints(data: Vec<u8>) -> (Vec<u8>, Vec<u8>, Vec<u8>) {
let sig_f = &data[0..20];
let dec_f = &data[20..40];
let auth_f = &data[40..60];
return (
sig_f.iter().cloned().collect(),
dec_f.iter().cloned().collect(),
auth_f.iter().cloned().collect(),
);
}
pub fn parse_card_serial(data: Vec<u8>) -> String {
let mut res = String::new();
for i in 10..14 {
res.push_str(&format!("{:02X}", data[i]));
}
res
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs::File;
use std::io::Read;
fn get_my_tlv(filename: &str) -> TLV {
let mut f = File::open(filename).expect("no file found");
let mut buffer: Vec<u8> = Vec::new();
f.read_to_end(&mut buffer).unwrap();
let big_box = &read_list(buffer, true)[0];
big_box.clone()
}
fn read_file(filename: &str) -> Vec<u8> {
let mut f = File::open(filename).expect("no file found");
let mut buffer: Vec<u8> = Vec::new();
f.read_to_end(&mut buffer).unwrap();
return buffer;
}
#[test]
fn test_create_tlv() {
let mut f = File::open("./data/capabilities_tlv.binary").expect("no file found");
let mut buffer: Vec<u8> = Vec::new();
f.read_to_end(&mut buffer).unwrap();
let big_box = read_list(buffer, true);
assert_eq!(big_box[0].get_t(), 0x006E);
for bigb in big_box {
let ts = bigb.subs.clone();
for tlv in ts {
dbg!(hex(tlv.t));
dbg!(hex(tlv.l));
dbg!(tlv.if_recursive());
}
}
}
#[test]
fn test_parse_name_tlv() {
let big_box = get_my_tlv("./data/name.binary");
let tb = big_box.get_name().unwrap();
assert_eq!(String::from_utf8(tb).unwrap(), String::from("Das<<Kushal"));
}
#[test]
fn test_parse_fingerprints() {
let hardcoded = (
vec![
11, 193, 53, 18, 94, 178, 255, 154, 15, 136, 238, 28, 198, 95, 240, 7, 199, 87,
102, 237,
],
vec![
210, 186, 246, 33, 46, 76, 222, 84, 140, 51, 12, 61, 251, 130, 170, 93, 50, 109,
167, 93,
],
vec![
98, 27, 19, 57, 205, 184, 49, 71, 154, 77, 235, 79, 124, 144, 242, 116, 158, 8, 94,
29,
],
);
let big_box = get_my_tlv("./data/capabilities_tlv.binary");
let tlv = big_box.get_fingerprints().unwrap();
assert_eq!(hardcoded, parse_fingerprints(tlv));
}
#[test]
fn test_parse_card_serial_number() {
let data = read_file("./data/aid.binary");
assert_eq!(parse_card_serial(data), "14490729");
}
}