diff --git a/NFC/Mifare DESFire/MifareDESFire.cs b/NFC/Mifare DESFire/MifareDESFire.cs index f6b5287..2a1ab65 100644 --- a/NFC/Mifare DESFire/MifareDESFire.cs +++ b/NFC/Mifare DESFire/MifareDESFire.cs @@ -70,18 +70,34 @@ namespace NFC.Mifare_DESFire return cmd; } + public APDUCommand Authenticate_GetChallenge(byte keyid) + { + APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)APDUInstructions., + Data = new byte[] + { + id_byte[0], + id_byte[1], + id_byte[2] + }, + Le = 0x00 + }; + } + /// - /// Select Application by ID + /// Delete Application by ID /// /// 3 Byte ID - public APDUCommand CreateApplication(UInt32 id) + public APDUCommand DeleteApplication(UInt32 id) { byte[] id_byte = BitConverter.GetBytes(id); APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) { CLA = 0x90, - INS = (byte)APDUInstructions.CREATE_APPLICATION, + INS = (byte)APDUInstructions.DELETE_APPLICATION, Data = new byte[] { id_byte[0], @@ -94,18 +110,170 @@ namespace NFC.Mifare_DESFire return cmd; } - public byte GenerateKeySetting1() + /// + /// Select Application by ID + /// + /// 3 Byte ID + public APDUCommand CreateApplication(UInt32 id, byte keysetting1, byte keysetting2) { - return 0x00; + byte[] id_byte = BitConverter.GetBytes(id); + + APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)APDUInstructions.CREATE_APPLICATION, + Data = new byte[] + { + id_byte[0], + id_byte[1], + id_byte[2], + keysetting1, + keysetting2 + }, + Le = 0x00 + }; + + return cmd; } /// - /// + /// Genearte KeySetting1 for Application Settings or PICC Setting /// - public enum ChangeKey : byte + 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(CryptoOperations cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys) + { + if(numberOfKeys < 0x01 || numberOfKeys >= 0x0D) + { + throw new ArgumentOutOfRangeException(); + } + + return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys); + } + + /// + /// Crypto method of the application + /// + public enum CryptoOperations : byte + { + TDES = 0x00, + TKTDES = 0x40, + AES = 0x80, + } + + /// + /// Indicates use of 2 byte ISO/IEC 7816-4 File Identifies for files within the Application + /// + public enum FileIdentifies : byte + { + NOTUSED = 0x00, + USED = 0x20 + } + + /// + /// hold the Access Rights for changing application keys (Change Key command) + /// + public enum ChangeApplicationKey : byte + { + /// + /// Application master key authentication is necessary to change any key (default) + /// MASTERKEY = 0x00, - + /// + /// Authentication with the key to be changed (same Key#) is necessary to change a key + /// + SAMEKEY = 0x0E, + /// + /// All keys (except application master key, see Bit 0) within this application are frozen + /// + ALLKEYS = 0x0F + } + + /// + /// codes whether a change of the application master key settings is allowed + /// + public enum ChangeMasterKeySettings : byte + { + + /// + /// configuration not changeable anymore (frozen) + /// + FROZEN = 0x00, + + /// + /// this configuration is changeable if authenticated with the application master key (default) + /// + WITHMASTERKEY = 0x08 + } + + /// + /// codes whether application master key authentication is needed before “Create File” / “Delete File” + /// + public enum CreateDeleteFile : byte + { + /// + /// “Create File”/ “Delete File”is permitted only with application master key authentication + /// + ONLYMASTERKEY = 0x00, + + /// + /// “Create File”/ “Delete File”is permitted also without application master key authentication (default) + /// + NOKEY = 0x04, + } + + /// + /// codes whether application master key authentication is needed for file directory access + /// + public enum FileDirectoryAccess : byte + { + /// + /// Successful application master key authentication is required for executing the “Get FID List”, “Get File Settings”and “Get Key Settings”commands + /// + ONLYMASTERKEY = 0x00, + + /// + /// “Get FID List”, “Get File Settings” and “Get Key Settings” commands succeed independentlyof a preceding application master key authentication (default) + /// + NOKEY = 0x02, + } + + /// + /// codes whether the application master key is changeable + /// + public enum ChangeMasterKey : byte + { + /// + /// Application master key is not changeable anymore (frozen) + /// + FROZEN = 0x00, + + /// + /// Application master key is changeable (authentication with the current application master key necessary, default) + /// + CHANGEABLE = 0x01, } } } diff --git a/NFC_Test/MifareDESFire_Commands.cs b/NFC_Test/MifareDESFire_Commands.cs new file mode 100644 index 0000000..79207bd --- /dev/null +++ b/NFC_Test/MifareDESFire_Commands.cs @@ -0,0 +1,33 @@ +using NFC; +using NFC.Mifare_DESFire; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC_Test +{ + [TestFixture] + public class MifareDESFire_Commands + { + private MifareDESFire _MifareDESFire; + + [SetUp] + public void SetUp() + { + _MifareDESFire = new MifareDESFire(); + } + + [Test] + public void GetApplicationIDs() + { + + } + + [Test] + public void GenerateKeySetting1() + { + Assert.AreEqual(0xEF, _MifareDESFire.GenerateKeySetting1(MifareDESFire.ChangeApplicationKey.SAMEKEY, MifareDESFire.ChangeMasterKeySettings.WITHMASTERKEY, MifareDESFire.CreateDeleteFile.NOKEY, MifareDESFire.FileDirectoryAccess.NOKEY, MifareDESFire.ChangeMasterKey.CHANGEABLE)); + } + } +} diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index fdb6f2f..1ec7d56 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -134,5 +134,82 @@ namespace NFC_Test reader.Stop(); 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(); + + MifareDESFire desfire = new MifareDESFire(); + + 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)] + 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(); + + MifareDESFire desfire = new MifareDESFire(); + + byte keysetting1 = desfire.GenerateKeySetting1(MifareDESFire.ChangeApplicationKey.SAMEKEY, MifareDESFire.ChangeMasterKeySettings.WITHMASTERKEY, MifareDESFire.CreateDeleteFile.NOKEY, MifareDESFire.FileDirectoryAccess.NOKEY, MifareDESFire.ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(MifareDESFire.CryptoOperations.AES, MifareDESFire.FileIdentifies.NOTUSED, 0x01); + + 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; + } } }