added tests for write_data and read_data

This commit is contained in:
Kai Jan Kriegel 2021-12-26 02:33:57 +01:00
parent 099c78d979
commit 3dd731e1cc

View File

@ -11,7 +11,6 @@ use crate::crypto::util::expand_to_blocksize;
use crate::desfire::{FileCommunication, ChangeMasterKeySettings, CreateDeleteFile, FileDirectoryAccess, ChangeMasterKey, ChangeApplicationKey, CryptoOperationsType, FileIdentifiers}; use crate::desfire::{FileCommunication, ChangeMasterKeySettings, CreateDeleteFile, FileDirectoryAccess, ChangeMasterKey, ChangeApplicationKey, CryptoOperationsType, FileIdentifiers};
use crate::iso7816_4::apduresponse::APDUResponse; use crate::iso7816_4::apduresponse::APDUResponse;
use num_traits::FromPrimitive; use num_traits::FromPrimitive;
use std::fs::read_to_string;
pub struct Desfire { pub struct Desfire {
card: Box<dyn Card>, card: Box<dyn Card>,
@ -81,6 +80,8 @@ impl Desfire {
rnd_b_rl.rotate_left(1); rnd_b_rl.rotate_left(1);
println!("RND_B_RL: {:x?}", rnd_b_rl); println!("RND_B_RL: {:x?}", rnd_b_rl);
//FIXME: This is ugly, we should find a better way to make the function testable
//TODO: Check if we need a CSPRNG here
let rnd_a = match rnd_a { let rnd_a = match rnd_a {
None => { rand::random() } None => { rand::random() }
Some(i) => { i } Some(i) => { i }
@ -169,6 +170,8 @@ impl Desfire {
rnd_b_rl.rotate_left(1); rnd_b_rl.rotate_left(1);
println!("RND_B_RL: {:x?}", rnd_b_rl); println!("RND_B_RL: {:x?}", rnd_b_rl);
//FIXME: This is ugly, we should find a better way to make the function testable
//TODO: Check if we need a CSPRNG here
let rnd_a = match rnd_a { let rnd_a = match rnd_a {
None => { rand::random() } None => { rand::random() }
Some(i) => { i } Some(i) => { i }
@ -425,6 +428,8 @@ impl Desfire {
return Err(InvalidFileID); return Err(InvalidFileID);
} }
println!("Writing data to file {}", file_id);
const MAX_BYTES_PER_TRANSACTION: usize = 47; const MAX_BYTES_PER_TRANSACTION: usize = 47;
let mut bytes_writen: usize = 0; let mut bytes_writen: usize = 0;
let length: usize = data.len(); let length: usize = data.len();
@ -438,11 +443,14 @@ impl Desfire {
}; };
let mut write_buffer = vec![file_id]; let mut write_buffer = vec![file_id];
write_buffer.append(&mut offset.to_le_bytes()[..3].to_vec()); write_buffer.append(&mut (offset as usize + bytes_writen).to_le_bytes()[..3].to_vec());
write_buffer.append(&mut bytes_towrite.to_le_bytes()[..3].to_vec()); write_buffer.append(&mut bytes_towrite.to_le_bytes()[..3].to_vec());
write_buffer.append(&mut data[bytes_writen..bytes_writen + bytes_towrite].to_vec()); write_buffer.append(&mut data[bytes_writen..bytes_writen + bytes_towrite].to_vec());
bytes_writen += bytes_towrite; bytes_writen += bytes_towrite;
println!("WRITE_BUFFER: {:x?}", write_buffer);
println!("BYTES_WRITEN: {}", bytes_writen);
let cmd_write_data = APDUCommand { let cmd_write_data = APDUCommand {
case: IsoCase::Case4Short, case: IsoCase::Case4Short,
cla: 0x90, cla: 0x90,
@ -450,8 +458,10 @@ impl Desfire {
data: Option::from(write_buffer), data: Option::from(write_buffer),
..Default::default() ..Default::default()
}; };
println!("CMD_WRITE_DATA: {}", cmd_write_data);
let response = self.card.transmit(cmd_write_data).unwrap(); let response = self.card.transmit(cmd_write_data).unwrap();
println!("RESPONSE: {}", response);
ret = response.check(); ret = response.check();
}; };
@ -482,7 +492,7 @@ impl Desfire {
}; };
let mut send_buffer = vec![file_id]; let mut send_buffer = vec![file_id];
send_buffer.append(&mut offset.to_le_bytes()[..3].to_vec()); send_buffer.append(&mut (offset as usize + bytes_read).to_le_bytes()[..3].to_vec());
send_buffer.append(&mut bytes_toread.to_le_bytes()[..3].to_vec()); send_buffer.append(&mut bytes_toread.to_le_bytes()[..3].to_vec());
bytes_read += bytes_toread; bytes_read += bytes_toread;
@ -493,8 +503,10 @@ impl Desfire {
data: Option::from(send_buffer), data: Option::from(send_buffer),
..Default::default() ..Default::default()
}; };
println!("CMD_READ_DATA: {}", cmd_read_data);
let response = self.card.transmit(cmd_read_data).unwrap(); let response = self.card.transmit(cmd_read_data).unwrap();
println!("RESPONSE: {}", response);
response.check().or_else(|e| return Err(e)); response.check().or_else(|e| return Err(e));
@ -1114,4 +1126,151 @@ mod tests {
let access_rights = generate_file_access_rights(FileAccessRights::FREE as u8, 0x00, 0x00, 0x00).unwrap(); let access_rights = generate_file_access_rights(FileAccessRights::FREE as u8, 0x00, 0x00, 0x00).unwrap();
desfire.create_file_standard(0xFF, FileCommunication::PLAIN, access_rights, 0xF0).unwrap(); desfire.create_file_standard(0xFF, FileCommunication::PLAIN, access_rights, 0xF0).unwrap();
} }
#[test]
fn write_data() {
let mut mock = MockVirtualCard::new();
mock.expect_transmit().withf(|x: &APDUCommand| (Vec::<u8>::try_from(x.clone()).unwrap()) == hex!("903d00000f01000000080000546573743132333400")).return_once(move |_| Ok(APDUResponse {
sw1: 0x91,
sw2: 0x00,
body: None
}));
let mut desfire = Desfire {
card: Box::new(mock),
cbc_iv: None,
session_key: None
};
let data = "Test1234".as_bytes();
assert!(desfire.write_data(0x01, 0x00, data.as_ref()).is_ok());
}
#[test]
fn write_data_long() {
let mut mock = MockVirtualCard::new();
mock.expect_transmit().withf(|x: &APDUCommand| (Vec::<u8>::try_from(x.clone()).unwrap()) == hex!("903d000036010000002f0000546573743132333454657374313233345465737431323334546573743132333454657374313233345465737431323300")).return_once(move |_| Ok(APDUResponse {
sw1: 0x91,
sw2: 0x00,
body: None
}));
mock.expect_transmit().withf(|x: &APDUCommand| (Vec::<u8>::try_from(x.clone()).unwrap()) == hex!("903d000036012f00002f0000345465737431323334546573743132333454657374313233345465737431323334546573743132333454657374313200")).return_once(move |_| Ok(APDUResponse {
sw1: 0x91,
sw2: 0x00,
body: None
}));
mock.expect_transmit().withf(|x: &APDUCommand| (Vec::<u8>::try_from(x.clone()).unwrap()) == hex!("903d000019015e000012000033345465737431323334546573743132333400")).return_once(move |_| Ok(APDUResponse {
sw1: 0x91,
sw2: 0x00,
body: None
}));
let mut desfire = Desfire {
card: Box::new(mock),
cbc_iv: None,
session_key: None
};
let data = "Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234".as_bytes();
assert!(desfire.write_data(0x01, 0x00, data.as_ref()).is_ok());
}
#[test]
#[should_panic(expected = "InvalidFileID")]
fn write_data_invalid_file_id() {
let mut mock = MockVirtualCard::new();
let mut desfire = Desfire {
card: Box::new(mock),
cbc_iv: None,
session_key: None
};
desfire.write_data(0xFF, 0x00, &[0 as u8; 1]).unwrap();
}
#[test]
fn read_data() {
let mut mock = MockVirtualCard::new();
mock.expect_transmit().withf(|x: &APDUCommand| (Vec::<u8>::try_from(x.clone()).unwrap()) == hex!("90bd0000070100000020000000")).return_once(move |_| Ok(APDUResponse {
sw1: 0x91,
sw2: 0x00,
body: Some(hex!("54657374313233340000000000000000000000000000000000000000000000009100").to_vec())
}));
let mut desfire = Desfire {
card: Box::new(mock),
cbc_iv: None,
session_key: None
};
let data = desfire.read_data(0x01, 0x00, 0x20).unwrap();
assert_eq!("Test1234", String::from_utf8(data).unwrap().replace("\0", ""));
}
#[test]
fn read_data_cmac() {
let mut mock = MockVirtualCard::new();
mock.expect_transmit().withf(|x: &APDUCommand| (Vec::<u8>::try_from(x.clone()).unwrap()) == hex!("90bd0000070100000020000000")).return_once(move |_| Ok(APDUResponse {
sw1: 0x91,
sw2: 0x00,
body: Some(hex!("5465737431323334000000000000000000000000000000000000000000000000809a9bedbc559a5b9100").to_vec())
}));
let mut desfire = Desfire {
card: Box::new(mock),
cbc_iv: None,
session_key: None
};
let data = desfire.read_data(0x01, 0x00, 0x20).unwrap();
assert_eq!("Test1234", String::from_utf8(data).unwrap().replace("\0", ""));
}
#[test]
fn read_data_long() {
let mut mock = MockVirtualCard::new();
mock.expect_transmit().withf(|x: &APDUCommand| (Vec::<u8>::try_from(x.clone()).unwrap()) == hex!("90bd000007010000002f000000")).return_once(move |_| Ok(APDUResponse {
sw1: 0x91,
sw2: 0x00,
body: Some(hex!("54657374313233340000000000000000000000000000000000000000000000000000000000000000000000000000009100").to_vec())
}));
mock.expect_transmit().withf(|x: &APDUCommand| (Vec::<u8>::try_from(x.clone()).unwrap()) == hex!("90bd000007012f00002f000000")).return_once(move |_| Ok(APDUResponse {
sw1: 0x91,
sw2: 0x00,
body: Some(hex!("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009100").to_vec())
}));
mock.expect_transmit().withf(|x: &APDUCommand| (Vec::<u8>::try_from(x.clone()).unwrap()) == hex!("90bd000007015e000002000000")).return_once(move |_| Ok(APDUResponse {
sw1: 0x91,
sw2: 0x00,
body: Some(hex!("00009100").to_vec())
}));
let mut desfire = Desfire {
card: Box::new(mock),
cbc_iv: None,
session_key: None
};
let data = desfire.read_data(0x01, 0x00, 0x60).unwrap();
assert_eq!("Test1234", String::from_utf8(data).unwrap().replace("\0", ""));
}
#[test]
#[should_panic(expected = "InvalidFileID")]
fn read_data_invalid_file_id() {
let mut mock = MockVirtualCard::new();
let mut desfire = Desfire {
card: Box::new(mock),
cbc_iv: None,
session_key: None
};
desfire.read_data(0xFF, 0x00, 0x20).unwrap();
}
} }