From f5dffcec5b75f18f0de150cac187d3e27052a8a4 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Tue, 6 Oct 2020 15:59:53 +0200 Subject: [PATCH] BackUp --- Borepin/Borepin.iOS/CNFC/Card.cs | 1 + NFC/Crypto/CRC32.cs | 44 +++++ NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs | 213 ++++++++++++++++++++++- NFC_Test/AuthCrypto_Test.cs | 1 + NFC_Test/REAL_Windows.cs | 146 ++++++++++------ 5 files changed, 338 insertions(+), 67 deletions(-) create mode 100644 NFC/Crypto/CRC32.cs 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; + } } }