borepin/NFC/ISO7816-4/APDUResponse.cs

155 lines
4.9 KiB
C#
Raw Normal View History

2020-09-15 15:27:01 +02:00
using System;
2020-11-07 01:14:51 +01:00
using System.Collections.Generic;
2020-09-15 15:27:01 +02:00
using System.Linq;
using NFC.Mifare_DESFire;
2020-10-05 18:39:45 +02:00
namespace NFC.ISO7816_4
2020-09-15 15:27:01 +02:00
{
public class APDUResponse
{
2020-10-05 18:39:45 +02:00
#region constructor
public APDUResponse()
{
}
2020-09-15 15:27:01 +02:00
/// <summary>
2020-10-05 18:39:45 +02:00
/// Creates a new APDUResponse from the raw received data.
2020-09-15 15:27:01 +02:00
/// </summary>
2020-10-05 18:39:45 +02:00
public APDUResponse(byte[] raw)
{
Body = raw.Take(raw.Length - 1).ToArray();
SW1 = raw[raw.Length - 2];
SW2 = raw[raw.Length - 3];
}
#endregion
2020-09-15 15:27:01 +02:00
2020-10-05 18:39:45 +02:00
#region Properties
2020-09-15 15:27:01 +02:00
/// <summary>
2020-10-05 18:39:45 +02:00
/// ISO 7816-4-4 - Body - Body
2020-09-15 15:27:01 +02:00
/// </summary>
2020-10-05 18:39:45 +02:00
public byte[] Body { get; set; }
2020-09-15 15:27:01 +02:00
/// <summary>
2020-10-05 18:39:45 +02:00
/// ISO 7816-4 - SW1 - Status Word 1
2020-09-15 15:27:01 +02:00
/// </summary>
2020-10-05 18:39:45 +02:00
public byte SW1 { get; set; }
2020-09-15 15:27:01 +02:00
/// <summary>
2020-10-05 18:39:45 +02:00
/// ISO 7816-4 - SW2 - Status Word 2
2020-09-15 15:27:01 +02:00
/// </summary>
2020-10-05 18:39:45 +02:00
public byte SW2 { get; set; }
2020-09-15 15:27:01 +02:00
public APDUStatusWords StatusWord
{
get
{
// Some status words only require a specific first byte
// and in some cases SW2 contains additional information.
// This will filter out those errors. When there is more information separate methods for getting those are available.
switch(SW1) {
case 0x61:
// Kommando erfolgreich ausgeführt. xx Datenbytes können mit dem GET RESPONSE-Kommando abgeholt werden. Statuswort zur Steuerung des T=0-Protokolls
return APDUStatusWords.DATA_READY;
case 0x62:
// Warnung; Zustand des nichtflüchtigen Speichers nicht verändert
return APDUStatusWords.STORAGE_NOT_CHANGED;
case 0x63:
if((SW2 & 0xF0) == 0xC0) {
// Zähler hat den Wert x erreicht (die genaue Bedeutung ist vom Kommando abhängig)
return APDUStatusWords.COUNTER_REACHED;
}
// Warnung; Zustand des nichtflüchtigen Speichers verändert
return APDUStatusWords.STORAGE_CHANGED;
case 0x64:
// Ausführungsfehler; Zustand des nichtflüchtigen Speichers nicht verändert
return APDUStatusWords.EXECUTION_ERROR_WITHOUT_CHANGE;
case 0x65:
// Ausführungsfehler; Zustand des nichtflüchtigen Speichers verändert
return APDUStatusWords.EXECUTION_ERROR_WITH_CHANGE;
case 0x6C:
// Falsche Länge Le; xx gibt die korrekte Länge an Statuswort zur Steuerung des T=0-Protokolls
return APDUStatusWords.INVALID_LE;
}
return (APDUStatusWords) (((UInt16) SW1) << 8 | ((UInt16) SW2));
}
}
/// <summary>
/// If the reponse status is DATA_READY this method can be used to get the amount of data that can be read from the card.
/// </summary>
public byte DataLength
{
get
{
return SW2;
}
}
/// <summary>
/// If the reponse status is COUNTER_REACHED this method can be used to get the value that the counter reached.
/// </summary>
public byte Counter
{
get
{
return (byte)(SW2 & 0x0F);
}
}
/// <summary>
/// If the reponse status is INVALID_LE this method can be used to get the correct LE.
/// </summary>
public byte CorrectLE
{
get
{
return SW2;
}
}
2020-10-05 18:39:45 +02:00
#endregion
2020-10-07 19:25:51 +02:00
#region Methodes
public byte[] ToArray()
{
byte[] array = null;
if (Body != null)
{
array = new byte[Body.Length + 2];
Body.CopyTo(array, 0);
array[Body.Length] = SW1;
array[Body.Length + 1] = SW2;
}
else
{
array = new byte[2];
array[0] = SW1;
array[1] = SW2;
}
return array;
}
2020-11-07 01:14:51 +01:00
public override bool Equals(object obj)
{
return obj is APDUResponse response &&
EqualityComparer<byte[]>.Default.Equals(Body, response.Body) &&
SW1 == response.SW1 &&
SW2 == response.SW2;
}
public override int GetHashCode()
{
return HashCode.Combine(Body, SW1, SW2);
}
public override string ToString()
{
string pattern = "SW1: 0x{0:x} | SW2: 0x{1:x} | Body: 0x{2:x}";
return string.Format(pattern, SW1, SW2, Body);
}
2020-10-07 19:25:51 +02:00
#endregion
2020-09-15 15:27:01 +02:00
}
}