diff --git a/Borepin/Borepin.iOS/CNFC/Reader.cs b/Borepin/Borepin.iOS/CNFC/Reader.cs
index 2623290..992eb5e 100644
--- a/Borepin/Borepin.iOS/CNFC/Reader.cs
+++ b/Borepin/Borepin.iOS/CNFC/Reader.cs
@@ -62,6 +62,5 @@ namespace Borepin.iOS.CNFC
// TODO: decide what to do
Console.WriteLine("reader session invalidated");
}
-
}
}
diff --git a/NFC/Crypto/CRC16.cs b/NFC/Crypto/CRC/CRC16.cs
similarity index 59%
rename from NFC/Crypto/CRC16.cs
rename to NFC/Crypto/CRC/CRC16.cs
index 25f2a22..1530396 100644
--- a/NFC/Crypto/CRC16.cs
+++ b/NFC/Crypto/CRC/CRC16.cs
@@ -2,26 +2,14 @@
namespace NFC.Crypto
{
+ ///
+ /// CRC16 for DESFire Card
+ ///
public class CRC16
{
- public byte[] Calculate(byte[] data)
- {
- UInt16 crc16 = 0x6363;
+ public UInt16 Polynomial { get; } = 0x8408;
- crc16 = Calculate(data, crc16);
-
- return BitConverter.GetBytes(crc16);
- }
-
- public byte[] Calculate(byte[] cmd, byte[] data)
- {
- UInt16 crc16 = 0x6363;
-
- crc16 = Calculate(cmd, crc16);
- crc16 = Calculate(data, crc16);
-
- return BitConverter.GetBytes(crc16);
- }
+ public UInt16 InitValue { get; } = 0x6363;
public UInt16 Calculate(byte[] data, UInt16 crc16)
{
@@ -34,11 +22,23 @@ namespace NFC.Crypto
crc16 >>= 1;
if (b_Bit)
{
- crc16 ^= 0x8408;
+ crc16 ^= Polynomial;
}
}
}
return crc16;
}
+
+ public byte[] Calculate(params byte[][] data)
+ {
+ UInt16 crc16 = InitValue;
+
+ foreach(byte[] d in data)
+ {
+ crc16 = Calculate(d, crc16);
+ }
+
+ return BitConverter.GetBytes(crc16);
+ }
}
}
diff --git a/NFC/Crypto/CRC32.cs b/NFC/Crypto/CRC/CRC32.cs
similarity index 57%
rename from NFC/Crypto/CRC32.cs
rename to NFC/Crypto/CRC/CRC32.cs
index e3e6f1d..1d1c45a 100644
--- a/NFC/Crypto/CRC32.cs
+++ b/NFC/Crypto/CRC/CRC32.cs
@@ -1,28 +1,15 @@
using System;
-using System.Linq;
namespace NFC.Crypto
{
+ ///
+ /// CRC32 for DESFire Card
+ ///
public class CRC32
{
- public byte[] Calculate(byte[] data)
- {
- UInt32 crc32 = 0xFFFFFFFF;
+ public UInt32 Polynomial { get; } = 0xEDB88320;
- crc32 = Calculate(data, crc32);
-
- return BitConverter.GetBytes(crc32);
- }
-
- public byte[] Calculate(byte[] cmd, byte[] data)
- {
- UInt32 crc32 = 0xFFFFFFFF;
-
- crc32 = Calculate(cmd, crc32);
- crc32 = Calculate(data, crc32);
-
- return BitConverter.GetBytes(crc32);
- }
+ public UInt32 InitValue { get; } = 0xFFFFFFFF;
public UInt32 Calculate(byte[] data, UInt32 crc32)
{
@@ -35,11 +22,23 @@ namespace NFC.Crypto
crc32 >>= 1;
if (b_Bit)
{
- crc32 ^= 0xEDB88320;
+ crc32 ^= Polynomial;
}
}
}
return crc32;
}
+
+ public byte[] Calculate(params byte[][] data)
+ {
+ UInt32 crc32 = InitValue;
+
+ foreach(byte[] d in data)
+ {
+ crc32 = Calculate(d, crc32);
+ }
+
+ return BitConverter.GetBytes(crc32);
+ }
}
}
diff --git a/NFC/Crypto/AES.cs b/NFC/Crypto/Cipher/AES.cs
similarity index 93%
rename from NFC/Crypto/AES.cs
rename to NFC/Crypto/Cipher/AES.cs
index 4c5be9a..83a7676 100644
--- a/NFC/Crypto/AES.cs
+++ b/NFC/Crypto/Cipher/AES.cs
@@ -1,13 +1,16 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
-using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
namespace NFC.Crypto
{
- public class AES
+ public class AES : ICipher
{
+ public uint BlockSize { get; } = 16;
+
+ public uint KeySize { get; } = 16;
+
public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
AesEngine engine = new AesEngine();
diff --git a/NFC/Crypto/Cipher/TDES.cs b/NFC/Crypto/Cipher/TDES.cs
new file mode 100644
index 0000000..59e591e
--- /dev/null
+++ b/NFC/Crypto/Cipher/TDES.cs
@@ -0,0 +1,49 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Engines;
+using Org.BouncyCastle.Crypto.Modes;
+using Org.BouncyCastle.Crypto.Parameters;
+
+namespace NFC.Crypto
+{
+ public class TDES : ICipher
+ {
+ public uint BlockSize { get; } = 8;
+
+ // Two times the DES Key
+ public uint KeySize { get; } = 16;
+
+ public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
+ {
+ DesEngine engine = new DesEdeEngine();
+ CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
+ BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
+ KeyParameter keyParam = new KeyParameter(key);
+ ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv);
+
+ // Encrypt
+ cipher.Init(true, keyParamWithIV);
+ byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)];
+ int length = cipher.ProcessBytes(data, outputBytes, 0);
+ cipher.DoFinal(outputBytes, length);
+
+ return outputBytes;
+ }
+
+ public byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
+ {
+ DesEngine engine = new DesEdeEngine();
+ CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
+ BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
+ KeyParameter keyParam = new KeyParameter(key);
+ ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv);
+
+ // Decrypt
+ cipher.Init(false, keyParamWithIV);
+ byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)];
+ int length = cipher.ProcessBytes(data, outputBytes, 0);
+ cipher.DoFinal(outputBytes, length);
+
+ return outputBytes;
+ }
+ }
+}
diff --git a/NFC/Crypto/TripleDES.cs b/NFC/Crypto/Cipher/TDES_2K.cs
similarity index 92%
rename from NFC/Crypto/TripleDES.cs
rename to NFC/Crypto/Cipher/TDES_2K.cs
index bf4c4fe..142f6cc 100644
--- a/NFC/Crypto/TripleDES.cs
+++ b/NFC/Crypto/Cipher/TDES_2K.cs
@@ -1,13 +1,16 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
-using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
namespace NFC.Crypto
{
- public class TripleDES
+ public class TDES_2K : ICipher
{
+ public uint BlockSize { get; } = 8;
+
+ public uint KeySize { get; } = 16;
+
public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
DesEngine engine = new DesEdeEngine();
diff --git a/NFC/Crypto/DES.cs b/NFC/Crypto/Cipher/TDES_3K.cs
similarity index 87%
rename from NFC/Crypto/DES.cs
rename to NFC/Crypto/Cipher/TDES_3K.cs
index db9356a..87a3bf5 100644
--- a/NFC/Crypto/DES.cs
+++ b/NFC/Crypto/Cipher/TDES_3K.cs
@@ -1,16 +1,19 @@
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
-using Org.BouncyCastle.Crypto.Paddings;
using Org.BouncyCastle.Crypto.Parameters;
namespace NFC.Crypto
{
- public class DES
+ public class TDES_3K : ICipher
{
+ public uint BlockSize { get; } = 8;
+
+ public uint KeySize { get; } = 24;
+
public byte[] Encrypt(byte[] data, byte[] key, byte[] iv)
{
- DesEngine engine = new DesEngine();
+ DesEngine engine = new DesEdeEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
KeyParameter keyParam = new KeyParameter(key);
@@ -27,7 +30,7 @@ namespace NFC.Crypto
public byte[] Decrypt(byte[] data, byte[] key, byte[] iv)
{
- DesEngine engine = new DesEngine();
+ DesEngine engine = new DesEdeEngine();
CbcBlockCipher blockCipher = new CbcBlockCipher(engine);
BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher);
KeyParameter keyParam = new KeyParameter(key);
diff --git a/NFC/Crypto/CipherKey.cs b/NFC/Crypto/CipherKey.cs
new file mode 100644
index 0000000..519ab2a
--- /dev/null
+++ b/NFC/Crypto/CipherKey.cs
@@ -0,0 +1,171 @@
+using System;
+
+namespace NFC.Crypto
+{
+ ///
+ /// Key for DESFire Card
+ ///
+ public class CipherKey
+ {
+ #region Constructors
+ ///
+ /// Creates Key from Array
+ ///
+ /// Key
+ /// Cipher for Key
+ /// Version of Key
+ public CipherKey(byte[] key, CipherType cipher, byte keyVersion)
+ {
+ _Cipher = cipher;
+
+ if (cipher == CipherType.AES && keyVersion < 0x10)
+ {
+ throw new ArgumentOutOfRangeException("KeyVersion is to low for AES Key (Minimum = 0x10)");
+ }
+ _KeyVersion = keyVersion;
+
+ if (!CheckKey(key, cipher))
+ {
+ throw new ArgumentException("Key is not vaild for CipherType");
+ }
+
+ if (cipher == CipherType.TDES || cipher == CipherType.TDES_2K || cipher == CipherType.TDES_3K)
+ {
+ _Key = SetKeyVersion(key, keyVersion);
+ }
+ else
+ {
+ _Key = key;
+ }
+ }
+
+ ///
+ /// Generates Empty Key
+ ///
+ /// Cipher for Key
+ ///
+ public CipherKey(CipherType cipher)
+ {
+ _Cipher = cipher;
+ _Key = GenerateEmptyKey(cipher);
+
+ if (cipher == CipherType.AES)
+ {
+ _KeyVersion = 0x10;
+ }
+ else
+ {
+ _KeyVersion = 0x00;
+ }
+ }
+ #endregion
+
+ #region Properties
+ ///
+ /// Key as Array
+ ///
+ public byte[] _Key { get; private set; }
+
+ ///
+ /// CipherType of Key
+ ///
+ public CipherType _Cipher { get; private set; }
+
+ ///
+ /// KeyVersion of Key
+ /// For AES 0x10 is minimum
+ ///
+ public byte _KeyVersion { get; private set; }
+ #endregion
+
+ #region Methods
+ ///
+ /// Generate Empty Key for CipherType
+ ///
+ /// Type of Cipher
+ public byte[] GenerateEmptyKey(CipherType cipher)
+ {
+ uint size = GetKeySize(cipher);
+
+ byte[] key = new byte[size];
+ for (int i = 0; i < size; i++)
+ {
+ key[i] = 0;
+ }
+
+ return key;
+ }
+
+ ///
+ /// Check Key Array
+ ///
+ /// Key
+ /// Cipher Type of Key
+ public bool CheckKey(byte[] key, CipherType cipher)
+ {
+ if (key.Length != GetKeySize(cipher))
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ ///
+ /// Get KeySize for CipherType
+ ///
+ /// Type of Cipher
+ public uint GetKeySize(CipherType cipher)
+ {
+ switch (cipher)
+ {
+ case CipherType.TDES:
+ return 8;
+ case CipherType.TDES_2K:
+ return 16;
+ case CipherType.TDES_3K:
+ return 24;
+ case CipherType.AES:
+ return 16;
+ default:
+ throw new ArgumentOutOfRangeException("Unknown CipherType.");
+ }
+ }
+
+ ///
+ /// Set Key Version for DES/TDES Keys
+ /// KeyVersion is stored in the LSBits of the first 8 Bytes
+ /// Parity Bits are not used from DESFire Cars
+ ///
+ ///
+ ///
+ ///
+ public byte[] SetKeyVersion(byte[] key, byte version)
+ {
+ 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 ((version & pow2[i]) > 0)
+ {
+ new_key[i] = (byte)(new_key[5] | 0x01);
+ }
+ else
+ {
+ new_key[i] = (byte)(new_key[5] & 0x7F);
+ }
+ }
+
+ return new_key;
+ }
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/NFC/Crypto/CipherType.cs b/NFC/Crypto/CipherType.cs
new file mode 100644
index 0000000..c0b7dfa
--- /dev/null
+++ b/NFC/Crypto/CipherType.cs
@@ -0,0 +1,25 @@
+namespace NFC.Crypto
+{
+ public enum CipherType
+ {
+ ///
+ /// DES / Triple DES
+ ///
+ TDES,
+
+ ///
+ /// Triple DES with 2 DES Keys
+ ///
+ TDES_2K,
+
+ ///
+ /// Triple DES with 3 DES Keys
+ ///
+ TDES_3K,
+
+ ///
+ /// AES
+ ///
+ AES
+ }
+}
diff --git a/NFC/Crypto/ICipher.cs b/NFC/Crypto/ICipher.cs
new file mode 100644
index 0000000..84583a4
--- /dev/null
+++ b/NFC/Crypto/ICipher.cs
@@ -0,0 +1,32 @@
+namespace NFC.Crypto
+{
+ public interface ICipher
+ {
+ ///
+ /// Size of Cipher Block in Byte
+ ///
+ public uint BlockSize { get; }
+
+ ///
+ /// Size of Key in Byte
+ ///
+ public uint KeySize { get; }
+
+ ///
+ /// Encrypt Data
+ ///
+ /// Data in BlockSize
+ /// Key
+ /// Initialisation Vector
+ ///
+ public byte[] Encrypt(byte[] data, byte[] key, byte[] IV);
+
+ ///
+ /// Decrypt Data
+ ///
+ /// Data in BlockSize
+ /// Key
+ /// Initialisation Vector
+ public byte[] Decrypt(byte[] data, byte[] key, byte[] IV);
+ }
+}
diff --git a/NFC/HexConverter.cs b/NFC/HexConverter.cs
new file mode 100644
index 0000000..b6e07a7
--- /dev/null
+++ b/NFC/HexConverter.cs
@@ -0,0 +1,51 @@
+using System;
+
+namespace NFC
+{
+ ///
+ /// Converts to and from Byte Array from and to String
+ ///
+ public static class HexConverter
+ {
+ ///
+ /// Converts byte[] to string with HEX Code
+ /// No 0x is created
+ ///
+ /// Data
+ public static string ConvertToHexString(byte[] data)
+ {
+ return BitConverter.ToString(data).Replace("-", "").ToLower();
+ }
+
+ ///
+ /// Converts string with HEX Code to byte[]
+ /// No 0x is requiered
+ ///
+ /// Data
+ public static 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;
+ }
+
+ private static 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));
+ }
+ }
+}
diff --git a/NFC/ISO7816-4/APDUCommand.cs b/NFC/ISO7816-4/APDUCommand.cs
index bf60034..ef6a5e3 100644
--- a/NFC/ISO7816-4/APDUCommand.cs
+++ b/NFC/ISO7816-4/APDUCommand.cs
@@ -1,7 +1,7 @@
using PCSC;
using PCSC.Iso7816;
using System;
-using System.Collections.Generic;
+using System.Linq;
namespace NFC.ISO7816_4
{
@@ -13,7 +13,7 @@ namespace NFC.ISO7816_4
}
public override bool Equals(object obj)
- {
+ {
return obj is APDUCommand command &&
Case == command.Case &&
Protocol == command.Protocol &&
@@ -21,7 +21,8 @@ namespace NFC.ISO7816_4
INS == command.INS &&
P1 == command.P1 &&
P2 == command.P2 &&
- EqualityComparer.Default.Equals(Data, command.Data);
+ Data.SequenceEqual(command.Data) &&
+ Le == command.Le;
}
public override int GetHashCode()
@@ -43,5 +44,40 @@ namespace NFC.ISO7816_4
hash.Add(IsValid);
return hash.ToHashCode();
}
+
+ public static bool operator ==(APDUCommand obj1, APDUCommand obj2)
+ {
+ return obj1.Equals(obj2);
+ }
+
+ public static bool operator !=(APDUCommand obj1, APDUCommand obj2)
+ {
+ return !(obj1.Equals(obj2));
+ }
+
+ public override string ToString()
+ {
+ string pattern_case1 = "(CASE: 1) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x}";
+ string pattern_case2 = "(CASE: 2) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x} | LE: 0x{4:x} |";
+ string pattern_case3 = "(CASE: 3) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x} | LC: 0x{4:x} | Data: {5:x}";
+ string pattern_case4 = "(CASE: 4) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x} | LC: 0x{4:x} | Data: {5:x} | LE: 0x{6:x} |";
+
+ switch (Case)
+ {
+ case IsoCase.Case1:
+ return string.Format(pattern_case1, CLA, INS, P1, P2);
+ case IsoCase.Case2Short:
+ case IsoCase.Case2Extended:
+ return string.Format(pattern_case2, CLA, INS, P1, P2, Le);
+ case IsoCase.Case3Short:
+ case IsoCase.Case3Extended:
+ return string.Format(pattern_case3, CLA, INS, P1, P2, Lc, BitConverter.ToString(Data).Replace("-", " "));
+ case IsoCase.Case4Short:
+ case IsoCase.Case4Extended:
+ return string.Format(pattern_case4, CLA, INS, P1, P2, Lc, BitConverter.ToString(Data).Replace("-", " "), Le);
+ default:
+ throw new Exception("Unknown IsoCase");
+ }
+ }
}
}
diff --git a/NFC/NXP MIFARE DESFire/APDUInstructions.cs b/NFC/NXP MIFARE DESFire/APDUInstructions.cs
index dd3025c..934c08d 100644
--- a/NFC/NXP MIFARE DESFire/APDUInstructions.cs
+++ b/NFC/NXP MIFARE DESFire/APDUInstructions.cs
@@ -28,7 +28,7 @@
CREATE_CYCLIC_RECORD_FILE = 0xC0,
DELETE_FILE = 0xDF,
GET_ISO_FILE_IDS = 0x61,
- READ_DATA = 0x8D,
+ READ_DATA = 0xBD,
WRITE_DATA = 0x3D,
GET_VALUE = 0x6C,
CREDIT = 0x0C,
diff --git a/NFC/NXP MIFARE DESFire/CMAC.cs b/NFC/NXP MIFARE DESFire/CMAC.cs
new file mode 100644
index 0000000..532aa23
--- /dev/null
+++ b/NFC/NXP MIFARE DESFire/CMAC.cs
@@ -0,0 +1,106 @@
+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
+ ///
+ /// Generate Key with all Zeros, in KeySize
+ ///
+ public byte[] GenerateEmpytKey()
+ {
+ byte[] key = new byte[_Cipher.KeySize];
+ for (int i = 0; i < _Cipher.KeySize; i++)
+ {
+ key[i] = 0;
+ }
+
+ return key;
+ }
+
+ ///
+ /// Generate IV with all Zeros, in KeySize
+ ///
+ public byte[] GenerateEmpytIV()
+ {
+ byte[] key = new byte[_Cipher.BlockSize];
+ for (int i = 0; i < _Cipher.BlockSize; i++)
+ {
+ key[i] = 0;
+ }
+
+ return key;
+ }
+
+ ///
+ /// Encrypt Data
+ ///
+ public byte[] Encrypt(byte[] data)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ /// Decrypt Data
+ ///
+ public byte[] Decrypt(byte[] data)
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ ///
+ ///
+ /// Two Keys
+ public byte[][] GenerateSubKey()
+ {
+ throw new NotImplementedException();
+ }
+
+ ///
+ ///
+ ///
+ ///
+ ///
+ public byte[] Digest(byte[] data)
+ {
+ throw new NotImplementedException();
+ }
+
+ #endregion
+ }
+}
diff --git a/NFC/NXP MIFARE DESFire/Enums/AccessRights.cs b/NFC/NXP MIFARE DESFire/Enums/FileAccessRights.cs
similarity index 70%
rename from NFC/NXP MIFARE DESFire/Enums/AccessRights.cs
rename to NFC/NXP MIFARE DESFire/Enums/FileAccessRights.cs
index 0c91aa1..fd91f3a 100644
--- a/NFC/NXP MIFARE DESFire/Enums/AccessRights.cs
+++ b/NFC/NXP MIFARE DESFire/Enums/FileAccessRights.cs
@@ -1,6 +1,6 @@
namespace NFC.Mifare_DESFire.Enums
{
- public enum AccessRights : byte
+ public enum FileAccessRights : byte
{
FREE = 0x0E,
NEVER = 0x0F
diff --git a/NFC/NXP MIFARE DESFire/FileTypes.cs b/NFC/NXP MIFARE DESFire/Enums/FileTypes.cs
similarity index 93%
rename from NFC/NXP MIFARE DESFire/FileTypes.cs
rename to NFC/NXP MIFARE DESFire/Enums/FileTypes.cs
index 9c1fb13..0a18ea3 100644
--- a/NFC/NXP MIFARE DESFire/FileTypes.cs
+++ b/NFC/NXP MIFARE DESFire/Enums/FileTypes.cs
@@ -1,4 +1,4 @@
-namespace NFC.Mifare_DESFire
+namespace NFC.Mifare_DESFire.Enums
{
enum FileTypes : byte
{
diff --git a/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationMissingException.cs b/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationMissingException.cs
new file mode 100644
index 0000000..04c19cd
--- /dev/null
+++ b/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationMissingException.cs
@@ -0,0 +1,26 @@
+using System;
+
+namespace NFC.NXP_MIFARE_DESFire.Exceptions
+{
+ ///
+ /// Current authentication status does not allow there- quested command.
+ /// 0x91AE
+ ///
+ public class AuthenticationMissingException : Exception
+ {
+ public AuthenticationMissingException()
+ {
+
+ }
+
+ public AuthenticationMissingException(string message) : base(message)
+ {
+
+ }
+
+ public AuthenticationMissingException(string message, Exception inner) : base(message, inner)
+ {
+
+ }
+ }
+}
diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs
index 2c3840e..149d04e 100644
--- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs
+++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs
@@ -1,6 +1,8 @@
-using NFC.Crypto;
+using log4net.Repository.Hierarchy;
+using NFC.Crypto;
using NFC.ISO7816_4;
using NFC.Mifare_DESFire.Enums;
+using NFC.NXP_MIFARE_DESFire.Exceptions;
using PCSC.Iso7816;
using System;
using System.Collections.Generic;
@@ -12,6 +14,10 @@ namespace NFC.Mifare_DESFire
{
// Docs https://hackmd.io/qATu8uYdRnOC40aFrB9afg
+ #region Log
+ private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
+ #endregion
+
#region Contructors
///
/// Construct MIFRARE_DESFire Object with ICard Interface
@@ -29,16 +35,25 @@ namespace NFC.Mifare_DESFire
///
private ICard _Card;
+ ///
+ /// SessionKey, is set after Successfull Authentication
+ ///
public byte[] _SessionKey;
+
+ ///
+ /// Initialation Vector for CBC Encryption
+ /// Is 0 bytes after Successfull Authentication
+ ///
public byte[] _IV;
#endregion
#region Methods
+ #region Helper Methods
///
/// Generate Byte Array filled with 0
///
/// Size of Array
- public byte[] GenerateDefaultKey(uint size)
+ public byte[] GenerateEmptyKey(uint size)
{
byte[] key = new byte[size];
for (int i = 0; i < size; i++)
@@ -56,93 +71,121 @@ namespace NFC.Mifare_DESFire
/// Data
public string ConvertToHexString(byte[] data)
{
- return BitConverter.ToString(data).Replace("-", " ");
+ return BitConverter.ToString(data).Replace("-", "").ToLower();
}
+ ///
+ /// Converts string with HEX Code to byte[]
+ /// No 0x is requiered
+ ///
+ /// Data
+ 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;
+ }
+
+ 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));
+ }
+
+ ///
+ /// Check APDU Response for DESFire Error Codes
+ /// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf
+ /// Section: 11.3
+ ///
public void CheckAPDUResponse(APDUResponse response)
{
-
- }
-
- public bool CheckKey(byte[] key)
- {
- try
+ if (response == null)
{
- GetKeyTypeDES(key);
- return true;
+ throw new ArgumentNullException("Response cannot be null.");
}
- catch
+
+ if (response.SW1 == 0x91)
{
- return false;
+ switch (response.SW2)
+ {
+ case 0x00: // OPERATION_OK
+ return;
+ case 0x0C: // NO_CHANGES
+ return;
+ case 0x1C: // ILLEGAL_COMMAND_CODE
+ throw new IllegalCommandCodeException();
+ case 0x1E: // INTEGRITY_ERROR
+ throw new IntegrityErrorException();
+ case 0x40: // NO_SUCH_KEY
+ throw new NoSuchKeyException();
+ case 0x7E: // LENGTH_ERROR
+ throw new LengthErrorException();
+ case 0x9D: // PERMISSION_DENIED
+ throw new PermissionDeniedException();
+ case 0x9E: // PARAMETER_ERROR
+ throw new ParameterErrorException();
+ case 0xAD: // AUTHENTICATION_DELAY
+ throw new AuthenticationDelayException();
+ case 0xAE: // AUTHENTICATION_ERROR
+ throw new AuthenticationErrorException();
+ case 0xAF: // ADDITIONAL_FRAME
+ return;
+ case 0xBE: // BOUNDARY_ERROR
+ throw new BoundaryErrorException();
+ case 0xCA: // COMMAND_ABORTED
+ throw new CommandAbortedException();
+ case 0xDE: // DUPLICATE_ERROR
+ throw new DuplicateErrorException();
+ case 0xF0: // FILE_NOT_FOUND
+ throw new FileNotFoundException();
+ default:
+ break;
+ }
}
+
+ throw new Exception(string.Format("Unknown Response Code: 0x{0}.", BitConverter.ToString(new byte[] { response.SW1, response.SW2 }).Replace("-", string.Empty)));
}
+ #endregion
- ///
- /// Key Types used for DESFire Cards
- ///
- public enum KeyType
- {
- ///
- /// DES Key - 8 Byte - 64 Bit
- ///
- DES,
-
- ///
- /// Triple DES Key with two DES Keys - 16 Byte - 128 Bit
- ///
- TDES_2K,
-
- ///
- /// Triple DES Key with three DES Keys - 24 Byte - 192 Bit
- ///
- TDES_3K,
-
- ///
- /// AES Key - 16 Byte - 128 Bit
- ///
- AES
- }
-
- ///
- /// Check the Key Length to get Type of DES/3DES Key
- ///
- public KeyType GetKeyTypeDES(byte[] key)
- {
- switch(key.Length)
- {
- case 8:
- return KeyType.DES;
- case 16:
- return KeyType.TDES_2K;
- case 24:
- return KeyType.TDES_3K;
- default:
- throw new ArgumentException(string.Format("No valid DES/3DES Key Size({0})", key.Length));
- }
- }
-
- #region Methods for Crypto Operation
+ #region Crypto Operation
///
/// Return a copy of the last Block of data
///
/// Data compatible to blocksize
- /// Size of Block, default is 8
- public byte[] GetLastBlock(byte[] data, uint blocksize = 8)
+ /// in byte
+ public byte[] ExtractLastBlock(byte[] data, uint blocksize)
{
- if(data.Length % blocksize != 0)
+ if (data == null)
{
- throw new ArgumentException(string.Format("Data is not compatible with blocksize(data(length):{0}, blocksize:{1}", data.Length, blocksize));
+ throw new ArgumentNullException("Data cannot be null.");
}
- byte[] block = new byte[blocksize];
+ if (data.Length % blocksize != 0)
+ {
+ throw new ArgumentException(string.Format("Data is not compatible with blocksize(data(length):{0}, blocksize:{1}.", data.Length, blocksize));
+ }
+
+ byte[] lastblock = new byte[blocksize];
for (int i = 0; i < blocksize; i++)
{
- block[i] = data[data.Length - blocksize + i];
+ lastblock[i] = data[data.Length - blocksize + i];
}
- return block;
+ return lastblock;
}
///
@@ -150,8 +193,13 @@ namespace NFC.Mifare_DESFire
///
/// Data
/// Copy of data
- public byte[] rotateLeft(byte[] data)
+ public byte[] RotateLeft(byte[] data)
{
+ if (data == null)
+ {
+ throw new ArgumentNullException("Data cannot be null.");
+ }
+
byte[] rotate = new byte[data.Length];
data.CopyTo(rotate, 0);
@@ -170,8 +218,13 @@ namespace NFC.Mifare_DESFire
///
/// Data
/// Copy of data
- public byte[] rotateRight(byte[] data)
+ public byte[] RotateRight(byte[] data)
{
+ if (data == null)
+ {
+ throw new ArgumentNullException("Data cannot be null.");
+ }
+
byte[] rotate = new byte[data.Length];
data.CopyTo(rotate, 0);
@@ -186,25 +239,47 @@ namespace NFC.Mifare_DESFire
}
///
- /// Concatenates two Arrays, Array A start at index 0
+ /// Concatenates Arrays
+ ///
+ /// List of Byte Array
+ public byte[] Concatenate(params byte[][] data)
+ {
+ if (data == null)
+ {
+ throw new ArgumentNullException("Data cannot be null.");
+ }
+
+ List cat = new List();
+
+ foreach(byte[] d in data)
+ {
+ cat.AddRange(d);
+ }
+
+ return cat.ToArray();
+ }
+
+ ///
+ /// Boolean Operation XOR on all Bytes
///
/// Array A
/// Array B
/// Copy of Data
- public byte[] concatenate(byte[] a, byte[] b)
+ public byte[] XOR(byte[] a, byte[] b)
{
- byte[] c = new byte[a.Length + b.Length];
- a.CopyTo(c, 0);
- b.CopyTo(c, a.Length);
-
- return c;
- }
-
- public byte[] xor(byte[] a, byte[] b)
- {
- if(a.Length != b.Length)
+ if (a == null)
{
- throw new ArgumentException("Array are not same Length");
+ throw new ArgumentNullException("Array A cannot be null.");
+ }
+
+ if (b == null)
+ {
+ throw new ArgumentNullException("Array B cannot be null.");
+ }
+
+ if (a.Length != b.Length)
+ {
+ throw new ArgumentException(string.Format("Arrays are not same Length(Length A:{0}, Lenght B:{1})", a.Length, b.Length));
}
byte[] c = new byte[a.Length];
@@ -216,246 +291,18 @@ namespace NFC.Mifare_DESFire
return c;
}
- #endregion
-
- #endregion
-
- #region DESFire Commands
- ///
- /// Get Application IDs from Card
- ///
- /// AIDs as Array
- public UInt32[] GetApplicationIDs()
- {
- APDUCommand cmd = new APDUCommand(IsoCase.Case2Short)
- {
- CLA = 0x90,
- INS = (byte)APDUInstructions.GET_APPLICATION_IDS
- };
-
- APDUResponse response = _Card.Transmit(cmd);
-
- CheckAPDUResponse(response);
-
- if (response.Body.Length % 3 != 0)
- {
- throw new Exception(string.Format("Invalid body length (was: {0}).", response.Body.Length));
- }
-
- if(response.Body.Length == 0)
- {
- throw new Exception("Missing PICC Entry 0x000000.");
- }
-
- List applicationIDs = new List();
-
- for (int i = 0; i < response.Body.Length; i += 3)
- {
- UInt32 new_applicationID = 0;
- new_applicationID = (UInt32)((response.Body[i] << 16) + (response.Body[i + 1] << 8) + response.Body[i + 2]);
- applicationIDs.Add(new_applicationID);
- }
-
- return applicationIDs.ToArray();
- }
///
- /// Select Application by AID
+ /// Generates SessionKey for DES Authentification
///
- /// 3 Byte AID
- public void SelectApplication(UInt32 aid)
- {
- byte[] id_byte = BitConverter.GetBytes(aid);
-
- APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = (byte)APDUInstructions.SELECT_APPLICATION,
- Data = new byte[]
- {
- id_byte[0],
- id_byte[1],
- id_byte[2]
- }
- };
-
- APDUResponse response = _Card.Transmit(cmd);
-
- CheckAPDUResponse(response);
- }
- #endregion
-
- ///
- /// Expand Array to Block Size
- ///
- ///
- ///
- public byte[] expandToBlockSize(byte[] data, int bocksize)
- {
- int diff = data.Length % 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;
- }
-
- public void ChangeKeyDES(byte key_no, byte[] key_new, byte[] key_current)
- {
- Console.WriteLine("key_new: {0}", ConvertToHexString(key_new));
- key_new = concatenate(key_new, key_new);
- Console.WriteLine("key_new_double: {0}", ConvertToHexString(key_new));
-
- byte[] header = new byte[]
- {
- 0xC4, key_no
- };
- Console.WriteLine("header: {0}", ConvertToHexString(header));
-
- byte[] cmd_ = concatenate(header, key_new);
- Console.WriteLine("cmd_: {0}", ConvertToHexString(cmd_));
-
- CRC32 crc = new CRC32();
- byte[] cmd_crc = crc.Calculate(cmd_);
- Console.WriteLine("cmd_crc: {0}", ConvertToHexString(cmd_crc));
- byte[] cryptogram = concatenate(key_new, cmd_crc);
- Console.WriteLine("cryptogram: {0}", ConvertToHexString(cryptogram));
-
- byte[] cryptogram_block = expandToBlockSize(cryptogram, 8);
- Console.WriteLine("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
-
- DES des = new DES();
-
- byte[] cryptogram_block_enc = des.Encrypt(cryptogram_block, _SessionKey, _IV);
- Console.WriteLine("cryptogram_block_enc: {0}", ConvertToHexString(cryptogram_block_enc));
-
- byte[] data = concatenate(new byte[] { key_no }, cryptogram_block_enc);
- Console.WriteLine("data: {0}", ConvertToHexString(data));
-
- APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = 0xC4,
- Data = data
- };
- Console.WriteLine("cmd: {0}", ConvertToHexString(cmd.ToArray()));
-
- APDUResponse response = _Card.Transmit(cmd);
-
- CheckAPDUResponse(response);
- }
-
-
-
-
-
-
-
- ///
- /// Create new Application with AID
- ///
- /// Appilication ID
- public APDUCommand CreateApplication(UInt64 aid)
- {
- throw new NotImplementedException();
- }
-
- public void Format()
- {
- throw new NotImplementedException();
- }
-
- ///
- /// Authenticate to Card
- ///
- /// 0x01 - 0x0D
- ///
-
- // TODO
- public void AuthenticateDES(byte key_id, byte[] key)
- {
- APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = (byte)0x1A,
- Data = new byte[]
- {
- key_id
- }
- };
- APDUResponse response = _Card.Transmit(cmd_challange_request);
-
- byte[] rndB_enc = response.Body;
- Console.WriteLine("rndB_enc: {0}", ConvertToHexString(rndB_enc));
-
- DES des = new DES();
- byte[] rndB = des.Decrypt(rndB_enc, key, GenerateDefaultKey(8));
- Console.WriteLine("rndB: {0}", ConvertToHexString(rndB));
-
- byte[] iv = new byte[8];
- rndB.CopyTo(iv, 0);
-
- byte[] rndB_rl = rotateLeft(rndB);
- Console.WriteLine("rndB_enc: {0}", ConvertToHexString(rndB_rl));
-
- byte[] rndA = new byte[]
- {
- 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
- };
- Console.WriteLine("rndA: {0}", ConvertToHexString(rndA));
-
- byte[] rndAB = concatenate(rndA, rndB_rl);
- Console.WriteLine("rndAB: {0}", ConvertToHexString(rndAB));
-
- byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc);
- Console.WriteLine("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc));
- iv = GetLastBlock(rndAB_enc);
-
- APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = (byte)0xAF,
- Data = rndAB_enc
- };
- Console.WriteLine("cmd_challange_response: {0}", ConvertToHexString(cmd_challange_response.ToArray()));
-
- response = _Card.Transmit(cmd_challange_response);
-
- byte[] encryptedRndAFromCard = response.Body;
- Console.WriteLine("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard));
-
- byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv);
- Console.WriteLine("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard));
-
- byte[] rndAFromCard = rotateRight(rotatedRndAFromCard);
- Console.WriteLine("rndAFromCard: {0}", ConvertToHexString(rndAFromCard));
-
- if (!rndA.SequenceEqual(rndAFromCard))
- {
- throw new Exception("PICC Challenge is not correct answered.");
- }
-
- _SessionKey = GenerateDESSesionKey(rndA, rndB);
- _IV = GenerateDefaultKey(8);
- }
-
- private byte[] GenerateDESSesionKey(byte[] rndA, byte[] rndB)
+ /// 16Byte SessionKey
+ public byte[] GenerateSesionKey_DES(byte[] rndA, byte[] rndB)
{
byte[] sesssionkey = new byte[8];
- for(int i = 0; i < sesssionkey.Length; i++)
+ for (int i = 0; i < sesssionkey.Length; i++)
{
- if(i < 4)
+ if (i < 4)
{
sesssionkey[i] = rndA[i];
}
@@ -465,13 +312,45 @@ namespace NFC.Mifare_DESFire
}
}
- // Set Key Verion of Key to 0x55 to LSB
- // TODO
- byte[] key_version = SetKeyVersion(sesssionkey, 0x55);
-
- return concatenate(key_version, key_version);
+ // DES SessionKey is a double DES Key
+ return Concatenate(sesssionkey, sesssionkey);
}
+ ///
+ /// Generates SessionKey for AES Authentification
+ ///
+ /// 16Byte SessionKey
+ public byte[] GenerateSesionKey_AES(byte[] rndA, byte[] rndB)
+ {
+ byte[] sesssionkey = new byte[16];
+
+ for (int i = 0; i < sesssionkey.Length; i++)
+ {
+ if (i < 4)
+ {
+ sesssionkey[i] = rndA[i];
+ }
+ else if(i >= 4 && i < 8)
+ {
+ sesssionkey[i] = rndB[i - 4];
+ }
+ else if (i >= 8 && i < 12)
+ {
+ sesssionkey[i] = rndA[i + 4];
+ }
+ else
+ {
+ sesssionkey[i] = rndB[i];
+ }
+ }
+
+ return sesssionkey;
+ }
+
+ ///
+ /// Set KeyVersion in DES Key
+ /// KeyVersion is stored in LSB of the first 8 Bytes of the DES Key
+ ///
public byte[] SetKeyVersion(byte[] key, byte keyversion)
{
byte[] pow2 = new byte[]
@@ -482,10 +361,9 @@ namespace NFC.Mifare_DESFire
byte[] new_key = new byte[key.Length];
key.CopyTo(new_key, 0);
-
- for(int i = 0; i < 8; i++)
+ for (int i = 0; i < 8; i++)
{
- if((keyversion & pow2[i]) > 0)
+ if ((keyversion & pow2[i]) > 0)
{
new_key[i] = (byte)(new_key[5] | 0x01);
}
@@ -498,53 +376,162 @@ namespace NFC.Mifare_DESFire
return new_key;
}
- public void ChangeApplicationMasterKey(byte[] aPP_MasterKey)
- {
- throw new NotImplementedException();
- }
-
///
- /// Delete Application by ID
+ /// Expand Array to Block Size, fill with 0x00
///
- /// 3 Byte ID
- public void DeleteApplication(UInt32 id)
+ ///
+ public byte[] ExpandToBlockSize(byte[] data, uint bocksize)
{
- byte[] id_byte = BitConverter.GetBytes(id);
+ int diff = data.Length % (int)bocksize;
+ if (diff == 0)
+ {
+ return data;
+ }
- APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
+ 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;
+ }
+ #endregion
+
+ #region DESFire Commands
+ ///
+ /// Authenticate to PICC, with ISO Authenticate
+ ///
+ /// 0x01 - 0x0D
+ ///
+ /// !!! WARNING For Testing only !!!
+ /// Retry after short Time
+ public void AuthenticateISO_DES(byte key_id, byte[] key, byte[] rndA = null)
+ {
+ _Log.Debug("Start AuthenticateISO_DES");
+
+ // Sepearte InitialisationVector for Authentication
+ byte[] iv = new byte[8];
+
+ APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
- INS = (byte)APDUInstructions.DELETE_APPLICATION,
+ INS = 0x1A,
Data = new byte[]
{
- id_byte[0],
- id_byte[1],
- id_byte[2]
- },
- Le = 0x00
+ key_id
+ }
};
+ _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray()));
+
+ APDUResponse response = _Card.Transmit(cmd_challange_request);
+ _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray()));
- APDUResponse response = _Card.Transmit(cmd);
CheckAPDUResponse(response);
- }
- public void ChangeApplicationKey(int v, byte[] aPP_Key_1)
- {
- throw new NotImplementedException();
+ byte[] rndB_enc = response.Body;
+ _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc));
+
+ TDES des = new TDES();
+ byte[] rndB = des.Decrypt(rndB_enc, key, GenerateEmptyKey(8));
+ _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB));
+
+ rndB.CopyTo(iv, 0);
+
+ byte[] rndB_rl = RotateLeft(rndB);
+ _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl));
+
+ if(rndA == null)
+ {
+ Random rnd = new Random();
+ rndA = new byte[8];
+ rnd.NextBytes(rndA);
+ }
+ _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA));
+
+ byte[] rndAB = Concatenate(rndA, rndB_rl);
+ _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB));
+
+ byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc);
+ _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc));
+ iv = ExtractLastBlock(rndAB_enc, 8);
+
+ APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0xAF,
+ Data = rndAB_enc
+ };
+ _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
+
+ response = _Card.Transmit(cmd_challange_response);
+ _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
+
+ CheckAPDUResponse(response);
+
+ byte[] encryptedRndAFromCard = response.Body;
+ _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard));
+
+ byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv);
+ _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard));
+
+ byte[] rndAFromCard = RotateRight(rotatedRndAFromCard);
+ _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard));
+
+ if (!rndA.SequenceEqual(rndAFromCard))
+ {
+ throw new Exception("Authentication failed, PICC Challenge is not corret");
+ }
+
+ _SessionKey = GenerateSesionKey_DES(rndA, rndB);
+ _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey));
+
+ _IV = GenerateEmptyKey(8);
+ _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
+
+ _Log.Debug("End AuthenticateISO_DES");
}
///
- /// Select Application by ID
+ /// Format PICC
///
- /// 3 Byte ID
- public APDUCommand CreateApplication(UInt32 id, byte keysetting1, byte keysetting2)
+ public void Format()
{
- byte[] id_byte = BitConverter.GetBytes(id);
+ _Log.Debug("Start Format");
- APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
+ APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short)
{
CLA = 0x90,
- INS = (byte)APDUInstructions.CREATE_APPLICATION,
+ 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");
+ }
+
+ ///
+ /// Create Application for ID
+ ///
+ /// 3 Byte ID
+ public void CreateApplication(UInt32 aid, byte keysetting1, byte keysetting2)
+ {
+ _Log.Debug("Start CreateApplication");
+
+ byte[] id_byte = BitConverter.GetBytes(aid);
+ _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray()));
+
+ APDUCommand cmd_CreateApplication = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0xCA,
Data = new byte[]
{
id_byte[0],
@@ -552,38 +539,476 @@ namespace NFC.Mifare_DESFire
id_byte[2],
keysetting1,
keysetting2
- },
- Le = 0x00
+ }
+ };
+ _Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", ConvertToHexString(cmd_CreateApplication.ToArray()));
+
+ APDUResponse response = _Card.Transmit(cmd_CreateApplication);
+ _Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", ConvertToHexString(response.ToArray()));
+
+ CheckAPDUResponse(response);
+
+ _Log.Debug("End CreateApplication");
+ }
+
+ ///
+ /// Select Application by AID
+ ///
+ /// 3 Byte AID
+ public void SelectApplication(UInt32 aid)
+ {
+ _Log.Debug("Start SelectApplication");
+
+ byte[] id_byte = BitConverter.GetBytes(aid);
+ _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray()));
+
+ APDUCommand cmd_SelectApplication = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = (byte)APDUInstructions.SELECT_APPLICATION,
+ Data = new byte[]
+ {
+ id_byte[0],
+ id_byte[1],
+ id_byte[2]
+ }
+ };
+ _Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", ConvertToHexString(cmd_SelectApplication.ToArray()));
+
+ APDUResponse response = _Card.Transmit(cmd_SelectApplication);
+ _Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", ConvertToHexString(response.ToArray()));
+
+ CheckAPDUResponse(response);
+
+ _Log.Debug("End SelectApplication");
+ }
+
+ ///
+ /// Authenticate to PICC, with ISO Authenticate
+ ///
+ /// 0x01 - 0x0D
+ ///
+ /// !!! WARNING For Testing only !!!
+ /// Retry after short Time
+ public void AuthenticateISO_AES(byte key_id, byte[] key, byte[] rndA = null)
+ {
+ _Log.Debug("Start AuthenticateISO_AES");
+
+ // Sepearte InitialisationVector for Authentication
+ byte[] iv = new byte[16];
+
+ APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0xAA,
+ Data = new byte[]
+ {
+ key_id
+ }
+ };
+ _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray()));
+
+ APDUResponse response = _Card.Transmit(cmd_challange_request);
+ _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray()));
+
+ CheckAPDUResponse(response);
+
+ byte[] rndB_enc = response.Body;
+ _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc));
+
+ AES aes = new AES();
+ byte[] rndB = aes.Decrypt(rndB_enc, key, GenerateEmptyKey(16));
+ _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB));
+
+ rndB.CopyTo(iv, 0);
+
+ byte[] rndB_rl = RotateLeft(rndB);
+ _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl));
+
+ if (rndA == null)
+ {
+ Random rnd = new Random();
+ rndA = new byte[16];
+ rnd.NextBytes(rndA);
+ }
+ _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA));
+
+ byte[] rndAB = Concatenate(rndA, rndB_rl);
+ _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB));
+
+ byte[] rndAB_enc = aes.Encrypt(rndAB, key, rndB_enc);
+ _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc));
+ iv = ExtractLastBlock(rndAB_enc, 16);
+
+ APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0xAF,
+ Data = rndAB_enc
+ };
+ _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
+
+ response = _Card.Transmit(cmd_challange_response);
+ _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
+
+ CheckAPDUResponse(response);
+
+ byte[] encryptedRndAFromCard = response.Body;
+ _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard));
+
+ byte[] rotatedRndAFromCard = aes.Decrypt(encryptedRndAFromCard, key, iv);
+ _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard));
+
+ byte[] rndAFromCard = RotateRight(rotatedRndAFromCard);
+ _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard));
+
+ if (!rndA.SequenceEqual(rndAFromCard))
+ {
+ throw new Exception("Authentication failed, PICC Challenge is not corret");
+ }
+
+ _SessionKey = GenerateSesionKey_AES(rndA, rndB);
+ _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey));
+
+ _IV = GenerateEmptyKey(16);
+ _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
+
+ _Log.Debug("End AuthenticateISO_DES");
+ }
+
+ ///
+ /// Change Same AES key as Authenticated
+ ///
+ ///
+ ///
+ ///
+ public void ChangeKey_AES(byte key_id, byte[] new_key, byte key_version)
+ {
+ _Log.Debug("Start ChangeKey_AES");
+
+ byte[] header = new byte[]
+ {
+ 0xC4, key_id
+ };
+ _Log.DebugFormat("header: {0}", 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));
+
+ CRC32 crc32 = new CRC32();
+ byte[] crc = crc32.Calculate(command);
+ _Log.DebugFormat("crc: {0}", ConvertToHexString(crc));
+
+ byte[] cryptogram = Concatenate(key_and_version, crc);
+ _Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram));
+
+ byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16);
+ _Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
+
+ AES aes = new AES();
+ byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV);
+ _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc));
+
+ _IV = ExtractLastBlock(cryptogram_enc, 16);
+ _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
+
+ byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc);
+ _Log.DebugFormat("data: {0}", ConvertToHexString(data));
+
+ APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0xC4,
+ Data = data
+ };
+ _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray()));
+
+ APDUResponse response = _Card.Transmit(cmd_ChangeKey);
+ _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray()));
+
+ CheckAPDUResponse(response);
+
+ _Log.Debug("End ChangeKey_AES");
+ }
+
+ ///
+ /// Change other AES key as Authenticated
+ ///
+ ///
+ ///
+ ///
+ public void ChangeOtherKey_AES(byte key_id, byte[] new_key, byte[] old_key, byte key_version)
+ {
+ _Log.Debug("Start ChangeOtherKey_AES");
+
+ byte[] header = new byte[]
+ {
+ 0xC4, key_id
+ };
+ _Log.DebugFormat("header: {0}", 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));
+
+ CRC32 crc32 = new CRC32();
+ byte[] crc_cmd = crc32.Calculate(command);
+ _Log.DebugFormat("crc_cmd: {0}", ConvertToHexString(crc_cmd));
+ byte[] crc_key = crc32.Calculate(new_key);
+ _Log.DebugFormat("crc_key: {0}", ConvertToHexString(crc_key));
+
+ byte[] cryptogram = Concatenate(key_and_version, crc_cmd);
+ cryptogram = Concatenate(cryptogram, crc_key);
+ _Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram));
+
+ byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16);
+ _Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
+
+ AES aes = new AES();
+ byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV);
+ _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc));
+
+ _IV = ExtractLastBlock(cryptogram_enc, 16);
+ _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
+
+ byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc);
+ _Log.DebugFormat("data: {0}", ConvertToHexString(data));
+
+ APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0xC4,
+ Data = data
+ };
+ _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray()));
+
+ APDUResponse response = _Card.Transmit(cmd_ChangeKey);
+ _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray()));
+
+ CheckAPDUResponse(response);
+
+ _Log.Debug("End ChangeOtherKey_AES");
+ }
+
+ ///
+ /// Create Standard Data File
+ ///
+ /// ID of File (0x01 - 0x10)
+ /// Type of File Communicaton
+ /// Access Rights for File
+ /// Size of File in Bytes
+ public void CreateFile_Standard(byte file_id, FileCommunication communication, UInt16 accessRights, UInt32 size)
+ {
+ _Log.Debug("Start CreateFile_Standard");
+
+ _Log.DebugFormat("FID: {0}", file_id);
+
+ byte[] accessRights_byte = BitConverter.GetBytes(accessRights);
+ byte[] size_byte_tolong = BitConverter.GetBytes(size);
+ // Use only 3 Bytes
+ byte[] size_byte = new byte[]
+ {
+ size_byte_tolong[0],
+ size_byte_tolong[1],
+ size_byte_tolong[2],
};
- return cmd;
+ byte[] data = new byte[]
+ {
+ file_id,
+ (byte)communication
+ };
+
+ APDUCommand cmd_CreateFile_Standard = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ 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()));
+
+ APDUResponse response = _Card.Transmit(cmd_CreateFile_Standard);
+ _Log.DebugFormat("APDU_RES(cmd_CreateFile_Standard): {0}", ConvertToHexString(response.ToArray()));
+
+ CheckAPDUResponse(response);
+
+ _Log.Debug("End CreateFile_Standard");
}
- public void CreateFile(byte fabAccessIdentFileID, FileCommunication pLAIN, ushort fileAccessRight, UInt32 v)
+ ///
+ /// Read Data from File
+ ///
+ /// ID of File (0x01 - 0x10)
+ /// Offset for File
+ /// Lenght of Data
+ public byte[] ReadData(byte file_id, UInt32 offset, UInt32 length)
{
- throw new NotImplementedException();
+ _Log.Debug("Start ReadData");
+
+ byte[] data = new byte[]
+ {
+ file_id
+ };
+
+ byte[] offset_byte_tolong = BitConverter.GetBytes(offset);
+ // Use only 3 Bytes
+ byte[] offset_byte = new byte[]
+ {
+ offset_byte_tolong[0],
+ offset_byte_tolong[1],
+ offset_byte_tolong[2],
+ };
+
+ byte[] length_byte_tolong = BitConverter.GetBytes(length);
+ // Use only 3 Bytes
+ byte[] length_byte = new byte[]
+ {
+ length_byte_tolong[0],
+ length_byte_tolong[1],
+ length_byte_tolong[2],
+ };
+
+ APDUCommand cmd_ReadData = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = (byte)APDUInstructions.READ_DATA,
+ Data = Concatenate(data, offset_byte, length_byte)
+ };
+ _Log.DebugFormat("APDU_CMD(cmd_ReadData): {0}", ConvertToHexString(cmd_ReadData.ToArray()));
+
+ APDUResponse response = _Card.Transmit(cmd_ReadData);
+ _Log.DebugFormat("APDU_RES(cmd_ReadData): {0}", ConvertToHexString(response.ToArray()));
+
+ CheckAPDUResponse(response);
+
+ _Log.Debug("End ReadData");
+
+ return response.Body;
}
- public ushort GenerateFileAccessRight(AccessRights fREE, int v1, int v2, int v3)
+ ///
+ /// Write Data to File
+ ///
+ /// ID of File (0x01 - 0x10)
+ /// Offset for File
+ /// Data to write
+ public void WriteData(byte file_id, UInt32 offset, byte[] data)
{
- throw new NotImplementedException();
+ _Log.Debug("Start WriteData");
+
+ byte[] file_id_array = new byte[]
+ {
+ file_id
+ };
+
+ byte[] offset_byte_tolong = BitConverter.GetBytes(offset);
+ // 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],
+ };
+
+ 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()));
+
+ APDUResponse response = _Card.Transmit(cmd_WriteData);
+ _Log.DebugFormat("APDU_RES(cmd_WriteData): {0}", ConvertToHexString(response.ToArray()));
+
+ CheckAPDUResponse(response);
+
+ _Log.Debug("End WriteData");
}
- public void WirteData(byte fabAccessIdentFileID, int v1, int v2, byte[] vs)
- {
- throw new NotImplementedException();
- }
+ ///
+ /// Get all ApplicationIDS from PICC
+ ///
+ /// AIDs (3 Byte) as Array
+ //public UInt32[] GetApplicationIDs()
+ //{
+ // _Log.Debug("Start GetApplicationIDs");
- public void CreateFile(byte fabAccessIdentFileID, object plain, AccessRights fREE, int v1, int v2, int v3)
- {
- throw new NotImplementedException();
- }
+ // APDUCommand cmd = new APDUCommand(IsoCase.Case2Short)
+ // {
+ // CLA = 0x90,
+ // INS = (byte)APDUInstructions.GET_APPLICATION_IDS
+ // };
- public byte[] ReadData(byte identFileID, int v1, int v2)
- {
- throw new NotImplementedException();
- }
+ // APDUResponse response = _Card.Transmit(cmd);
+ // CheckAPDUResponse(response);
+
+ // if (response.Body.Length % 3 != 0)
+ // {
+ // throw new Exception(string.Format("Invalid body length (was: {0}).", response.Body.Length));
+ // }
+
+ // if (response.Body.Length == 0)
+ // {
+ // throw new Exception("Missing PICC Entry 0x000000.");
+ // }
+
+ // List applicationIDs = new List();
+
+ // for (int i = 0; i < response.Body.Length; i += 3)
+ // {
+ // UInt32 new_applicationID = 0;
+ // new_applicationID = (UInt32)((response.Body[i] << 16) + (response.Body[i + 1] << 8) + response.Body[i + 2]);
+ // applicationIDs.Add(new_applicationID);
+ // }
+
+ // _Log.Debug("End GetApplicationIDs");
+
+ // return applicationIDs.ToArray();
+ //}
+
+ ///
+ /// Delete Application by ID
+ ///
+ /// 3 Byte ID
+ //public void DeleteApplication(UInt32 id)
+ //{
+ // byte[] id_byte = BitConverter.GetBytes(id);
+
+ // APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
+ // {
+ // CLA = 0x90,
+ // INS = (byte)APDUInstructions.DELETE_APPLICATION,
+ // Data = new byte[]
+ // {
+ // id_byte[0],
+ // id_byte[1],
+ // id_byte[2]
+ // },
+ // Le = 0x00
+ // };
+
+ // APDUResponse response = _Card.Transmit(cmd);
+ // CheckAPDUResponse(response);
+ //}
+ #endregion
+
+ #region Configuration Generator
///
/// Genearte KeySetting1 for Application Settings or PICC Setting
///
@@ -592,6 +1017,53 @@ namespace NFC.Mifare_DESFire
return (byte)(((byte)changeKey << 4) | (byte)changeMasterKeySettings | (byte)createDeleteFile | (byte)fileDirectoryAccess | (byte)changeMasterKey);
}
-
+ ///
+ /// Genearte KeySetting1 for Application Settings or PICC Setting
+ ///
+ /// ID of Key for changing Application Keys
+ ///
+ 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);
+ }
+
+ ///
+ /// Genearte KeySetting2 for Application Creation
+ ///
+ /// Number of keys that can be stored within the application (0x01-0x0D)
+ ///
+ public byte GenerateKeySetting2(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys)
+ {
+ if (numberOfKeys < 0x01 || numberOfKeys >= 0x0D)
+ {
+ throw new ArgumentOutOfRangeException();
+ }
+
+ return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys);
+ }
+
+ ///
+ /// 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
+ 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
}
}
diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs
deleted file mode 100644
index b0bda50..0000000
--- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs
+++ /dev/null
@@ -1,844 +0,0 @@
-using log4net.Repository.Hierarchy;
-using NFC.Crypto;
-using NFC.ISO7816_4;
-using NFC.Mifare_DESFire.Enums;
-using NFC.NXP_MIFARE_DESFire.Exceptions;
-using PCSC.Iso7816;
-using System;
-using System.Linq;
-
-namespace NFC.Mifare_DESFire
-{
- public class MIFARE_DESFire_V2
- {
- // Docs https://hackmd.io/qATu8uYdRnOC40aFrB9afg
-
- #region Log
- private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
- #endregion
-
- #region Contructors
- ///
- /// Construct MIFRARE_DESFire Object with ICard Interface
- ///
- /// Implementation of ICard, only transmit is used
- public MIFARE_DESFire_V2(ICard card)
- {
- _Card = card;
- }
- #endregion
-
- #region Properties
- ///
- /// ICard Implementation used to transmit APDUCommands and recive APDUResponses
- ///
- private ICard _Card;
-
- ///
- /// SessionKey, is set after Successfull Authentication
- ///
- public byte[] _SessionKey;
-
- ///
- /// Initialation Vector for CBC Encryption
- /// Is 0 bytes after Successfull Authentication
- ///
- public byte[] _IV;
- #endregion
-
- #region Methods
- #region Helper Methods
- ///
- /// Generate Byte Array filled with 0
- ///
- /// Size of Array
- public byte[] GenerateEmptyKey(uint size)
- {
- byte[] key = new byte[size];
- for (int i = 0; i < size; i++)
- {
- key[i] = 0;
- }
-
- return key;
- }
-
- ///
- /// Converts byte[] to string with HEX Code
- /// No 0x is created
- ///
- /// Data
- public string ConvertToHexString(byte[] data)
- {
- return BitConverter.ToString(data).Replace("-", "").ToLower();
- }
-
- ///
- /// Converts string with HEX Code to byte[]
- /// No 0x is requiered
- ///
- /// Data
- 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;
- }
-
- 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));
- }
-
- ///
- /// Check APDU Response for DESFire Error Codes
- /// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf
- /// Section: 11.3
- ///
- public void CheckAPDUResponse(APDUResponse response)
- {
- if (response == null)
- {
- throw new ArgumentNullException("Response cannot be null.");
- }
-
- if (response.SW1 == 0x91)
- {
- switch (response.SW2)
- {
- case 0x00: // OPERATION_OK
- return;
- case 0x0C: // NO_CHANGES
- return;
- case 0x1C: // ILLEGAL_COMMAND_CODE
- throw new IllegalCommandCodeException();
- case 0x1E: // INTEGRITY_ERROR
- throw new IntegrityErrorException();
- case 0x40: // NO_SUCH_KEY
- throw new NoSuchKeyException();
- case 0x7E: // LENGTH_ERROR
- throw new LengthErrorException();
- case 0x9D: // PERMISSION_DENIED
- throw new PermissionDeniedException();
- case 0x9E: // PARAMETER_ERROR
- throw new ParameterErrorException();
- case 0xAD: // AUTHENTICATION_DELAY
- throw new AuthenticationDelayException();
- case 0xAE: // AUTHENTICATION_ERROR
- throw new AuthenticationErrorException();
- case 0xAF: // ADDITIONAL_FRAME
- return;
- case 0xBE: // BOUNDARY_ERROR
- throw new BoundaryErrorException();
- case 0xCA: // COMMAND_ABORTED
- throw new CommandAbortedException();
- case 0xDE: // DUPLICATE_ERROR
- throw new DuplicateErrorException();
- case 0xF0: // FILE_NOT_FOUND
- throw new FileNotFoundException();
- default:
- break;
- }
- }
-
- throw new Exception(string.Format("Unknown Response Code: 0x{0}.", BitConverter.ToString(new byte[] { response.SW1, response.SW2 }).Replace("-", string.Empty)));
- }
- #endregion
-
- #region Crypto Operation
- ///
- /// Return a copy of the last Block of data
- ///
- /// Data compatible to blocksize
- /// in byte
- public byte[] ExtractLastBlock(byte[] data, uint blocksize)
- {
- if (data == null)
- {
- throw new ArgumentNullException("Data cannot be null.");
- }
-
- if (data.Length % blocksize != 0)
- {
- throw new ArgumentException(string.Format("Data is not compatible with blocksize(data(length):{0}, blocksize:{1}.", data.Length, blocksize));
- }
-
- byte[] lastblock = new byte[blocksize];
-
- for (int i = 0; i < blocksize; i++)
- {
- lastblock[i] = data[data.Length - blocksize + i];
- }
-
- return lastblock;
- }
-
- ///
- /// Rotates Array to the left
- ///
- /// Data
- /// Copy of data
- public byte[] RotateLeft(byte[] data)
- {
- if (data == null)
- {
- throw new ArgumentNullException("Data cannot be null.");
- }
-
- byte[] rotate = new byte[data.Length];
- data.CopyTo(rotate, 0);
-
- byte tmp = rotate[0];
- for (var i = 0; i < rotate.Length - 1; i++)
- {
- rotate[i] = rotate[i + 1];
- }
- rotate[rotate.Length - 1] = tmp;
-
- return rotate;
- }
-
- ///
- /// Rotates Array to the right
- ///
- /// Data
- /// Copy of data
- public byte[] RotateRight(byte[] data)
- {
- if (data == null)
- {
- throw new ArgumentNullException("Data cannot be null.");
- }
-
- byte[] rotate = new byte[data.Length];
- data.CopyTo(rotate, 0);
-
- byte tmp = rotate[rotate.Length - 1];
- for (var i = rotate.Length - 1; i > 0; i--)
- {
- rotate[i] = rotate[i - 1];
- }
- rotate[0] = tmp;
-
- return rotate;
- }
-
- ///
- /// Concatenates two Arrays, Array A start at index 0
- ///
- /// Array A
- /// Array B
- /// Copy of Data (a.Size + b.Size)
- public byte[] Concatenate(byte[] a, byte[] b)
- {
- if (a == null)
- {
- throw new ArgumentNullException("Array A cannot be null.");
- }
-
- if (b == null)
- {
- throw new ArgumentNullException("Array B cannot be null.");
- }
-
- byte[] c = new byte[a.Length + b.Length];
- a.CopyTo(c, 0);
- b.CopyTo(c, a.Length);
-
- return c;
- }
-
- ///
- /// Boolean Operation XOR on all Bytes
- ///
- /// Array A
- /// Array B
- /// Copy of Data
- public byte[] XOR(byte[] a, byte[] b)
- {
- if (a == null)
- {
- throw new ArgumentNullException("Array A cannot be null.");
- }
-
- if (b == null)
- {
- throw new ArgumentNullException("Array B cannot be null.");
- }
-
- if (a.Length != b.Length)
- {
- throw new ArgumentException(string.Format("Arrays are not same Length(Length A:{0}, Lenght B:{1})", a.Length, b.Length));
- }
-
- byte[] c = new byte[a.Length];
-
- for(int i = 0; i < a.Length; i++)
- {
- c[i] = (byte)(a[i] ^ b[i]);
- }
-
- return c;
- }
-
- ///
- /// Generates SessionKey for DES Authentification
- ///
- /// 16Byte SessionKey
- public byte[] GenerateSesionKey_DES(byte[] rndA, byte[] rndB)
- {
- byte[] sesssionkey = new byte[8];
-
- for (int i = 0; i < sesssionkey.Length; i++)
- {
- if (i < 4)
- {
- sesssionkey[i] = rndA[i];
- }
- else
- {
- sesssionkey[i] = rndB[i - 4];
- }
- }
-
- // DES SessionKey is a double DES Key
- return Concatenate(sesssionkey, sesssionkey);
- }
-
- ///
- /// Generates SessionKey for AES Authentification
- ///
- /// 16Byte SessionKey
- public byte[] GenerateSesionKey_AES(byte[] rndA, byte[] rndB)
- {
- byte[] sesssionkey = new byte[16];
-
- for (int i = 0; i < sesssionkey.Length; i++)
- {
- if (i < 4)
- {
- sesssionkey[i] = rndA[i];
- }
- else if(i >= 4 && i < 8)
- {
- sesssionkey[i] = rndB[i - 4];
- }
- else if (i >= 8 && i < 12)
- {
- sesssionkey[i] = rndA[i + 4];
- }
- else
- {
- sesssionkey[i] = rndB[i];
- }
- }
-
- return sesssionkey;
- }
-
- ///
- /// Set KeyVersion in DES Key
- /// KeyVersion is stored in LSB of the first 8 Bytes of the DES Key
- ///
- public byte[] SetKeyVersion(byte[] key, byte keyversion)
- {
- 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;
- }
-
- ///
- /// Expand Array to Block Size, fill with 0x00
- ///
- ///
- public byte[] ExpandToBlockSize(byte[] data, uint bocksize)
- {
- 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;
- }
- #endregion
-
- #region DESFire Commands
- ///
- /// Authenticate to PICC, with ISO Authenticate
- ///
- /// 0x01 - 0x0D
- ///
- /// !!! WARNING For Testing only !!!
- /// Retry after short Time
- public void AuthenticateISO_DES(byte key_id, byte[] key, byte[] rndA = null)
- {
- _Log.Debug("Start AuthenticateISO_DES");
-
- // Sepearte InitialisationVector for Authentication
- byte[] iv = new byte[8];
-
- APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = 0x1A,
- Data = new byte[]
- {
- key_id
- }
- };
- _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray()));
-
- APDUResponse response = _Card.Transmit(cmd_challange_request);
- _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray()));
-
- CheckAPDUResponse(response);
-
- byte[] rndB_enc = response.Body;
- _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc));
-
- DES des = new DES();
- byte[] rndB = des.Decrypt(rndB_enc, key, GenerateEmptyKey(8));
- _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB));
-
- rndB.CopyTo(iv, 0);
-
- byte[] rndB_rl = RotateLeft(rndB);
- _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl));
-
- if(rndA == null)
- {
- Random rnd = new Random();
- rndA = new byte[8];
- rnd.NextBytes(rndA);
- }
- _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA));
-
- byte[] rndAB = Concatenate(rndA, rndB_rl);
- _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB));
-
- byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc);
- _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc));
- iv = ExtractLastBlock(rndAB_enc, 8);
-
- APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = 0xAF,
- Data = rndAB_enc
- };
- _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
-
- response = _Card.Transmit(cmd_challange_response);
- _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
-
- CheckAPDUResponse(response);
-
- byte[] encryptedRndAFromCard = response.Body;
- _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard));
-
- byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv);
- _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard));
-
- byte[] rndAFromCard = RotateRight(rotatedRndAFromCard);
- _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard));
-
- if (!rndA.SequenceEqual(rndAFromCard))
- {
- throw new Exception("Authentication failed, PICC Challenge is not corret");
- }
-
- _SessionKey = GenerateSesionKey_DES(rndA, rndB);
- _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey));
-
- _IV = GenerateEmptyKey(8);
- _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
-
- _Log.Debug("End AuthenticateISO_DES");
- }
-
- ///
- /// Format PICC
- ///
- 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");
- }
-
- ///
- /// Create Application for ID
- ///
- /// 3 Byte ID
- public void CreateApplication(UInt32 aid, byte keysetting1, byte keysetting2)
- {
- _Log.Debug("Start CreateApplication");
-
- byte[] id_byte = BitConverter.GetBytes(aid);
- _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray()));
-
- APDUCommand cmd_CreateApplication = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = 0xCA,
- Data = new byte[]
- {
- id_byte[0],
- id_byte[1],
- id_byte[2],
- keysetting1,
- keysetting2
- }
- };
- _Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", ConvertToHexString(cmd_CreateApplication.ToArray()));
-
- APDUResponse response = _Card.Transmit(cmd_CreateApplication);
- _Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", ConvertToHexString(response.ToArray()));
-
- CheckAPDUResponse(response);
-
- _Log.Debug("End CreateApplication");
- }
-
- ///
- /// Select Application by AID
- ///
- /// 3 Byte AID
- public void SelectApplication(UInt32 aid)
- {
- _Log.Debug("Start SelectApplication");
-
- byte[] id_byte = BitConverter.GetBytes(aid);
- _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray()));
-
- APDUCommand cmd_SelectApplication = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = (byte)APDUInstructions.SELECT_APPLICATION,
- Data = new byte[]
- {
- id_byte[0],
- id_byte[1],
- id_byte[2]
- }
- };
- _Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", ConvertToHexString(cmd_SelectApplication.ToArray()));
-
- APDUResponse response = _Card.Transmit(cmd_SelectApplication);
- _Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", ConvertToHexString(response.ToArray()));
-
- CheckAPDUResponse(response);
-
- _Log.Debug("End SelectApplication");
- }
-
- ///
- /// Authenticate to PICC, with ISO Authenticate
- ///
- /// 0x01 - 0x0D
- ///
- /// !!! WARNING For Testing only !!!
- /// Retry after short Time
- public void AuthenticateISO_AES(byte key_id, byte[] key, byte[] rndA = null)
- {
- _Log.Debug("Start AuthenticateISO_AES");
-
- // Sepearte InitialisationVector for Authentication
- byte[] iv = new byte[16];
-
- APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = 0xAA,
- Data = new byte[]
- {
- key_id
- }
- };
- _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray()));
-
- APDUResponse response = _Card.Transmit(cmd_challange_request);
- _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray()));
-
- CheckAPDUResponse(response);
-
- byte[] rndB_enc = response.Body;
- _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc));
-
- AES aes = new AES();
- byte[] rndB = aes.Decrypt(rndB_enc, key, GenerateEmptyKey(16));
- _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB));
-
- rndB.CopyTo(iv, 0);
-
- byte[] rndB_rl = RotateLeft(rndB);
- _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl));
-
- if (rndA == null)
- {
- Random rnd = new Random();
- rndA = new byte[16];
- rnd.NextBytes(rndA);
- }
- _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA));
-
- byte[] rndAB = Concatenate(rndA, rndB_rl);
- _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB));
-
- byte[] rndAB_enc = aes.Encrypt(rndAB, key, rndB_enc);
- _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc));
- iv = ExtractLastBlock(rndAB_enc, 16);
-
- APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = 0xAF,
- Data = rndAB_enc
- };
- _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
-
- response = _Card.Transmit(cmd_challange_response);
- _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray()));
-
- CheckAPDUResponse(response);
-
- byte[] encryptedRndAFromCard = response.Body;
- _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard));
-
- byte[] rotatedRndAFromCard = aes.Decrypt(encryptedRndAFromCard, key, iv);
- _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard));
-
- byte[] rndAFromCard = RotateRight(rotatedRndAFromCard);
- _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard));
-
- if (!rndA.SequenceEqual(rndAFromCard))
- {
- throw new Exception("Authentication failed, PICC Challenge is not corret");
- }
-
- _SessionKey = GenerateSesionKey_AES(rndA, rndB);
- _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey));
-
- _IV = GenerateEmptyKey(16);
- _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
-
- _Log.Debug("End AuthenticateISO_DES");
- }
-
- ///
- /// Change Same AES key as Authenticated
- ///
- ///
- ///
- ///
- public void ChangeKey_AES(byte key_id, byte[] new_key, byte key_version)
- {
- _Log.Debug("Start ChangeKey_AES");
-
- byte[] header = new byte[]
- {
- 0xC4, key_id
- };
- _Log.DebugFormat("header: {0}", 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));
-
- CRC32 crc32 = new CRC32();
- byte[] crc = crc32.Calculate(command);
- _Log.DebugFormat("crc: {0}", ConvertToHexString(crc));
-
- byte[] cryptogram = Concatenate(key_and_version, crc);
- _Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram));
-
- byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16);
- _Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
-
- AES aes = new AES();
- byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV);
- _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc));
-
- _IV = ExtractLastBlock(cryptogram_enc, 16);
- _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
-
- byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc);
- _Log.DebugFormat("data: {0}", ConvertToHexString(data));
-
- APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = 0xC4,
- Data = data
- };
- _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray()));
-
- APDUResponse response = _Card.Transmit(cmd_ChangeKey);
- _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray()));
-
- CheckAPDUResponse(response);
-
- _Log.Debug("End ChangeKey_AES");
- }
-
- ///
- /// Change other AES key as Authenticated
- ///
- ///
- ///
- ///
- public void ChangeOtherKey_AES(byte key_id, byte[] new_key, byte[] old_key, byte key_version)
- {
- _Log.Debug("Start ChangeOtherKey_AES");
-
- byte[] header = new byte[]
- {
- 0xC4, key_id
- };
- _Log.DebugFormat("header: {0}", 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));
-
- CRC32 crc32 = new CRC32();
- byte[] crc_cmd = crc32.Calculate(command);
- _Log.DebugFormat("crc_cmd: {0}", ConvertToHexString(crc_cmd));
- byte[] crc_key = crc32.Calculate(new_key);
- _Log.DebugFormat("crc_key: {0}", ConvertToHexString(crc_key));
-
- byte[] cryptogram = Concatenate(key_and_version, crc_cmd);
- cryptogram = Concatenate(cryptogram, crc_key);
- _Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram));
-
- byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16);
- _Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
-
- AES aes = new AES();
- byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV);
- _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc));
-
- _IV = ExtractLastBlock(cryptogram_enc, 16);
- _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
-
- byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc);
- _Log.DebugFormat("data: {0}", ConvertToHexString(data));
-
- APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = 0xC4,
- Data = data
- };
- _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray()));
-
- APDUResponse response = _Card.Transmit(cmd_ChangeKey);
- _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray()));
-
- CheckAPDUResponse(response);
-
- _Log.Debug("End ChangeOtherKey_AES");
- }
-
- public void CreateFile_STD()
- #endregion
-
- #region Configuration Generator
- ///
- /// Genearte KeySetting1 for Application Settings or PICC Setting
- ///
- 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);
- }
-
- ///
- /// Genearte KeySetting1 for Application Settings or PICC Setting
- ///
- /// ID of Key for changing Application Keys
- ///
- 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);
- }
-
- ///
- /// Genearte KeySetting2 for Application Creation
- ///
- /// Number of keys that can be stored within the application (0x01-0x0D)
- ///
- public byte GenerateKeySetting2(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys)
- {
- if (numberOfKeys < 0x01 || numberOfKeys >= 0x0D)
- {
- throw new ArgumentOutOfRangeException();
- }
-
- return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys);
- }
- #endregion
- #endregion
- }
-}
diff --git a/NFC_Test/AuthCrypto_Test.cs b/NFC_Test/AuthCrypto_Test.cs
deleted file mode 100644
index 58e6b6f..0000000
--- a/NFC_Test/AuthCrypto_Test.cs
+++ /dev/null
@@ -1,211 +0,0 @@
-using NFC;
-using NFC.Crypto;
-using NFC.ISO7816_4;
-using NFC.Mifare_DESFire;
-using NSubstitute;
-using NUnit.Framework;
-using PCSC.Iso7816;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace NFC_Test
-{
- public class AuthCrypto_Test
- {
- public byte[] GenerateDefaultKey(int size)
- {
- List key = new List();
- for (int i = 0; i < size; i++)
- {
- key.Add(0);
- }
-
- return key.ToArray();
- }
-
- [Test]
- // https://www.linkedin.com/pulse/mifare-desfire-introduction-david-coelho
- public void AuthExample()
- {
- DES des = new DES();
-
- byte[] challenge = new byte[]
- {
- 0x93 ,0x9d ,0x2c ,0x2e ,0xa1 ,0x65 ,0x75 ,0xd5
- };
-
- byte[] key = GenerateDefaultKey(8);
- byte[] iv = GenerateDefaultKey(8);
-
- byte[] rndA = new byte[]
- {
- 0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07
- };
-
- byte[] rndB = des.Decrypt(challenge, key, iv);
-
- byte[] rndB_expected = new byte[]
- {
- 0xea ,0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67
- };
-
- Assert.AreEqual(rndB_expected, rndB);
- }
-
- [Test]
- public void concatenate()
- {
- MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(null);
-
- byte[] rndA = new byte[]
- {
- 0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07
- };
-
- byte[] rndB = new byte[]
- {
- 0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67 ,0xea
- };
-
- byte[] rndA_rndB_expected = new byte[]
- {
- 0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07, 0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67 ,0xea
- };
-
- byte[] rndA_rndB = mifareDESFire.concatenate(rndA, rndB);
-
- Assert.AreEqual(rndA_rndB_expected, rndA_rndB);
- }
-
- [Test]
- public void Auth()
- {
- APDUCommand cmd_getchallange = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = (byte)0x1A,
- Data = new byte[]
- {
- 0x00
- }
- };
-
- APDUCommand cmd_answerchallange = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = (byte)0xAF,
- Data = new byte[]
- {
- 0x69, 0x17, 0x8b, 0x93, 0x8c, 0x03, 0xed, 0xf1, 0x86, 0xd3, 0x05, 0x6b, 0xed, 0xc8, 0xd6, 0xcf
- }
- };
-
- APDUResponse response = new APDUResponse()
- {
- Body = new byte[]
- {
- 0xB8, 0x90, 0x04, 0x7F, 0x2D, 0xC8, 0xD6, 0x8B
- }
- };
-
- APDUResponse response2 = new APDUResponse()
- {
- Body = new byte[]
- {
- 0x04, 0x79, 0xed, 0x6c, 0x4f, 0x74, 0xda, 0x4a
- }
- };
-
- ICard card = Substitute.For();
-
- card.Transmit(cmd_getchallange).ReturnsForAnyArgs(response);
- card.Transmit(cmd_answerchallange).Returns(response2);
-
- MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
-
- mifareDESFire.AuthenticateDES(0x00, mifareDESFire.GenerateDefaultKey(16));
- }
-
- [Test]
- public void ChangeKey()
- {
- ICard card = Substitute.For();
- MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
-
- mifareDESFire._SessionKey = new byte[]
- {
- 0xDC, 0xB0, 0x96, 0xC2, 0xA4, 0x0E, 0x78, 0xE0, 0xA0, 0xE4, 0x7A, 0x96, 0xF4, 0x2E, 0x62, 0xAE
- };
- mifareDESFire._IV = new byte[]
- {
- 0x33, 0x45 , 0xAA , 0x95 , 0xF2 , 0xD9 , 0x56 , 0xCF
- };
-
- mifareDESFire.ChangeKeyDES(0x00, GenerateDefaultKey(16), GenerateDefaultKey(16));
- }
-
- [Test]
- public void CRC()
- {
- byte[] data = StringToByteArrayFastest("c40045eeb8338ae8f49a032e85bb1114353010");
-
- CRC32 crc32 = new CRC32();
-
- byte[] crc = crc32.Calculate(data);
-
- MIFARE_DESFire dESFire = new MIFARE_DESFire(null);
-
- Console.WriteLine("data: {0}", dESFire.ConvertToHexString(data));
- Console.WriteLine("crc: {0}", dESFire.ConvertToHexString(crc));
-
- byte[] data_crc = dESFire.concatenate(data, crc);
- Console.WriteLine("data_crc: {0}", dESFire.ConvertToHexString(data_crc));
- }
-
- public static byte[] StringToByteArrayFastest(string hex)
- {
- if (hex.Length % 2 == 1)
- throw new Exception("The binary key cannot have an odd number of digits");
-
- byte[] arr = new byte[hex.Length >> 1];
-
- for (int i = 0; i < hex.Length >> 1; ++i)
- {
- arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
- }
-
- return arr;
- }
-
- public static 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));
- }
-
- [Test]
- public void AES()
- {
- byte[] data = StringToByteArrayFastest("45eeb8338ae8f49a032e85bb111435301095c3894b0000000000000000000000");
- byte[] key = StringToByteArrayFastest("d99aca2b5b4de3a949fa2cf12b0eb673");
- byte[] iv = StringToByteArrayFastest("00000000000000000000000000000000");
-
- MIFARE_DESFire dESFire = new MIFARE_DESFire(null);
-
- Console.WriteLine("data: {0}", dESFire.ConvertToHexString(data));
- Console.WriteLine("key: {0}", dESFire.ConvertToHexString(key));
- Console.WriteLine("iv: {0}", dESFire.ConvertToHexString(iv));
-
- AES aes = new AES();
-
- byte[] data_enc = aes.Encrypt(data, key, iv);
- Console.WriteLine("data_enc: {0}", dESFire.ConvertToHexString(data_enc));
- }
- }
-}
diff --git a/NFC_Test/AES_Test.cs b/NFC_Test/Crypto/AES_Test.cs
similarity index 89%
rename from NFC_Test/AES_Test.cs
rename to NFC_Test/Crypto/AES_Test.cs
index b35fee2..a4a2cf0 100644
--- a/NFC_Test/AES_Test.cs
+++ b/NFC_Test/Crypto/AES_Test.cs
@@ -2,7 +2,7 @@
using NFC.Mifare_DESFire;
using NUnit.Framework;
-namespace NFC_Test
+namespace NFC_Test.Crypto
{
[TestFixture]
public class AES_Test
@@ -10,7 +10,7 @@ namespace NFC_Test
[Test]
public void Encrypt()
{
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12104a3b07e8eb77a7ac00000000000000");
byte[] key = desfire.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b");
diff --git a/NFC_Test/Crypto/CRC16_Test.cs b/NFC_Test/Crypto/CRC16_Test.cs
new file mode 100644
index 0000000..d174e05
--- /dev/null
+++ b/NFC_Test/Crypto/CRC16_Test.cs
@@ -0,0 +1,23 @@
+using NFC;
+using NFC.Crypto;
+using NUnit.Framework;
+
+namespace NFC_Test.Crypto
+{
+ [TestFixture]
+ public class CRC16_Test
+ {
+ [Test]
+ [Ignore("Unknown Expected Data")]
+ public void Caluclate()
+ {
+ byte[] data = HexConverter.ConvertFromHexString("");
+ byte[] crc_expected = HexConverter.ConvertFromHexString("");
+
+ CRC16 crc16 = new CRC16();
+ byte[] crc = crc16.Calculate(data);
+
+ Assert.AreEqual(crc_expected, crc);
+ }
+ }
+}
diff --git a/NFC_Test/Crypto/CRC32_Test.cs b/NFC_Test/Crypto/CRC32_Test.cs
new file mode 100644
index 0000000..aa14248
--- /dev/null
+++ b/NFC_Test/Crypto/CRC32_Test.cs
@@ -0,0 +1,22 @@
+using NFC;
+using NFC.Crypto;
+using NUnit.Framework;
+
+namespace NFC_Test.Crypto
+{
+ [TestFixture]
+ public class CRC32_Test
+ {
+ [Test]
+ public void Caluclate()
+ {
+ byte[] data = HexConverter.ConvertFromHexString("c40045eeb8338ae8f49a032e85bb1114353010");
+ byte[] crc_expected = HexConverter.ConvertFromHexString("95c3894b");
+
+ CRC32 crc32 = new CRC32();
+ byte[] crc = crc32.Calculate(data);
+
+ Assert.AreEqual(crc_expected, crc);
+ }
+ }
+}
diff --git a/NFC_Test/Crypto/TDES_Test.cs b/NFC_Test/Crypto/TDES_Test.cs
new file mode 100644
index 0000000..3789040
--- /dev/null
+++ b/NFC_Test/Crypto/TDES_Test.cs
@@ -0,0 +1,61 @@
+using NFC.Crypto;
+using NFC.Mifare_DESFire;
+using NUnit.Framework;
+
+namespace NFC_Test.Crypto
+{
+ [TestFixture]
+ public class TDES_Test
+ {
+ [Test]
+ [Ignore("Unknown Expected Data")]
+ public void Encrypt_TDES()
+ {
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
+
+ byte[] data = desfire.ConvertFromHexString("");
+ byte[] key = desfire.ConvertFromHexString("");
+ byte[] iv = desfire.ConvertFromHexString("0000000000000000");
+
+ TDES des = new TDES();
+ byte[] data_enc = des.Encrypt(data, key, iv);
+
+ byte[] data_enc_expected = desfire.ConvertFromHexString("");
+ Assert.AreEqual(data_enc_expected, data_enc);
+ }
+
+ [Test]
+ [Ignore("Unknown Expected Data")]
+ public void Encrypt_TDES_2K()
+ {
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
+
+ byte[] data = desfire.ConvertFromHexString("");
+ byte[] key = desfire.ConvertFromHexString("");
+ byte[] iv = desfire.ConvertFromHexString("0000000000000000");
+
+ TDES_2K des = new TDES_2K();
+ byte[] data_enc = des.Encrypt(data, key, iv);
+
+ byte[] data_enc_expected = desfire.ConvertFromHexString("");
+ Assert.AreEqual(data_enc_expected, data_enc);
+ }
+
+ [Test]
+ [Ignore("Unknown Expected Data")]
+ public void Encrypt_TDES_3K()
+ {
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
+
+ byte[] data = desfire.ConvertFromHexString("");
+ byte[] key = desfire.ConvertFromHexString("");
+ byte[] iv = desfire.ConvertFromHexString("0000000000000000");
+
+ TDES_3K des = new TDES_3K();
+ byte[] data_enc = des.Encrypt(data, key, iv);
+
+ byte[] data_enc_expected = desfire.ConvertFromHexString("");
+ Assert.AreEqual(data_enc_expected, data_enc);
+ }
+ }
+}
\ No newline at end of file
diff --git a/NFC_Test/ISO7816-4/APDUCommand_Test.cs b/NFC_Test/ISO7816-4/APDUCommand_Test.cs
new file mode 100644
index 0000000..28c68e1
--- /dev/null
+++ b/NFC_Test/ISO7816-4/APDUCommand_Test.cs
@@ -0,0 +1,119 @@
+using System;
+using NFC.ISO7816_4;
+using NUnit.Framework;
+using PCSC.Iso7816;
+
+namespace NFC_Test.ISO7816_4
+{
+ [TestFixture]
+ public class APDUCommand_Test
+ {
+ [Test]
+ public void Compare()
+ {
+ APDUCommand command1 = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0xAA,
+ Data = new byte[]
+ {
+ 0x01, 0x02, 0x03
+ }
+ };
+
+ APDUCommand command2 = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0xAA,
+ Data = new byte[]
+ {
+ 0x01, 0x02, 0x03
+ }
+ };
+
+ Assert.IsTrue(command1 == command2);
+ }
+
+ [Test]
+ public void Compare_Diff()
+ {
+ APDUCommand command1 = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0xAA,
+ Data = new byte[]
+ {
+ 0x01, 0x02, 0x03
+ }
+ };
+
+ APDUCommand command2 = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0x1A,
+ Data = new byte[]
+ {
+ 0x01, 0x02, 0x03
+ }
+ };
+
+ Assert.IsFalse(command1 == command2);
+ }
+
+ [Test]
+ public void ToString_Case1()
+ {
+ APDUCommand command = new APDUCommand(IsoCase.Case1)
+ {
+ CLA = 0x90,
+ INS = 0x1A
+ };
+
+ Console.WriteLine(command.ToString());
+ }
+
+ [Test]
+ public void ToString_Case2()
+ {
+ APDUCommand command = new APDUCommand(IsoCase.Case2Short)
+ {
+ CLA = 0x90,
+ INS = 0x1A
+ };
+
+ Console.WriteLine(command.ToString());
+ }
+
+ [Test]
+ public void ToString_Case3()
+ {
+ APDUCommand command = new APDUCommand(IsoCase.Case3Short)
+ {
+ CLA = 0x90,
+ INS = 0x1A,
+ Data = new byte[]
+ {
+ 0x01, 0x02, 0x03
+ }
+ };
+
+ Console.WriteLine(command.ToString());
+ }
+
+ [Test]
+ public void ToString_Case4()
+ {
+ APDUCommand command = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = 0x1A,
+ Data = new byte[]
+ {
+ 0x01, 0x02, 0x03
+ }
+ };
+
+ Console.WriteLine(command.ToString());
+ }
+ }
+}
diff --git a/NFC_Test/MifareDESFire_Commands.cs b/NFC_Test/MifareDESFire_Commands.cs
deleted file mode 100644
index 504b25a..0000000
--- a/NFC_Test/MifareDESFire_Commands.cs
+++ /dev/null
@@ -1,34 +0,0 @@
-using NFC;
-using NFC.Mifare_DESFire;
-using NFC.Mifare_DESFire.Enums;
-using NUnit.Framework;
-using System;
-using System.Collections.Generic;
-using System.Text;
-
-namespace NFC_Test
-{
- [TestFixture]
- public class MifareDESFire_Commands
- {
- private MIFARE_DESFire _MifareDESFire;
-
- [SetUp]
- public void SetUp()
- {
- //_MifareDESFire = new MifareDESFire();
- }
-
- [Test]
- public void GetApplicationIDs()
- {
-
- }
-
- [Test]
- public void GenerateKeySetting1()
- {
- Assert.AreEqual(0xEF, _MifareDESFire.GenerateKeySetting1(ChangeApplicationKey.SAMEKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE));
- }
- }
-}
diff --git a/NFC_Test/NFC_Test.csproj b/NFC_Test/NFC_Test.csproj
index d420e5c..28d0baf 100644
--- a/NFC_Test/NFC_Test.csproj
+++ b/NFC_Test/NFC_Test.csproj
@@ -1,4 +1,4 @@
-
+
netcoreapp3.1
diff --git a/NFC_Test/MIFARE_DESFire_V2_Test.cs b/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs
similarity index 73%
rename from NFC_Test/MIFARE_DESFire_V2_Test.cs
rename to NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs
index a3a8a2b..0a1b6d5 100644
--- a/NFC_Test/MIFARE_DESFire_V2_Test.cs
+++ b/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs
@@ -3,17 +3,13 @@ using NFC.ISO7816_4;
using NFC.Mifare_DESFire;
using NFC.NXP_MIFARE_DESFire.Exceptions;
using NSubstitute;
-using NSubstitute.Core;
using NUnit.Framework;
-using PCSC.Iso7816;
using System;
-using System.Collections.Generic;
-using System.Net;
-namespace NFC_Test
+namespace NFC_Test.NXP_MIFARE_DESFire
{
[TestFixture]
- public class MIFARE_DESFire_V2_Test
+ public class MIFARE_DESFire_Test
{
#region Helper Methods
[Test]
@@ -21,7 +17,7 @@ namespace NFC_Test
{
uint i = 16;
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data = desfire.GenerateEmptyKey(i);
@@ -37,7 +33,7 @@ namespace NFC_Test
[Test]
public void CheckAPDUResponse__NULL()
{
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
{
@@ -54,7 +50,7 @@ namespace NFC_Test
SW2 = 0x00
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
{
@@ -71,7 +67,7 @@ namespace NFC_Test
SW2 = 0x00
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
desfire.CheckAPDUResponse(response);
}
@@ -85,7 +81,7 @@ namespace NFC_Test
SW2 = 0x0C
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
desfire.CheckAPDUResponse(response);
}
@@ -98,7 +94,7 @@ namespace NFC_Test
SW2 = 0x1C
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -116,7 +112,7 @@ namespace NFC_Test
SW2 = 0x1E
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -134,7 +130,7 @@ namespace NFC_Test
SW2 = 0x40
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -152,7 +148,7 @@ namespace NFC_Test
SW2 = 0x7E
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -170,7 +166,7 @@ namespace NFC_Test
SW2 = 0x9D
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -189,7 +185,7 @@ namespace NFC_Test
SW2 = 0x9E
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -208,7 +204,7 @@ namespace NFC_Test
SW2 = 0xAD
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -226,7 +222,7 @@ namespace NFC_Test
SW2 = 0xAE
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -244,7 +240,7 @@ namespace NFC_Test
SW2 = 0xAF
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
desfire.CheckAPDUResponse(response);
}
@@ -258,7 +254,7 @@ namespace NFC_Test
SW2 = 0xBE
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -276,7 +272,7 @@ namespace NFC_Test
SW2 = 0xCA
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -294,7 +290,7 @@ namespace NFC_Test
SW2 = 0xDE
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -312,7 +308,7 @@ namespace NFC_Test
SW2 = 0xF0
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -336,7 +332,7 @@ namespace NFC_Test
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] lastblock = desfire.ExtractLastBlock(data, 8);
@@ -351,7 +347,7 @@ namespace NFC_Test
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -365,7 +361,7 @@ namespace NFC_Test
{
byte[] data = null;
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -387,7 +383,7 @@ namespace NFC_Test
0x02, 0x03, 0x04, 0x01
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_left = desfire.RotateLeft(data);
@@ -397,7 +393,7 @@ namespace NFC_Test
[Test]
public void RotateLeft_Null()
{
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -419,7 +415,7 @@ namespace NFC_Test
0x04, 0x01, 0x02, 0x03
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_left = desfire.RotateRight(data);
@@ -429,7 +425,7 @@ namespace NFC_Test
[Test]
public void RotateRight_Null()
{
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -456,17 +452,47 @@ namespace NFC_Test
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_c = desfire.Concatenate(data_a, data_b);
Assert.AreEqual(expected_data_c, data_c);
}
+ [Test]
+ public void Concatenate_ABC()
+ {
+ byte[] data_a = new byte[]
+ {
+ 0x01, 0x02, 0x03, 0x04
+ };
+
+ byte[] data_b = new byte[]
+ {
+ 0x05, 0x06, 0x07, 0x08
+ };
+
+ byte[] data_c = new byte[]
+ {
+ 0x09, 0xA0, 0xB0, 0xC0
+ };
+
+ byte[] expected_data_d = new byte[]
+ {
+ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xA0, 0xB0, 0xC0
+ };
+
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
+
+ byte[] data_d = desfire.Concatenate(data_a, data_b, data_c);
+
+ Assert.AreEqual(expected_data_d, data_d);
+ }
+
[Test]
public void Concatenate_Null()
{
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -493,7 +519,7 @@ namespace NFC_Test
0x0F, 0xF0, 0x0F, 0xF0
};
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] data_c = desfire.XOR(data_a, data_b);
@@ -503,7 +529,7 @@ namespace NFC_Test
[Test]
public void XOR_null()
{
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
Assert.Throws(
delegate
@@ -515,7 +541,7 @@ namespace NFC_Test
[Test]
public void GenerateSessionKey_AES()
{
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
byte[] rndA = desfire.ConvertFromHexString("bc14dfde20074617e45a8822f06fdd91");
Console.WriteLine(desfire.ConvertToHexString(rndA));
@@ -537,31 +563,31 @@ namespace NFC_Test
{
ICard card = Substitute.For();
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response_challenge_request = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xAF,
- Body = desfire.ConvertFromHexString("5D994CE085F24089")
+ Body = HexConverter.ConvertFromHexString("5D994CE085F24089")
};
APDUResponse response_challenge_response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x00,
- Body = desfire.ConvertFromHexString("913C6DED84221C41")
+ Body = HexConverter.ConvertFromHexString("913C6DED84221C41")
};
- byte[] rndA = desfire.ConvertFromHexString("849B36C5F8BF4A09");
- byte[] key = desfire.ConvertFromHexString("00000000000000000000000000000000");
+ byte[] rndA = HexConverter.ConvertFromHexString("849B36C5F8BF4A09");
+ byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
card.Transmit(Arg.Is(x => x.INS == 0x1A)).Returns(response_challenge_request);
card.Transmit(Arg.Is(x => x.INS == 0xAF)).Returns(response_challenge_response);
desfire.AuthenticateISO_DES(0x00, key, rndA);
- byte[] expected_sessionkey = desfire.ConvertFromHexString("849B36C54FD1B759849B36C54FD1B759");
+ byte[] expected_sessionkey = HexConverter.ConvertFromHexString("849B36C54FD1B759849B36C54FD1B759");
byte[] expected_iv = desfire.GenerateEmptyKey(8);
Assert.AreEqual(expected_sessionkey, desfire._SessionKey);
@@ -573,31 +599,31 @@ namespace NFC_Test
{
ICard card = Substitute.For();
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response_challenge_request = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0xAF,
- Body = desfire.ConvertFromHexString("43a28e28c653df83cd85039714bccb51")
+ Body = HexConverter.ConvertFromHexString("43a28e28c653df83cd85039714bccb51")
};
APDUResponse response_challenge_response = new APDUResponse()
{
SW1 = 0x91,
SW2 = 0x00,
- Body = desfire.ConvertFromHexString("d8f70a0f9a43f522f775a56f5688592f")
+ Body = HexConverter.ConvertFromHexString("d8f70a0f9a43f522f775a56f5688592f")
};
- byte[] rndA = desfire.ConvertFromHexString("8a8b3c15e576ae3a21c2b18e6aead1f1");
- byte[] key = desfire.ConvertFromHexString("00000000000000000000000000000000");
+ byte[] rndA = HexConverter.ConvertFromHexString("8a8b3c15e576ae3a21c2b18e6aead1f1");
+ byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
card.Transmit(Arg.Is(x => x.INS == 0xAA)).Returns(response_challenge_request);
card.Transmit(Arg.Is(x => x.INS == 0xAF)).Returns(response_challenge_response);
desfire.AuthenticateISO_AES(0x00, key, rndA);
- byte[] expected_sessionkey = desfire.ConvertFromHexString("8a8b3c15c71d0cf46aead1f148f27703");
+ byte[] expected_sessionkey = HexConverter.ConvertFromHexString("8a8b3c15c71d0cf46aead1f148f27703");
byte[] expected_iv = desfire.GenerateEmptyKey(16);
Assert.AreEqual(expected_sessionkey, desfire._SessionKey);
@@ -609,7 +635,7 @@ namespace NFC_Test
{
ICard card = Substitute.For();
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response = new APDUResponse()
{
@@ -617,10 +643,10 @@ namespace NFC_Test
SW2 = 0x00
};
- byte[] new_key = desfire.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530");
+ byte[] new_key = HexConverter.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530");
- byte[] sessionkey = desfire.ConvertFromHexString("2f96515262e1beb0129de2df3e97feb3");
- byte[] iv = desfire.ConvertFromHexString("00000000000000000000000000000000");
+ byte[] sessionkey = HexConverter.ConvertFromHexString("2f96515262e1beb0129de2df3e97feb3");
+ byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
desfire._SessionKey = sessionkey;
desfire._IV = iv;
@@ -635,7 +661,7 @@ namespace NFC_Test
{
ICard card = Substitute.For();
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(card);
APDUResponse response = new APDUResponse()
{
@@ -643,11 +669,11 @@ namespace NFC_Test
SW2 = 0x00
};
- byte[] new_key = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12");
- byte[] old_key = desfire.ConvertFromHexString("00000000000000000000000000000000");
+ byte[] new_key = HexConverter.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12");
+ byte[] old_key = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
- byte[] sessionkey = desfire.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b");
- byte[] iv = desfire.ConvertFromHexString("00000000000000000000000000000000");
+ byte[] sessionkey = HexConverter.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b");
+ byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000");
desfire._SessionKey = sessionkey;
desfire._IV = iv;
@@ -657,5 +683,27 @@ namespace NFC_Test
desfire.ChangeOtherKey_AES(0x01, new_key, old_key, 0x10);
}
#endregion
+
+ #region Configuration Generator
+ [Test]
+ public void GenerateFileAccessRights()
+ {
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
+
+ Assert.AreEqual(0x1234, desfire.GenerateFileAccessRights(0x01, 0x02, 0x03, 0x04));
+ }
+
+ [Test]
+ public void GenerateFileAccessRights_OutOfRange()
+ {
+ MIFARE_DESFire desfire = new MIFARE_DESFire(null);
+
+ Assert.Throws(
+ delegate
+ {
+ desfire.GenerateFileAccessRights(0x10, 0x00, 0x00, 0x00);
+ });
+ }
+ #endregion
}
}
diff --git a/NFC_Test/NamespaceSetUp.cs b/NFC_Test/NamespaceSetUp.cs
index 4cb85ab..eb86856 100644
--- a/NFC_Test/NamespaceSetUp.cs
+++ b/NFC_Test/NamespaceSetUp.cs
@@ -1,14 +1,11 @@
-using log4net;
-using log4net.Config;
+using log4net.Config;
using NUnit.Framework;
-using System;
namespace NFC_Test
{
[SetUpFixture]
public class NamespaceSetUp
- {
- private static readonly ILog log = LogManager.GetLogger(typeof(NamespaceSetUp));
+ {
[OneTimeSetUp]
public void OneTimeSetUp()
{
diff --git a/NFC_Test/OTA.cs b/NFC_Test/OTA.cs
index 217efa4..9e1cd36 100644
--- a/NFC_Test/OTA.cs
+++ b/NFC_Test/OTA.cs
@@ -3,6 +3,8 @@ using NFC;
using NFC.Readers.PCSC;
using NFC.Mifare_DESFire;
using NFC.Mifare_DESFire.Enums;
+using System;
+using System.Text;
namespace NFC_Test
{
@@ -23,7 +25,7 @@ namespace NFC_Test
{
card.Connect();
- MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card);
+ MIFARE_DESFire desfire = new MIFARE_DESFire(card);
desfire.SelectApplication(0x000000);
desfire.AuthenticateISO_DES(0x00, desfire.GenerateEmptyKey(16));
@@ -49,6 +51,15 @@ namespace NFC_Test
desfire.AuthenticateISO_AES(0x00, key_master);
desfire.ChangeOtherKey_AES(0x02, key_2, desfire.GenerateEmptyKey(16), 0x10);
+ UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00);
+ desfire.CreateFile_Standard(0x01, FileCommunication.PLAIN, accesRights, 0x100);
+
+ desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes("user@domain.org"));
+
+ byte[] data = desfire.ReadData(0x01, 0, 32);
+
+ Console.WriteLine(Encoding.ASCII.GetString(data));
+
transmit_successfully = true;
card.Disconnect();
diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs
index 0e35f12..0951e4b 100644
--- a/NFC_Test/REAL_Windows.cs
+++ b/NFC_Test/REAL_Windows.cs
@@ -58,275 +58,5 @@ namespace NFC_Test
reader.Stop();
reader.CardDiscovered -= handler;
}
-
- [TestCase("ACS ACR122U PICC Interface 0")]
- public void GetApplicationIDs(string readerID)
- {
- IHardware hardware = new Hardware();
- IReader reader = hardware.OpenReader(readerID);
-
- bool transmit_successfully = false;
-
- ReaderEventHandler handler = (sender, card) =>
- {
- card.Connect();
-
- MIFARE_DESFire desfire = new MIFARE_DESFire(card);
-
- //APDUCommand cmd = desfire.GetApplicationIDs();
-
- //APDUResponse response = card.Transmit(cmd);
-
- //if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK)
- //{
- // UInt32[] ApplicationIDs = desfire.ConvertApplicationIDs(response);
-
- // foreach(UInt32 id in ApplicationIDs)
- // {
- // Console.WriteLine("0x{0:X3}", id);
- // }
-
- // transmit_successfully = true;
- //}
-
- card.Disconnect();
- };
-
- reader.CardDiscovered += handler;
- reader.Start();
-
- Assert.AreEqual(true, transmit_successfully);
-
- reader.Stop();
- reader.CardDiscovered -= handler;
- }
-
- [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xC0FFEE)]
- public void SelectApplication(string readerID, UInt32 applicationID)
- {
- IHardware hardware = new Hardware();
- IReader reader = hardware.OpenReader(readerID);
-
- bool transmit_successfully = false;
-
- ReaderEventHandler handler = (sender, card) =>
- {
- card.Connect();
-
- //MIFARE_DESFire desfire = new MIFARE_DESFire(card);
-
- //APDUCommand cmd = desfire.SelectApplication(applicationID);
-
- //cmd.ToArray();
-
- //APDUResponse response = card.Transmit(cmd);
-
- //if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK)
- //{
- // transmit_successfully = true;
- //}
-
- card.Disconnect();
- };
-
- reader.CardDiscovered += handler;
- reader.Start();
-
- Assert.AreEqual(true, transmit_successfully);
-
- reader.Stop();
- reader.CardDiscovered -= handler;
- }
-
- [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)]
- public void CreateApplication(string readerID, UInt32 applicationID)
- {
- //IHardware hardware = new Hardware();
- //IReader reader = hardware.OpenReader(readerID);
-
- //bool transmit_successfully = false;
-
- //ReaderEventHandler handler = (sender, card) =>
- //{
- // card.Connect();
-
- // MIFARE_DESFire desfire = new MIFARE_DESFire(card);
-
- // byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE);
- // byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.TDES, FileIdentifies.NOTUSED, 0x03);
-
- // APDUCommand cmd = desfire.CreateApplication(applicationID, keysetting1, keysetting2);
-
- // Console.WriteLine(cmd.ToArray());
-
- // APDUResponse response = card.Transmit(cmd);
-
- // if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK)
- // {
- // transmit_successfully = true;
- // }
-
- // card.Disconnect();
- //};
-
- //reader.CardDiscovered += handler;
- //reader.Start();
-
- //Assert.AreEqual(true, transmit_successfully);
-
- //reader.Stop();
- //reader.CardDiscovered -= handler;
- }
-
- [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)]
- public void DeleteApplication(string readerID, UInt32 applicationID)
- {
- IHardware hardware = new Hardware();
- IReader reader = hardware.OpenReader(readerID);
-
- bool transmit_successfully = false;
-
- ReaderEventHandler handler = (sender, card) =>
- {
- card.Connect();
-
- MIFARE_DESFire desfire = new MIFARE_DESFire(card);
-
- desfire.SelectApplication(0x000000);
- desfire.AuthenticateDES(0x00, GenerateDefaultKey(8));
- desfire.DeleteApplication(applicationID);
-
- transmit_successfully = true;
-
- card.Disconnect();
- };
-
- reader.CardDiscovered += handler;
- reader.Start();
-
- Assert.AreEqual(true, transmit_successfully);
-
- reader.Stop();
- reader.CardDiscovered -= handler;
- }
-
- public byte[] GenerateDefaultKey(int size)
- {
- List key = new List();
- for(int i = 0; i < size; i++)
- {
- key.Add(0);
- }
-
- return key.ToArray();
- }
-
- ///
- /// Used Default PICC Key with PICC authenticate
- ///
- ///
- [TestCase("ACS ACR122U PICC Interface 0")]
- public void Authenticate(string readerID)
- {
- IHardware hardware = new Hardware();
- IReader reader = hardware.OpenReader(readerID);
-
- bool transmit_successfully = false;
-
- ReaderEventHandler handler = (sender, card) =>
- {
- card.Connect();
-
- MIFARE_DESFire desfire = new MIFARE_DESFire(card);
-
- desfire.SelectApplication(0x000000);
- desfire.AuthenticateDES(0x00, GenerateDefaultKey(8));
-
- transmit_successfully = true;
-
- card.Disconnect();
- };
-
- reader.CardDiscovered += handler;
- reader.Start();
-
- Assert.AreEqual(true, transmit_successfully);
-
- reader.Stop();
- reader.CardDiscovered -= handler;
- }
-
- [TestCase("ACS ACR122U PICC Interface 0")]
- public void ChangeKey(string readerID)
- {
- IHardware hardware = new Hardware();
- IReader reader = hardware.OpenReader(readerID);
-
- bool transmit_successfully = false;
-
- ReaderEventHandler handler = (sender, card) =>
- {
- card.Connect();
-
- MIFARE_DESFire desfire = new MIFARE_DESFire(card);
-
- desfire.SelectApplication(0xAAFFEE);
- desfire.AuthenticateDES(0x00, GenerateDefaultKey(8));
- desfire.ChangeKeyDES(0x00, GenerateDefaultKey(8), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF });
-
- transmit_successfully = true;
-
- card.Disconnect();
- };
-
- reader.CardDiscovered += handler;
- reader.Start();
-
- Assert.AreEqual(true, transmit_successfully);
-
- reader.Stop();
- reader.CardDiscovered -= handler;
- }
-
- [TestCase("ACS ACR122U PICC Interface 0")]
- public void ChangeKey_Test(string readerID)
- {
- IHardware hardware = new Hardware();
- IReader reader = hardware.OpenReader(readerID);
-
- bool transmit_successfully = false;
-
- ReaderEventHandler handler = (sender, card) =>
- {
- card.Connect();
-
- MIFARE_DESFire desfire = new MIFARE_DESFire(card);
-
- desfire.SelectApplication(0xAAFFEE);
- desfire.AuthenticateDES(0x00, GenerateDefaultKey(8));
-
- APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
- {
- CLA = 0x90,
- INS = 0xC4,
- Data = GenerateDefaultKey(1 + 16 + 4 + 4)
- // KEY_NO, KEY, CRC32, PADDING
- };
-
- card.Transmit(cmd);
-
- transmit_successfully = true;
-
- card.Disconnect();
- };
-
- reader.CardDiscovered += handler;
- reader.Start();
-
- Assert.AreEqual(true, transmit_successfully);
-
- reader.Stop();
- reader.CardDiscovered -= handler;
- }
}
}
diff --git a/NFC_Test/REAL_Windows_CardSetUp.cs b/NFC_Test/REAL_Windows_CardSetUp.cs
index 652913b..931a17a 100644
--- a/NFC_Test/REAL_Windows_CardSetUp.cs
+++ b/NFC_Test/REAL_Windows_CardSetUp.cs
@@ -9,183 +9,183 @@ using System.Text;
namespace NFC_Test
{
- [TestFixture]
- public class REAL_Windows_CardSetUp
- {
- public static UInt32 FabAccessAID = 0x001100;
- public static string CardReaderID = "ACS ACR122U PICC Interface 0";
- public static byte[] PICC_MasterKey = new byte[]
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
+ //[TestFixture]
+ //public class REAL_Windows_CardSetUp
+ //{
+ // public static UInt32 FabAccessAID = 0x001100;
+ // public static string CardReaderID = "ACS ACR122U PICC Interface 0";
+ // public static byte[] PICC_MasterKey = new byte[]
+ // {
+ // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ // };
- public static byte[] APP_MasterKey = new byte[]
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
+ // public static byte[] APP_MasterKey = new byte[]
+ // {
+ // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ // };
- public static byte[] APP_Key_1 = new byte[]
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
+ // public static byte[] APP_Key_1 = new byte[]
+ // {
+ // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ // };
- public static byte[] APP_Key_2 = new byte[]
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
+ // public static byte[] APP_Key_2 = new byte[]
+ // {
+ // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ // };
- public static byte[] Empty_Key = new byte[]
- {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
+ // public static byte[] Empty_Key = new byte[]
+ // {
+ // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+ // };
- public static byte FabAccessIdentFileID = 0x01;
- public static string UserDomain = "user1@fabaccess.org";
+ // public static byte FabAccessIdentFileID = 0x01;
+ // public static string UserDomain = "user1@fabaccess.org";
- [Test]
- public void ResetCard()
- {
- IHardware hardware = new Hardware();
- IReader reader = hardware.OpenReader(CardReaderID);
+ // [Test]
+ // public void ResetCard()
+ // {
+ // IHardware hardware = new Hardware();
+ // IReader reader = hardware.OpenReader(CardReaderID);
- bool connected_successfully = false;
+ // bool connected_successfully = false;
- ReaderEventHandler handler = (sender, card) =>
- {
- card.Connect();
+ // ReaderEventHandler handler = (sender, card) =>
+ // {
+ // card.Connect();
- MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
+ // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
- mifareDESFire.AuthenticateDES(0x01, PICC_MasterKey);
+ // mifareDESFire.AuthenticateISO_DES(0x01, PICC_MasterKey);
- mifareDESFire.Format();
+ // mifareDESFire.Format();
- connected_successfully = true;
+ // connected_successfully = true;
- card.Disconnect();
- };
+ // card.Disconnect();
+ // };
- reader.CardDiscovered += handler;
- reader.Start();
+ // reader.CardDiscovered += handler;
+ // reader.Start();
- Assert.AreEqual(true, connected_successfully);
+ // Assert.AreEqual(true, connected_successfully);
- reader.Stop();
- reader.CardDiscovered -= handler;
- }
+ // reader.Stop();
+ // reader.CardDiscovered -= handler;
+ // }
- [Test]
- public void ProvisionCard()
- {
- IHardware hardware = new Hardware();
- IReader reader = hardware.OpenReader(CardReaderID);
+ // [Test]
+ // public void ProvisionCard()
+ // {
+ // IHardware hardware = new Hardware();
+ // IReader reader = hardware.OpenReader(CardReaderID);
- bool connected_successfully = false;
+ // bool connected_successfully = false;
- ReaderEventHandler handler = (sender, card) =>
- {
- card.Connect();
+ // ReaderEventHandler handler = (sender, card) =>
+ // {
+ // card.Connect();
- MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
+ // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
- mifareDESFire.AuthenticateDES(0x01, APP_MasterKey);
- mifareDESFire.CreateApplication(FabAccessAID);
- mifareDESFire.SelectApplication(FabAccessAID);
+ // mifareDESFire.AuthenticateISO_DES(0x01, APP_MasterKey);
+ // mifareDESFire.CreateApplication(FabAccessAID);
+ // mifareDESFire.SelectApplication(FabAccessAID);
- mifareDESFire.AuthenticateDES(0x00, Empty_Key);
- mifareDESFire.ChangeApplicationMasterKey(APP_MasterKey);
+ // mifareDESFire.AuthenticateDES(0x00, Empty_Key);
+ // mifareDESFire.ChangeApplicationMasterKey(APP_MasterKey);
- mifareDESFire.AuthenticateDES(0x00, APP_MasterKey);
- mifareDESFire.ChangeApplicationKey(0x01, APP_Key_1);
+ // mifareDESFire.AuthenticateDES(0x00, APP_MasterKey);
+ // mifareDESFire.ChangeApplicationKey(0x01, APP_Key_1);
- connected_successfully = true;
+ // connected_successfully = true;
- card.Disconnect();
- };
+ // card.Disconnect();
+ // };
- reader.CardDiscovered += handler;
- reader.Start();
+ // reader.CardDiscovered += handler;
+ // reader.Start();
- Assert.AreEqual(true, connected_successfully);
+ // Assert.AreEqual(true, connected_successfully);
- reader.Stop();
- reader.CardDiscovered -= handler;
- }
+ // reader.Stop();
+ // reader.CardDiscovered -= handler;
+ // }
- [Test]
- public void SetUpUserCard()
- {
- IHardware hardware = new Hardware();
- IReader reader = hardware.OpenReader(CardReaderID);
+ // [Test]
+ // public void SetUpUserCard()
+ // {
+ // IHardware hardware = new Hardware();
+ // IReader reader = hardware.OpenReader(CardReaderID);
- bool connected_successfully = false;
+ // bool connected_successfully = false;
- ReaderEventHandler handler = (sender, card) =>
- {
- card.Connect();
+ // ReaderEventHandler handler = (sender, card) =>
+ // {
+ // card.Connect();
- MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
+ // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
- mifareDESFire.SelectApplication(FabAccessAID);
- mifareDESFire.AuthenticateDES(0x00, Empty_Key);
- UInt16 fileAccessRight = mifareDESFire.GenerateFileAccessRight(AccessRights.FREE, 0x00, 0x00, 0x00);
- mifareDESFire.CreateFile(FabAccessIdentFileID, FileCommunication.PLAIN, fileAccessRight, (UInt32)0x90);
+ // mifareDESFire.SelectApplication(FabAccessAID);
+ // mifareDESFire.AuthenticateDES(0x00, Empty_Key);
+ // UInt16 fileAccessRight = mifareDESFire.GenerateFileAccessRight(AccessRights.FREE, 0x00, 0x00, 0x00);
+ // mifareDESFire.CreateFile(FabAccessIdentFileID, FileCommunication.PLAIN, fileAccessRight, (UInt32)0x90);
- System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
+ // System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
- mifareDESFire.WirteData(FabAccessIdentFileID, 0x00000000, 0x00000000, enc.GetBytes(UserDomain));
+ // mifareDESFire.WirteData(FabAccessIdentFileID, 0x00000000, 0x00000000, enc.GetBytes(UserDomain));
- connected_successfully = true;
+ // connected_successfully = true;
- card.Disconnect();
- };
+ // card.Disconnect();
+ // };
- reader.CardDiscovered += handler;
- reader.Start();
+ // reader.CardDiscovered += handler;
+ // reader.Start();
- Assert.AreEqual(true, connected_successfully);
+ // Assert.AreEqual(true, connected_successfully);
- reader.Stop();
- reader.CardDiscovered -= handler;
- }
+ // reader.Stop();
+ // reader.CardDiscovered -= handler;
+ // }
- [Test]
- public void AuthenticateCard()
- {
- IHardware hardware = new Hardware();
- IReader reader = hardware.OpenReader(CardReaderID);
+ // [Test]
+ // public void AuthenticateCard()
+ // {
+ // IHardware hardware = new Hardware();
+ // IReader reader = hardware.OpenReader(CardReaderID);
- bool connected_successfully = false;
+ // bool connected_successfully = false;
- ReaderEventHandler handler = (sender, card) =>
- {
- card.Connect();
+ // ReaderEventHandler handler = (sender, card) =>
+ // {
+ // card.Connect();
- MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
+ // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card);
- mifareDESFire.SelectApplication(FabAccessAID);
- byte[] filedata = mifareDESFire.ReadData(FabAccessIdentFileID, 0x00000000, 0x00000000);
+ // mifareDESFire.SelectApplication(FabAccessAID);
+ // byte[] filedata = mifareDESFire.ReadData(FabAccessIdentFileID, 0x00000000, 0x00000000);
- System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
- string userdomain = enc.GetString(filedata);
+ // System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
+ // string userdomain = enc.GetString(filedata);
- Console.WriteLine(userdomain);
+ // Console.WriteLine(userdomain);
- mifareDESFire.AuthenticateDES(0x01, APP_Key_1);
+ // mifareDESFire.AuthenticateDES(0x01, APP_Key_1);
- connected_successfully = true;
+ // connected_successfully = true;
- card.Disconnect();
- };
+ // card.Disconnect();
+ // };
- reader.CardDiscovered += handler;
- reader.Start();
+ // reader.CardDiscovered += handler;
+ // reader.Start();
- Assert.AreEqual(true, connected_successfully);
+ // Assert.AreEqual(true, connected_successfully);
- reader.Stop();
- reader.CardDiscovered -= handler;
- }
- }
+ // reader.Stop();
+ // reader.CardDiscovered -= handler;
+ // }
+ //}
}