From dce2bc30a898273d8a9b3ec7d0e993e2c4b09c39 Mon Sep 17 00:00:00 2001 From: Kai Jan Kriegel Date: Sat, 25 Dec 2021 06:28:37 +0100 Subject: [PATCH] added tests Added tests for: select_application, DES auth, AES auth, format_picc, create_application, change_key_aes, change_other_key_aes, create_file_standard --- src/desfire/desfire.rs | 208 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 203 insertions(+), 5 deletions(-) diff --git a/src/desfire/desfire.rs b/src/desfire/desfire.rs index 6a01389..3abca30 100644 --- a/src/desfire/desfire.rs +++ b/src/desfire/desfire.rs @@ -577,7 +577,7 @@ fn generate_file_access_rights(read: u8, write: u8, read_write: u8, configure: u mod tests { use std::convert::TryFrom; use std::ffi::{CStr, CString}; - use std::fs::read; + use std::fs::{File, read}; use std::ops::Deref; use hex_literal::hex; use mockall::{mock, predicate}; @@ -587,7 +587,7 @@ mod tests { use crate::crypto::cipher_key::CipherKey; use crate::crypto::cipher_type::CipherType; use crate::desfire::desfire::{generate_session_key_des, generate_session_key_aes, generate_keysetting1, generate_keysetting2, generate_file_access_rights, Desfire}; - use crate::desfire::{ChangeApplicationKey, ChangeMasterKeySettings, CreateDeleteFile, FileDirectoryAccess, ChangeMasterKey, CryptoOperationsType, FileIdentifiers}; + use crate::desfire::{ChangeApplicationKey, ChangeMasterKeySettings, CreateDeleteFile, FileDirectoryAccess, ChangeMasterKey, CryptoOperationsType, FileIdentifiers, FileAccessRights, FileCommunication}; use crate::desfire::CryptoOperationsType::TDES; use crate::error::Error::{InvalidKeyID, CardError}; use crate::iso7816_4::apdustatuswords::APDUStatusWord::OK; @@ -635,7 +635,6 @@ mod tests { return Err(CardError) } }; - println!("APDU response: {:x?}", rapdu); return Ok(APDUResponse::new(rapdu)) } } @@ -742,6 +741,20 @@ mod tests { assert!(desfire.select_application(0x112233).is_ok()) } + #[test] + #[should_panic(expected = "InvalidApplicationID")] + fn select_application_invalidaid() { + let mock = MockVirtualCard::new(); + + let mut desfire = Desfire{ + card: Box::new(mock), + cbc_iv: None, + session_key: None + }; + + desfire.select_application(0xff000000).unwrap(); + } + #[test] #[ignore] fn select_application_hardware() { @@ -825,6 +838,20 @@ mod tests { } + #[test] + #[should_panic(expected = "InvalidKeyID")] + fn authenticate_des_invalid_keyno() { + let mock = MockVirtualCard::new(); + + let mut desfire = Desfire{ + card: Box::new(mock), + cbc_iv: None, + session_key: None + }; + + desfire.authenticate_iso_des(0x0F, &[0x00 as u8], None).unwrap(); + } + #[test] #[ignore] fn authenticate_des_hardware() { @@ -909,11 +936,182 @@ mod tests { desfire.authenticate_iso_aes(0x00, key.key.as_ref(), Some(rndA)).unwrap(); - let sessionkey_expected = hex!("5f7d1dd1f449db5c5f7d1dd1f449db5c"); - let iv_expected = hex!("0000000000000000"); + let sessionkey_expected = hex!("2176770e11c512ca201d1e57fde6e15a"); + let iv_expected = hex!("00000000000000000000000000000000"); assert_eq!(desfire.session_key.unwrap(), sessionkey_expected); assert_eq!(desfire.cbc_iv.unwrap(), iv_expected); } + + #[test] + #[should_panic(expected = "InvalidKeyID")] + fn authenticate_aes_invalid_keyno() { + let mock = MockVirtualCard::new(); + + let mut desfire = Desfire{ + card: Box::new(mock), + cbc_iv: None, + session_key: None + }; + + desfire.authenticate_iso_aes(0x0F, &[0x00 as u8], None).unwrap(); + } + + #[test] + fn format_picc() { + let mut mock = MockVirtualCard::new(); + mock.expect_transmit().withf(|x: &APDUCommand| (Vec::::try_from(x.clone()).unwrap()) == hex!("90fc000000")).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 + }; + + assert!(desfire.format_picc().is_ok()); + + + + } + + #[test] + fn create_application() { + let mut mock = MockVirtualCard::new(); + mock.expect_transmit().withf(|x: &APDUCommand| (Vec::::try_from(x.clone()).unwrap()) == hex!("90ca000005eeffaa0b8200")).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 + }; + + assert!(desfire.create_application(0xAAFFEE, 0x0b, 0x82).is_ok()); + + } + + #[test] + #[should_panic(expected = "InvalidApplicationID")] + fn create_application_invalid_aid() { + let mut mock = MockVirtualCard::new(); + + let mut desfire = Desfire{ + card: Box::new(mock), + cbc_iv: None, + session_key: None + }; + + desfire.create_application(0xFF000000, 0x0b, 0x82).unwrap(); + } + + #[test] + fn change_key_aes() { + let mut mock = MockVirtualCard::new(); + mock.expect_transmit().withf(|x: &APDUCommand| (Vec::::try_from(x.clone()).unwrap()) == hex!("90c400002100c2b54a718d0251845653199909bb32e8e38bd6719e8dc21799c29c922a0984fc00")).return_once(move |_| Ok(APDUResponse { + sw1: 0x91, + sw2: 0x00, + body: None + })); + + let new_key = hex!("25432a462d4a614e645267556b587032"); + + let mut desfire = Desfire { + card: Box::new(mock), + cbc_iv: Some(hex!("00000000000000000000000000000000").to_vec()), + session_key: Some(hex!("a8514dd0350f3dfbc86e80744bcc9b57").to_vec()) + }; + + assert!(desfire.change_key_aes(0x00, new_key.as_ref(), 0x10).is_ok()); + } + + #[test] + #[should_panic(expected = "InvalidKeyID")] + fn change_key_aes_invalid_keyno() { + let mut mock = MockVirtualCard::new(); + + let mut desfire = Desfire { + card: Box::new(mock), + cbc_iv: None, + session_key: None + }; + + desfire.change_key_aes(0x0F, &[0x00 as u8], 0x10).unwrap(); + } + + #[test] + fn change_other_key_aes() { + let mut mock = MockVirtualCard::new(); + mock.expect_transmit().withf(|x: &APDUCommand| (Vec::::try_from(x.clone()).unwrap()) == hex!("90c400002101a8c5a61a06f56f38dc91266fed2e87dc00a5ad72a634ff0e62c8d6d80707dd6000")).return_once(move |_| Ok(APDUResponse { + sw1: 0x91, + sw2: 0x00, + body: None + })); + + let old_key = hex!("00000000000000000000000000000000"); + let new_key = hex!("25432a462d4a614e645267556b587032"); + + let mut desfire = Desfire { + card: Box::new(mock), + cbc_iv: Some(hex!("00000000000000000000000000000000").to_vec()), + session_key: Some(hex!("1677623e1e158a62dc3d128db55f947d").to_vec()) + }; + + assert!(desfire.change_other_key_aes(0x01, new_key.as_ref(), old_key.as_ref(), 0x10).is_ok()); + } + + #[test] + #[should_panic(expected = "InvalidKeyID")] + fn change_other_key_aes_invalid_keyno() { + let mut mock = MockVirtualCard::new(); + + let mut desfire = Desfire { + card: Box::new(mock), + cbc_iv: None, + session_key: None + }; + + desfire.change_other_key_aes(0x0F, &[0x00 as u8], &[0x00 as u8],0x10).unwrap(); + } + + #[test] + fn create_file_standard() { + let mut mock = MockVirtualCard::new(); + mock.expect_transmit().withf(|x: &APDUCommand| (Vec::::try_from(x.clone()).unwrap()) == hex!("90cd000007010000e0f0000000")).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 access_rights = generate_file_access_rights(FileAccessRights::FREE as u8, 0x00, 0x00, 0x00).unwrap(); + assert!(desfire.create_file_standard(0x01, FileCommunication::PLAIN, access_rights, 0xF0).is_ok()); + } + + #[test] + #[should_panic(expected = "InvalidFileID")] + fn create_file_standard_invalid_file_id() { + let mut mock = MockVirtualCard::new(); + + let mut desfire = Desfire { + card: Box::new(mock), + cbc_iv: None, + session_key: None + }; + + 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(); + } } \ No newline at end of file