mirror of
https://gitlab.com/fabinfra/fabaccess/nfc_rs.git
synced 2025-03-12 06:41:46 +01:00
cleanup
This commit is contained in:
parent
d76554741b
commit
26277f067b
@ -2,7 +2,7 @@
|
|||||||
name = "desfire"
|
name = "desfire"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Kai Jan Kriegel <kai@kjkriegel.de>"]
|
authors = ["Kai Jan Kriegel <kai@kjkriegel.de>"]
|
||||||
edition = "2018"
|
edition = "2021"
|
||||||
license = "MIT OR Apache-2.0"
|
license = "MIT OR Apache-2.0"
|
||||||
description = "Library for interfacing with Mifare Desfire cards."
|
description = "Library for interfacing with Mifare Desfire cards."
|
||||||
repository = "https://gitlab.com/fabinfra/fabaccess/nfc_rs"
|
repository = "https://gitlab.com/fabinfra/fabaccess/nfc_rs"
|
||||||
|
@ -12,9 +12,11 @@ pub struct CipherKey {
|
|||||||
pub key: Box<[u8]>, //TODO: Decide if this should be pub
|
pub key: Box<[u8]>, //TODO: Decide if this should be pub
|
||||||
|
|
||||||
/// CipherType of Key
|
/// CipherType of Key
|
||||||
|
#[allow(dead_code)]
|
||||||
cipher: CipherType,
|
cipher: CipherType,
|
||||||
|
|
||||||
/// KeyVersion of Key
|
/// KeyVersion of Key
|
||||||
|
#[allow(dead_code)]
|
||||||
key_version: u8,
|
key_version: u8,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::error::{Error, Result};
|
use crate::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.
|
||||||
|
@ -1,41 +1,42 @@
|
|||||||
|
#[allow(dead_code)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum APDUInstructions {
|
pub enum APDUInstructions {
|
||||||
AUTHENTICATE_ISO = 0x1A,
|
AuthenticateIso = 0x1A,
|
||||||
AUTHENTICATE_AES = 0xAA,
|
AuthenticateAes = 0xAA,
|
||||||
CHANGE_KEY_SETTINGS = 0x54,
|
ChangeKeySettings = 0x54,
|
||||||
SET_CONFIGURATION = 0x5C,
|
SetConfiguration = 0x5C,
|
||||||
CHANGE_KEY = 0xC4,
|
ChangeKey = 0xC4,
|
||||||
GET_KEY_VERSION = 0x64,
|
GetKeyVersion = 0x64,
|
||||||
CREATE_APPLICATION = 0xCA,
|
CreateApplication = 0xCA,
|
||||||
DELETE_APPLICATION = 0xDA,
|
DeleteApplication = 0xDA,
|
||||||
GET_APPLICATION_IDS = 0x6A,
|
GetApplicationIds = 0x6A,
|
||||||
FREE_MEMORY = 0x6E,
|
FreeMemory = 0x6E,
|
||||||
GET_DF_NAMES = 0x6D,
|
GetDfNames = 0x6D,
|
||||||
GET_KEY_SETTINGS = 0x45,
|
GetKeySettings = 0x45,
|
||||||
SELECT_APPLICATION = 0x5A,
|
SelectApplication = 0x5A,
|
||||||
FORMAT_PICC = 0xFC,
|
FormatPicc = 0xFC,
|
||||||
GET_VERSION = 0x60,
|
GetVersion = 0x60,
|
||||||
GET_CARD_UID = 0x51,
|
GetCardUid = 0x51,
|
||||||
GET_FILE_IDS = 0x6F,
|
GetFileIds = 0x6F,
|
||||||
GET_FILE_SETTINGS = 0xF5,
|
GetFileSettings = 0xF5,
|
||||||
CHANGE_FILE_SETTINGS = 0x5F,
|
ChangeFileSettings = 0x5F,
|
||||||
CREATE_STDDATAFILE = 0xCD,
|
CreateStddatafile = 0xCD,
|
||||||
CREATE_BACKUPDATAFILE = 0xCB,
|
CreateBackupdatafile = 0xCB,
|
||||||
CREATE_VALUE_FILE = 0xCC,
|
CreateValueFile = 0xCC,
|
||||||
CREATE_LINEAR_RECORD_FILE = 0xC1,
|
CreateLinearRecordFile = 0xC1,
|
||||||
CREATE_CYCLIC_RECORD_FILE = 0xC0,
|
CreateCyclicRecordFile = 0xC0,
|
||||||
DELETE_FILE = 0xDF,
|
DeleteFile = 0xDF,
|
||||||
GET_ISO_FILE_IDS = 0x61,
|
GetIsoFileIds = 0x61,
|
||||||
READ_DATA = 0xBD,
|
ReadData = 0xBD,
|
||||||
WRITE_DATA = 0x3D,
|
WriteData = 0x3D,
|
||||||
GET_VALUE = 0x6C,
|
GetValue = 0x6C,
|
||||||
CREDIT = 0x0C,
|
Credit = 0x0C,
|
||||||
DEBIT = 0xDC,
|
Debit = 0xDC,
|
||||||
LIMITED_CREDIT = 0x1C,
|
LimitedCredit = 0x1C,
|
||||||
WRITE_RECORD = 0x3B,
|
WriteRecord = 0x3B,
|
||||||
READ_RECORDS = 0xBB,
|
ReadRecords = 0xBB,
|
||||||
CLEAR_RECORD_FILE = 0xEB,
|
ClearRecordFile = 0xEB,
|
||||||
COMMIT_TRANSACTION = 0xC7,
|
CommitTransaction = 0xC7,
|
||||||
ABORT_TRANSACTION = 0xA7,
|
AbortTransaction = 0xA7,
|
||||||
CONTINUE = 0xAF,
|
Continue = 0xAF,
|
||||||
}
|
}
|
||||||
|
@ -1,68 +1,69 @@
|
|||||||
|
#[allow(dead_code)]
|
||||||
#[repr(u16)]
|
#[repr(u16)]
|
||||||
pub enum APDUStatusCodes {
|
pub enum APDUStatusCodes {
|
||||||
/// Successful operation
|
/// Successful operation
|
||||||
OPERATION_OK = 0x9000,
|
OperationOk = 0x9000,
|
||||||
|
|
||||||
/// No changes done to backup files, CommitTransaction / AbortTransaction not necessary
|
/// No changes done to backup files, CommitTransaction / AbortTransaction not necessary
|
||||||
NO_CHANGES = 0x900C,
|
NoChanges = 0x900C,
|
||||||
|
|
||||||
/// Insufficient NV-Memory to complete command
|
/// Insufficient NV-Memory to complete command
|
||||||
OUT_OF_EEPROM_ERROR = 0x900E,
|
OutOfEepromError = 0x900E,
|
||||||
|
|
||||||
/// Command code not supported
|
/// Command code not supported
|
||||||
ILLEGAL_COMMAND_CODE = 0x901C,
|
IllegalCommandCode = 0x901C,
|
||||||
|
|
||||||
/// CRC or MAC does not match data Padding bytes not valid
|
/// CRC or MAC does not match data Padding bytes not valid
|
||||||
INTEGRITY_ERROR = 0x901E,
|
IntegrityError = 0x901E,
|
||||||
|
|
||||||
/// Invalid key number specified
|
/// Invalid key number specified
|
||||||
NO_SUCH_KEY = 0x9040,
|
NoSuchKey = 0x9040,
|
||||||
|
|
||||||
/// Invalid key number specified
|
/// Invalid key number specified
|
||||||
LENGTH_ERROR = 0x907E,
|
LengthError = 0x907E,
|
||||||
|
|
||||||
/// Current configuration / status does not allow the requested command
|
/// Current configuration / status does not allow the requested command
|
||||||
PERMISSION_DENIED = 0x909D,
|
PermissionDenied = 0x909D,
|
||||||
|
|
||||||
/// Value of the parameter(s) invalid
|
/// Value of the parameter(s) invalid
|
||||||
PARAMETER_ERROR = 0x909E,
|
ParameterError = 0x909E,
|
||||||
|
|
||||||
/// Requested AID not present on PICC
|
/// Requested AID not present on PICC
|
||||||
APPLICATION_NOT_FOUND = 0x90A0,
|
ApplicationNotFound = 0x90A0,
|
||||||
|
|
||||||
/// Unrecoverable error within application, application will be disabled
|
/// Unrecoverable error within application, application will be disabled
|
||||||
APPL_INTEGRITY_ERROR = 0x90A1,
|
ApplIntegrityError = 0x90A1,
|
||||||
|
|
||||||
/// Current authentication status does not allow the requested command
|
/// Current authentication status does not allow the requested command
|
||||||
AUTHENTICATION_ERROR = 0x90AE,
|
AuthenticationError = 0x90AE,
|
||||||
|
|
||||||
/// Additional data frame is expected to be sent
|
/// Additional data frame is expected to be sent
|
||||||
ADDITIONAL_FRAME = 0x90AF,
|
AdditionalFrame = 0x90AF,
|
||||||
|
|
||||||
/// Attempt to read/write data from/to beyond the file\'s/record\'s limits. Attempt to exceed the limits of a value file.
|
/// Attempt to read/write data from/to beyond the file\'s/record\'s limits. Attempt to exceed the limits of a value file.
|
||||||
BOUNDARY_ERROR = 0x90BE,
|
BoundaryError = 0x90BE,
|
||||||
|
|
||||||
/// Unrecoverable error within PICC, PICC will be disabled
|
/// Unrecoverable error within PICC, PICC will be disabled
|
||||||
PICC_INTEGRITY_ERROR = 0x90C1,
|
PiccIntegrityError = 0x90C1,
|
||||||
|
|
||||||
/// Previous Command was not fully completed Not all Frames were requested or provided by the PCD
|
/// Previous Command was not fully completed Not all Frames were requested or provided by the PCD
|
||||||
COMMAND_ABORTED = 0x90CA,
|
CommandAborted = 0x90CA,
|
||||||
|
|
||||||
/// PICC was disabled by an unrecoverable error
|
/// PICC was disabled by an unrecoverable error
|
||||||
PICC_DISABLED_ERROR = 0x90CD,
|
PiccDisabledError = 0x90CD,
|
||||||
|
|
||||||
/// Number of Applications limited to 28, no additional CreateApplication possible
|
/// Number of Applications limited to 28, no additional CreateApplication possible
|
||||||
COUNT_ERROR = 0x90CE,
|
CountError = 0x90CE,
|
||||||
|
|
||||||
/// Creation of file/application failed because file/application with same number already exists
|
/// Creation of file/application failed because file/application with same number already exists
|
||||||
DUPLICATE_ERROR = 0x90DE,
|
DuplicateError = 0x90DE,
|
||||||
|
|
||||||
/// Could not complete NV-write operation due to loss of power, internal backup/rollback mechanism activated
|
/// Could not complete NV-write operation due to loss of power, internal backup/rollback mechanism activated
|
||||||
EEPROM_ERROR = 0x90EE,
|
EepromError = 0x90EE,
|
||||||
|
|
||||||
/// Specified file number does not exist
|
/// Specified file number does not exist
|
||||||
FILE_NOT_FOUND = 0x90F0,
|
FileNotFound = 0x90F0,
|
||||||
|
|
||||||
/// Unrecoverable error within file, file will be disabled
|
/// Unrecoverable error within file, file will be disabled
|
||||||
FILE_INTEGRITY_ERROR = 0x90F1,
|
FileIntegrityError = 0x90F1,
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,6 @@ use crate::error::{Result, Error};
|
|||||||
use crate::error::Error::{InvalidApplicationID, InvalidKeyID, InvalidFileID, NumKeys, InvalidKeyVersion};
|
use crate::error::Error::{InvalidApplicationID, InvalidKeyID, InvalidFileID, NumKeys, InvalidKeyVersion};
|
||||||
use crate::crypto::util::expand_to_blocksize;
|
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 num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
|
|
||||||
pub struct Desfire {
|
pub struct Desfire {
|
||||||
@ -33,7 +32,7 @@ impl Desfire {
|
|||||||
let cmd_select_app = APDUCommand {
|
let cmd_select_app = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::SELECT_APPLICATION as u8,
|
ins: APDUInstructions::SelectApplication as u8,
|
||||||
data: Option::from(aid.to_le_bytes()[..3].to_vec()), //FIXME: Which byteorder?
|
data: Option::from(aid.to_le_bytes()[..3].to_vec()), //FIXME: Which byteorder?
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -57,7 +56,7 @@ impl Desfire {
|
|||||||
let cmd_challenge_request = APDUCommand {
|
let cmd_challenge_request = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::AUTHENTICATE_ISO as u8,
|
ins: APDUInstructions::AuthenticateIso as u8,
|
||||||
data: Option::from(vec!(key_id)),
|
data: Option::from(vec!(key_id)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -97,7 +96,7 @@ impl Desfire {
|
|||||||
let cmd_challenge_response = APDUCommand {
|
let cmd_challenge_response = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::CONTINUE as u8,
|
ins: APDUInstructions::Continue as u8,
|
||||||
data: Some(rnd_ab_enc.clone()),
|
data: Some(rnd_ab_enc.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -144,7 +143,7 @@ impl Desfire {
|
|||||||
let cmd_challenge_request = APDUCommand {
|
let cmd_challenge_request = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::AUTHENTICATE_AES as u8,
|
ins: APDUInstructions::AuthenticateAes as u8,
|
||||||
data: Option::from(vec!(key_id)),
|
data: Option::from(vec!(key_id)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -162,7 +161,7 @@ impl Desfire {
|
|||||||
let rnd_b_enc = rnd_b_response_body.as_slice();
|
let rnd_b_enc = rnd_b_response_body.as_slice();
|
||||||
println!("RND_B_ENC: {:x?}", rnd_b_enc);
|
println!("RND_B_ENC: {:x?}", rnd_b_enc);
|
||||||
|
|
||||||
let mut rnd_b = AES::decrypt(rnd_b_enc, key, vec![0 as u8; 16].as_slice()).unwrap();
|
let rnd_b = AES::decrypt(rnd_b_enc, key, vec![0 as u8; 16].as_slice()).unwrap();
|
||||||
println!("RND_B: {:x?}", rnd_b);
|
println!("RND_B: {:x?}", rnd_b);
|
||||||
|
|
||||||
// auth_iv = rnd_b.clone();
|
// auth_iv = rnd_b.clone();
|
||||||
@ -187,7 +186,7 @@ impl Desfire {
|
|||||||
let cmd_challenge_response = APDUCommand {
|
let cmd_challenge_response = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::CONTINUE as u8,
|
ins: APDUInstructions::Continue as u8,
|
||||||
data: Some(rnd_ab_enc.clone()),
|
data: Some(rnd_ab_enc.clone()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -231,7 +230,7 @@ impl Desfire {
|
|||||||
let cmd_format = APDUCommand {
|
let cmd_format = APDUCommand {
|
||||||
case: IsoCase::Case2Short,
|
case: IsoCase::Case2Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::FORMAT_PICC as u8,
|
ins: APDUInstructions::FormatPicc as u8,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -255,7 +254,7 @@ impl Desfire {
|
|||||||
let cmd_create_application = APDUCommand {
|
let cmd_create_application = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::CREATE_APPLICATION as u8,
|
ins: APDUInstructions::CreateApplication as u8,
|
||||||
data: Option::from(data), //FIXME: Which byteorder?
|
data: Option::from(data), //FIXME: Which byteorder?
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -312,7 +311,7 @@ impl Desfire {
|
|||||||
let cmd_change_key = APDUCommand {
|
let cmd_change_key = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::CHANGE_KEY as u8,
|
ins: APDUInstructions::ChangeKey as u8,
|
||||||
data: Option::from(data), //FIXME: Which byteorder?
|
data: Option::from(data), //FIXME: Which byteorder?
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -381,7 +380,7 @@ impl Desfire {
|
|||||||
let cmd_change_key = APDUCommand {
|
let cmd_change_key = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::CHANGE_KEY as u8,
|
ins: APDUInstructions::ChangeKey as u8,
|
||||||
data: Option::from(data), //FIXME: Which byteorder?
|
data: Option::from(data), //FIXME: Which byteorder?
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -407,7 +406,7 @@ impl Desfire {
|
|||||||
let cmd_create_file_standard = APDUCommand {
|
let cmd_create_file_standard = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::CREATE_STDDATAFILE as u8,
|
ins: APDUInstructions::CreateStddatafile as u8,
|
||||||
data: Option::from(data),
|
data: Option::from(data),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -455,7 +454,7 @@ impl Desfire {
|
|||||||
let cmd_write_data = APDUCommand {
|
let cmd_write_data = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::WRITE_DATA as u8,
|
ins: APDUInstructions::WriteData as u8,
|
||||||
data: Option::from(write_buffer),
|
data: Option::from(write_buffer),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -500,7 +499,7 @@ impl Desfire {
|
|||||||
let cmd_read_data = APDUCommand {
|
let cmd_read_data = APDUCommand {
|
||||||
case: IsoCase::Case4Short,
|
case: IsoCase::Case4Short,
|
||||||
cla: 0x90,
|
cla: 0x90,
|
||||||
ins: APDUInstructions::READ_DATA as u8,
|
ins: APDUInstructions::ReadData as u8,
|
||||||
data: Option::from(send_buffer),
|
data: Option::from(send_buffer),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
@ -509,7 +508,7 @@ impl Desfire {
|
|||||||
let response = self.card.transmit(cmd_read_data).unwrap();
|
let response = self.card.transmit(cmd_read_data).unwrap();
|
||||||
println!("RESPONSE: {}", response);
|
println!("RESPONSE: {}", response);
|
||||||
|
|
||||||
response.check().or_else(|e| return Err(e));
|
response.check().or_else(|e| return Err(e))?;
|
||||||
// println!("RESPONSE_DATA: {:x?}, WITHOUT_CMAC: {:x?}", response.body.as_ref().unwrap(), response.body.as_ref().unwrap()[..bytes_toread].to_vec());
|
// println!("RESPONSE_DATA: {:x?}, WITHOUT_CMAC: {:x?}", response.body.as_ref().unwrap(), response.body.as_ref().unwrap()[..bytes_toread].to_vec());
|
||||||
|
|
||||||
read_buffer.append(&mut response.body.unwrap()[..bytes_toread].to_vec());
|
read_buffer.append(&mut response.body.unwrap()[..bytes_toread].to_vec());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user