2020-09-26 18:02:44 +02:00
|
|
|
|
using NFC.Mifare_DESFire.Enums;
|
|
|
|
|
using PCSC.Iso7816;
|
2020-09-17 16:07:58 +02:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Text;
|
|
|
|
|
|
|
|
|
|
namespace NFC.Mifare_DESFire
|
|
|
|
|
{
|
|
|
|
|
public class MifareDESFire
|
|
|
|
|
{
|
2020-09-26 18:02:44 +02:00
|
|
|
|
private ICard _Card;
|
|
|
|
|
|
|
|
|
|
public MifareDESFire(ICard card)
|
|
|
|
|
{
|
|
|
|
|
_Card = card;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-17 16:07:58 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Create new Application with AID
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="aid">Appilication ID</param>
|
|
|
|
|
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<UInt32> applicationIDs = new List<UInt32>();
|
|
|
|
|
|
|
|
|
|
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();
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-26 18:02:44 +02:00
|
|
|
|
public void Format()
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Authenticate(int v, byte[] aPP_MasterKey)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-17 16:07:58 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Select Application by ID
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">3 Byte ID</param>
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-26 18:02:44 +02:00
|
|
|
|
public void ChangeApplicationMasterKey(byte[] aPP_MasterKey)
|
2020-09-25 20:23:33 +02:00
|
|
|
|
{
|
2020-09-26 18:02:44 +02:00
|
|
|
|
throw new NotImplementedException();
|
2020-09-25 20:23:33 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Delete Application by ID
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">3 Byte ID</param>
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-26 18:02:44 +02:00
|
|
|
|
public void ChangeApplicationKey(int v, byte[] aPP_Key_1)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-17 16:07:58 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Select Application by ID
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="id">3 Byte ID</param>
|
2020-09-25 20:23:33 +02:00
|
|
|
|
public APDUCommand CreateApplication(UInt32 id, byte keysetting1, byte keysetting2)
|
2020-09-17 16:07:58 +02:00
|
|
|
|
{
|
|
|
|
|
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],
|
2020-09-25 20:23:33 +02:00
|
|
|
|
id_byte[2],
|
|
|
|
|
keysetting1,
|
|
|
|
|
keysetting2
|
2020-09-17 16:07:58 +02:00
|
|
|
|
},
|
|
|
|
|
Le = 0x00
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return cmd;
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-26 18:02:44 +02:00
|
|
|
|
public void CreateFile(byte fabAccessIdentFileID, FileCommunication pLAIN, ushort fileAccessRight, int v)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ushort GenerateFileAccessRight(AccessRights fREE, int v1, int v2, int v3)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void WirteData(byte fabAccessIdentFileID, int v1, int v2, byte[] vs)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CreateFile(byte fabAccessIdentFileID, object plain, AccessRights fREE, int v1, int v2, int v3)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public byte[] ReadData(byte identFileID, int v1, int v2)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-25 20:23:33 +02:00
|
|
|
|
/// <summary>
|
|
|
|
|
/// Genearte KeySetting1 for Application Settings or PICC Setting
|
|
|
|
|
/// </summary>
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Genearte KeySetting1 for Application Settings or PICC Setting
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="changeKey">ID of Key for changing Application Keys</param>
|
|
|
|
|
/// <returns></returns>
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Genearte KeySetting2 for Application Creation
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="numberOfKeys">Number of keys that can be stored within the application (0x01-0x0D)</param>
|
|
|
|
|
/// <returns></returns>
|
2020-09-26 18:02:44 +02:00
|
|
|
|
public byte GenerateKeySetting2(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys)
|
2020-09-25 20:23:33 +02:00
|
|
|
|
{
|
|
|
|
|
if(numberOfKeys < 0x01 || numberOfKeys >= 0x0D)
|
|
|
|
|
{
|
|
|
|
|
throw new ArgumentOutOfRangeException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys);
|
|
|
|
|
}
|
2020-09-17 16:07:58 +02:00
|
|
|
|
}
|
|
|
|
|
}
|