This commit is contained in:
TheJoKlLa
2020-11-06 21:36:37 +01:00
parent 4004413af7
commit 872aeccee7
14 changed files with 597 additions and 338 deletions

View File

@ -5,9 +5,9 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="log4net" Version="2.0.11" />
<PackageReference Include="log4net" Version="2.0.12" />
<PackageReference Include="PCSC" Version="5.0.0" />
<PackageReference Include="PCSC.Iso7816" Version="5.0.0" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.6.7" />
<PackageReference Include="Portable.BouncyCastle" Version="1.8.8" />
</ItemGroup>
</Project>

View File

@ -95,6 +95,23 @@ namespace NFC.Mifare_DESFire
return arr;
}
/// <summary>
/// Get Range of Array
/// </summary>
/// <param name="array"></param>
/// <param name="offset"></param>
/// <param name="length"></param>
/// <returns></returns>
public byte[] GetSubArray(byte[] array, long offset, long length)
{
byte[] subarray = new byte[length];
for (long i = offset; i < offset + length; i++)
{
subarray[i - offset] = array[i];
}
return subarray;
}
private int GetHexVal(char hex)
{
int val = (int)hex;
@ -677,6 +694,62 @@ namespace NFC.Mifare_DESFire
_Log.Debug("End AuthenticateISO_DES");
}
/// <summary>
/// Change Same DES key as Authenticated
/// </summary>
/// <param name="key_id"></param>
/// <param name="new_key"></param>
/// <param name="key_version"></param>
public void ChangeKey_DES(byte key_id, byte[] new_key, byte key_version)
{
_Log.Debug("Start ChangeKey_DES");
byte[] header = new byte[]
{
0xC4, key_id
};
_Log.DebugFormat("header: {0}", ConvertToHexString(header));
byte[] key_and_version = new_key;
byte[] command = Concatenate(header, key_and_version);
_Log.DebugFormat("command: {0}", ConvertToHexString(command));
CRC32 crc32 = new CRC32();
byte[] crc = crc32.Calculate(command);
_Log.DebugFormat("crc: {0}", ConvertToHexString(crc));
byte[] cryptogram = Concatenate(key_and_version, crc);
_Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram));
byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16);
_Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block));
TDES des = new TDES();
byte[] cryptogram_enc = des.Encrypt(cryptogram_block, _SessionKey, _IV);
_Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc));
_IV = ExtractLastBlock(cryptogram_enc, 8);
_Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV));
byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc);
_Log.DebugFormat("data: {0}", ConvertToHexString(data));
APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = 0xC4,
Data = data
};
_Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray()));
APDUResponse response = _Card.Transmit(cmd_ChangeKey);
_Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
_Log.Debug("End ChangeKey_AES");
}
/// <summary>
/// Change Same AES key as Authenticated
/// </summary>
@ -851,58 +924,63 @@ namespace NFC.Mifare_DESFire
{
_Log.Debug("Start ReadData");
byte[] data = new byte[]
{
file_id
};
int max_read_bytes_pre_transaction = 58;
long bytes_readed = 0;
byte[] offset_byte_tolong = BitConverter.GetBytes(offset);
// Use only 3 Bytes
byte[] offset_byte = new byte[]
List<byte> read_data = new List<byte>();
while (bytes_readed != length)
{
byte[] data = new byte[]
{
file_id
};
byte[] offset_byte_tolong = BitConverter.GetBytes(offset + bytes_readed);
// Use only 3 Bytes
byte[] offset_byte = new byte[]
{
offset_byte_tolong[0],
offset_byte_tolong[1],
offset_byte_tolong[2],
};
};
byte[] length_byte_tolong = BitConverter.GetBytes(length);
// Use only 3 Bytes
byte[] length_byte = new byte[]
{
length_byte_tolong[0],
length_byte_tolong[1],
length_byte_tolong[2],
};
long bytes_toread = 0;
APDUCommand cmd_ReadData = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = (byte)APDUInstructions.READ_DATA,
Data = Concatenate(data, offset_byte, length_byte)
};
APDUResponse response;
List<byte> read_data = new List<byte>();
do
{
_Log.DebugFormat("APDU_CMD(cmd_ReadData): {0}", ConvertToHexString(cmd_ReadData.ToArray()));
response = _Card.Transmit(cmd_ReadData);
_Log.DebugFormat("APDU_RES(cmd_ReadData): {0}", ConvertToHexString(response.ToArray()));
if (response.SW1 == 0x91 && response.SW2 == 0xAF)
if (length - bytes_readed < max_read_bytes_pre_transaction)
{
read_data.AddRange(response.Body);
bytes_toread = length - bytes_readed;
}
else
{
CheckAPDUResponse(response);
bytes_toread = max_read_bytes_pre_transaction;
}
cmd_ReadData.INS = 0xAF;
} while (response.SW1 == 0x91 && response.SW2 == 0xAF);
byte[] length_byte_tolong = BitConverter.GetBytes(bytes_toread);
bytes_readed += bytes_toread;
// Use only 3 Bytes
byte[] length_byte = new byte[]
{
length_byte_tolong[0],
length_byte_tolong[1],
length_byte_tolong[2],
};
APDUCommand cmd_ReadData = new APDUCommand(IsoCase.Case4Short)
{
CLA = 0x90,
INS = (byte)APDUInstructions.READ_DATA,
Data = Concatenate(data, offset_byte, length_byte)
};
_Log.DebugFormat("APDU_CMD(cmd_ReadData): {0}", ConvertToHexString(cmd_ReadData.ToArray()));
APDUResponse response = _Card.Transmit(cmd_ReadData);
_Log.DebugFormat("APDU_RES(cmd_ReadData): {0}", ConvertToHexString(response.ToArray()));
CheckAPDUResponse(response);
read_data.AddRange(response.Body);
}
_Log.Debug("End ReadData");
return read_data.ToArray();
@ -957,6 +1035,80 @@ namespace NFC.Mifare_DESFire
_Log.Debug("End WriteData");
}
///// <summary>
///// Write Data to File
///// </summary>
///// <param name="file_id">ID of File (0x01 - 0x10)</param>
///// <param name="offset">Offset for File</param>
///// <param name="data">Data to write</param>
//public void WriteData(byte file_id, UInt32 offset, byte[] data)
//{
// _Log.Debug("Start WriteData");
// int max_write_bytes_pre_transaction = 8;
// byte[] write_buffer;
// long bytes_writed = 0;
// long length = data.Length;
// while (bytes_writed != data.Length)
// {
// byte[] file_id_array = new byte[]
// {
// file_id
// };
// byte[] offset_byte_tolong = BitConverter.GetBytes(offset + bytes_writed);
// // Use only 3 Bytes
// byte[] offset_byte = new byte[]
// {
// offset_byte_tolong[0],
// offset_byte_tolong[1],
// offset_byte_tolong[2],
// };
// long bytes_towrite = 0;
// if (length - bytes_writed < max_write_bytes_pre_transaction)
// {
// bytes_towrite = length - bytes_writed;
// }
// else
// {
// bytes_towrite = max_write_bytes_pre_transaction;
// }
// byte[] length_byte_tolong = BitConverter.GetBytes(bytes_towrite);
// write_buffer = GetSubArray(data, bytes_writed, bytes_towrite);
// bytes_writed += bytes_towrite;
// // Use only 3 Bytes
// byte[] length_byte = new byte[]
// {
// length_byte_tolong[0],
// length_byte_tolong[1],
// length_byte_tolong[2],
// };
// APDUCommand cmd_WriteData = new APDUCommand(IsoCase.Case4Short)
// {
// CLA = 0x90,
// INS = (byte)APDUInstructions.WRITE_DATA,
// Data = Concatenate(file_id_array, offset_byte, length_byte, write_buffer)
// };
// _Log.DebugFormat("APDU_CMD(cmd_WriteData): {0}", ConvertToHexString(cmd_WriteData.ToArray()));
// APDUResponse response = _Card.Transmit(cmd_WriteData);
// _Log.DebugFormat("APDU_RES(cmd_WriteData): {0}", ConvertToHexString(response.ToArray()));
// CheckAPDUResponse(response);
// }
// _Log.Debug("End WriteData");
//}
/// <summary>
/// Get all ApplicationIDS from PICC
/// </summary>