diff --git a/src/desfire/desfire.rs b/src/desfire/desfire.rs
index 2e56181..8da1c51 100644
--- a/src/desfire/desfire.rs
+++ b/src/desfire/desfire.rs
@@ -16,8 +16,7 @@ use crate::iso7816_4::apducommand::{APDUCommand, IsoCase};
use crate::{error, Card};
use num_traits::FromPrimitive;
-
-
+/// Maximum number of bytes in a single transaction while communicating with a nfc token
pub const MAX_BYTES_PER_TRANSACTION: usize = 47;
pub struct Desfire {
@@ -43,10 +42,7 @@ impl Desfire {
})
}
- ///
- /// Select Application by ApplicationID (AID)
- ///
- /// 3 Byte AID
+ /// Select Application by 3 Byte ApplicationID `aid`
pub fn select_application(&self, aid: u32) -> Result<()> {
let cmd_select_app = self.select_application_cmd(aid)?;
@@ -55,12 +51,12 @@ impl Desfire {
response.check()
}
- ///
/// Authenticate to PICC, with ISO Authenticate for DES Key
- ///
- /// 0x01 - 0x0D
- /// Array of 8/16 Bytes
- /// !!! WARNING For Testing only !!!
+ ///
+ /// Arguments:
+ /// * `key_id`: 0x01 - 0x0D
+ /// * `key`: Array of 8/16 bytes
+ /// * `rnd_a`: !!! WARNING for testing only !!!
pub fn authenticate_iso_des(
&mut self,
key_id: u8,
@@ -243,12 +239,12 @@ impl Desfire {
Ok(())
}
- ///
/// Authenticate to PICC, with ISO Authenticate for AES Key
- ///
- /// 0x01 - 0x0D
- /// Array of 8/16 Bytes
- /// !!! WARNING For Testing only !!!
+ ///
+ /// # Parameters
+ /// * `key_id`: 0x01 - 0x0D
+ /// * `key`: Array of 8/16 bytes
+ /// * `rnd_a`: !!! WARNING for testing only !!!
pub fn authenticate_iso_aes(
&mut self,
key_id: u8,
@@ -311,10 +307,10 @@ impl Desfire {
)
}
- ///
- /// Format PICC
- /// Need Authentication for PICC / Application 0x000000
- ///
+ /// Format PICC, this is akin to a factory reset
+ ///
+ /// # Note
+ /// This function will fail if you haven't authenticated against the PICC (Application ID: 0)
pub fn format_picc(&self) -> Result<()> {
let cmd_format = APDUCommand {
case: IsoCase::Case2Short,
@@ -328,10 +324,12 @@ impl Desfire {
response.check()
}
- ///
- /// Create Application for ApplicationID
- ///
- /// 3 Byte ID
+ /// Create a new application with `aid` as the application ID
+ ///
+ /// # Arguments
+ /// * `aid`: 3 byte ID
+ /// * `keysetting1`: TODO
+ /// * `keysetting2`: TODO
pub fn create_application(&self, aid: u32, keysetting1: u8, keysetting2: u8) -> Result<()> {
if aid > 0xFFFFFF {
return Err(InvalidApplicationID);
@@ -358,12 +356,18 @@ impl Desfire {
response.check()
}
- ///
- /// Change AES key, the same as Authenticated
- ///
- /// 0x01 - 0x0D
- /// Array of 16 Bytes
- /// Version of Key(min. 0x10)
+ /// Change AES key, that is currently authenticated
+ ///
+ /// # Notes
+ ///
+ /// This will fail if the key you are trying to change isn't authenticated
+ ///
+ /// # Arguments
+ /// * `key_id` - 0x01 - 0x0D
+ /// * `new_key` - Array of 16 Bytes
+ /// * `key_version` - Version of Key(min. 0x10)
+ ///
+ /// Also see: [`Desfire::change_other_key_aes`]
pub fn change_key_aes(&mut self, key_id: u8, new_key: &[u8], key_version: u8) -> Result<()> {
if key_id >= 0x0E {
return Err(InvalidKeyID);
@@ -426,13 +430,15 @@ impl Desfire {
response.check()
}
- ///
- /// Change AES key, other than Authenticated
- ///
- /// 0x01 - 0x0D
- /// Array of 16 Bytes
- /// Array of 16 Bytes
- /// Version of Key(min. 0x10)
+ /// Change AES key, of a currently not authenticated key
+ ///
+ /// # Arguments:
+ /// * `key_id` - 0x01 - 0x0D
+ /// * `new_key` - Array of 16 Bytes
+ /// * `old_key` - Array of 16 Bytes
+ /// * `key_version` - Version of Key(min. 0x10)
+ ///
+ /// Also see: [`Desfire::change_key_aes`]
pub fn change_other_key_aes(
&mut self,
key_id: u8,
@@ -514,6 +520,13 @@ impl Desfire {
response.check()
}
+ /// Create a new standard file
+ ///
+ /// # Arguments
+ /// * `file_id` - ID of the new file (0x00 - 0x20)
+ /// * `communication` - TODO
+ /// * `access_rights` - TODO
+ /// * `size` - size of the file in bytes
pub fn create_file_standard(
&self,
file_id: u8,
@@ -551,12 +564,12 @@ impl Desfire {
response.check()
}
- ///
/// Write Data to File
- ///
- /// ID of File (0x00 - 0x20)
- /// Offset for File
- /// Data to write
+ ///
+ /// # Parameters
+ /// * `file_id` - Id of the file (0x00 - 0x20)
+ /// * `offset` - offset of the file
+ /// * `data` - data to write
pub fn write_data(&self, file_id: u8, offset: u32, data: &[u8]) -> Result<()> {
if file_id >= 0x20 {
return Err(InvalidFileID);
@@ -638,12 +651,15 @@ impl Desfire {
return Ok(cmd_read_data_chunk);
}
- ///
- /// Read Data from File
- ///
- /// ID of File (0x00 - 0x20)
- /// Offset for File
- /// Lenght of Data
+ /// Read data from a file
+ ///
+ /// # Note
+ /// This operation will fail if you try to read more data then there is in the file
+ ///
+ /// # Parameters
+ /// * `file_id` - ID of the file (0x00 - 0x20)
+ /// * `offset` - Offset of the file
+ /// * `length` - lenght of the data to read
pub fn read_data(&self, file_id: u8, offset: u32, length: usize) -> Result> {
if file_id >= 0x20 {
return Err(InvalidFileID);
@@ -679,29 +695,30 @@ impl Desfire {
}
}
-///
/// Generates SessionKey for DES Authentification
-///
-/// 8Byte SessionKey
+///
+/// returns 8Byte SessionKey
fn generate_session_key_des(rnd_a: &[u8], rnd_b: &[u8]) -> Option> {
let sessionkey = [&rnd_a[..4], &rnd_b[..4]].concat();
Some([sessionkey.as_slice(), sessionkey.as_slice()].concat())
}
-///
/// Generates SessionKey for AES Authentification
-///
-/// 16Byte SessionKey
+///
+/// returns 16Byte SessionKey
fn generate_session_key_aes(rnd_a: &[u8], rnd_b: &[u8]) -> Option> {
//FIXME: Check math
Some([&rnd_a[..4], &rnd_b[..4], &rnd_a[12..], &rnd_b[12..]].concat())
}
-///
/// Generate KeySetting1 for Application Settings or PICC Setting
-///
-/// ID of Key for changing Application Keys
-/// generated keysettings
+///
+/// # Parameters
+/// * `change_key` - ID of the key for changing application keys
+/// * `change_master_key` - TODO
+/// * `create_delete_file` - TODO
+/// * `file_directory_access` - TODO
+/// * `change_master_key` - TODO
pub fn generate_keysetting1(
change_key: u8,
change_masterkey_settings: ChangeMasterKeySettings,
@@ -731,11 +748,12 @@ pub fn generate_keysetting1(
};
}
-///
/// Generate KeySetting2 for Application Creation
-///
-/// Number of keys that can be stored within the application (0x01-0x0D)
-/// generated keysettings
+///
+/// # Parameters
+/// * `crypto_operations` - TODO
+/// * `file_identifier` - TODO
+/// * `num_keys` - Number of keys that can be stored within the application (0x01 - 0x0D)
pub fn generate_keysetting2(
crypto_operations: CryptoOperationsType,
file_identifier: FileIdentifiers,
@@ -748,14 +766,18 @@ pub fn generate_keysetting2(
};
}
-///
/// Generate FileAccess Rights for File Settings
-/// Use enum AccesRights for Free or Never Option
-///
-/// KeyID for Read Access
-/// KeyID for Write Access
-/// KeyID for Read and Write Access
-/// KeyID for Configuration Access
+///
+/// # Note
+/// Use [`FileAccessRights`] for Free or Never Option
+///
+/// # Parameters
+/// * `read` key_id for read access
+/// * `write` key_id for write access
+/// * `read_write` key_id for read and write access
+/// * `configure` key_id for configuration access
+///
+/// [`FileAccessRights`]: crate::desfire::FileAccessRights
pub fn generate_file_access_rights(
read: u8,
write: u8,
@@ -780,23 +802,21 @@ mod tests {
generate_file_access_rights, generate_keysetting1, generate_keysetting2,
generate_session_key_aes, generate_session_key_des, Desfire,
};
-
+
use crate::desfire::{
ChangeApplicationKey, ChangeMasterKey, ChangeMasterKeySettings, CreateDeleteFile,
CryptoOperationsType, FileAccessRights, FileCommunication, FileDirectoryAccess,
FileIdentifiers,
};
- use crate::error::Error::{CardError};
+ use crate::error::Error::CardError;
use crate::error::Result;
-
+
use crate::{APDUCommand, APDUResponse, Card as CardTrait};
use hex_literal::hex;
- use mockall::{mock};
+ use mockall::mock;
use pcsc::{Card, Context, Protocols, Scope, ShareMode, MAX_BUFFER_SIZE};
use std::convert::TryFrom;
- use std::ffi::{CString};
-
-
+ use std::ffi::CString;
mock! {
pub VirtualCard {}
diff --git a/src/desfire/mod.rs b/src/desfire/mod.rs
index d4d3569..1812fd8 100644
--- a/src/desfire/mod.rs
+++ b/src/desfire/mod.rs
@@ -1,79 +1,51 @@
use num_derive::FromPrimitive;
-///
-/// hold the Access Rights for changing application keys (Change Key command)
-///
+/// Access Rights for changing application keys (Change Key command)
#[repr(u8)]
#[derive(Clone, Copy, FromPrimitive)]
pub enum ChangeApplicationKey {
- ///
/// Application master key authentication is necessary to change any key (default)
- ///
MASTERKEY = 0x00,
- ///
/// Authentication with the key to be changed (same Key#) is necessary to change a key
- ///
SAMEKEY = 0x0E,
- ///
/// All keys (except application master key, see Bit 0) within this application are frozen
- ///
ALLKEYS = 0x0F,
}
-///
/// codes whether the application master key is changeable
-///
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum ChangeMasterKey {
- ///
/// Application master key is not changeable anymore (frozen)
- ///
FROZEN = 0x00,
- ///
/// Application master key is changeable (authentication with the current application master key necessary, default)
- ///
CHANGEABLE = 0x01,
}
-///
/// codes whether a change of the application master key settings is allowed
-///
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum ChangeMasterKeySettings {
- ///
/// configuration not changeable anymore (frozen)
- ///
FROZEN = 0x00,
- ///
/// this configuration is changeable if authenticated with the application master key (default)
- ///
WITHMASTERKEY = 0x08,
}
-///
/// codes whether application master key authentication is needed before “Create File” / “Delete File”
-///
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum CreateDeleteFile {
- ///
/// “Create File”/ “Delete File”is permitted only with application master key authentication
- ///
ONLYMASTERKEY = 0x00,
- ///
/// “Create File”/ “Delete File”is permitted also without application master key authentication (default)
- ///
NOKEY = 0x04,
}
-///
/// Crypto method of the application
-///
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum CryptoOperationsType {
@@ -92,42 +64,30 @@ pub enum FileAccessRights {
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum FileCommunication {
- ///
/// "Plain communication"
- ///
PLAIN = 0x00,
- ///
/// Plain communication secured by DES/3DES MACing
- ///
MAC = 0x01,
- ///
/// Fully DES/3DES enciphered communication
- ///
ENCRYPT = 0x03,
}
-///
/// codes whether application master key authentication is needed for file directory access
-///
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum FileDirectoryAccess {
- ///
- /// Successful application master key authentication is required for executing the “Get FID List”, “Get File Settings”and “Get Key Settings”commands
- ///
+ /// Successful application master key authentication is required for executing
+ /// the “Get FID List”, “Get File Settings”and “Get Key Settings”commands
ONLYMASTERKEY = 0x00,
- ///
- /// “Get FID List”, “Get File Settings” and “Get Key Settings” commands succeed independentlyof a preceding application master key authentication (default)
- ///
+ /// “Get FID List”, “Get File Settings” and “Get Key Settings” commands succeed
+ /// independently of a preceding application master key authentication (default)
NOKEY = 0x02,
}
-///
/// Indicates use of 2 byte ISO/IEC 7816-4 File Identifies for files within the Application
-///
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum FileIdentifiers {
@@ -138,29 +98,19 @@ pub enum FileIdentifiers {
#[repr(u8)]
#[derive(Clone, Copy)]
pub enum FileTypes {
- ///
/// Standard Data File
- ///
STANDARD = 0x00,
- ///
/// Backup Data Files
- ///
BACKUP = 0x01,
- ///
/// Value Files with Backup
- ///
VALUE = 0x02,
- ///
/// Linear Record Files with Backup
- ///
LINEARRECORD = 0x03,
- ///
/// Cyclic Record Files with Backup
- ///
CYCLICRECORD = 0x04,
}
diff --git a/src/iso7816_4/apducommand.rs b/src/iso7816_4/apducommand.rs
index d88450f..2e9fe5e 100644
--- a/src/iso7816_4/apducommand.rs
+++ b/src/iso7816_4/apducommand.rs
@@ -6,74 +6,60 @@ use std::fmt::Formatter;
#[repr(u8)]
#[derive(Eq, PartialEq, Hash, Debug, Clone)]
pub enum IsoCase {
- /// No command data. No response data.
- ///
- ///
- /// - lc is valued to 0.
- /// - le is valued to 0.
- /// - No data byte is present.
- ///
- ///
+ /// No command data. No response data.
+ ///
+ /// # Notes
+ /// * lc is valued to 0.
+ /// * le is valued to 0.
+ /// * No data byte is present.
Case1 = 0,
- /// No command data. Expected response data.
- ///
- ///
- /// - lc is valued to 0.
- /// - le is valued from 1 to 256.
- /// - No data byte is present.
- ///
- ///
+ /// No command data. Expected response data.
+ ///
+ /// # Notes
+ /// * lc is valued to 0.
+ /// * le is valued from 1 to 256.
+ /// * No data byte is present.
Case2Short = 1,
- /// Command data. No response data.
- ///
- ///
- /// - lc is valued from 1 to 255.
- /// - le is valued to 0.
- /// - lc data bytes are present.
- ///
- ///
+ /// Command data. No response data.
+ ///
+ /// # Notes
+ /// * lc is valued from 1 to 255.
+ /// * le is valued to 0.
+ /// * lc data bytes are present.
Case3Short = 2,
- /// Command data. Expected response data.
- ///
- ///
- /// - lc is valued from 1 to 255.
- /// - le is valued from 1 to 256.
- /// - lc data bytes are present.
- ///
- ///
+ /// Command data. Expected response data.
+ ///
+ /// # Notes
+ /// * lc is valued from 1 to 255.
+ /// * le is valued from 1 to 256.
+ /// * lc data bytes are present.
Case4Short = 3,
- /// No command data. Expected response data.
- ///
- ///
- /// - lc is valued to 0.
- /// - le is valued from 1 to 65536.
- /// - No data byte is present.
- ///
- ///
+ /// No command data. Expected response data.
+ ///
+ /// # Notes
+ /// * lc is valued to 0.
+ /// * le is valued from 1 to 65536.
+ /// * No data byte is present.
Case2Extended = 4,
- /// Command data. No response data.
- ///
- ///
- /// - lc is valued from 1 to 65536.
- /// - le is valued to 0.
- /// - lc data bytes are present.
- ///
- ///
+ /// Command data. No response data.
+ ///
+ /// # Notes
+ /// * lc is valued from 1 to 65536.
+ /// * le is valued to 0.
+ /// * lc data bytes are present.
Case3Extended = 5,
- /// Command data. Expected response data.
- ///
- ///
- /// - lc is valued from 1 to 65535.
- /// - le is valued from 1 to 65536.
- /// - lc data bytes are present.
- ///
- ///
+ /// Command data. Expected response data.
+ ///
+ /// Notes
+ /// * lc is valued from 1 to 65535.
+ /// * le is valued from 1 to 65536.
+ /// * lc data bytes are present.
Case4Extended = 6,
}
@@ -86,24 +72,22 @@ impl Default for IsoCase {
#[repr(u8)]
#[derive(Eq, PartialEq, Hash, Debug, Clone)]
pub enum SCardProtocol {
- ///
/// protocol not defined.
- ///
Unset = 0x0000,
- /// T=0 active protocol.
+ /// T=0 active protocol.
T0 = 0x0001,
- /// T=1 active protocol.
+ /// T=1 active protocol.
T1 = 0x0002,
- /// Raw active protocol. Use with memory type cards.
+ /// Raw active protocol. Use with memory type cards.
Raw = 0x0004,
- /// T=15 protocol.
+ /// T=15 protocol.
T15 = 0x0008,
- /// ( | ). IFD (Interface device) determines protocol.
+ /// (see [`SCardProtocol::T0`] and [`SCardProtocol::T1`]). IFD (Interface device) determines protocol.
Any = (0x0001 | 0x0002),
}
diff --git a/src/lib.rs b/src/lib.rs
index c4470e6..eb9cfeb 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,7 +2,7 @@
//!
//! **WARNING** This is alpha quality software at best and should not be relied upon. **WARNING**
//!
-//!The `desfire` Crate provides the cryptographic methods and specific commands for interfacing
+//! The `desfire` Crate provides the cryptographic methods and specific commands for interfacing
//! with NXP MiFare Desfire cards.
//!
@@ -16,20 +16,17 @@ pub mod error;
pub mod iso7816_4;
pub trait Card {
- ///
/// Connect to Smartcard
- ///
fn connect(&mut self) -> Result<()>;
- ///
/// Disconnect from Smartcard
- ///
fn disconnect(&mut self) -> Result<()>;
- ///
/// Transmit APDU Command to Smartcard
- ///
- /// Application Protocol Data Unit Command - ISO 7816
- /// Application Protocol Data Unit Response - ISO 7816
+ ///
+ /// # Parameters
+ /// * `apdu_cmd` - Application Protocol Data Unit Command - ISO 7816
+ ///
+ /// returns a Application Protocol Data Unit Response - ISO 7816
fn transmit(&self, apdu_cmd: APDUCommand) -> Result;
}