using NFC; using NFC.Cards.NXP_MIFARE_DESFire; using NFC.Cards.NXP_MIFARE_DESFire.Enums; using NFC.Cards.NXP_MIFARE_DESFire.Exceptions; using NFC.Helper; using NFC.Interfaces; using NSubstitute; using NUnit.Framework; using System; using System.Text; namespace NFC_Test.Cards { [TestFixture] public class MIFARE_DESFire_Test { #region Helper Methods [Test] public void CheckAPDUResponse__NULL() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(null); }); } [Test] public void CheckAPDUResponse__UNKNOWN() { APDUResponse response = new APDUResponse() { SW1 = 0x00, SW2 = 0x00 }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__OPERATION_OK() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00 }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); desfire.CheckAPDUResponse(response); } [Test] public void CheckAPDUResponse__NO_CHANGES() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x0C }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); desfire.CheckAPDUResponse(response); } [Test] public void CheckAPDUResponse__ILLEGAL_COMMAND_CODE() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x1C }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__INTEGRITY_ERROR() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x1E }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__NO_SUCH_KEY() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x40 }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__LENGTH_ERROR() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x7E }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__PERMISSION_DENIED() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x9D }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__PARAMETER_ERROR() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x9E }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__AUTHENTICATION_DELAY() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0xAD }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__AUTHENTICATION_ERROR() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0xAE }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__ADDITIONAL_FRAME() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0xAF }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); desfire.CheckAPDUResponse(response); } [Test] public void CheckAPDUResponse__BOUNDARY_ERROR() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0xBE }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__COMMAND_ABORTED() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0xCA }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__DUPLICATE_ERROR() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0xDE }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } [Test] public void CheckAPDUResponse__FILE_NOT_FOUND() { APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0xF0 }; NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CheckAPDUResponse(response); }); } #endregion #region Crypto Operation [Test] public void GenerateSessionKey_DES() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); byte[] rndA = HexConverter.ConvertFromHexString("a541a9dc9138df07"); Console.WriteLine(HexConverter.ConvertToHexString(rndA)); byte[] rndB = HexConverter.ConvertFromHexString("cbe55aa893b2da25"); Console.WriteLine(HexConverter.ConvertToHexString(rndB)); byte[] expected_sessionkey = HexConverter.ConvertFromHexString("a541a9dccbe55aa8a541a9dccbe55aa8"); Console.WriteLine(HexConverter.ConvertToHexString(expected_sessionkey)); byte[] sessionkey = desfire.GenerateSesionKey_DES(rndA, rndB); Console.WriteLine(HexConverter.ConvertToHexString(sessionkey)); Assert.AreEqual(expected_sessionkey, sessionkey); } [Test] public void GenerateSessionKey_AES() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); byte[] rndA = HexConverter.ConvertFromHexString("bc14dfde20074617e45a8822f06fdd91"); Console.WriteLine(HexConverter.ConvertToHexString(rndA)); byte[] rndB = HexConverter.ConvertFromHexString("482ddc54426e6dee560413b8d95471f5"); Console.WriteLine(HexConverter.ConvertToHexString(rndB)); byte[] expected_sessionkey = HexConverter.ConvertFromHexString("bc14dfde482ddc54f06fdd91d95471f5"); Console.WriteLine(HexConverter.ConvertToHexString(expected_sessionkey)); byte[] sessionkey = desfire.GenerateSesionKey_AES(rndA, rndB); Console.WriteLine(HexConverter.ConvertToHexString(sessionkey)); Assert.AreEqual(expected_sessionkey, sessionkey); } #endregion #region Configuration Generator [Test] public void GenerateKeySetting1() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.AreEqual(0x0B, desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE)); } [Test] public void GenerateKeySetting1_ChangeKey() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.AreEqual(0x1B, desfire.GenerateKeySetting1(0x01, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE)); } [Test] public void GenerateKeySetting1_Wrong_KeyID() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.GenerateKeySetting1(0x10, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); }); } [Test] public void GenerateKeySetting2() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.AreEqual(0x82, desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x02)); } [Test] public void GenerateKeySetting2_Wrong_KeyNumbers() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x10); }); } [Test] public void GenerateFileAccessRights() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.AreEqual(0x1234, desfire.GenerateFileAccessRights(0x01, 0x02, 0x03, 0x04)); } [Test] public void GenerateFileAccessRights_OutOfRange() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.GenerateFileAccessRights(0x10, 0x00, 0x00, 0x00); }); } #endregion #region DESFire Commands [Test] public void SelectApplication() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00 }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "905a00000342414600")).Returns(response); desfire.SelectApplication(0x464142); } [Test] public void SelectApplication_InvalidAID() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.SelectApplication(0xFF000000); }); } [Test] public void AuthenticateISO_DES() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response_challenge_request = new APDUResponse() { SW1 = 0x91, SW2 = 0xAF, Body = HexConverter.ConvertFromHexString("2bf9a938ecca02e2") }; APDUResponse response_challenge_response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, Body = HexConverter.ConvertFromHexString("07d825607a552e2e") }; byte[] rndA = HexConverter.ConvertFromHexString("5f7d1dd12d979173"); byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "901a0000010000")).Returns(response_challenge_request); nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90af000010f8cdb2eaa42a3167dfcb53852ce267fd00")).Returns(response_challenge_response); desfire.AuthenticateISO_DES(0x00, key, rndA); byte[] expected_sessionkey = HexConverter.ConvertFromHexString("5f7d1dd1f449db5c5f7d1dd1f449db5c"); byte[] expected_iv = HexConverter.ConvertFromHexString("0000000000000000"); Assert.AreEqual(expected_sessionkey, desfire._SessionKey); Assert.AreEqual(expected_iv, desfire._IV); } [Test] public void AuthenticateISO_DES_InvalidKeyNo() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.AuthenticateISO_DES(0x0F, null); }); } [Test] public void Format() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00 }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90fc000000")).Returns(response); desfire.Format(); } [Test] public void CreateApplication() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00 }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90ca000005eeffaa0b8200")).Returns(response); desfire.CreateApplication(0xAAFFEE, 0x0b, 0x82); } [Test] public void CreateApplication_InvalidAID() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.CreateApplication(0xFF000000, 0x00, 0x00); }); } [Test] public void AuthenticateISO_AES() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response_challenge_request = new APDUResponse() { SW1 = 0x91, SW2 = 0xAF, Body = HexConverter.ConvertFromHexString("a33856932308775cf464610c2b17a558") }; APDUResponse response_challenge_response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, Body = HexConverter.ConvertFromHexString("8fdc476f6bac44fe9150e285abd68d48") }; byte[] rndA = HexConverter.ConvertFromHexString("2176770e7a6eb4bef00d5e4b201d1e57"); byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90aa0000010000")).Returns(response_challenge_request); nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90af000020cbe9726faf54bc76b2055d0b9700e7dc97ecad5627f1d1702a16e8408d2a0ada00")).Returns(response_challenge_response); desfire.AuthenticateISO_AES(0x00, key, rndA); byte[] expected_sessionkey = HexConverter.ConvertFromHexString("2176770e11c512ca201d1e57fde6e15a"); byte[] expected_iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); Assert.AreEqual(expected_sessionkey, desfire._SessionKey); Assert.AreEqual(expected_iv, desfire._IV); } [Test] public void AuthenticateISO_AES_InvalidKeyNo() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.AuthenticateISO_AES(0x0F, null); }); } [Test] public void ChangeKey_AES() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00 }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90c400002100c2b54a718d0251845653199909bb32e8e38bd6719e8dc21799c29c922a0984fc00")).Returns(response); byte[] new_key = HexConverter.ConvertFromHexString("25432a462d4a614e645267556b587032"); byte[] sessionkey = HexConverter.ConvertFromHexString("a8514dd0350f3dfbc86e80744bcc9b57"); byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); desfire._SessionKey = sessionkey; desfire._IV = iv; desfire.ChangeKey_AES(0x00, new_key, 0x10); } [Test] public void ChangeKey_AES_InvalidKeyNo() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.ChangeKey_AES(0x0F, null, 0x10); }); } [Test] public void ChangeOtherKey_AES() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00 }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90c400002101a8c5a61a06f56f38dc91266fed2e87dc00a5ad72a634ff0e62c8d6d80707dd6000")).Returns(response); byte[] new_key = HexConverter.ConvertFromHexString("25432a462d4a614e645267556b587032"); byte[] old_key = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); byte[] sessionkey = HexConverter.ConvertFromHexString("1677623e1e158a62dc3d128db55f947d"); byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); desfire._SessionKey = sessionkey; desfire._IV = iv; desfire.ChangeOtherKey_AES(0x01, new_key, old_key, 0x10); } [Test] public void ChangeOtherKey_AES_InvalidKeyNo() { NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(null); Assert.Throws( delegate { desfire.ChangeKey_AES(0x0F, null, 0x10); }); } [Test] public void CreateFile_Standard() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00 }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90cd000007010000e0f0000000")).Returns(response); UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00); desfire.CreateFile_Standard(0x01, FileCommunication.PLAIN, accesRights, 0xF0); } [Test] public void CreateFile_Standard_InvalidFID() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); Assert.Throws( delegate { desfire.CreateFile_Standard(0x21, FileCommunication.PLAIN, 0x0000, 0xF0); }); } [Test] public void WriteData() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00 }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "903d00000f01000000080000546573743132333400")).Returns(response); desfire._SessionKey = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes("Test1234")); } [Test] public void WriteData_Long() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00 }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "903d000036010000002f0000546573743132333454657374313233345465737431323334546573743132333454657374313233345465737431323300")).Returns(response); nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "903d000036012f00002f0000345465737431323334546573743132333454657374313233345465737431323334546573743132333454657374313200")).Returns(response); nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "903d000019015e000012000033345465737431323334546573743132333400")).Returns(response); desfire._SessionKey = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes("Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234")); } [Test] public void WriteData_InvalidFileID() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); Assert.Throws( delegate { desfire.WriteData(0x21, 0x00, Encoding.ASCII.GetBytes("Test1234")); }); } [Test] public void ReadData() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, Body = HexConverter.ConvertFromHexString("54657374313233340000000000000000000000000000000000000000000000009100") }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90bd0000070100000020000000")).Returns(response); byte[] data = desfire.ReadData(0x01, 0x00, 0x20); Assert.AreEqual("Test1234", Encoding.ASCII.GetString(data).Replace("\u0000", "")); } [Test] public void ReadData_CMAC() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, Body = HexConverter.ConvertFromHexString("5465737431323334000000000000000000000000000000000000000000000000809a9bedbc559a5b9100") }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90bd0000070100000020000000")).Returns(response); byte[] data = desfire.ReadData(0x01, 0x00, 0x20); Assert.AreEqual("Test1234", Encoding.ASCII.GetString(data).Replace("\u0000", "")); } [Test] public void ReadData_Long() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); APDUResponse response_1 = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, Body = HexConverter.ConvertFromHexString("54657374313233340000000000000000000000000000000000000000000000000000000000000000000000000000009100") }; APDUResponse response_2 = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, Body = HexConverter.ConvertFromHexString("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009100") }; APDUResponse response_3 = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, Body = HexConverter.ConvertFromHexString("00009100") }; nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90bd000007010000002f000000")).Returns(response_1); nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90bd000007012f00002f000000")).Returns(response_2); nfcService.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90bd000007015e000002000000")).Returns(response_3); byte[] data = desfire.ReadData(0x01, 0x00, 0x60); Assert.AreEqual("Test1234", Encoding.ASCII.GetString(data).Replace("\u0000", "")); } [Test] public void ReadData_InvalidFileID() { INFCService nfcService = Substitute.For(); NXP_MIFARE_DESFire desfire = new NXP_MIFARE_DESFire(nfcService); Assert.Throws( delegate { desfire.ReadData(0x21, 0x00, 0x20); }); } #endregion } }