mirror of
https://gitlab.com/fabinfra/fabaccess/nfc_rs.git
synced 2025-03-12 14:51:50 +01:00
reformated files with rustfmt
This commit is contained in:
parent
dce2bc30a8
commit
099c78d979
@ -1,8 +1,8 @@
|
|||||||
use aes::Aes128;
|
|
||||||
use block_modes::{BlockMode, Cbc};
|
|
||||||
use block_modes::block_padding::NoPadding;
|
|
||||||
use crate::error::{Result, Error};
|
|
||||||
use super::Cipher;
|
use super::Cipher;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
|
use aes::Aes128;
|
||||||
|
use block_modes::block_padding::NoPadding;
|
||||||
|
use block_modes::{BlockMode, Cbc};
|
||||||
|
|
||||||
type Aes128Cbc = Cbc<Aes128, NoPadding>;
|
type Aes128Cbc = Cbc<Aes128, NoPadding>;
|
||||||
|
|
||||||
@ -23,16 +23,16 @@ impl Cipher for AES {
|
|||||||
|
|
||||||
let result = cipher.decrypt_vec(data);
|
let result = cipher.decrypt_vec(data);
|
||||||
return match result {
|
return match result {
|
||||||
Ok(data) => { Ok(data) }
|
Ok(data) => Ok(data),
|
||||||
Err(err) => { Err(Error::BlockModeError(err)) }
|
Err(err) => Err(Error::BlockModeError(err)),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use hex_literal::hex;
|
|
||||||
use crate::crypto::cipher::Cipher;
|
use crate::crypto::cipher::Cipher;
|
||||||
|
use hex_literal::hex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn encrypt() {
|
fn encrypt() {
|
||||||
|
@ -10,6 +10,6 @@ pub trait Cipher {
|
|||||||
const BLOCK_SIZE: usize;
|
const BLOCK_SIZE: usize;
|
||||||
const KEY_SIZE: usize;
|
const KEY_SIZE: usize;
|
||||||
|
|
||||||
fn encrypt (data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>>;
|
fn encrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>>;
|
||||||
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>>;
|
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>>;
|
||||||
}
|
}
|
@ -1,9 +1,9 @@
|
|||||||
//FIXME: Which TDES Mode should be used by this?
|
//FIXME: Which TDES Mode should be used by this?
|
||||||
use des::TdesEde2;
|
|
||||||
use block_modes::{BlockMode, Cbc};
|
|
||||||
use block_modes::block_padding::NoPadding;
|
|
||||||
use crate::error::{Result, Error};
|
|
||||||
use crate::crypto::cipher::Cipher;
|
use crate::crypto::cipher::Cipher;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
|
use block_modes::block_padding::NoPadding;
|
||||||
|
use block_modes::{BlockMode, Cbc};
|
||||||
|
use des::TdesEde2;
|
||||||
|
|
||||||
type TDesEde2Cbc = Cbc<TdesEde2, NoPadding>;
|
type TDesEde2Cbc = Cbc<TdesEde2, NoPadding>;
|
||||||
|
|
||||||
@ -22,19 +22,18 @@ impl Cipher for Tdes {
|
|||||||
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||||
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
||||||
|
|
||||||
|
|
||||||
let result = cipher.decrypt_vec(data);
|
let result = cipher.decrypt_vec(data);
|
||||||
return match result {
|
return match result {
|
||||||
Ok(data) => { Ok(data) }
|
Ok(data) => Ok(data),
|
||||||
Err(err) => { Err(Error::BlockModeError(err)) }
|
Err(err) => Err(Error::BlockModeError(err)),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use hex_literal::hex;
|
|
||||||
use crate::crypto::cipher::Cipher;
|
use crate::crypto::cipher::Cipher;
|
||||||
|
use hex_literal::hex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
//FIXME: Which TDES Mode should be used by this?
|
//FIXME: Which TDES Mode should be used by this?
|
||||||
use des::TdesEde2;
|
|
||||||
use block_modes::{BlockMode, Cbc};
|
|
||||||
use block_modes::block_padding::NoPadding;
|
|
||||||
use crate::error::{Result, Error};
|
|
||||||
use crate::crypto::cipher::Cipher;
|
use crate::crypto::cipher::Cipher;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
|
use block_modes::block_padding::NoPadding;
|
||||||
|
use block_modes::{BlockMode, Cbc};
|
||||||
|
use des::TdesEde2;
|
||||||
|
|
||||||
type TDesEde2Cbc = Cbc<TdesEde2, NoPadding>;
|
type TDesEde2Cbc = Cbc<TdesEde2, NoPadding>;
|
||||||
|
|
||||||
@ -22,19 +22,18 @@ impl Cipher for Tdes2k {
|
|||||||
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||||
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
let cipher = TDesEde2Cbc::new_var(&key, &iv)?;
|
||||||
|
|
||||||
|
|
||||||
let result = cipher.decrypt_vec(data);
|
let result = cipher.decrypt_vec(data);
|
||||||
return match result {
|
return match result {
|
||||||
Ok(data) => { Ok(data) }
|
Ok(data) => Ok(data),
|
||||||
Err(err) => { Err(Error::BlockModeError(err)) }
|
Err(err) => Err(Error::BlockModeError(err)),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use hex_literal::hex;
|
|
||||||
use crate::crypto::cipher::Cipher;
|
use crate::crypto::cipher::Cipher;
|
||||||
|
use hex_literal::hex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
//FIXME: Which TDES Mode should be used by this?
|
//FIXME: Which TDES Mode should be used by this?
|
||||||
use des::TdesEde3;
|
|
||||||
use block_modes::{BlockMode, Cbc};
|
|
||||||
use block_modes::block_padding::NoPadding;
|
|
||||||
use crate::error::{Result, Error};
|
|
||||||
use crate::crypto::cipher::Cipher;
|
use crate::crypto::cipher::Cipher;
|
||||||
|
use crate::error::{Error, Result};
|
||||||
|
use block_modes::block_padding::NoPadding;
|
||||||
|
use block_modes::{BlockMode, Cbc};
|
||||||
|
use des::TdesEde3;
|
||||||
|
|
||||||
type TDesEde3Cbc = Cbc<TdesEde3, NoPadding>;
|
type TDesEde3Cbc = Cbc<TdesEde3, NoPadding>;
|
||||||
|
|
||||||
@ -22,19 +22,18 @@ impl Cipher for Tdes3k {
|
|||||||
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
fn decrypt(data: &[u8], key: &[u8], iv: &[u8]) -> Result<Vec<u8>> {
|
||||||
let cipher = TDesEde3Cbc::new_var(&key, &iv)?;
|
let cipher = TDesEde3Cbc::new_var(&key, &iv)?;
|
||||||
|
|
||||||
|
|
||||||
let result = cipher.decrypt_vec(data);
|
let result = cipher.decrypt_vec(data);
|
||||||
return match result {
|
return match result {
|
||||||
Ok(data) => { Ok(data) }
|
Ok(data) => Ok(data),
|
||||||
Err(err) => { Err(Error::BlockModeError(err)) }
|
Err(err) => Err(Error::BlockModeError(err)),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use hex_literal::hex;
|
|
||||||
use crate::crypto::cipher::Cipher;
|
use crate::crypto::cipher::Cipher;
|
||||||
|
use hex_literal::hex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[ignore]
|
#[ignore]
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
use crate::crypto::cipher::{aes, tdes, tdes_2k, tdes_3k, Cipher};
|
||||||
use crate::crypto::cipher_type::CipherType;
|
use crate::crypto::cipher_type::CipherType;
|
||||||
use crate::crypto::cipher_type::CipherType::*;
|
use crate::crypto::cipher_type::CipherType::*;
|
||||||
use crate::crypto::cipher::{aes, tdes, tdes_2k, tdes_3k, Cipher};
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::error::Result;
|
use crate::error::Result;
|
||||||
|
|
||||||
@ -15,17 +15,21 @@ pub struct CipherKey {
|
|||||||
cipher: CipherType,
|
cipher: CipherType,
|
||||||
|
|
||||||
/// KeyVersion of Key
|
/// KeyVersion of Key
|
||||||
key_version: u8
|
key_version: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CipherKey {
|
impl CipherKey {
|
||||||
pub fn new(key: &[u8], cipher: CipherType, key_version: u8) -> Result<CipherKey> {
|
pub fn new(key: &[u8], cipher: CipherType, key_version: u8) -> Result<CipherKey> {
|
||||||
if cipher == AES && key_version < 0x10 {
|
if cipher == AES && key_version < 0x10 {
|
||||||
return Err(Error::Boxed(Box::new(simple_error!("KeyVersion is to low for AES Key (Minimum = 0x10)"))))
|
return Err(Error::Boxed(Box::new(simple_error!(
|
||||||
|
"KeyVersion is to low for AES Key (Minimum = 0x10)"
|
||||||
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !check_key(key, cipher.clone()) {
|
if !check_key(key, cipher.clone()) {
|
||||||
return Err(Error::Boxed(Box::new(simple_error!("Key is not valid for CipherType"))))
|
return Err(Error::Boxed(Box::new(simple_error!(
|
||||||
|
"Key is not valid for CipherType"
|
||||||
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut key: Box<[u8]> = Box::from(key);
|
let mut key: Box<[u8]> = Box::from(key);
|
||||||
@ -36,7 +40,7 @@ impl CipherKey {
|
|||||||
Ok(CipherKey {
|
Ok(CipherKey {
|
||||||
cipher,
|
cipher,
|
||||||
key_version,
|
key_version,
|
||||||
key
|
key,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,10 +49,10 @@ impl CipherKey {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_empty(cipher: CipherType) -> Result<CipherKey> {
|
pub fn new_empty(cipher: CipherType) -> Result<CipherKey> {
|
||||||
Ok(CipherKey{
|
Ok(CipherKey {
|
||||||
key: generate_empty_key(cipher.clone()),
|
key: generate_empty_key(cipher.clone()),
|
||||||
key_version: if cipher == AES { 0x10u8 } else { 0x00u8 },
|
key_version: if cipher == AES { 0x10u8 } else { 0x00u8 },
|
||||||
cipher
|
cipher,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -72,7 +76,11 @@ pub fn get_key_size(cipher: CipherType) -> usize {
|
|||||||
|
|
||||||
/// Check Key Slice
|
/// Check Key Slice
|
||||||
pub fn check_key(key: &[u8], cipher: CipherType) -> bool {
|
pub fn check_key(key: &[u8], cipher: CipherType) -> bool {
|
||||||
if key.len() != get_key_size(cipher) { false } else { true }
|
if key.len() != get_key_size(cipher) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set Key Version for DES/TDES Keys
|
/// Set Key Version for DES/TDES Keys
|
||||||
@ -80,7 +88,9 @@ pub fn check_key(key: &[u8], cipher: CipherType) -> bool {
|
|||||||
/// Parity Bits are not used from DESFire Cars
|
/// Parity Bits are not used from DESFire Cars
|
||||||
|
|
||||||
pub fn set_key_version(key: &[u8], version: u8) -> Box<[u8]> {
|
pub fn set_key_version(key: &[u8], version: u8) -> Box<[u8]> {
|
||||||
let pow2 = [0x01u8, 0x02u8, 0x04u8, 0x08u8, 0x10u8, 0x20u8, 0x40u8, 0x80u8];
|
let pow2 = [
|
||||||
|
0x01u8, 0x02u8, 0x04u8, 0x08u8, 0x10u8, 0x20u8, 0x40u8, 0x80u8,
|
||||||
|
];
|
||||||
|
|
||||||
let mut new_key = key.to_vec();
|
let mut new_key = key.to_vec();
|
||||||
|
|
||||||
|
@ -10,5 +10,5 @@ pub enum CipherType {
|
|||||||
TDES3K,
|
TDES3K,
|
||||||
|
|
||||||
/// AES
|
/// AES
|
||||||
AES
|
AES,
|
||||||
}
|
}
|
@ -1,5 +1,5 @@
|
|||||||
pub mod cipher;
|
pub mod cipher;
|
||||||
pub mod crc;
|
|
||||||
pub mod cipher_type;
|
|
||||||
pub mod cipher_key;
|
pub mod cipher_key;
|
||||||
|
pub mod cipher_type;
|
||||||
|
pub mod crc;
|
||||||
pub mod util;
|
pub mod util;
|
@ -1,10 +1,15 @@
|
|||||||
use crate::error::{Result, Error};
|
use crate::error::{Error, Result};
|
||||||
use simple_error::simple_error;
|
use simple_error::simple_error;
|
||||||
|
|
||||||
/// Extracts the the last `n` bytes of a slice. n being the blocksize.
|
/// Extracts the the last `n` bytes of a slice. n being the blocksize.
|
||||||
pub fn extract_last_block(data: &[u8], blocksize: usize) -> Result<&[u8]> {
|
pub fn extract_last_block(data: &[u8], blocksize: usize) -> Result<&[u8]> {
|
||||||
if data.len() % blocksize != 0 {
|
if data.len() % blocksize != 0 {
|
||||||
return Err(simple_error!("Data is not compatible with blocksize: data(length): {}, blocksize: {}.", data.len(), blocksize).into())
|
return Err(simple_error!(
|
||||||
|
"Data is not compatible with blocksize: data(length): {}, blocksize: {}.",
|
||||||
|
data.len(),
|
||||||
|
blocksize
|
||||||
|
)
|
||||||
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(&data[(data.len() - blocksize)..])
|
Ok(&data[(data.len() - blocksize)..])
|
||||||
|
@ -1,41 +1,41 @@
|
|||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum APDUInstructions {
|
pub enum APDUInstructions {
|
||||||
AUTHENTICATE_ISO = 0x1A,
|
AUTHENTICATE_ISO = 0x1A,
|
||||||
AUTHENTICATE_AES = 0xAA,
|
AUTHENTICATE_AES = 0xAA,
|
||||||
CHANGE_KEY_SETTINGS = 0x54,
|
CHANGE_KEY_SETTINGS = 0x54,
|
||||||
SET_CONFIGURATION = 0x5C,
|
SET_CONFIGURATION = 0x5C,
|
||||||
CHANGE_KEY = 0xC4,
|
CHANGE_KEY = 0xC4,
|
||||||
GET_KEY_VERSION = 0x64,
|
GET_KEY_VERSION = 0x64,
|
||||||
CREATE_APPLICATION = 0xCA,
|
CREATE_APPLICATION = 0xCA,
|
||||||
DELETE_APPLICATION = 0xDA,
|
DELETE_APPLICATION = 0xDA,
|
||||||
GET_APPLICATION_IDS = 0x6A,
|
GET_APPLICATION_IDS = 0x6A,
|
||||||
FREE_MEMORY = 0x6E,
|
FREE_MEMORY = 0x6E,
|
||||||
GET_DF_NAMES = 0x6D,
|
GET_DF_NAMES = 0x6D,
|
||||||
GET_KEY_SETTINGS = 0x45,
|
GET_KEY_SETTINGS = 0x45,
|
||||||
SELECT_APPLICATION = 0x5A,
|
SELECT_APPLICATION = 0x5A,
|
||||||
FORMAT_PICC = 0xFC,
|
FORMAT_PICC = 0xFC,
|
||||||
GET_VERSION = 0x60,
|
GET_VERSION = 0x60,
|
||||||
GET_CARD_UID = 0x51,
|
GET_CARD_UID = 0x51,
|
||||||
GET_FILE_IDS = 0x6F,
|
GET_FILE_IDS = 0x6F,
|
||||||
GET_FILE_SETTINGS = 0xF5,
|
GET_FILE_SETTINGS = 0xF5,
|
||||||
CHANGE_FILE_SETTINGS = 0x5F,
|
CHANGE_FILE_SETTINGS = 0x5F,
|
||||||
CREATE_STDDATAFILE = 0xCD,
|
CREATE_STDDATAFILE = 0xCD,
|
||||||
CREATE_BACKUPDATAFILE = 0xCB,
|
CREATE_BACKUPDATAFILE = 0xCB,
|
||||||
CREATE_VALUE_FILE = 0xCC,
|
CREATE_VALUE_FILE = 0xCC,
|
||||||
CREATE_LINEAR_RECORD_FILE = 0xC1,
|
CREATE_LINEAR_RECORD_FILE = 0xC1,
|
||||||
CREATE_CYCLIC_RECORD_FILE = 0xC0,
|
CREATE_CYCLIC_RECORD_FILE = 0xC0,
|
||||||
DELETE_FILE = 0xDF,
|
DELETE_FILE = 0xDF,
|
||||||
GET_ISO_FILE_IDS = 0x61,
|
GET_ISO_FILE_IDS = 0x61,
|
||||||
READ_DATA = 0xBD,
|
READ_DATA = 0xBD,
|
||||||
WRITE_DATA = 0x3D,
|
WRITE_DATA = 0x3D,
|
||||||
GET_VALUE = 0x6C,
|
GET_VALUE = 0x6C,
|
||||||
CREDIT = 0x0C,
|
CREDIT = 0x0C,
|
||||||
DEBIT = 0xDC,
|
DEBIT = 0xDC,
|
||||||
LIMITED_CREDIT = 0x1C,
|
LIMITED_CREDIT = 0x1C,
|
||||||
WRITE_RECORD = 0x3B,
|
WRITE_RECORD = 0x3B,
|
||||||
READ_RECORDS = 0xBB,
|
READ_RECORDS = 0xBB,
|
||||||
CLEAR_RECORD_FILE = 0xEB,
|
CLEAR_RECORD_FILE = 0xEB,
|
||||||
COMMIT_TRANSACTION = 0xC7,
|
COMMIT_TRANSACTION = 0xC7,
|
||||||
ABORT_TRANSACTION = 0xA7,
|
ABORT_TRANSACTION = 0xA7,
|
||||||
CONTINUE = 0xAF,
|
CONTINUE = 0xAF,
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use num_derive::FromPrimitive;
|
use num_derive::FromPrimitive;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// hold the Access Rights for changing application keys (Change Key command)
|
/// hold the Access Rights for changing application keys (Change Key command)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -28,13 +27,13 @@ pub enum ChangeApplicationKey {
|
|||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum ChangeMasterKey {
|
pub enum ChangeMasterKey {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Application master key is not changeable anymore (frozen)
|
/// Application master key is not changeable anymore (frozen)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FROZEN = 0x00,
|
FROZEN = 0x00,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Application master key is changeable (authentication with the current application master key necessary, default)
|
/// Application master key is changeable (authentication with the current application master key necessary, default)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
CHANGEABLE = 0x01,
|
CHANGEABLE = 0x01,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,16 +43,15 @@ pub enum ChangeMasterKey {
|
|||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum ChangeMasterKeySettings {
|
pub enum ChangeMasterKeySettings {
|
||||||
|
/// <summary>
|
||||||
|
/// configuration not changeable anymore (frozen)
|
||||||
|
/// </summary>
|
||||||
|
FROZEN = 0x00,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// configuration not changeable anymore (frozen)
|
/// this configuration is changeable if authenticated with the application master key (default)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FROZEN = 0x00,
|
WITHMASTERKEY = 0x08,
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// this configuration is changeable if authenticated with the application master key (default)
|
|
||||||
/// </summary>
|
|
||||||
WITHMASTERKEY = 0x08
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -62,15 +60,15 @@ WITHMASTERKEY = 0x08
|
|||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum CreateDeleteFile {
|
pub enum CreateDeleteFile {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// “Create File”/ “Delete File”is permitted only with application master key authentication
|
/// “Create File”/ “Delete File”is permitted only with application master key authentication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ONLYMASTERKEY = 0x00,
|
ONLYMASTERKEY = 0x00,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// “Create File”/ “Delete File”is permitted also without application master key authentication (default)
|
/// “Create File”/ “Delete File”is permitted also without application master key authentication (default)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
NOKEY = 0x04,
|
NOKEY = 0x04,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -88,7 +86,7 @@ pub enum CryptoOperationsType {
|
|||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum FileAccessRights {
|
pub enum FileAccessRights {
|
||||||
FREE = 0x0E,
|
FREE = 0x0E,
|
||||||
NEVER = 0x0F
|
NEVER = 0x0F,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
@ -107,7 +105,7 @@ pub enum FileCommunication {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fully DES/3DES enciphered communication
|
/// Fully DES/3DES enciphered communication
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ENCRYPT = 0x03
|
ENCRYPT = 0x03,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -134,7 +132,7 @@ pub enum FileDirectoryAccess {
|
|||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy)]
|
||||||
pub enum FileIdentifiers {
|
pub enum FileIdentifiers {
|
||||||
NOTUSED = 0x00,
|
NOTUSED = 0x00,
|
||||||
USED = 0x20
|
USED = 0x20,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
@ -143,7 +141,7 @@ pub enum FileTypes {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Standard Data File
|
/// Standard Data File
|
||||||
/// </summary>
|
/// </summary>
|
||||||
STANDARD = 0x00,
|
STANDARD = 0x00,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Backup Data Files
|
/// Backup Data Files
|
||||||
@ -163,7 +161,7 @@ pub enum FileTypes {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cyclic Record Files with Backup
|
/// Cyclic Record Files with Backup
|
||||||
/// </summary>
|
/// </summary>
|
||||||
CYCLICRECORD = 0x04
|
CYCLICRECORD = 0x04,
|
||||||
}
|
}
|
||||||
|
|
||||||
mod apduinstructions;
|
mod apduinstructions;
|
||||||
|
29
src/error.rs
29
src/error.rs
@ -1,5 +1,5 @@
|
|||||||
use std::io;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
use std::io;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -66,7 +66,10 @@ impl fmt::Display for Error {
|
|||||||
write!(f, "SW2: Command code not supported.")
|
write!(f, "SW2: Command code not supported.")
|
||||||
}
|
}
|
||||||
Error::IntegrityError => {
|
Error::IntegrityError => {
|
||||||
write!(f, "SW2: CRC or MAC does not match data. Paddingbytes not valid.")
|
write!(
|
||||||
|
f,
|
||||||
|
"SW2: CRC or MAC does not match data. Paddingbytes not valid."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Error::NoSuchKey => {
|
Error::NoSuchKey => {
|
||||||
write!(f, "SW2: Invalid key number specified.")
|
write!(f, "SW2: Invalid key number specified.")
|
||||||
@ -75,7 +78,10 @@ impl fmt::Display for Error {
|
|||||||
write!(f, "SW2: Length of command string invalid.")
|
write!(f, "SW2: Length of command string invalid.")
|
||||||
}
|
}
|
||||||
Error::PermissionDenied => {
|
Error::PermissionDenied => {
|
||||||
write!(f, "SW2: Current configuration / status does not allow the requested command.")
|
write!(
|
||||||
|
f,
|
||||||
|
"SW2: Current configuration / status does not allow the requested command."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Error::ParameterError => {
|
Error::ParameterError => {
|
||||||
write!(f, "SW2: Value of the parameter(s) invalid.")
|
write!(f, "SW2: Value of the parameter(s) invalid.")
|
||||||
@ -84,7 +90,10 @@ impl fmt::Display for Error {
|
|||||||
write!(f, "SW2: Currently not allowed to authenticate. Keeptrying until full delay is spent.")
|
write!(f, "SW2: Currently not allowed to authenticate. Keeptrying until full delay is spent.")
|
||||||
}
|
}
|
||||||
Error::AuthenticationError => {
|
Error::AuthenticationError => {
|
||||||
write!(f, "SW2: Current authentication status does not allow the requested command.")
|
write!(
|
||||||
|
f,
|
||||||
|
"SW2: Current authentication status does not allow the requested command."
|
||||||
|
)
|
||||||
}
|
}
|
||||||
Error::BoundaryError => {
|
Error::BoundaryError => {
|
||||||
write!(f, "SW2: Attempt to read/write data from/to beyond the file’s/record’s limits. Attempt to exceed the limits of a value file.")
|
write!(f, "SW2: Attempt to read/write data from/to beyond the file’s/record’s limits. Attempt to exceed the limits of a value file.")
|
||||||
@ -139,7 +148,9 @@ impl From<io::Error> for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<simple_error::SimpleError> for Error {
|
impl From<simple_error::SimpleError> for Error {
|
||||||
fn from(e: simple_error::SimpleError) -> Error { Error::Simple(e) }
|
fn from(e: simple_error::SimpleError) -> Error {
|
||||||
|
Error::Simple(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<block_modes::BlockModeError> for Error {
|
impl From<block_modes::BlockModeError> for Error {
|
||||||
@ -155,11 +166,15 @@ impl From<block_modes::InvalidKeyIvLength> for Error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<hex::FromHexError> for Error {
|
impl From<hex::FromHexError> for Error {
|
||||||
fn from(e: hex::FromHexError) -> Error { Error::FromHexError(e) }
|
fn from(e: hex::FromHexError) -> Error {
|
||||||
|
Error::FromHexError(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<block_modes::block_padding::PadError> for Error {
|
impl From<block_modes::block_padding::PadError> for Error {
|
||||||
fn from(e: block_modes::block_padding::PadError) -> Error { Error::PadError(e) }
|
fn from(e: block_modes::block_padding::PadError) -> Error {
|
||||||
|
Error::PadError(e)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) type Result<T> = std::result::Result<T, Error>;
|
pub(crate) type Result<T> = std::result::Result<T, Error>;
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
|
use crate::error::{Error, Result};
|
||||||
|
use std::convert::TryFrom;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Formatter;
|
use std::fmt::Formatter;
|
||||||
use std::convert::TryFrom;
|
|
||||||
use crate::error::{Result, Error};
|
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
#[derive(Eq, PartialEq, Hash, Debug, Clone)]
|
#[derive(Eq, PartialEq, Hash, Debug, Clone)]
|
||||||
pub enum IsoCase {
|
pub enum IsoCase {
|
||||||
/// <summary>No command data. No response data.</summary>
|
/// <summary>No command data. No response data.</summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <list type="bullet">
|
/// <list type="bullet">
|
||||||
/// <item><description>lc is valued to 0.</description></item>
|
/// <item><description>lc is valued to 0.</description></item>
|
||||||
/// <item><description>le is valued to 0.</description></item>
|
/// <item><description>le is valued to 0.</description></item>
|
||||||
/// <item><description>No data byte is present.</description></item>
|
/// <item><description>No data byte is present.</description></item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
Case1 = 0,
|
Case1 = 0,
|
||||||
|
|
||||||
/// <summary>No command data. Expected response data.</summary>
|
/// <summary>No command data. Expected response data.</summary>
|
||||||
@ -78,7 +78,9 @@ pub enum IsoCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Default for IsoCase {
|
impl Default for IsoCase {
|
||||||
fn default() -> Self { IsoCase::Case1 }
|
fn default() -> Self {
|
||||||
|
IsoCase::Case1
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
@ -106,7 +108,9 @@ pub enum SCardProtocol {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SCardProtocol {
|
impl Default for SCardProtocol {
|
||||||
fn default() -> Self { SCardProtocol::Any }
|
fn default() -> Self {
|
||||||
|
SCardProtocol::Any
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash, Debug, Default, Clone)]
|
#[derive(Eq, PartialEq, Hash, Debug, Default, Clone)]
|
||||||
@ -155,10 +159,7 @@ impl TryFrom<APDUCommand> for Vec<u8> {
|
|||||||
v.push(cmd.le as u8);
|
v.push(cmd.le as u8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => return Err(Error::InvalidIsoCase),
|
||||||
|
|
||||||
return Err(Error::InvalidIsoCase)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(v)
|
Ok(v)
|
||||||
}
|
}
|
||||||
@ -180,10 +181,18 @@ impl fmt::Display for APDUCommand {
|
|||||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||||
match self.case {
|
match self.case {
|
||||||
IsoCase::Case1 => {
|
IsoCase::Case1 => {
|
||||||
write!(f, "(CASE: 1) cla: {:#X} | ins: {:#X} | p1: {:#X} | p2: {:#X}", self.cla, self.ins, self.p1, self.p2)
|
write!(
|
||||||
|
f,
|
||||||
|
"(CASE: 1) cla: {:#X} | ins: {:#X} | p1: {:#X} | p2: {:#X}",
|
||||||
|
self.cla, self.ins, self.p1, self.p2
|
||||||
|
)
|
||||||
}
|
}
|
||||||
IsoCase::Case2Short | IsoCase::Case2Extended => {
|
IsoCase::Case2Short | IsoCase::Case2Extended => {
|
||||||
write!(f, "(CASE: 2) cla: {:#X} | ins: {:#X} | p1: {:#X} | p2: {:#X} | LE: {:#X}", self.cla, self.ins, self.p1, self.p2, self.le)
|
write!(
|
||||||
|
f,
|
||||||
|
"(CASE: 2) cla: {:#X} | ins: {:#X} | p1: {:#X} | p2: {:#X} | LE: {:#X}",
|
||||||
|
self.cla, self.ins, self.p1, self.p2, self.le
|
||||||
|
)
|
||||||
}
|
}
|
||||||
IsoCase::Case3Short | IsoCase::Case3Extended => {
|
IsoCase::Case3Short | IsoCase::Case3Extended => {
|
||||||
write!(f, "(CASE: 3) cla: {:#X} | ins: {:#X} | p1: {:#X} | p2: {:#X} | LC: {:#X} | data: [ ", self.cla, self.ins, self.p1, self.p2, self.lc())?;
|
write!(f, "(CASE: 3) cla: {:#X} | ins: {:#X} | p1: {:#X} | p2: {:#X} | LC: {:#X} | data: [ ", self.cla, self.ins, self.p1, self.p2, self.lc())?;
|
||||||
@ -205,11 +214,11 @@ impl fmt::Display for APDUCommand {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::iso7816_4::apducommand::{APDUCommand, SCardProtocol, IsoCase};
|
use crate::iso7816_4::apducommand::{APDUCommand, IsoCase, SCardProtocol};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compare() {
|
fn compare() {
|
||||||
let command1 = APDUCommand{
|
let command1 = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
protocol: SCardProtocol::Unset,
|
protocol: SCardProtocol::Unset,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
@ -218,7 +227,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let command2 = APDUCommand{
|
let command2 = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
protocol: SCardProtocol::Unset,
|
protocol: SCardProtocol::Unset,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
@ -232,7 +241,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn compare_diff() {
|
fn compare_diff() {
|
||||||
let command1 = APDUCommand{
|
let command1 = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
protocol: SCardProtocol::Unset,
|
protocol: SCardProtocol::Unset,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
@ -241,7 +250,7 @@ mod tests {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let command2 = APDUCommand{
|
let command2 = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
protocol: SCardProtocol::Unset,
|
protocol: SCardProtocol::Unset,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
@ -255,7 +264,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn to_string_case1() {
|
fn to_string_case1() {
|
||||||
let command1 = APDUCommand{
|
let command1 = APDUCommand {
|
||||||
case: IsoCase::Case1,
|
case: IsoCase::Case1,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: 0x1A,
|
ins: 0x1A,
|
||||||
@ -263,12 +272,15 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
println!("{}", command1.to_string());
|
println!("{}", command1.to_string());
|
||||||
assert_eq!("(CASE: 1) cla: 0x90 | ins: 0x1A | p1: 0x0 | p2: 0x0", command1.to_string());
|
assert_eq!(
|
||||||
|
"(CASE: 1) cla: 0x90 | ins: 0x1A | p1: 0x0 | p2: 0x0",
|
||||||
|
command1.to_string()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn to_string_case2() {
|
fn to_string_case2() {
|
||||||
let command1 = APDUCommand{
|
let command1 = APDUCommand {
|
||||||
case: IsoCase::Case2Short,
|
case: IsoCase::Case2Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: 0x1A,
|
ins: 0x1A,
|
||||||
@ -276,12 +288,15 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
println!("{}", command1.to_string());
|
println!("{}", command1.to_string());
|
||||||
assert_eq!("(CASE: 2) cla: 0x90 | ins: 0x1A | p1: 0x0 | p2: 0x0 | LE: 0x0", command1.to_string());
|
assert_eq!(
|
||||||
|
"(CASE: 2) cla: 0x90 | ins: 0x1A | p1: 0x0 | p2: 0x0 | LE: 0x0",
|
||||||
|
command1.to_string()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn to_string_case3() {
|
fn to_string_case3() {
|
||||||
let command1 = APDUCommand{
|
let command1 = APDUCommand {
|
||||||
case: IsoCase::Case3Short,
|
case: IsoCase::Case3Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: 0x1A,
|
ins: 0x1A,
|
||||||
@ -290,12 +305,15 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
println!("{}", command1.to_string());
|
println!("{}", command1.to_string());
|
||||||
assert_eq!("(CASE: 3) cla: 0x90 | ins: 0x1A | p1: 0x0 | p2: 0x0 | LC: 0x3 | data: [ 0x1 0x2 0x3 ]", command1.to_string());
|
assert_eq!(
|
||||||
|
"(CASE: 3) cla: 0x90 | ins: 0x1A | p1: 0x0 | p2: 0x0 | LC: 0x3 | data: [ 0x1 0x2 0x3 ]",
|
||||||
|
command1.to_string()
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn to_string_case4() {
|
fn to_string_case4() {
|
||||||
let command1 = APDUCommand{
|
let command1 = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: 0x1A,
|
ins: 0x1A,
|
||||||
|
@ -1,7 +1,11 @@
|
|||||||
|
use crate::error::Error::{
|
||||||
|
ApplicationNotFound, AuthenticationDelay, AuthenticationError, BoundaryError, CommandAborted,
|
||||||
|
DuplicateError, FileNotFound, IllegalCommandCode, IntegrityError, InvalidStatusWord,
|
||||||
|
LengthError, NoSuchKey, ParameterError, PermissionDenied,
|
||||||
|
};
|
||||||
|
use crate::error::Result;
|
||||||
use crate::iso7816_4::apdustatuswords::{APDUStatusWord, APDUStatusWord2};
|
use crate::iso7816_4::apdustatuswords::{APDUStatusWord, APDUStatusWord2};
|
||||||
use crate::error::{Result};
|
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use crate::error::Error::{InvalidStatusWord, IllegalCommandCode, IntegrityError, NoSuchKey, LengthError, PermissionDenied, ParameterError, AuthenticationDelay, AuthenticationError, BoundaryError, CommandAborted, DuplicateError, FileNotFound, ApplicationNotFound};
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash, Debug, Default)]
|
#[derive(Eq, PartialEq, Hash, Debug, Default)]
|
||||||
@ -22,7 +26,9 @@ impl From<APDUResponse> for Vec<u8> {
|
|||||||
let mut v: Vec<u8> = vec![];
|
let mut v: Vec<u8> = vec![];
|
||||||
match resp.body {
|
match resp.body {
|
||||||
None => {}
|
None => {}
|
||||||
Some(body) => {v.extend(body);}
|
Some(body) => {
|
||||||
|
v.extend(body);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
v.push(resp.sw1);
|
v.push(resp.sw1);
|
||||||
v.push(resp.sw2);
|
v.push(resp.sw2);
|
||||||
@ -35,9 +41,13 @@ impl fmt::Display for APDUResponse {
|
|||||||
match &self.body {
|
match &self.body {
|
||||||
None => {
|
None => {
|
||||||
write!(f, "SW1: {:#X} | SW2: 0x{:#X}", self.sw1, self.sw2)
|
write!(f, "SW1: {:#X} | SW2: 0x{:#X}", self.sw1, self.sw2)
|
||||||
},
|
}
|
||||||
Some(body) => {
|
Some(body) => {
|
||||||
write!(f, "SW1: {:#X} | SW2: {:#X} | Body: {:#X?}", self.sw1, self.sw2, body)
|
write!(
|
||||||
|
f,
|
||||||
|
"SW1: {:#X} | SW2: {:#X} | Body: {:#X?}",
|
||||||
|
self.sw1, self.sw2, body
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -66,12 +76,17 @@ impl APDUResponse {
|
|||||||
0x61 => Ok(APDUStatusWord::DataReady),
|
0x61 => Ok(APDUStatusWord::DataReady),
|
||||||
0x62 => Ok(APDUStatusWord::StorageNotChanged),
|
0x62 => Ok(APDUStatusWord::StorageNotChanged),
|
||||||
0x63 => {
|
0x63 => {
|
||||||
if (self.sw2 & 0xF0) == 0xC0 { Ok(APDUStatusWord::CounterReached) } else { Ok(APDUStatusWord::StorageChanged) }
|
if (self.sw2 & 0xF0) == 0xC0 {
|
||||||
},
|
Ok(APDUStatusWord::CounterReached)
|
||||||
|
} else {
|
||||||
|
Ok(APDUStatusWord::StorageChanged)
|
||||||
|
}
|
||||||
|
}
|
||||||
0x64 => Ok(APDUStatusWord::ExecutionErrorWithoutChange),
|
0x64 => Ok(APDUStatusWord::ExecutionErrorWithoutChange),
|
||||||
0x65 => Ok(APDUStatusWord::ExecutionErrorWithChange),
|
0x65 => Ok(APDUStatusWord::ExecutionErrorWithChange),
|
||||||
0x6C => Ok(APDUStatusWord::InvalidLe),
|
0x6C => Ok(APDUStatusWord::InvalidLe),
|
||||||
_ => FromPrimitive::from_u16(((self.sw1 as u16) << 8) | self.sw2 as u16).ok_or(InvalidStatusWord)
|
_ => FromPrimitive::from_u16(((self.sw1 as u16) << 8) | self.sw2 as u16)
|
||||||
|
.ok_or(InvalidStatusWord),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,24 +105,26 @@ impl APDUResponse {
|
|||||||
pub fn check(&self) -> Result<()> {
|
pub fn check(&self) -> Result<()> {
|
||||||
if self.sw1 == 0x91 {
|
if self.sw1 == 0x91 {
|
||||||
return match FromPrimitive::from_u8(self.sw2) {
|
return match FromPrimitive::from_u8(self.sw2) {
|
||||||
Some(APDUStatusWord2::OperationOk) => { Ok(()) }
|
Some(APDUStatusWord2::OperationOk) => Ok(()),
|
||||||
Some(APDUStatusWord2::NoChanges) => { Ok(()) }
|
Some(APDUStatusWord2::NoChanges) => Ok(()),
|
||||||
Some(APDUStatusWord2::IllegalCommandCode) => {Err(IllegalCommandCode)}
|
Some(APDUStatusWord2::IllegalCommandCode) => Err(IllegalCommandCode),
|
||||||
Some(APDUStatusWord2::IntegrityError) => {Err(IntegrityError)}
|
Some(APDUStatusWord2::IntegrityError) => Err(IntegrityError),
|
||||||
Some(APDUStatusWord2::NoSuchKey) => {Err(NoSuchKey)}
|
Some(APDUStatusWord2::NoSuchKey) => Err(NoSuchKey),
|
||||||
Some(APDUStatusWord2::LengthError) => {Err(LengthError)}
|
Some(APDUStatusWord2::LengthError) => Err(LengthError),
|
||||||
Some(APDUStatusWord2::PermissionDenied) => {Err(PermissionDenied)}
|
Some(APDUStatusWord2::PermissionDenied) => Err(PermissionDenied),
|
||||||
Some(APDUStatusWord2::ParameterError) => {Err(ParameterError)}
|
Some(APDUStatusWord2::ParameterError) => Err(ParameterError),
|
||||||
Some(APDUStatusWord2::AuthenticationDelay) => {Err(AuthenticationDelay)}
|
Some(APDUStatusWord2::AuthenticationDelay) => Err(AuthenticationDelay),
|
||||||
Some(APDUStatusWord2::AuthenticationError) => {Err(AuthenticationError)}
|
Some(APDUStatusWord2::AuthenticationError) => Err(AuthenticationError),
|
||||||
Some(APDUStatusWord2::AdditionalFrame) => {Ok(())}
|
Some(APDUStatusWord2::AdditionalFrame) => Ok(()),
|
||||||
Some(APDUStatusWord2::BoundaryError) => {Err(BoundaryError)}
|
Some(APDUStatusWord2::BoundaryError) => Err(BoundaryError),
|
||||||
Some(APDUStatusWord2::CommandAborted) => {Err(CommandAborted)}
|
Some(APDUStatusWord2::CommandAborted) => Err(CommandAborted),
|
||||||
Some(APDUStatusWord2::DuplicateError) => {Err(DuplicateError)}
|
Some(APDUStatusWord2::DuplicateError) => Err(DuplicateError),
|
||||||
Some(APDUStatusWord2::FileNotFound) => {Err(FileNotFound)}
|
Some(APDUStatusWord2::FileNotFound) => Err(FileNotFound),
|
||||||
Some(APDUStatusWord2::ApplicationNotFound) => {Err(ApplicationNotFound)}
|
Some(APDUStatusWord2::ApplicationNotFound) => Err(ApplicationNotFound),
|
||||||
None => { Err(InvalidStatusWord)}
|
None => Err(InvalidStatusWord),
|
||||||
}
|
};
|
||||||
} else { Err(InvalidStatusWord) }
|
} else {
|
||||||
|
Err(InvalidStatusWord)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -108,19 +108,15 @@ pub enum APDUStatusWord {
|
|||||||
/// Parameter P1/P2 falsch
|
/// Parameter P1/P2 falsch
|
||||||
WrongParameters2 = 0x6B00,
|
WrongParameters2 = 0x6B00,
|
||||||
|
|
||||||
|
|
||||||
/// Falsche Lnge Le; xx gibt die korrekte Lnge an Statuswort zur Steuerung des T=0-Protokolls
|
/// Falsche Lnge Le; xx gibt die korrekte Lnge an Statuswort zur Steuerung des T=0-Protokolls
|
||||||
InvalidLe = 0x6C00,
|
InvalidLe = 0x6C00,
|
||||||
|
|
||||||
|
|
||||||
/// Das Kommando (INS) wird nicht untersttzt
|
/// Das Kommando (INS) wird nicht untersttzt
|
||||||
InstructionNotSupported = 0x6D00,
|
InstructionNotSupported = 0x6D00,
|
||||||
|
|
||||||
|
|
||||||
/// Die Kommandoklasse (CLA) wird nicht untersttzt
|
/// Die Kommandoklasse (CLA) wird nicht untersttzt
|
||||||
ClassNotSupported = 0x6E00,
|
ClassNotSupported = 0x6E00,
|
||||||
|
|
||||||
|
|
||||||
/// Kommando wurde mit unbekanntem Fehler abgebrochen
|
/// Kommando wurde mit unbekanntem Fehler abgebrochen
|
||||||
UnknownError = 0x6F00,
|
UnknownError = 0x6F00,
|
||||||
|
|
||||||
@ -129,7 +125,6 @@ pub enum APDUStatusWord {
|
|||||||
|
|
||||||
/// OK
|
/// OK
|
||||||
OK = 0x9100,
|
OK = 0x9100,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(FromPrimitive)]
|
#[derive(FromPrimitive)]
|
||||||
|
32
src/lib.rs
32
src/lib.rs
@ -1,27 +1,27 @@
|
|||||||
use crate::iso7816_4::apduresponse::APDUResponse;
|
|
||||||
use crate::iso7816_4::apducommand::APDUCommand;
|
use crate::iso7816_4::apducommand::APDUCommand;
|
||||||
|
use crate::iso7816_4::apduresponse::APDUResponse;
|
||||||
use error::Result;
|
use error::Result;
|
||||||
|
|
||||||
pub mod crypto;
|
pub mod crypto;
|
||||||
pub mod iso7816_4;
|
|
||||||
pub mod desfire;
|
pub mod desfire;
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
pub mod iso7816_4;
|
||||||
|
|
||||||
pub trait Card {
|
pub trait Card {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Connect to Smartcard
|
/// Connect to Smartcard
|
||||||
/// </summary>
|
/// </summary>
|
||||||
fn connect(&mut self) -> Result<()>;
|
fn connect(&mut self) -> Result<()>;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Disconnect from Smartcard
|
/// Disconnect from Smartcard
|
||||||
/// </summary>
|
/// </summary>
|
||||||
fn disconnect(&mut self) -> Result<()>;
|
fn disconnect(&mut self) -> Result<()>;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Transmit APDU Command to Smartcard
|
/// Transmit APDU Command to Smartcard
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="apdu_cmd">Application Protocol Data Unit Command - ISO 7816</param>
|
/// <param name="apdu_cmd">Application Protocol Data Unit Command - ISO 7816</param>
|
||||||
/// <returns>Application Protocol Data Unit Response - ISO 7816</returns>
|
/// <returns>Application Protocol Data Unit Response - ISO 7816</returns>
|
||||||
fn transmit(&self, apdu_cmd: APDUCommand) -> Result<APDUResponse>;
|
fn transmit(&self, apdu_cmd: APDUCommand) -> Result<APDUResponse>;
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user