This commit is contained in:
TheJoKlLa
2020-10-05 18:39:45 +02:00
parent 6a5f521800
commit d601e9afb3
24 changed files with 319 additions and 213 deletions

View File

@ -0,0 +1,47 @@
using PCSC;
using PCSC.Iso7816;
using System;
using System.Collections.Generic;
namespace NFC.ISO7816_4
{
public class APDUCommand : CommandApdu
{
public APDUCommand(IsoCase isoCase) : base(isoCase, SCardProtocol.Any)
{
}
public override bool Equals(object obj)
{
return obj is APDUCommand command &&
Case == command.Case &&
Protocol == command.Protocol &&
CLA == command.CLA &&
INS == command.INS &&
P1 == command.P1 &&
P2 == command.P2 &&
EqualityComparer<byte[]>.Default.Equals(Data, command.Data);
}
public override int GetHashCode()
{
HashCode hash = new HashCode();
hash.Add(Case);
hash.Add(Protocol);
hash.Add(IsValid);
hash.Add(CLA);
hash.Add(INS);
hash.Add(P1);
hash.Add(P2);
hash.Add(P1P2);
hash.Add(Data);
hash.Add(Lc);
hash.Add(P3);
hash.Add(Le);
hash.Add(ExpectedResponseLength);
hash.Add(IsValid);
return hash.ToHashCode();
}
}
}

View File

@ -0,0 +1,111 @@
using System;
using System.Linq;
using NFC.Mifare_DESFire;
namespace NFC.ISO7816_4
{
public class APDUResponse
{
#region constructor
public APDUResponse()
{
}
/// <summary>
/// Creates a new APDUResponse from the raw received data.
/// </summary>
public APDUResponse(byte[] raw)
{
Body = raw.Take(raw.Length - 1).ToArray();
SW1 = raw[raw.Length - 2];
SW2 = raw[raw.Length - 3];
}
#endregion
#region Properties
/// <summary>
/// ISO 7816-4-4 - Body - Body
/// </summary>
public byte[] Body { get; set; }
/// <summary>
/// ISO 7816-4 - SW1 - Status Word 1
/// </summary>
public byte SW1 { get; set; }
/// <summary>
/// ISO 7816-4 - SW2 - Status Word 2
/// </summary>
public byte SW2 { get; set; }
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;
}
}
#endregion
}
}

View File

