using PCSC.Iso7816; using System; using System.Collections.Generic; using System.Text; namespace NFC.Mifare_DESFire { public class MifareDESFire { /// /// Create new Application with AID /// /// Appilication ID public APDUCommand CreateApplication(UInt64 aid) { throw new NotImplementedException(); } public APDUCommand GetApplicationIDs() { APDUCommand cmd = new APDUCommand(IsoCase.Case2Short) { CLA = 0x90, INS = (byte)APDUInstructions.GET_APPLICATION_IDS }; return cmd; } public UInt32[] ConvertApplicationIDs(APDUResponse response) { if(response.Body.Length % 3 != 0) { throw new Exception("Invalid Body Length."); } 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 ID /// /// 3 Byte ID public APDUCommand SelectApplication(UInt32 id) { byte[] id_byte = BitConverter.GetBytes(id); 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] }, Le = 0x00 }; 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 }; } /// /// Delete Application by ID /// /// 3 Byte ID public APDUCommand 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 }; return cmd; } /// /// Select Application by ID /// /// 3 Byte ID public APDUCommand CreateApplication(UInt32 id, byte keysetting1, byte keysetting2) { 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 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, } } }