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,
}
}
}