diff --git a/Borepin/Borepin.iOS/CNFC/Card.cs b/Borepin/Borepin.iOS/CNFC/Card.cs
index 1758062..34a573f 100644
--- a/Borepin/Borepin.iOS/CNFC/Card.cs
+++ b/Borepin/Borepin.iOS/CNFC/Card.cs
@@ -3,6 +3,7 @@ using System.Threading;
using CoreNFC;
using Foundation;
using NFC;
+using NFC.ISO7816_4;
namespace Borepin.iOS.CNFC
{
diff --git a/NFC/Crypto/CRC32.cs b/NFC/Crypto/CRC32.cs
new file mode 100644
index 0000000..6593d6e
--- /dev/null
+++ b/NFC/Crypto/CRC32.cs
@@ -0,0 +1,44 @@
+using System;
+
+namespace NFC.Crypto
+{
+ public class CRC32
+ {
+ public byte[] Calculate(byte[] data)
+ {
+ UInt32 crc32 = 0xFFFFFFFF;
+
+ 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 Calculate(byte[] data, UInt32 crc32)
+ {
+ for (int i = 0; i < data.Length; i++)
+ {
+ crc32 ^= data[i];
+ for (int b = 0; b < 8; b++)
+ {
+ bool b_Bit = (crc32 & 0x01) > 0;
+ crc32 >>= 1;
+ if (b_Bit)
+ {
+ crc32 ^= 0xEDB88320;
+ }
+ }
+ }
+ return crc32;
+ }
+ }
+}
diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs
index c079087..4fbe232 100644
--- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs
+++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs
@@ -1,16 +1,13 @@
using NFC.Crypto;
using NFC.ISO7816_4;
using NFC.Mifare_DESFire.Enums;
-using Org.BouncyCastle.Asn1.Crmf;
using PCSC.Iso7816;
using System;
using System.Collections.Generic;
-using System.Data;
using System.Linq;
namespace NFC.Mifare_DESFire
{
-
public class MIFARE_DESFire
{
// Docs https://hackmd.io/qATu8uYdRnOC40aFrB9afg
@@ -31,6 +28,9 @@ namespace NFC.Mifare_DESFire
/// ICard Implementation used to transmit APDUCommands and recive APDUResponses
///
private ICard _Card;
+
+ public byte[] _SessionKey;
+ public byte[] _IV;
#endregion
#region Methods
@@ -43,7 +43,7 @@ namespace NFC.Mifare_DESFire
byte[] key = new byte[size];
for (int i = 0; i < size; i++)
{
- key.[i] = 0;
+ key[i] = 0;
}
return key;
@@ -64,6 +64,63 @@ namespace NFC.Mifare_DESFire
}
+ public bool CheckKey(byte[] key)
+ {
+ try
+ {
+ GetKeyTypeDES(key);
+ return true;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ ///
+ /// 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
///
/// Return a copy of the last Block of data
@@ -141,6 +198,23 @@ namespace NFC.Mifare_DESFire
return c;
}
+
+ public byte[] xor(byte[] a, byte[] b)
+ {
+ if(a.Length != b.Length)
+ {
+ throw new ArgumentException("Array are not same Length");
+ }
+
+ byte[] c = new byte[a.Length];
+
+ for(int i = 0; i < a.Length; i++)
+ {
+ c[i] = (byte)(a[i] ^ b[i]);
+ }
+
+ return c;
+ }
#endregion
#endregion
@@ -192,7 +266,7 @@ namespace NFC.Mifare_DESFire
{
byte[] id_byte = BitConverter.GetBytes(aid);
- APDUCommand cmd = new APDUCommand(IsoCase.Case3Short)
+ APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = (byte)APDUInstructions.SELECT_APPLICATION,
@@ -201,8 +275,7 @@ namespace NFC.Mifare_DESFire
id_byte[0],
id_byte[1],
id_byte[2]
- },
- Le = 0x00
+ }
};
APDUResponse response = _Card.Transmit(cmd);
@@ -211,7 +284,76 @@ namespace NFC.Mifare_DESFire
}
#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 + 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)
+ {
+ if(!CheckKey(key_new))
+ {
+ throw new ArgumentException("key_new is invalid");
+ }
+
+ if (!CheckKey(key_current))
+ {
+ throw new ArgumentException("key_new is invalid");
+ }
+
+ if(GetKeyTypeDES(key_new) != GetKeyTypeDES(key_current))
+ {
+ throw new ArgumentException("key_new and key_current are not same KeyType");
+ }
+
+ byte[] keys_xor = xor(key_new, key_current);
+
+ keys_xor = concatenate(keys_xor, keys_xor);
+
+ CRC32 crc32 = new CRC32();
+ byte[] crc = crc32.Calculate(new byte[] { (byte)APDUInstructions.CHANGE_KEY, key_no }, keys_xor);
+
+ byte[] key_xor_crc = concatenate(keys_xor, crc);
+
+ byte[] key_xor_crc_block = expandToBlockSize(key_xor_crc, 8);
+
+
+ DES des = new DES();
+
+ byte[] key_xor_crc_block_enc = des.Encrypt(key_xor_crc_block, _SessionKey, _IV);
+
+ APDUCommand cmd = new APDUCommand(IsoCase.Case4Short)
+ {
+ CLA = 0x90,
+ INS = (byte)APDUInstructions.CHANGE_KEY,
+ Data = key_xor_crc_block_enc,
+ Le = 0x00
+ };
+
+ APDUResponse response = _Card.Transmit(cmd);
+
+ CheckAPDUResponse(response);
+ }
@@ -302,6 +444,58 @@ namespace NFC.Mifare_DESFire
{
throw new Exception("PICC Challenge is not correct answered.");
}
+
+ _SessionKey = GenerateDESSesionKey(rndA, rndB);
+ _IV = GenerateDefaultKey(8);
+ }
+
+ private byte[] GenerateDESSesionKey(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];
+ }
+ }
+
+ // Set Key Verion of Key to 0x55 to LSB
+ // TODO
+ byte[] key_version = SetKeyVersion(sesssionkey, 0x55);
+
+ return concatenate(key_version, key_version);
+ }
+
+ 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;
}
public void ChangeApplicationMasterKey(byte[] aPP_MasterKey)
@@ -313,7 +507,7 @@ namespace NFC.Mifare_DESFire
/// Delete Application by ID
///
/// 3 Byte ID
- public APDUCommand DeleteApplication(UInt32 id)
+ public void DeleteApplication(UInt32 id)
{
byte[] id_byte = BitConverter.GetBytes(id);
@@ -330,7 +524,8 @@ namespace NFC.Mifare_DESFire
Le = 0x00
};
- return cmd;
+ APDUResponse response = _Card.Transmit(cmd);
+ CheckAPDUResponse(response);
}
public void ChangeApplicationKey(int v, byte[] aPP_Key_1)
diff --git a/NFC_Test/AuthCrypto_Test.cs b/NFC_Test/AuthCrypto_Test.cs
index f429834..49fde2b 100644
--- a/NFC_Test/AuthCrypto_Test.cs
+++ b/NFC_Test/AuthCrypto_Test.cs
@@ -1,5 +1,6 @@
using NFC;
using NFC.Crypto;
+using NFC.ISO7816_4;
using NFC.Mifare_DESFire;
using NSubstitute;
using NUnit.Framework;
diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs
index bb2ebfb..e6118b8 100644
--- a/NFC_Test/REAL_Windows.cs
+++ b/NFC_Test/REAL_Windows.cs
@@ -7,6 +7,7 @@ using NFC.Readers.PCSC;
using System.Threading;
using NFC.Mifare_DESFire;
using NFC.Mifare_DESFire.Enums;
+using NFC.ISO7816_4;
namespace NFC_Test
{
@@ -71,21 +72,21 @@ namespace NFC_Test
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
- APDUCommand cmd = desfire.GetApplicationIDs();
+ //APDUCommand cmd = desfire.GetApplicationIDs();
- APDUResponse response = card.Transmit(cmd);
+ //APDUResponse response = card.Transmit(cmd);
- if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK)
- {
- UInt32[] ApplicationIDs = desfire.ConvertApplicationIDs(response);
+ //if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK)
+ //{
+ // UInt32[] ApplicationIDs = desfire.ConvertApplicationIDs(response);
- foreach(UInt32 id in ApplicationIDs)
- {
- Console.WriteLine("0x{0:X3}", id);
- }
+ // foreach(UInt32 id in ApplicationIDs)
+ // {
+ // Console.WriteLine("0x{0:X3}", id);
+ // }
- transmit_successfully = true;
- }
+ // transmit_successfully = true;
+ //}
card.Disconnect();
};
@@ -111,18 +112,18 @@ namespace NFC_Test
{
card.Connect();
- MIFARE_DESFire desfire = new MIFARE_DESFire(card);
+ //MIFARE_DESFire desfire = new MIFARE_DESFire(card);
- APDUCommand cmd = desfire.SelectApplication(applicationID);
+ //APDUCommand cmd = desfire.SelectApplication(applicationID);
- cmd.ToArray();
+ //cmd.ToArray();
- APDUResponse response = card.Transmit(cmd);
+ //APDUResponse response = card.Transmit(cmd);
- if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK)
- {
- transmit_successfully = true;
- }
+ //if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK)
+ //{
+ // transmit_successfully = true;
+ //}
card.Disconnect();
};
@@ -136,44 +137,7 @@ namespace NFC_Test
reader.CardDiscovered -= handler;
}
- [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xC0FFEE)]
- 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);
-
- APDUCommand cmd = desfire.DeleteApplication(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)0xC0FFEE)]
+ [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)]
public void CreateApplication(string readerID, UInt32 applicationID)
{
IHardware hardware = new Hardware();
@@ -188,7 +152,7 @@ namespace NFC_Test
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.SAMEKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE);
- byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x01);
+ byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.TDES, FileIdentifies.NOTUSED, 0x03);
APDUCommand cmd = desfire.CreateApplication(applicationID, keysetting1, keysetting2);
@@ -213,6 +177,38 @@ namespace NFC_Test
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();
@@ -223,6 +219,7 @@ namespace NFC_Test
return key.ToArray();
}
+
///
/// Used Default PICC Key with PICC authenticate
///
@@ -241,6 +238,7 @@ namespace NFC_Test
MIFARE_DESFire desfire = new MIFARE_DESFire(card);
+ desfire.SelectApplication(0x000000);
desfire.AuthenticateDES(0x00, GenerateDefaultKey(8));
transmit_successfully = true;
@@ -256,5 +254,37 @@ namespace NFC_Test
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(0x01, 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;
+ }
}
}