@ -0,0 +1,212 @@
using System;
namespace NFC.Mifare_DESFire
{
public enum APDUStatusWords : UInt16
{
/// <summary>
/// Kommando erfolgreich ausgef<65>hrt. xx Datenbytes k<>nnen mit dem <20>GET RESPONSE<53>-Kommando abgeholt werden. Statuswort zur Steuerung des T=0-Protokolls
/// </summary>
DATA_READY = 0x6100,
/// <summary>
/// Die zur<75>ckgegebenen Daten k<>nnen fehlerhaft sein.
/// </summary>
FAULTY_DATA = 0x6281,
/// <summary>
/// Da das Dateiende vorher erreicht wurde, konnten nur weniger als Le Bytes gelesen werden.
/// </summary>
UNEXPECTED_END_OF_FILE = 0x6282,
/// <summary>
/// Die ausgew<65>hlte Datei ist gesperrt (englisch invalidated, w<>rtlich <20>ung<6E>ltig<69>).
/// </summary>
INVALIDATED_FILE = 0x6283,
/// <summary>
/// Die File Control Information (FCI) ist inkonform zu ISO 7816-4.
/// </summary>
FCI_NOT_CONFORM = 0x6284,
/// <summary>
/// Warnung; Zustand des nichtfl<66>chtigen Speichers nicht ver<65>ndert
/// </summary>
STORAGE_NOT_CHANGED = 0x6200,
/// <summary>
/// Z<>hler hat den Wert x erreicht (die genaue Bedeutung ist vom Kommando abh<62>ngig)
/// </summary>
COUNTER_REACHED = 0x63C0,
/// <summary>
/// Warnung; Zustand des nichtfl<66>chtigen Speichers ver<65>ndert
/// </summary>
STORAGE_CHANGED = 0x6300,
/// <summary>
/// Ausf<73>hrungsfehler; Zustand des nichtfl<66>chtigen Speichers nicht ver<65>ndert
/// </summary>
EXECUTION_ERROR_WITHOUT_CHANGE = 0x6400,
/// <summary>
/// Speicherfehler
/// </summary>
MEMORY_ERROR = 0x6581,
/// <summary>
/// Ausf<73>hrungsfehler; Zustand des nichtfl<66>chtigen Speichers ver<65>ndert
/// </summary>
EXECUTION_ERROR_WITH_CHANGE = 0x6500,
/// <summary>
/// Befehlsl<73>nge (Lc) oder erwartete Antwortl<74>nge (Le) falsch
/// </summary>
INVALID_LC_LE = 0x6700,
/// <summary>
/// Funktionen im Class-Byte werden nicht unterst<73>tzt
/// </summary>
CLASS_FEATURE_NOT_SUPPORTED = 0x6800,
/// <summary>
/// Logische Kan<61>le werden nicht unterst<73>tzt
/// </summary>
LOGIC_CHANNEL_NOT_SUPPORTED = 0x6881,
/// <summary>
/// Secure Messaging wird nicht unterst<73>tzt
/// </summary>
SECURE_MESSAGING_NOT_SUPPORTED = 0x6882,
/// <summary>
/// Kommando nicht erlaubt
/// </summary>
COMMAND_NOT_ALLOWED = 0x6900,
/// <summary>
/// Kommando inkompatibel zur Dateistruktur
/// </summary>
COMMAND_INCOMPATIBLE = 0x6981,
/// <summary>
/// Sicherheitszustand nicht erf<72>llt
/// </summary>
SAFETY_STATUS_NOT_FULFILLED = 0x6982,
/// <summary>
/// Authentisierungsmethode ist gesperrt
/// </summary>
AUTHENTICATION_METHOD_LOCKED = 0x6983,
/// <summary>
/// Referenzierte Daten sind gesperrt
/// </summary>
REFERENCED_FILE_LOCKED = 0x6984,
/// <summary>
/// Nutzungsbedingungen sind nicht erf<72>llt
/// </summary>
TERMS_OF_SERVICE_NOT_FULFILLED = 0x6985,
/// <summary>
/// Kommando nicht erlaubt (kein EF selektiert)
/// </summary>
COMMAND_NOT_ALLOWED_NO_EF_SELECTED = 0x6986,
/// <summary>
/// Erwartete Secure-Messaging-Objekte nicht gefunden
/// </summary>
EXPECTED_SECURE_MESSAGING_OBJECTS_NOT_FOUND = 0x6987,
/// <summary>
/// Secure-Messaging-Datenobjekte sind inkorrekt
/// </summary>
INVALID_SECURE_MESSAGING_OBJECTS = 0x6988,
/// <summary>
/// Falsche Parameter P1/P2
/// </summary>
WRONG_PARAMETERS = 0x6A00,
/// <summary>
/// Falsche Daten
/// </summary>
WRONG_DATA = 0x6A80,
/// <summary>
/// Funktion wird nicht unterst<73>tzt
/// </summary>
FEATURE_NOT_SUPPORTED = 0x6A81,
/// <summary>
/// Datei wurde nicht gefunden
/// </summary>
FILE_NOT_FOUND = 0x6A82,
/// <summary>
/// Datensatz (engl. record) der Datei nicht gefunden
/// </summary>
RECORD_NOT_FOUND = 0x6A83,
/// <summary>
/// Nicht gen<65>gend Speicherplatz in der Datei
/// </summary>
INSUFFICIENT_SPACE = 0x6A84,
/// <summary>
/// Lc nicht konsistent mit der TLV-Struktur
/// </summary>
LC_TLV_INCONSISTENT = 0x6A85,
/// <summary>
/// Inkorrekte Parameter P1/P2
/// </summary>
INCORRECT_PARAMETERs = 0x6A86,
/// <summary>
/// Lc inkonsistent mit P1/P2
/// </summary>
LC_PARAMETERS_INCONSISTENT = 0x6A87,
/// <summary>
/// Referenzierte Daten nicht gefunden
/// </summary>
REFERENCED_FILE_NOT_FOUND = 0x6A88,
/// <summary>
/// Parameter P1/P2 falsch
/// </summary>
WRONG_PARAMETERS_2 = 0x6B00,
/// <summary>
/// Falsche L<>nge Le; xx gibt die korrekte L<>nge an Statuswort zur Steuerung des T=0-Protokolls
/// </summary>
INVALID_LE = 0x6C00,
/// <summary>
/// Das Kommando (INS) wird nicht unterst<73>tzt
/// </summary>
INSTRUCTION_NOT_SUPPORTED = 0x6D00,
/// <summary>
/// Die Kommandoklasse (CLA) wird nicht unterst<73>tzt
/// </summary>
CLASS_NOT_SUPPORTED = 0x6E00,
/// <summary>
/// Kommando wurde mit unbekanntem Fehler abgebrochen
/// </summary>
UNKNOWN_ERROR = 0x6F00,
/// <summary>
/// Kommando erfolgreich ausgef<65>hrt
/// </summary>
SUCCESS = 0x9000,
/// <summary>
/// OK
/// </summary>
OK = 0x9100,
}
}