mirror of
https://gitlab.com/fabinfra/fabaccess/nfc_rs.git
synced 2025-03-12 06:41:46 +01:00
added tests for write_data and read_data
This commit is contained in:
parent
099c78d979
commit
3dd731e1cc
@ -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));
|
||||||
|
|
||||||
@ -785,7 +797,7 @@ mod tests {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut card = PCSCCard {
|
let mut card = PCSCCard {
|
||||||
ctx,
|
ctx,
|
||||||
reader: CString::from(reader),
|
reader: CString::from(reader),
|
||||||
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user