Added: Complete Real Test

This commit is contained in:
TheJoKlLa
2020-11-07 01:14:51 +01:00
parent 872aeccee7
commit 6c51e40891
23 changed files with 1020 additions and 1199 deletions

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NFC.Mifare_DESFire;
@ -129,6 +130,25 @@ namespace NFC.ISO7816_4
return array;
}
public override bool Equals(object obj)
{
return obj is APDUResponse response &&
EqualityComparer<byte[]>.Default.Equals(Body, response.Body) &&
SW1 == response.SW1 &&
SW2 == response.SW2;
}
public override int GetHashCode()
{
return HashCode.Combine(Body, SW1, SW2);
}
public override string ToString()
{
string pattern = "SW1: 0x{0:x} | SW2: 0x{1:x} | Body: 0x{2:x}";
return string.Format(pattern, SW1, SW2, Body);
}
#endregion
}
}

View File

@ -1,6 +1,4 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace NFC.Mifare_DESFire
{

View File

@ -1,106 +0,0 @@
using NFC.Crypto;
using System;
namespace NFC.NXP_MIFARE_DESFire
{
public class CMAC
{
#region Contructors
public CMAC(CipherType cipher)
{
switch(cipher)
{
case(CipherType.TDES):
_Cipher = new TDES();
break;
case(CipherType.TDES_2K):
_Cipher = new TDES_2K();
break;
case(CipherType.TDES_3K):
_Cipher = new TDES_3K();
break;
case (CipherType.AES):
_Cipher = new AES();
break;
default:
throw new ArgumentException("Unkown Cipher Type.");
}
}
public CMAC(ICipher cipher)
{
_Cipher = cipher ?? throw new ArgumentNullException();
}
#endregion
#region Properties
private ICipher _Cipher;
#endregion
#region Methods
/// <summary>
/// Generate Key with all Zeros, in KeySize
/// </summary>
public byte[] GenerateEmpytKey()
{
byte[] key = new byte[_Cipher.KeySize];
for (int i = 0; i < _Cipher.KeySize; i++)
{
key[i] = 0;
}
return key;
}
/// <summary>
/// Generate IV with all Zeros, in KeySize
/// </summary>
public byte[] GenerateEmpytIV()
{
byte[] key = new byte[_Cipher.BlockSize];
for (int i = 0; i < _Cipher.BlockSize; i++)
{
key[i] = 0;
}
return key;
}
/// <summary>
/// Encrypt Data
/// </summary>
public byte[] Encrypt(byte[] data)
{
throw new NotImplementedException();
}
/// <summary>
/// Decrypt Data
/// </summary>
public byte[] Decrypt(byte[] data)
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
/// <returns>Two Keys</returns>
public byte[][] GenerateSubKey()
{
throw new NotImplementedException();
}
/// <summary>
///
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public byte[] Digest(byte[] data)
{
throw new NotImplementedException();
}
#endregion
}
}

View File

@ -1,13 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace NFC.Mifare_DESFire
{
enum CryptoOperations : byte
{
TDES = 0x00,
TKTDES = 0x40,
AES = 0x80,
}
}

View File

@ -1,5 +1,4 @@
using log4net.Repository.Hierarchy;
using NFC.Crypto;
using NFC.Crypto;
using NFC.ISO7816_4;
using NFC.Mifare_DESFire.Enums;
using NFC.NXP_MIFARE_DESFire.Exceptions;
@ -7,7 +6,6 @@ using PCSC.Iso7816;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
namespace NFC.Mifare_DESFire
{
@ -54,7 +52,7 @@ namespace NFC.Mifare_DESFire
/// Generate Byte Array filled with 0
/// </summary>
/// <param name="size">Size of Array</param>
public byte[] GenerateEmptyKey(uint size)
public byte[] GenerateEmptyArray(uint size)
{
byte[] key = new byte[size];
for (int i = 0; i < size; i++)
@ -66,42 +64,12 @@ namespace NFC.Mifare_DESFire
}
/// <summary>
/// Converts byte[] to string with HEX Code
/// No 0x is created
/// Get Range of Array Elements
/// </summary>
/// <param name="data">Data</param>
public string ConvertToHexString(byte[] data)
{
return BitConverter.ToString(data).Replace("-", "").ToLower();
}
/// <summary>
/// Converts string with HEX Code to byte[]
/// No 0x is requiered
/// </summary>
/// <param name="data">Data</param>
public byte[] ConvertFromHexString(string data)
{
if (data.Length % 2 == 1)
throw new Exception("Data Length is uneven.");
byte[] arr = new byte[data.Length >> 1];
for (int i = 0; i < data.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(data[i << 1]) << 4) + (GetHexVal(data[(i << 1) + 1])));
}
return arr;
}
/// <summary>
/// Get Range of Array
/// </summary>
/// <param name="array"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
/// <param name="array">Array</param>
/// <param name="offset">Offset in Byte</param>
/// <param name="length">Lenght to read in Byte</param>
/// <returns>new Array with Range of Array Elements</returns>
public byte[] GetSubArray(byte[] array, long offset, long length)
{
byte[] subarray = new byte[length];
@ -112,17 +80,6 @@ namespace NFC.Mifare_DESFire
return subarray;
}
private int GetHexVal(char hex)
{
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
/// <summary>
/// Check APDU Response for DESFire Error Codes
/// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf
@ -206,6 +163,35 @@ namespace NFC.Mifare_DESFire
return lastblock;
}
/// <summary>
/// Expand Array to Block Size, fill with 0x00
/// </summary>
/// <param name="data"></param>
public byte[] ExpandToBlockSize(byte[] data, uint bocksize)
{
if (data == null)
{
throw new ArgumentNullException("Data cannot be null.");
}
int diff = data.Length % (int)bocksize;
if (diff == 0)
{
return data;
}
byte[] expand = new byte[data.Length + bocksize - diff];
data.CopyTo(expand, 0);
for (int i = expand.Length - 1; i > data.Length - 1; i--)
{
expand[i] = 0x00;
}
return expand;
}
/// <summary>
/// Rotates Array to the left
/// </summary>
@ -310,6 +296,7 @@ namespace NFC.Mifare_DESFire
return c;
}
/// <summary>
/// Generates SessionKey for DES Authentification
/// </summary>
@ -364,62 +351,89 @@ namespace NFC.Mifare_DESFire
return sesssionkey;
}
#endregion
#region Configuration Generator
/// <summary>
/// Set KeyVersion in DES Key
/// KeyVersion is stored in LSB of the first 8 Bytes of the DES Key
/// Genearte KeySetting1 for Application Settings or PICC Setting
/// </summary>
public byte[] SetKeyVersion(byte[] key, byte keyversion)
public byte GenerateKeySetting1(ChangeApplicationKey changeKey, ChangeMasterKeySettings changeMasterKeySettings, CreateDeleteFile createDeleteFile, FileDirectoryAccess fileDirectoryAccess, ChangeMasterKey changeMasterKey)
{
byte[] pow2 = new byte[]
{
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
};
byte[] new_key = new byte[key.Length];
key.CopyTo(new_key, 0);
for (int i = 0; i < 8; i++)
{
if ((keyversion & pow2[i]) > 0)
{
new_key[i] = (byte)(new_key[5] | 0x01);
}
else
{
new_key[i] = (byte)(new_key[5] & 0x7F);
}
}
return new_key;
return (byte)(((byte)changeKey << 4) | (byte)changeMasterKeySettings | (byte)createDeleteFile | (byte)fileDirectoryAccess | (byte)changeMasterKey);
}
/// <summary>
/// Expand Array to Block Size, fill with 0x00
/// Genearte KeySetting1 for Application Settings or PICC Setting
/// </summary>
/// <param name="data"></param>
public byte[] ExpandToBlockSize(byte[] data, uint bocksize)
/// <param name="changeKey">ID of Key for changing Application Keys</param>
/// <returns></returns>
public byte GenerateKeySetting1(byte changeKey, ChangeMasterKeySettings changeMasterKeySettings, CreateDeleteFile createDeleteFile, FileDirectoryAccess fileDirectoryAccess, ChangeMasterKey changeMasterKey)
{
int diff = data.Length % (int)bocksize;
if (diff == 0)
if (changeKey < 0x01 || changeKey >= 0x0E)
{
return data;
throw new ArgumentOutOfRangeException();
}
return GenerateKeySetting1((ChangeApplicationKey)changeKey, changeMasterKeySettings, createDeleteFile, fileDirectoryAccess, changeMasterKey);
}
/// <summary>
/// Genearte KeySetting2 for Application Creation
/// </summary>
/// <param name="numberOfKeys">Number of keys that can be stored within the application (0x01-0x0D)</param>
/// <returns></returns>
public byte GenerateKeySetting2(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys)
{
if (numberOfKeys < 0x01 || numberOfKeys >= 0x0D)
{
throw new ArgumentOutOfRangeException();
}
byte[] expand = new byte[data.Length + bocksize - diff];
return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys);
}
data.CopyTo(expand, 0);
for (int i = expand.Length - 1; i > data.Length - 1; i--)
/// <summary>
/// Generate FileAccess Rights for File Settings
/// Use enum AccesRights for Free or Never Option
/// </summary>
/// <param name="read">KeyID for Read Access</param>
/// <param name="write">KeyID for Write Access</param>
/// <param name="read_write">KeyID for Read and Write Access</param>
/// <param name="configure">KeyID for Configuration Access</param>
public UInt16 GenerateFileAccessRights(byte read, byte write, byte read_write, byte configure)
{
if (read > 0x0F || write > 0x0F || read_write > 0x0F || configure > 0x0F)
{
expand[i] = 0x00;
throw new ArgumentOutOfRangeException("One KeyID is not valid");
}
return expand;
return (UInt16)((read << 12) | (write << 8) | (read_write << 4) | configure);
}
#endregion
#region DESFire Commands
/// <summary>
/// Format PICC
/// Works after PICC Authentication
/// </summary>
public void Format()
{
_Log.Debug("Start Format");
APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short)
{
CLA = 0x90,
INS = 0xFC,
};
_Log.DebugFormat("APDU_CMD(cmd_format): {0}", HexConverter.ConvertToHexString(cmd_format.ToArray()));
APDUResponse response = _Card.Transmit(cmd_format);
_Log.DebugFormat("APDU_RES(cmd_format): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
_Log.Debug("End Format");
}
/// <summary>
/// Authenticate to PICC, with ISO Authenticate
/// </summary>
@ -443,24 +457,24 @@ namespace NFC.Mifare_DESFire
key_id
}
};
_Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", HexConverter.ConvertToHexString(cmd_challange_request.ToArray()));
APDUResponse response = _Card.Transmit(cmd_challange_request);
_Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
byte[] rndB_enc = response.Body;
_Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc));
_Log.DebugFormat("rndB_enc: {0}", HexConverter.ConvertToHexString(rndB_enc));
TDES des = new TDES();
byte[] rndB = des.Decrypt(rndB_enc, key, GenerateEmptyKey(8));
_Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB));
byte[] rndB = des.Decrypt(rndB_enc, key, GenerateEmptyArray(8));
_Log.DebugFormat("rndB: {0}", HexConverter.ConvertToHexString(rndB));
rndB.CopyTo(iv, 0);
byte[] rndB_rl = RotateLeft(rndB);
_Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl));
_Log.DebugFormat("rndB_enc: {0}", HexConverter.ConvertToHexString(rndB_rl));
if(rndA == null)
{
@ -468,13 +482,13 @@ namespace NFC.Mifare_DESFire
rndA = new byte[8];
rnd.NextBytes(rndA);
}
_Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA));
_Log.DebugFormat("rndA: {0}", HexConverter.ConvertToHexString(rndA));
byte[] rndAB = Concatenate(rndA, rndB_rl);
_Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB));
_Log.DebugFormat("rndAB: {0}", HexConverter.ConvertToHexString(rndAB));
byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc);
_Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc));
_Log.DebugFormat("rndA_rndB_enc: {0}", HexConverter.ConvertToHexString(rndAB_enc));
iv = ExtractLastBlock(rndAB_enc, 8);
APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short)
@ -483,21 +497,21 @@ namespace NFC.Mifare_DESFire
INS = 0xAF,
Data = rndAB_enc
};
_Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray()));
response = _Card.Transmit(cmd_challange_response);
_Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray()));
CheckAPDUResponse(response);
byte[] encryptedRndAFromCard = response.Body;
_Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard));
_Log.DebugFormat("encryptedRndAFromCard: {0}", HexConverter.ConvertToHexString(encryptedRndAFromCard));
byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv);
_Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard));
_Log.DebugFormat("rotatedRndAFromCard: {0}", HexConverter.ConvertToHexString(rotatedRndAFromCard));
byte[] rndAFromCard = RotateRight(rotatedRndAFromCard);
_Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard));
_Log.DebugFormat("rndAFromCard: {0}", HexConverter.ConvertToHexString(rndAFromCard));
if (!rndA.SequenceEqual(rndAFromCard))
{
@ -505,36 +519,14 @@ namespace NFC.Mifare_DESFire
}
_SessionKey = GenerateSesionKey_DES(rndA, rndB);
_Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey));
_Log.DebugFormat("_SessionKey: {0}", HexConverter.ConvertToHexString(_SessionKey));
_IV = GenerateEmptyKey(8);
_Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
_IV = GenerateEmptyArray(8);
_Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV));
_Log.Debug("End AuthenticateISO_DES");
}
/// <summary>
/// Format PICC
/// </summary>
public void Format()
{
_Log.Debug("Start Format");
APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short)
{
CLA = 0x90,
INS = 0xFC,
};
_Log.DebugFormat("APDU_CMD(cmd_format): {0}", ConvertToHexString(cmd_format.ToArray()));
APDUResponse response = _Card.Transmit(cmd_format);
_Log.DebugFormat("APDU_RES(cmd_format): {0}", ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
_Log.Debug("End Format");
}
/// <summary>
/// Create Application for ID
/// </summary>
@ -544,7 +536,7 @@ namespace NFC.Mifare_DESFire
_Log.Debug("Start CreateApplication");
byte[] id_byte = BitConverter.GetBytes(aid);
_Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray()));
_Log.DebugFormat("AID: {0}", HexConverter.ConvertToHexString(id_byte.ToArray()));
APDUCommand cmd_CreateApplication = new APDUCommand(IsoCase.Case4Short)
{
@ -559,10 +551,10 @@ namespace NFC.Mifare_DESFire
keysetting2
}
};
_Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", ConvertToHexString(cmd_CreateApplication.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", HexConverter.ConvertToHexString(cmd_CreateApplication.ToArray()));
APDUResponse response = _Card.Transmit(cmd_CreateApplication);
_Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", ConvertToHexString(response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
@ -578,7 +570,7 @@ namespace NFC.Mifare_DESFire
_Log.Debug("Start SelectApplication");
byte[] id_byte = BitConverter.GetBytes(aid);
_Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray()));
_Log.DebugFormat("AID: {0}", HexConverter.ConvertToHexString(id_byte.ToArray()));
APDUCommand cmd_SelectApplication = new APDUCommand(IsoCase.Case4Short)
{
@ -591,10 +583,10 @@ namespace NFC.Mifare_DESFire
id_byte[2]
}
};
_Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", ConvertToHexString(cmd_SelectApplication.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", HexConverter.ConvertToHexString(cmd_SelectApplication.ToArray()));
APDUResponse response = _Card.Transmit(cmd_SelectApplication);
_Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", ConvertToHexString(response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
@ -624,24 +616,24 @@ namespace NFC.Mifare_DESFire
key_id
}
};
_Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", HexConverter.ConvertToHexString(cmd_challange_request.ToArray()));
APDUResponse response = _Card.Transmit(cmd_challange_request);
_Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
byte[] rndB_enc = response.Body;
_Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc));
_Log.DebugFormat("rndB_enc: {0}", HexConverter.ConvertToHexString(rndB_enc));
AES aes = new AES();
byte[] rndB = aes.Decrypt(rndB_enc, key, GenerateEmptyKey(16));
_Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB));
byte[] rndB = aes.Decrypt(rndB_enc, key, GenerateEmptyArray(16));
_Log.DebugFormat("rndB: {0}", HexConverter.ConvertToHexString(rndB));
rndB.CopyTo(iv, 0);
byte[] rndB_rl = RotateLeft(rndB);
_Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl));
_Log.DebugFormat("rndB_enc: {0}", HexConverter.ConvertToHexString(rndB_rl));
if (rndA == null)
{
@ -649,13 +641,13 @@ namespace NFC.Mifare_DESFire
rndA = new byte[16];
rnd.NextBytes(rndA);
}
_Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA));
_Log.DebugFormat("rndA: {0}", HexConverter.ConvertToHexString(rndA));
byte[] rndAB = Concatenate(rndA, rndB_rl);
_Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB));
_Log.DebugFormat("rndAB: {0}", HexConverter.ConvertToHexString(rndAB));
byte[] rndAB_enc = aes.Encrypt(rndAB, key, rndB_enc);
_Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc));
_Log.DebugFormat("rndA_rndB_enc: {0}", HexConverter.ConvertToHexString(rndAB_enc));
iv = ExtractLastBlock(rndAB_enc, 16);
APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short)
@ -664,21 +656,21 @@ namespace NFC.Mifare_DESFire
INS = 0xAF,
Data = rndAB_enc
};
_Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray()));
response = _Card.Transmit(cmd_challange_response);
_Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray()));
CheckAPDUResponse(response);
byte[] encryptedRndAFromCard = response.Body;
_Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard));
_Log.DebugFormat("encryptedRndAFromCard: {0}", HexConverter.ConvertToHexString(encryptedRndAFromCard));
byte[] rotatedRndAFromCard = aes.Decrypt(encryptedRndAFromCard, key, iv);
_Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard));
_Log.DebugFormat("rotatedRndAFromCard: {0}", HexConverter.ConvertToHexString(rotatedRndAFromCard));
byte[] rndAFromCard = RotateRight(rotatedRndAFromCard);
_Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard));
_Log.DebugFormat("rndAFromCard: {0}", HexConverter.ConvertToHexString(rndAFromCard));
if (!rndA.SequenceEqual(rndAFromCard))
{
@ -686,10 +678,10 @@ namespace NFC.Mifare_DESFire
}
_SessionKey = GenerateSesionKey_AES(rndA, rndB);
_Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey));
_Log.DebugFormat("_SessionKey: {0}", HexConverter.ConvertToHexString(_SessionKey));
_IV = GenerateEmptyKey(16);
_Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
_IV = GenerateEmptyArray(16);
_Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV));
_Log.Debug("End AuthenticateISO_DES");
}
@ -708,31 +700,31 @@ namespace NFC.Mifare_DESFire
{
0xC4, key_id
};
_Log.DebugFormat("header: {0}", ConvertToHexString(header));
_Log.DebugFormat("header: {0}", HexConverter.ConvertToHexString(header));
byte[] key_and_version = new_key;
byte[] command = Concatenate(header, key_and_version);
_Log.DebugFormat("command: {0}", ConvertToHexString(command));
_Log.DebugFormat("command: {0}", HexConverter.ConvertToHexString(command));
CRC32 crc32 = new CRC32();
byte[] crc = crc32.Calculate(command);
_Log.DebugFormat("crc: {0}", ConvertToHexString(crc));
_Log.DebugFormat("crc: {0}", HexConverter.ConvertToHexString(crc));
byte[] cryptogram = Concatenate(key_and_version, crc);
_Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram));
_Log.DebugFormat("cryptogram: {0}", HexConverter.ConvertToHexString(cryptogram));
byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16);
_Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
_Log.DebugFormat("cryptogram_block: {0}", HexConverter.ConvertToHexString(cryptogram_block));
TDES des = new TDES();
byte[] cryptogram_enc = des.Encrypt(cryptogram_block, _SessionKey, _IV);
_Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc));
_Log.DebugFormat("cryptogram_enc: {0}", HexConverter.ConvertToHexString(cryptogram_enc));
_IV = ExtractLastBlock(cryptogram_enc, 8);
_Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
_Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV));
byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc);
_Log.DebugFormat("data: {0}", ConvertToHexString(data));
_Log.DebugFormat("data: {0}", HexConverter.ConvertToHexString(data));
APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short)
{
@ -740,10 +732,10 @@ namespace NFC.Mifare_DESFire
INS = 0xC4,
Data = data
};
_Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(cmd_ChangeKey.ToArray()));
APDUResponse response = _Card.Transmit(cmd_ChangeKey);
_Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
@ -764,32 +756,32 @@ namespace NFC.Mifare_DESFire
{
0xC4, key_id
};
_Log.DebugFormat("header: {0}", ConvertToHexString(header));
_Log.DebugFormat("header: {0}", HexConverter.ConvertToHexString(header));
// AES Key Version is Append to Key
byte[] key_and_version = Concatenate(new_key, new byte[] { key_version });
byte[] command = Concatenate(header, key_and_version);
_Log.DebugFormat("command: {0}", ConvertToHexString(command));
_Log.DebugFormat("command: {0}", HexConverter.ConvertToHexString(command));
CRC32 crc32 = new CRC32();
byte[] crc = crc32.Calculate(command);
_Log.DebugFormat("crc: {0}", ConvertToHexString(crc));
_Log.DebugFormat("crc: {0}", HexConverter.ConvertToHexString(crc));
byte[] cryptogram = Concatenate(key_and_version, crc);
_Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram));
_Log.DebugFormat("cryptogram: {0}", HexConverter.ConvertToHexString(cryptogram));
byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16);
_Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
_Log.DebugFormat("cryptogram_block: {0}", HexConverter.ConvertToHexString(cryptogram_block));
AES aes = new AES();
byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV);
_Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc));
_Log.DebugFormat("cryptogram_enc: {0}", HexConverter.ConvertToHexString(cryptogram_enc));
_IV = ExtractLastBlock(cryptogram_enc, 16);
_Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
_Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV));
byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc);
_Log.DebugFormat("data: {0}", ConvertToHexString(data));
_Log.DebugFormat("data: {0}", HexConverter.ConvertToHexString(data));
APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short)
{
@ -797,10 +789,10 @@ namespace NFC.Mifare_DESFire
INS = 0xC4,
Data = data
};
_Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(cmd_ChangeKey.ToArray()));
APDUResponse response = _Card.Transmit(cmd_ChangeKey);
_Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
@ -821,37 +813,37 @@ namespace NFC.Mifare_DESFire
{
0xC4, key_id
};
_Log.DebugFormat("header: {0}", ConvertToHexString(header));
_Log.DebugFormat("header: {0}", HexConverter.ConvertToHexString(header));
byte[] key_xor = XOR(new_key, old_key);
// AES Key Version is Append to Key
byte[] key_and_version = Concatenate(key_xor, new byte[] { key_version });
byte[] command = Concatenate(header, key_and_version);
_Log.DebugFormat("command: {0}", ConvertToHexString(command));
_Log.DebugFormat("command: {0}", HexConverter.ConvertToHexString(command));
CRC32 crc32 = new CRC32();
byte[] crc_cmd = crc32.Calculate(command);
_Log.DebugFormat("crc_cmd: {0}", ConvertToHexString(crc_cmd));
_Log.DebugFormat("crc_cmd: {0}", HexConverter.ConvertToHexString(crc_cmd));
byte[] crc_key = crc32.Calculate(new_key);
_Log.DebugFormat("crc_key: {0}", ConvertToHexString(crc_key));
_Log.DebugFormat("crc_key: {0}", HexConverter.ConvertToHexString(crc_key));
byte[] cryptogram = Concatenate(key_and_version, crc_cmd);
cryptogram = Concatenate(cryptogram, crc_key);
_Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram));
_Log.DebugFormat("cryptogram: {0}", HexConverter.ConvertToHexString(cryptogram));
byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16);
_Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
_Log.DebugFormat("cryptogram_block: {0}", HexConverter.ConvertToHexString(cryptogram_block));
AES aes = new AES();
byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV);
_Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc));
_Log.DebugFormat("cryptogram_enc: {0}", HexConverter.ConvertToHexString(cryptogram_enc));
_IV = ExtractLastBlock(cryptogram_enc, 16);
_Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
_Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV));
byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc);
_Log.DebugFormat("data: {0}", ConvertToHexString(data));
_Log.DebugFormat("data: {0}", HexConverter.ConvertToHexString(data));
APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short)
{
@ -859,10 +851,10 @@ namespace NFC.Mifare_DESFire
INS = 0xC4,
Data = data
};
_Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(cmd_ChangeKey.ToArray()));
APDUResponse response = _Card.Transmit(cmd_ChangeKey);
_Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
@ -904,10 +896,10 @@ namespace NFC.Mifare_DESFire
INS = (byte)APDUInstructions.CREATE_STDDATAFILE,
Data = Concatenate(data, accessRights_byte, size_byte)
};
_Log.DebugFormat("APDU_CMD(cmd_CreateFile_Standard): {0}", ConvertToHexString(cmd_CreateFile_Standard.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_CreateFile_Standard): {0}", HexConverter.ConvertToHexString(cmd_CreateFile_Standard.ToArray()));
APDUResponse response = _Card.Transmit(cmd_CreateFile_Standard);
_Log.DebugFormat("APDU_RES(cmd_CreateFile_Standard): {0}", ConvertToHexString(response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_CreateFile_Standard): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
@ -924,7 +916,7 @@ namespace NFC.Mifare_DESFire
{
_Log.Debug("Start ReadData");
int max_read_bytes_pre_transaction = 58;
int max_read_bytes_pre_transaction = 47;
long bytes_readed = 0;
List<byte> read_data = new List<byte>();
@ -973,10 +965,10 @@ namespace NFC.Mifare_DESFire
INS = (byte)APDUInstructions.READ_DATA,
Data = Concatenate(data, offset_byte, length_byte)
};
_Log.DebugFormat("APDU_CMD(cmd_ReadData): {0}", ConvertToHexString(cmd_ReadData.ToArray()));
_Log.DebugFormat("APDU_CMD(cmd_ReadData): {0}", HexConverter.ConvertToHexString(cmd_ReadData.ToArray()));
APDUResponse response = _Card.Transmit(cmd_ReadData);
_Log.DebugFormat("APDU_RES(cmd_ReadData): {0}", ConvertToHexString(response.ToArray()));
_Log.DebugFormat("APDU_RES(cmd_ReadData): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
read_data.AddRange(response.Body);
@ -996,119 +988,69 @@ namespace NFC.Mifare_DESFire
{
_Log.Debug("Start WriteData");
byte[] file_id_array = new byte[]
{
file_id
};
int max_write_bytes_pre_transaction = 47;
byte[] write_buffer;
byte[] offset_byte_tolong = BitConverter.GetBytes(offset);
// Use only 3 Bytes
byte[] offset_byte = new byte[]
long bytes_writed = 0;
long length = data.Length;
while (bytes_writed != data.Length)
{
byte[] file_id_array = new byte[]
{
file_id
};
byte[] offset_byte_tolong = BitConverter.GetBytes(offset + bytes_writed);
// Use only 3 Bytes
byte[] offset_byte = new byte[]
{
offset_byte_tolong[0],
offset_byte_tolong[1],
offset_byte_tolong[2],
};
};
byte[] lenght_byte_tolong = BitConverter.GetBytes(data.Length);
// Use only 3 Bytes
byte[] lenght_byte = new byte[]
{
lenght_byte_tolong[0],
lenght_byte_tolong[1],
lenght_byte_tolong[2],
};
long bytes_towrite = 0;
APDUCommand cmd_WriteData = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = (byte)APDUInstructions.WRITE_DATA,
Data = Concatenate(file_id_array, offset_byte, lenght_byte, data)
};
_Log.DebugFormat("APDU_CMD(cmd_WriteData): {0}", ConvertToHexString(cmd_WriteData.ToArray()));
if (length - bytes_writed < max_write_bytes_pre_transaction)
{
bytes_towrite = length - bytes_writed;
}
else
{
bytes_towrite = max_write_bytes_pre_transaction;
}
APDUResponse response = _Card.Transmit(cmd_WriteData);
_Log.DebugFormat("APDU_RES(cmd_WriteData): {0}", ConvertToHexString(response.ToArray()));
byte[] length_byte_tolong = BitConverter.GetBytes(bytes_towrite);
CheckAPDUResponse(response);
write_buffer = GetSubArray(data, bytes_writed, bytes_towrite);
bytes_writed += bytes_towrite;
// Use only 3 Bytes
byte[] length_byte = new byte[]
{
length_byte_tolong[0],
length_byte_tolong[1],
length_byte_tolong[2],
};
APDUCommand cmd_WriteData = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = (byte)APDUInstructions.WRITE_DATA,
Data = Concatenate(file_id_array, offset_byte, length_byte, write_buffer)
};
_Log.DebugFormat("APDU_CMD(cmd_WriteData): {0}", HexConverter.ConvertToHexString(cmd_WriteData.ToArray()));
APDUResponse response = _Card.Transmit(cmd_WriteData);
_Log.DebugFormat("APDU_RES(cmd_WriteData): {0}", HexConverter.ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
}
_Log.Debug("End WriteData");
}
///// <summary>
///// Write Data to File
///// </summary>
///// <param name="file_id">ID of File (0x01 - 0x10)</param>
///// <param name="offset">Offset for File</param>
///// <param name="data">Data to write</param>
//public void WriteData(byte file_id, UInt32 offset, byte[] data)
//{
// _Log.Debug("Start WriteData");
// int max_write_bytes_pre_transaction = 8;
// byte[] write_buffer;
// long bytes_writed = 0;
// long length = data.Length;
// while (bytes_writed != data.Length)
// {
// byte[] file_id_array = new byte[]
// {
// file_id
// };
// byte[] offset_byte_tolong = BitConverter.GetBytes(offset + bytes_writed);
// // Use only 3 Bytes
// byte[] offset_byte = new byte[]
// {
// offset_byte_tolong[0],
// offset_byte_tolong[1],
// offset_byte_tolong[2],
// };
// long bytes_towrite = 0;
// if (length - bytes_writed < max_write_bytes_pre_transaction)
// {
// bytes_towrite = length - bytes_writed;
// }
// else
// {
// bytes_towrite = max_write_bytes_pre_transaction;
// }
// byte[] length_byte_tolong = BitConverter.GetBytes(bytes_towrite);
// write_buffer = GetSubArray(data, bytes_writed, bytes_towrite);
// bytes_writed += bytes_towrite;
// // Use only 3 Bytes
// byte[] length_byte = new byte[]
// {
// length_byte_tolong[0],
// length_byte_tolong[1],
// length_byte_tolong[2],
// };
// APDUCommand cmd_WriteData = new APDUCommand(IsoCase.Case4Short)
// {
// CLA = 0x90,
// INS = (byte)APDUInstructions.WRITE_DATA,
// Data = Concatenate(file_id_array, offset_byte, length_byte, write_buffer)
// };
// _Log.DebugFormat("APDU_CMD(cmd_WriteData): {0}", ConvertToHexString(cmd_WriteData.ToArray()));
// APDUResponse response = _Card.Transmit(cmd_WriteData);
// _Log.DebugFormat("APDU_RES(cmd_WriteData): {0}", ConvertToHexString(response.ToArray()));
// CheckAPDUResponse(response);
// }
// _Log.Debug("End WriteData");
//}
/// <summary>
/// Get all ApplicationIDS from PICC
/// </summary>
@ -1176,63 +1118,6 @@ namespace NFC.Mifare_DESFire
// CheckAPDUResponse(response);
//}
#endregion
#region Configuration Generator
/// <summary>
/// Genearte KeySetting1 for Application Settings or PICC Setting
/// </summary>
public byte GenerateKeySetting1(ChangeApplicationKey changeKey, ChangeMasterKeySettings changeMasterKeySettings, CreateDeleteFile createDeleteFile, FileDirectoryAccess fileDirectoryAccess, ChangeMasterKey changeMasterKey)
{
return (byte)(((byte)changeKey << 4) | (byte)changeMasterKeySettings | (byte)createDeleteFile | (byte)fileDirectoryAccess | (byte)changeMasterKey);
}
/// <summary>
/// Genearte KeySetting1 for Application Settings or PICC Setting
/// </summary>
/// <param name="changeKey">ID of Key for changing Application Keys</param>
/// <returns></returns>
public byte GenerateKeySetting1(byte changeKey, ChangeMasterKeySettings changeMasterKeySettings, CreateDeleteFile createDeleteFile, FileDirectoryAccess fileDirectoryAccess, ChangeMasterKey changeMasterKey)
{
if (changeKey < 0x01 || changeKey >= 0x0E)
{
throw new ArgumentOutOfRangeException();
}
return GenerateKeySetting1(changeKey, changeMasterKeySettings, createDeleteFile, fileDirectoryAccess, changeMasterKey);
}
/// <summary>
/// Genearte KeySetting2 for Application Creation
/// </summary>
/// <param name="numberOfKeys">Number of keys that can be stored within the application (0x01-0x0D)</param>
/// <returns></returns>
public byte GenerateKeySetting2(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys)
{
if (numberOfKeys < 0x01 || numberOfKeys >= 0x0D)
{
throw new ArgumentOutOfRangeException();
}
return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys);
}
/// <summary>
/// Generate FileAccess Rights for File Settings
/// Use enum AccesRights for Free or Never Option
/// </summary>
/// <param name="read">KeyID for Read Access</param>
/// <param name="write">KeyID for Write Access</param>
/// <param name="read_write">KeyID for Read and Write Access</param>
/// <param name="configure">KeyID for Configuration Access</param>
public UInt16 GenerateFileAccessRights(byte read, byte write, byte read_write, byte configure)
{
if(read > 0x0F || write > 0x0F || read_write > 0x0F || configure > 0x0F)
{
throw new ArgumentOutOfRangeException("One KeyID is not valid");
}
return (UInt16)((read << 12) | (write << 8) | (read_write << 4) | configure);
}
#endregion
#endregion
}
}

View File

@ -2,7 +2,7 @@
namespace NFC.Readers.PCSC
{
public class Hardware : IHardware
public class PCSC_Hardware : IHardware
{
public string[] GetReaders()
{
@ -27,7 +27,7 @@ namespace NFC.Readers.PCSC
public IReader OpenReader(string readerID)
{
return new Reader(readerID);
return new PCSC_Reader(readerID);
}
}
}

View File

@ -1,13 +1,11 @@
using PCSC;
using PCSC.Iso7816;
using System;
using System.Collections.Generic;
using System.Text;
namespace NFC.Readers.PCSC
{
public class Reader : IReader, IDisposable
public class PCSC_Reader : IReader, IDisposable
{
private string _ReaderID;
private IContextFactory _ContextFactory;
@ -15,7 +13,7 @@ namespace NFC.Readers.PCSC
private IsoReader _ISOReader;
private ICard _Card;
public Reader(string readerID)
public PCSC_Reader(string readerID)
{
_ReaderID = readerID;
}