From 2034c08d3377510bed3515cae71a1f67f8485491 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Tue, 15 Sep 2020 10:47:46 +0200 Subject: [PATCH 01/21] Added: NFC csproj --- Borepin.sln | 28 ++++++++++++++++++- NFC/IReader.cs | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++ NFC/NFC.csproj | 7 +++++ 3 files changed, 110 insertions(+), 1 deletion(-) create mode 100644 NFC/IReader.cs create mode 100644 NFC/NFC.csproj diff --git a/Borepin.sln b/Borepin.sln index 011075a..dda3f6a 100644 --- a/Borepin.sln +++ b/Borepin.sln @@ -9,12 +9,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.Android", "Borepin\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.iOS", "Borepin\Borepin.iOS\Borepin.iOS.csproj", "{9985ED2B-0642-4DAC-98C3-F546196A1E36}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin", "Borepin\Borepin\Borepin.csproj", "{F93856BD-0C8D-4469-A8DB-6E513002BFD7}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Borepin", "Borepin\Borepin\Borepin.csproj", "{F93856BD-0C8D-4469-A8DB-6E513002BFD7}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.GTK", "Borepin\Borepin.GTK\Borepin.GTK.csproj", "{61D956D2-5819-4736-BBD8-AD8208DE6A62}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.macOS", "Borepin\Borepin.macOS\Borepin.macOS.csproj", "{3EC23FE7-395E-4BBC-B56B-9455354BDA34}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFC", "NFC\NFC.csproj", "{72DAC306-D4B2-4DBF-9C32-317203FD5D61}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -223,6 +225,30 @@ Global {3EC23FE7-395E-4BBC-B56B-9455354BDA34}.Release|x64.Build.0 = Release|Any CPU {3EC23FE7-395E-4BBC-B56B-9455354BDA34}.Release|x86.ActiveCfg = Release|Any CPU {3EC23FE7-395E-4BBC-B56B-9455354BDA34}.Release|x86.Build.0 = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|ARM.ActiveCfg = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|ARM.Build.0 = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|iPhone.Build.0 = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|x64.ActiveCfg = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|x64.Build.0 = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|x86.ActiveCfg = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|x86.Build.0 = Debug|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|Any CPU.Build.0 = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|ARM.ActiveCfg = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|ARM.Build.0 = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|iPhone.ActiveCfg = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|iPhone.Build.0 = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x64.ActiveCfg = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x64.Build.0 = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x86.ActiveCfg = Release|Any CPU + {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NFC/IReader.cs b/NFC/IReader.cs new file mode 100644 index 0000000..a0b05b1 --- /dev/null +++ b/NFC/IReader.cs @@ -0,0 +1,76 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC +{ + /// + /// Abstract representation of the platform specific NFC Hardware. + /// + public interface IHardware + { + /// + /// Check if the device has nfc support. + /// + /// Returns true if the device supports NFC. + bool IsAvailable(); + + /// Returns all available readers. + String[] GetReader(); + + /// + /// Create a new reader instance from the specified id. + /// + /// Returns the spatform specific reader that corresponds to the id. + /// Invalid reader id. + IReader OpenReader(String readerID); + } + + /// + /// Abstraction of a platform-specifc reader that can communicate with NFC cards. + /// + public interface IReader + { + /// + /// Event that will be called when a new tag was discovered. + /// + event EventHandler CardDiscovered; + + /// + /// Event that will be called when a tag that is in use gets disconnected. + /// + event EventHandler CardLost; + + void start(); + + void stop(); + } + + public interface ICard + { + /// + /// Connect to Smartcard + /// + void Connect(); + + /// + /// Disconnect from Smartcard + /// + void Disconnect(); + + /// + /// Transmit APDU Command to Smartcard + /// + /// Application Protocol Data Unit Command - ISO 7816 + /// Application Protocol Data Unit Response - ISO 7816 + byte[] Transmit(byte[] apdu_cmd); + } + + public class ReaderUnavailableException : Exception { } + + public class CardUnavailableException : Exception { } + + public class APDUException : Exception { + public readonly byte ResponseCode; + } +} diff --git a/NFC/NFC.csproj b/NFC/NFC.csproj new file mode 100644 index 0000000..cb63190 --- /dev/null +++ b/NFC/NFC.csproj @@ -0,0 +1,7 @@ + + + + netcoreapp3.1 + + + From 187dfc4f4a8c2d3bba8ecb413789e984201d1f94 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Tue, 15 Sep 2020 15:27:01 +0200 Subject: [PATCH 02/21] Added: PCSC Implementation --- Borepin.sln | 28 +++- NFC/APDUCommand.cs | 61 +++++++ NFC/APDUResponse.cs | 108 ++++++++++++ NFC/APDUStatusWords.cs | 209 ++++++++++++++++++++++++ NFC/IReader.cs | 14 +- NFC/Mifare DESFire/APDUInstructions.cs | 44 +++++ NFC/Mifare DESFire/APDUStatusCodes.cs | 32 ++++ NFC/Mifare DESFire/CryptoOperations.cs | 13 ++ NFC/Mifare DESFire/FileCommunication.cs | 20 +++ NFC/Mifare DESFire/FileTypes.cs | 30 ++++ NFC/NFC.csproj | 5 + NFC/Readers/PCSC/Card.cs | 63 +++++++ NFC/Readers/PCSC/Hardware.cs | 33 ++++ NFC/Readers/PCSC/Reader.cs | 51 ++++++ NFC_Test/NFC_Test.csproj | 17 ++ NFC_Test/REAL_Windows.cs | 37 +++++ 16 files changed, 757 insertions(+), 8 deletions(-) create mode 100644 NFC/APDUCommand.cs create mode 100644 NFC/APDUResponse.cs create mode 100644 NFC/APDUStatusWords.cs create mode 100644 NFC/Mifare DESFire/APDUInstructions.cs create mode 100644 NFC/Mifare DESFire/APDUStatusCodes.cs create mode 100644 NFC/Mifare DESFire/CryptoOperations.cs create mode 100644 NFC/Mifare DESFire/FileCommunication.cs create mode 100644 NFC/Mifare DESFire/FileTypes.cs create mode 100644 NFC/Readers/PCSC/Card.cs create mode 100644 NFC/Readers/PCSC/Hardware.cs create mode 100644 NFC/Readers/PCSC/Reader.cs create mode 100644 NFC_Test/NFC_Test.csproj create mode 100644 NFC_Test/REAL_Windows.cs diff --git a/Borepin.sln b/Borepin.sln index dda3f6a..da929dd 100644 --- a/Borepin.sln +++ b/Borepin.sln @@ -15,7 +15,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.GTK", "Borepin\Bore EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.macOS", "Borepin\Borepin.macOS\Borepin.macOS.csproj", "{3EC23FE7-395E-4BBC-B56B-9455354BDA34}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFC", "NFC\NFC.csproj", "{72DAC306-D4B2-4DBF-9C32-317203FD5D61}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NFC", "NFC\NFC.csproj", "{72DAC306-D4B2-4DBF-9C32-317203FD5D61}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFC_Test", "NFC_Test\NFC_Test.csproj", "{0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -249,6 +251,30 @@ Global {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x64.Build.0 = Release|Any CPU {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x86.ActiveCfg = Release|Any CPU {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x86.Build.0 = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|ARM.ActiveCfg = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|ARM.Build.0 = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhone.Build.0 = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x64.ActiveCfg = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x64.Build.0 = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x86.ActiveCfg = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x86.Build.0 = Debug|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|Any CPU.Build.0 = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|ARM.ActiveCfg = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|ARM.Build.0 = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhone.ActiveCfg = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhone.Build.0 = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x64.ActiveCfg = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x64.Build.0 = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x86.ActiveCfg = Release|Any CPU + {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/NFC/APDUCommand.cs b/NFC/APDUCommand.cs new file mode 100644 index 0000000..c568298 --- /dev/null +++ b/NFC/APDUCommand.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC +{ + public class APDUCommand + { + /// + /// ISO 7816 - CLA - Class + /// + public byte Class { get; set; } + + /// + /// ISO 7816 - INS - Instruction + /// + public byte Instruction { get; set; } + + /// + /// ISO 7816 - P1 - Parameter 1 + /// + public byte Parameter1 { get; set; } + + /// + /// ISO 7816 - P2 - Parameter 2 + /// + public byte Parameter2 { get; set; } + + /// + /// ISO 7816 - Lc - Length Command + /// + public byte LengthCommand + { + get + { + throw new NotImplementedException(); + } + } + + /// + /// ISO 7816 - Data - Data + /// + public byte[] Data { get; set; } + + /// + /// ISO 7816 - Le - Length expected + /// + public byte LengthExpected + { + get + { + throw new NotImplementedException(); + } + } + + public byte[] APDUCommandMessage() + { + throw new NotImplementedException(); + } + } +} diff --git a/NFC/APDUResponse.cs b/NFC/APDUResponse.cs new file mode 100644 index 0000000..bc4f810 --- /dev/null +++ b/NFC/APDUResponse.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Linq; +using NFC.Mifare_DESFire; + +namespace NFC +{ + public class APDUResponse + { + /// + /// ISO 7816 - Body - Body + /// + public byte[] Body { get; set; } + + /// + /// ISO 7816 - SW1 - Status Word 1 + /// + public byte SW1 { get; set; } + + /// + /// ISO 7816 - SW2 - Status Word 2 + /// + public byte SW2 { get; set; } + + /// + /// Creates a new APDUResponse from the raw received data. + /// + public APDUResponse(byte[] raw) { + Body = raw.Take(raw.Length-1).ToArray(); + SW1 = raw[raw.Length - 2]; + SW2 = raw[raw.Length - 3]; + } + + public APDUResponse() + { + + } + + 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)); + } + } + + /// + /// 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. + /// + public byte DataLength + { + get + { + return SW2; + } + } + + /// + /// If the reponse status is COUNTER_REACHED this method can be used to get the value that the counter reached. + /// + public byte Counter + { + get + { + return (byte)(SW2 & 0x0F); + } + } + + /// + /// If the reponse status is INVALID_LE this method can be used to get the correct LE. + /// + public byte CorrectLE + { + get + { + return SW2; + } + } + } +} diff --git a/NFC/APDUStatusWords.cs b/NFC/APDUStatusWords.cs new file mode 100644 index 0000000..b0680cd --- /dev/null +++ b/NFC/APDUStatusWords.cs @@ -0,0 +1,209 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC.Mifare_DESFire +{ + public enum APDUStatusWords : UInt16 + { + /// + /// Kommando erfolgreich ausgefhrt. xx Datenbytes knnen mit dem GET RESPONSE-Kommando abgeholt werden. Statuswort zur Steuerung des T=0-Protokolls + /// + DATA_READY = 0x6100, + + /// + /// Die zurckgegebenen Daten knnen fehlerhaft sein. + /// + FAULTY_DATA = 0x6281, + + /// + /// Da das Dateiende vorher erreicht wurde, konnten nur weniger als Le Bytes gelesen werden. + /// + UNEXPECTED_END_OF_FILE = 0x6282, + + /// + /// Die ausgewhlte Datei ist gesperrt (englisch invalidated, wrtlich ungltig). + /// + INVALIDATED_FILE = 0x6283, + + /// + /// Die File Control Information (FCI) ist inkonform zu ISO 7816-4. + /// + FCI_NOT_CONFORM = 0x6284, + + /// + /// Warnung; Zustand des nichtflchtigen Speichers nicht verndert + /// + STORAGE_NOT_CHANGED = 0x6200, + + /// + /// Zhler hat den Wert x erreicht (die genaue Bedeutung ist vom Kommando abhngig) + /// + COUNTER_REACHED = 0x63C0, + + /// + /// Warnung; Zustand des nichtflchtigen Speichers verndert + /// + STORAGE_CHANGED = 0x6300, + + /// + /// Ausfhrungsfehler; Zustand des nichtflchtigen Speichers nicht verndert + /// + EXECUTION_ERROR_WITHOUT_CHANGE = 0x6400, + + /// + /// Speicherfehler + /// + MEMORY_ERROR = 0x6581, + + /// + /// Ausfhrungsfehler; Zustand des nichtflchtigen Speichers verndert + /// + EXECUTION_ERROR_WITH_CHANGE = 0x6500, + + /// + /// Befehlslnge (Lc) oder erwartete Antwortlnge (Le) falsch + /// + INVALID_LC_LE = 0x6700, + + /// + /// Funktionen im Class-Byte werden nicht untersttzt + /// + CLASS_FEATURE_NOT_SUPPORTED = 0x6800, + + /// + /// Logische Kanle werden nicht untersttzt + /// + LOGIC_CHANNEL_NOT_SUPPORTED = 0x6881, + + /// + /// Secure Messaging wird nicht untersttzt + /// + SECURE_MESSAGING_NOT_SUPPORTED = 0x6882, + + /// + /// Kommando nicht erlaubt + /// + COMMAND_NOT_ALLOWED = 0x6900, + + /// + /// Kommando inkompatibel zur Dateistruktur + /// + COMMAND_INCOMPATIBLE = 0x6981, + + /// + /// Sicherheitszustand nicht erfllt + /// + SAFETY_STATUS_NOT_FULFILLED = 0x6982, + + /// + /// Authentisierungsmethode ist gesperrt + /// + AUTHENTICATION_METHOD_LOCKED = 0x6983, + + /// + /// Referenzierte Daten sind gesperrt + /// + REFERENCED_FILE_LOCKED = 0x6984, + + /// + /// Nutzungsbedingungen sind nicht erfllt + /// + TERMS_OF_SERVICE_NOT_FULFILLED = 0x6985, + + /// + /// Kommando nicht erlaubt (kein EF selektiert) + /// + COMMAND_NOT_ALLOWED_NO_EF_SELECTED = 0x6986, + + /// + /// Erwartete Secure-Messaging-Objekte nicht gefunden + /// + EXPECTED_SECURE_MESSAGING_OBJECTS_NOT_FOUND = 0x6987, + + /// + /// Secure-Messaging-Datenobjekte sind inkorrekt + /// + INVALID_SECURE_MESSAGING_OBJECTS = 0x6988, + + /// + /// Falsche Parameter P1/P2 + /// + WRONG_PARAMETERS = 0x6A00, + + /// + /// Falsche Daten + /// + WRONG_DATA = 0x6A80, + + /// + /// Funktion wird nicht untersttzt + /// + FEATURE_NOT_SUPPORTED = 0x6A81, + + /// + /// Datei wurde nicht gefunden + /// + FILE_NOT_FOUND = 0x6A82, + + /// + /// Datensatz (engl. record) der Datei nicht gefunden + /// + RECORD_NOT_FOUND = 0x6A83, + + /// + /// Nicht gengend Speicherplatz in der Datei + /// + INSUFFICIENT_SPACE = 0x6A84, + + /// + /// Lc nicht konsistent mit der TLV-Struktur + /// + LC_TLV_INCONSISTENT = 0x6A85, + + /// + /// Inkorrekte Parameter P1/P2 + /// + INCORRECT_PARAMETERs = 0x6A86, + + /// + /// Lc inkonsistent mit P1/P2 + /// + LC_PARAMETERS_INCONSISTENT = 0x6A87, + + /// + /// Referenzierte Daten nicht gefunden + /// + REFERENCED_FILE_NOT_FOUND = 0x6A88, + + /// + /// Parameter P1/P2 falsch + /// + WRONG_PARAMETERS_2 = 0x6B00, + + /// + /// Falsche Lnge Le; xx gibt die korrekte Lnge an Statuswort zur Steuerung des T=0-Protokolls + /// + INVALID_LE = 0x6C00, + + /// + /// Das Kommando (INS) wird nicht untersttzt + /// + INSTRUCTION_NOT_SUPPORTED = 0x6D00, + + /// + /// Die Kommandoklasse (CLA) wird nicht untersttzt + /// + CLASS_NOT_SUPPORTED = 0x6E00, + + /// + /// Kommando wurde mit unbekanntem Fehler abgebrochen + /// + UNKNOWN_ERROR = 0x6F00, + + /// + /// Kommando erfolgreich ausgefhrt + /// + SUCCESS = 0x9000, + } +} diff --git a/NFC/IReader.cs b/NFC/IReader.cs index a0b05b1..d068f9e 100644 --- a/NFC/IReader.cs +++ b/NFC/IReader.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace NFC { @@ -16,16 +14,18 @@ namespace NFC bool IsAvailable(); /// Returns all available readers. - String[] GetReader(); + string[] GetReaders(); /// /// Create a new reader instance from the specified id. /// /// Returns the spatform specific reader that corresponds to the id. /// Invalid reader id. - IReader OpenReader(String readerID); + IReader OpenReader(string readerID); } + public delegate void ReaderEventHandler(object sender, ICard card); + /// /// Abstraction of a platform-specifc reader that can communicate with NFC cards. /// @@ -34,12 +34,12 @@ namespace NFC /// /// Event that will be called when a new tag was discovered. /// - event EventHandler CardDiscovered; + event ReaderEventHandler CardDiscovered; /// /// Event that will be called when a tag that is in use gets disconnected. /// - event EventHandler CardLost; + event ReaderEventHandler CardLost; void start(); @@ -63,7 +63,7 @@ namespace NFC /// /// Application Protocol Data Unit Command - ISO 7816 /// Application Protocol Data Unit Response - ISO 7816 - byte[] Transmit(byte[] apdu_cmd); + APDUResponse Transmit(APDUCommand apdu_cmd); } public class ReaderUnavailableException : Exception { } diff --git a/NFC/Mifare DESFire/APDUInstructions.cs b/NFC/Mifare DESFire/APDUInstructions.cs new file mode 100644 index 0000000..dd3025c --- /dev/null +++ b/NFC/Mifare DESFire/APDUInstructions.cs @@ -0,0 +1,44 @@ +namespace NFC.Mifare_DESFire +{ + enum APDUInstructions : byte + { + AUTHENTICATE_ISO = 0x1A, + AUTHENTICATE_AES = 0xAA, + CHANGE_KEY_SETTINGS = 0x54, + SET_CONFIGURATION = 0x5C, + CHANGE_KEY = 0xC4, + GET_KEY_VERSION = 0x64, + CREATE_APPLICATION = 0xCA, + DELETE_APPLICATION = 0xDA, + GET_APPLICATION_IDS = 0x6A, + FREE_MEMORY = 0x6E, + GET_DF_NAMES = 0x6D, + GET_KEY_SETTINGS = 0x45, + SELECT_APPLICATION = 0x5A, + FORMAT_PICC = 0xFC, + GET_VERSION = 0x60, + GET_CARD_UID = 0x51, + GET_FILE_IDS = 0x6F, + GET_FILE_SETTINGS = 0xF5, + CHANGE_FILE_SETTINGS = 0x5F, + CREATE_STDDATAFILE = 0xCD, + CREATE_BACKUPDATAFILE = 0xCB, + CREATE_VALUE_FILE = 0xCC, + CREATE_LINEAR_RECORD_FILE = 0xC1, + CREATE_CYCLIC_RECORD_FILE = 0xC0, + DELETE_FILE = 0xDF, + GET_ISO_FILE_IDS = 0x61, + READ_DATA = 0x8D, + WRITE_DATA = 0x3D, + GET_VALUE = 0x6C, + CREDIT = 0x0C, + DEBIT = 0xDC, + LIMITED_CREDIT = 0x1C, + WRITE_RECORD = 0x3B, + READ_RECORDS = 0xBB, + CLEAR_RECORD_FILE = 0xEB, + COMMIT_TRANSACTION = 0xC7, + ABORT_TRANSACTION = 0xA7, + CONTINUE = 0xAF, + } +} diff --git a/NFC/Mifare DESFire/APDUStatusCodes.cs b/NFC/Mifare DESFire/APDUStatusCodes.cs new file mode 100644 index 0000000..a06327b --- /dev/null +++ b/NFC/Mifare DESFire/APDUStatusCodes.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC.Mifare_DESFire +{ + public enum APDUStatusCodes : UInt16 + { + OPERATION_OK = 0x9000, // = Successful operation + NO_CHANGES = 0x900C, // = No changes done to backup files, CommitTransaction / AbortTransaction not necessary + OUT_OF_EEPROM_ERROR = 0x900E, // = Insufficient NV-Memory to complete command + ILLEGAL_COMMAND_CODE = 0x901C, // = Command code not supported + INTEGRITY_ERROR = 0x901E, // = CRC or MAC does not match data Padding bytes not valid + NO_SUCH_KEY = 0x9040, // = Invalid key number specified + LENGTH_ERROR = 0x907E, // = Length of command string invalid + PERMISSION_DENIED = 0x909D, // = Current configuration / status does not allow the requested command + PARAMETER_ERROR = 0x909E, // = Value of the parameter(s) invalid + APPLICATION_NOT_FOUND = 0x90A0, // = Requested AID not present on PICC + APPL_INTEGRITY_ERROR = 0x90A1, // = Unrecoverable error within application, application will be disabled + AUTHENTICATION_ERROR = 0x90AE, // = Current authentication status does not allow the requested command + ADDITIONAL_FRAME = 0x90AF, // = Additional data frame is expected to be sent + BOUNDARY_ERROR = 0x90BE, // = Attempt to read/write data from/to beyond the file\'s/record\'s limits. Attempt to exceed the limits of a value file. + PICC_INTEGRITY_ERROR = 0x90C1, // = Unrecoverable error within PICC, PICC will be disabled + COMMAND_ABORTED = 0x90CA, // = Previous Command was not fully completed Not all Frames were requested or provided by the PCD + PICC_DISABLED_ERROR = 0x90CD, // = PICC was disabled by an unrecoverable error + COUNT_ERROR = 0x90CE, // = Number of Applications limited to 28, no additional CreateApplication possible + DUPLICATE_ERROR = 0x90DE, // = Creation of file/application failed because file/application with same number already exists + EEPROM_ERROR = 0x90EE, // = Could not complete NV-write operation due to loss of power, internal backup/rollback mechanism activated + FILE_NOT_FOUND = 0x90F0, // = Specified file number does not exist + FILE_INTEGRITY_ERROR = 0x90F1, // = Unrecoverable error within file, file will be disabled + } +} \ No newline at end of file diff --git a/NFC/Mifare DESFire/CryptoOperations.cs b/NFC/Mifare DESFire/CryptoOperations.cs new file mode 100644 index 0000000..0ae77af --- /dev/null +++ b/NFC/Mifare DESFire/CryptoOperations.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC.Mifare_DESFire +{ + enum CryptoOperations : byte + { + TDES = 0x00, + TKTDES = 0x40, + AES = 0x80, + } +} diff --git a/NFC/Mifare DESFire/FileCommunication.cs b/NFC/Mifare DESFire/FileCommunication.cs new file mode 100644 index 0000000..efce035 --- /dev/null +++ b/NFC/Mifare DESFire/FileCommunication.cs @@ -0,0 +1,20 @@ +namespace NFC.Mifare_DESFire +{ + enum FileCommunication : byte + { + /// + /// "Plain communication" + /// + PLAIN = 0x00, + + /// + /// Plain communication secured by DES/3DES MACing + /// + MAC = 0x01, + + /// + /// Fully DES/3DES enciphered communication + /// + ENCRYPT = 0x03 + } +} diff --git a/NFC/Mifare DESFire/FileTypes.cs b/NFC/Mifare DESFire/FileTypes.cs new file mode 100644 index 0000000..9c1fb13 --- /dev/null +++ b/NFC/Mifare DESFire/FileTypes.cs @@ -0,0 +1,30 @@ +namespace NFC.Mifare_DESFire +{ + enum FileTypes : byte + { + /// + /// Standard Data File + /// + STANDARD = 0x00, + + /// + /// Backup Data Files + /// + BACKUP = 0x01, + + /// + /// Value Files with Backup + /// + VALUE = 0x02, + + /// + /// Linear Record Files with Backup + /// + LINEARRECORD = 0x03, + + /// + /// Cyclic Record Files with Backup + /// + CYCLICRECORD = 0x04 + } +} diff --git a/NFC/NFC.csproj b/NFC/NFC.csproj index cb63190..3c87e5e 100644 --- a/NFC/NFC.csproj +++ b/NFC/NFC.csproj @@ -4,4 +4,9 @@ netcoreapp3.1 + + + + + diff --git a/NFC/Readers/PCSC/Card.cs b/NFC/Readers/PCSC/Card.cs new file mode 100644 index 0000000..cd70e1b --- /dev/null +++ b/NFC/Readers/PCSC/Card.cs @@ -0,0 +1,63 @@ +using PCSC; +using PCSC.Iso7816; + +namespace NFC.Readers.PCSC +{ + public class Card : ICard + { + private IsoReader _ISOReader; + private string _ReaderID; + + public Card(IsoReader isoreader, string readerID) + { + _ISOReader = isoreader; + _ReaderID = readerID; + } + public void Connect() + { + _ISOReader.Connect(_ReaderID, SCardShareMode.Shared, SCardProtocol.Any); + } + + public void Disconnect() + { + _ISOReader.Disconnect(SCardReaderDisposition.Eject); + } + + public APDUResponse Transmit(APDUCommand apdu_cmd) + { + Response response = _ISOReader.Transmit(Convert(apdu_cmd)); + return Convert(response); + } + + public CommandApdu Convert(APDUCommand apdu_cmd) + { + CommandApdu apdu = new CommandApdu(IsoCase.Case2Short, _ISOReader.ActiveProtocol) + { + CLA = apdu_cmd.Class, + INS = apdu_cmd.Instruction, + P1 = apdu_cmd.Parameter1, + P2 = apdu_cmd.Parameter2, + + Data = apdu_cmd.Data, + + Le = apdu_cmd.LengthExpected + }; + + return apdu; + } + + public APDUResponse Convert(Response response) + { + ResponseApdu responseApdu = response.Get(0); + + APDUResponse apduResponse = new APDUResponse() + { + SW1 = responseApdu.SW1, + SW2 = responseApdu.SW2, + Body = responseApdu.GetData() + }; + + return apduResponse; + } + } +} diff --git a/NFC/Readers/PCSC/Hardware.cs b/NFC/Readers/PCSC/Hardware.cs new file mode 100644 index 0000000..efc2373 --- /dev/null +++ b/NFC/Readers/PCSC/Hardware.cs @@ -0,0 +1,33 @@ +using PCSC; + +namespace NFC.Readers.PCSC +{ + public class Hardware : IHardware + { + public string[] GetReaders() + { + var contextFactory = ContextFactory.Instance; + using (var context = contextFactory.Establish(SCardScope.System)) + { + return context.GetReaders(); + } + } + + public bool IsAvailable() + { + if(GetReaders().Length == 0) + { + return false; + } + else + { + return true; + } + } + + public IReader OpenReader(string readerID) + { + return new Reader(readerID); + } + } +} diff --git a/NFC/Readers/PCSC/Reader.cs b/NFC/Readers/PCSC/Reader.cs new file mode 100644 index 0000000..d3e9686 --- /dev/null +++ b/NFC/Readers/PCSC/Reader.cs @@ -0,0 +1,51 @@ +using PCSC; +using PCSC.Iso7816; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC.Readers.PCSC +{ + + public class Reader : IReader, IDisposable + { + private string _ReaderID; + private IContextFactory _ContextFactory; + private ISCardContext _SCardContext; + private IsoReader _ISOReader; + private ICard _Card; + + public Reader(string readerID) + { + _ReaderID = readerID; + } + + public event ReaderEventHandler CardDiscovered; + public event ReaderEventHandler CardLost; + + public void Dispose() + { + stop(); + } + + public void start() + { + _ContextFactory = ContextFactory.Instance; + _SCardContext = _ContextFactory.Establish(SCardScope.System); + + _ISOReader = new IsoReader(_SCardContext); + + _Card = new Card(_ISOReader, _ReaderID); + + CardDiscovered?.Invoke(this, _Card); + } + + public void stop() + { + CardLost?.Invoke(this, _Card); + + _ISOReader.Dispose(); + _SCardContext.Dispose(); + } + } +} diff --git a/NFC_Test/NFC_Test.csproj b/NFC_Test/NFC_Test.csproj new file mode 100644 index 0000000..df2e516 --- /dev/null +++ b/NFC_Test/NFC_Test.csproj @@ -0,0 +1,17 @@ + + + + netcoreapp3.1 + + + + + + + + + + + + + diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs new file mode 100644 index 0000000..f144ee8 --- /dev/null +++ b/NFC_Test/REAL_Windows.cs @@ -0,0 +1,37 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Text; +using NFC; +using NFC.Readers.PCSC; + +namespace NFC_Test +{ + [TestFixture, Explicit] + public class REAL_Windows + { + [Test] + public void GetReaders() + { + Hardware hardware = new Hardware(); + string[] readers = hardware.GetReaders(); + + Console.WriteLine("Readers detected: {0}", readers.Length); + + if(readers.Length > 0) + { + Console.WriteLine("List of ReaderIDs:"); + foreach (string readerID in readers) + { + Console.WriteLine("{0}", readerID); + } + } + } + + [TestCase("")] + public void Connect(string readerID) + { + + } + } +} From 2e68052008bef77b9b955429a63bbca94817508e Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Thu, 17 Sep 2020 16:07:58 +0200 Subject: [PATCH 03/21] Added: GetApplication --- NFC/APDUCommand.cs | 56 +------------- NFC/APDUStatusWords.cs | 7 +- NFC/IReader.cs | 4 +- NFC/Mifare DESFire/MifareDESFire.cs | 111 ++++++++++++++++++++++++++++ NFC/Readers/PCSC/Card.cs | 13 +--- NFC/Readers/PCSC/Reader.cs | 6 +- NFC_Test/REAL_Windows.cs | 105 +++++++++++++++++++++++++- 7 files changed, 230 insertions(+), 72 deletions(-) create mode 100644 NFC/Mifare DESFire/MifareDESFire.cs diff --git a/NFC/APDUCommand.cs b/NFC/APDUCommand.cs index c568298..7a22e30 100644 --- a/NFC/APDUCommand.cs +++ b/NFC/APDUCommand.cs @@ -1,61 +1,13 @@ -using System; -using System.Collections.Generic; -using System.Text; +using PCSC; +using PCSC.Iso7816; namespace NFC { - public class APDUCommand + public class APDUCommand : CommandApdu { - /// - /// ISO 7816 - CLA - Class - /// - public byte Class { get; set; } - - /// - /// ISO 7816 - INS - Instruction - /// - public byte Instruction { get; set; } - - /// - /// ISO 7816 - P1 - Parameter 1 - /// - public byte Parameter1 { get; set; } - - /// - /// ISO 7816 - P2 - Parameter 2 - /// - public byte Parameter2 { get; set; } - - /// - /// ISO 7816 - Lc - Length Command - /// - public byte LengthCommand + public APDUCommand(IsoCase isoCase) : base(isoCase, SCardProtocol.Any) { - get - { - throw new NotImplementedException(); - } - } - /// - /// ISO 7816 - Data - Data - /// - public byte[] Data { get; set; } - - /// - /// ISO 7816 - Le - Length expected - /// - public byte LengthExpected - { - get - { - throw new NotImplementedException(); - } - } - - public byte[] APDUCommandMessage() - { - throw new NotImplementedException(); } } } diff --git a/NFC/APDUStatusWords.cs b/NFC/APDUStatusWords.cs index b0680cd..a9c4bd8 100644 --- a/NFC/APDUStatusWords.cs +++ b/NFC/APDUStatusWords.cs @@ -204,6 +204,11 @@ namespace NFC.Mifare_DESFire /// /// Kommando erfolgreich ausgefhrt /// - SUCCESS = 0x9000, + SUCCESS = 0x9000, + + /// + /// OK + /// + OK = 0x9100, } } diff --git a/NFC/IReader.cs b/NFC/IReader.cs index d068f9e..447a543 100644 --- a/NFC/IReader.cs +++ b/NFC/IReader.cs @@ -41,9 +41,9 @@ namespace NFC /// event ReaderEventHandler CardLost; - void start(); + void Start(); - void stop(); + void Stop(); } public interface ICard diff --git a/NFC/Mifare DESFire/MifareDESFire.cs b/NFC/Mifare DESFire/MifareDESFire.cs new file mode 100644 index 0000000..f6b5287 --- /dev/null +++ b/NFC/Mifare DESFire/MifareDESFire.cs @@ -0,0 +1,111 @@ +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; + } + + /// + /// Select Application by ID + /// + /// 3 Byte ID + public APDUCommand CreateApplication(UInt32 id) + { + 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] + }, + Le = 0x00 + }; + + return cmd; + } + + public byte GenerateKeySetting1() + { + return 0x00; + } + + /// + /// + /// + public enum ChangeKey : byte + { + MASTERKEY = 0x00, + + } + } +} diff --git a/NFC/Readers/PCSC/Card.cs b/NFC/Readers/PCSC/Card.cs index cd70e1b..4b38a7a 100644 --- a/NFC/Readers/PCSC/Card.cs +++ b/NFC/Readers/PCSC/Card.cs @@ -31,18 +31,7 @@ namespace NFC.Readers.PCSC public CommandApdu Convert(APDUCommand apdu_cmd) { - CommandApdu apdu = new CommandApdu(IsoCase.Case2Short, _ISOReader.ActiveProtocol) - { - CLA = apdu_cmd.Class, - INS = apdu_cmd.Instruction, - P1 = apdu_cmd.Parameter1, - P2 = apdu_cmd.Parameter2, - - Data = apdu_cmd.Data, - - Le = apdu_cmd.LengthExpected - }; - + CommandApdu apdu = (CommandApdu)apdu_cmd; return apdu; } diff --git a/NFC/Readers/PCSC/Reader.cs b/NFC/Readers/PCSC/Reader.cs index d3e9686..dfb440d 100644 --- a/NFC/Readers/PCSC/Reader.cs +++ b/NFC/Readers/PCSC/Reader.cs @@ -25,10 +25,10 @@ namespace NFC.Readers.PCSC public void Dispose() { - stop(); + Stop(); } - public void start() + public void Start() { _ContextFactory = ContextFactory.Instance; _SCardContext = _ContextFactory.Establish(SCardScope.System); @@ -40,7 +40,7 @@ namespace NFC.Readers.PCSC CardDiscovered?.Invoke(this, _Card); } - public void stop() + public void Stop() { CardLost?.Invoke(this, _Card); diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index f144ee8..fdb6f2f 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.Text; using NFC; using NFC.Readers.PCSC; +using System.Threading; +using NFC.Mifare_DESFire; namespace NFC_Test { @@ -13,7 +15,7 @@ namespace NFC_Test [Test] public void GetReaders() { - Hardware hardware = new Hardware(); + IHardware hardware = new Hardware(); string[] readers = hardware.GetReaders(); Console.WriteLine("Readers detected: {0}", readers.Length); @@ -28,10 +30,109 @@ namespace NFC_Test } } - [TestCase("")] + [TestCase("ACS ACR122U PICC Interface 0")] public void Connect(string readerID) { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + bool connected_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + connected_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, connected_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [TestCase("ACS ACR122U PICC Interface 0")] + public void GetApplicationIDs(string readerID) + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MifareDESFire desfire = new MifareDESFire(); + + APDUCommand cmd = desfire.GetApplicationIDs(); + + APDUResponse response = card.Transmit(cmd); + + if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) + { + UInt32[] ApplicationIDs = desfire.ConvertApplicationIDs(response); + + foreach(UInt32 id in ApplicationIDs) + { + Console.WriteLine("0x{0:X3}", id); + } + + transmit_successfully = true; + } + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xC0FFEE)] + public void SelectApplication(string readerID, UInt32 applicationID) + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MifareDESFire desfire = new MifareDESFire(); + + APDUCommand cmd = desfire.SelectApplication(applicationID); + + cmd.ToArray(); + + APDUResponse response = card.Transmit(cmd); + + if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) + { + transmit_successfully = true; + } + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; } } } From 78b832187a9090a2132bf9e978f1baf9ba72bb62 Mon Sep 17 00:00:00 2001 From: Jannis Rieger Date: Fri, 18 Sep 2020 02:04:58 +0200 Subject: [PATCH 04/21] implemented NFC on iOS --- Borepin.sln | 100 ++++++++++++------------- Borepin/Borepin.iOS/Borepin.iOS.csproj | 15 +++- Borepin/Borepin.iOS/CNFC/Card.cs | 66 ++++++++++++++++ Borepin/Borepin.iOS/CNFC/Hardware.cs | 24 ++++++ Borepin/Borepin.iOS/CNFC/Reader.cs | 67 +++++++++++++++++ NFC/NFC.csproj | 23 +++--- 6 files changed, 231 insertions(+), 64 deletions(-) create mode 100644 Borepin/Borepin.iOS/CNFC/Card.cs create mode 100644 Borepin/Borepin.iOS/CNFC/Hardware.cs create mode 100644 Borepin/Borepin.iOS/CNFC/Reader.cs diff --git a/Borepin.sln b/Borepin.sln index da929dd..f2e2b0c 100644 --- a/Borepin.sln +++ b/Borepin.sln @@ -15,9 +15,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.GTK", "Borepin\Bore EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Borepin.macOS", "Borepin\Borepin.macOS\Borepin.macOS.csproj", "{3EC23FE7-395E-4BBC-B56B-9455354BDA34}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NFC", "NFC\NFC.csproj", "{72DAC306-D4B2-4DBF-9C32-317203FD5D61}" +Project("{9344BDBB-3E7F-41FC-A0DD-8665D75EE146}") = "NFC_Test", "NFC_Test\NFC_Test.csproj", "{41EC0C17-B456-42AE-89F2-79DDB8ED9858}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFC_Test", "NFC_Test\NFC_Test.csproj", "{0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NFC", "NFC\NFC.csproj", "{9C2ED2EB-D91C-4D80-9580-6A135C05AF11}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -227,54 +227,54 @@ Global {3EC23FE7-395E-4BBC-B56B-9455354BDA34}.Release|x64.Build.0 = Release|Any CPU {3EC23FE7-395E-4BBC-B56B-9455354BDA34}.Release|x86.ActiveCfg = Release|Any CPU {3EC23FE7-395E-4BBC-B56B-9455354BDA34}.Release|x86.Build.0 = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|Any CPU.Build.0 = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|ARM.ActiveCfg = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|ARM.Build.0 = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|iPhone.Build.0 = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|x64.ActiveCfg = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|x64.Build.0 = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|x86.ActiveCfg = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Debug|x86.Build.0 = Debug|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|Any CPU.ActiveCfg = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|Any CPU.Build.0 = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|ARM.ActiveCfg = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|ARM.Build.0 = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|iPhone.ActiveCfg = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|iPhone.Build.0 = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x64.ActiveCfg = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x64.Build.0 = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x86.ActiveCfg = Release|Any CPU - {72DAC306-D4B2-4DBF-9C32-317203FD5D61}.Release|x86.Build.0 = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|ARM.ActiveCfg = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|ARM.Build.0 = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhone.ActiveCfg = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhone.Build.0 = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x64.ActiveCfg = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x64.Build.0 = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x86.ActiveCfg = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Debug|x86.Build.0 = Debug|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|Any CPU.Build.0 = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|ARM.ActiveCfg = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|ARM.Build.0 = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhone.ActiveCfg = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhone.Build.0 = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|iPhoneSimulator.Build.0 = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x64.ActiveCfg = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x64.Build.0 = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x86.ActiveCfg = Release|Any CPU - {0DC42C5F-FB5D-48E1-81C2-25AF23F3916A}.Release|x86.Build.0 = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|Any CPU.Build.0 = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|ARM.ActiveCfg = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|ARM.Build.0 = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|iPhone.Build.0 = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|x64.ActiveCfg = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|x64.Build.0 = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|x86.ActiveCfg = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Debug|x86.Build.0 = Debug|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|Any CPU.ActiveCfg = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|Any CPU.Build.0 = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|ARM.ActiveCfg = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|ARM.Build.0 = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|iPhone.ActiveCfg = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|iPhone.Build.0 = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|x64.ActiveCfg = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|x64.Build.0 = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|x86.ActiveCfg = Release|Any CPU + {41EC0C17-B456-42AE-89F2-79DDB8ED9858}.Release|x86.Build.0 = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|ARM.ActiveCfg = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|ARM.Build.0 = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|iPhone.Build.0 = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|x64.ActiveCfg = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|x64.Build.0 = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|x86.ActiveCfg = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Debug|x86.Build.0 = Debug|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|Any CPU.Build.0 = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|ARM.ActiveCfg = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|ARM.Build.0 = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|iPhone.ActiveCfg = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|iPhone.Build.0 = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|x64.ActiveCfg = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|x64.Build.0 = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|x86.ActiveCfg = Release|Any CPU + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Borepin/Borepin.iOS/Borepin.iOS.csproj b/Borepin/Borepin.iOS/Borepin.iOS.csproj index d59a79f..33b6ba5 100644 --- a/Borepin/Borepin.iOS/Borepin.iOS.csproj +++ b/Borepin/Borepin.iOS/Borepin.iOS.csproj @@ -15,6 +15,7 @@ true NSUrlSessionHandler automatic + true true @@ -46,11 +47,12 @@ prompt 4 ARM64 - Apple Development: jannis@rieger-kaulsdorf.de (T4279FN3P6) + iPhone Developer true Entitlements.plist - None + Full -all + --optimize=experimental-xforms-product-type none @@ -61,6 +63,8 @@ ARM64 iPhone Developer Entitlements.plist + --optimize=experimental-xforms-product-type + Full @@ -68,6 +72,9 @@ + + + @@ -132,5 +139,9 @@ {F93856BD-0C8D-4469-A8DB-6E513002BFD7} Borepin + + {9C2ED2EB-D91C-4D80-9580-6A135C05AF11} + NFC + \ No newline at end of file diff --git a/Borepin/Borepin.iOS/CNFC/Card.cs b/Borepin/Borepin.iOS/CNFC/Card.cs new file mode 100644 index 0000000..1758062 --- /dev/null +++ b/Borepin/Borepin.iOS/CNFC/Card.cs @@ -0,0 +1,66 @@ +using System; +using System.Threading; +using CoreNFC; +using Foundation; +using NFC; + +namespace Borepin.iOS.CNFC +{ + public class Card : ICard + { + private NFCTagReaderSession _session; + private INFCMiFareTag _tag; + + public Card(NFCTagReaderSession session, INFCMiFareTag tag) + { + _session = session; + _tag = tag; + } + + public void Connect() + { + var counter = new CountdownEvent(1); + NSError err = null; + + _session.ConnectTo(_tag, (error) => + { + err = error; + counter.Signal(); + }); + + counter.Wait(); + + if (err != null) + { + throw new Exception(err.LocalizedDescription); + } + } + + public void Disconnect() + { + // TODO: decide on which should be used + //_session.RestartPolling(); + _session.InvalidateSession("card disconnect"); + } + + public APDUResponse Transmit(APDUCommand cmd) + { + var counter = new CountdownEvent(1); + byte[] buf = null; + + _tag.SendMiFareIso7816Command(new NFCIso7816Apdu(NSData.FromArray(cmd.Data)), (response, sw1, sw2, NSError) => + { + // reassembly the original apdu message + buf = new byte[response.Length + 2]; + response.ToArray().CopyTo(buf, 0); + buf[response.Length + 0] = sw1; + buf[response.Length + 1] = sw2; + counter.Signal(); + }); + + counter.Wait(); + + return new APDUResponse(buf); + } + } +} diff --git a/Borepin/Borepin.iOS/CNFC/Hardware.cs b/Borepin/Borepin.iOS/CNFC/Hardware.cs new file mode 100644 index 0000000..e523b9e --- /dev/null +++ b/Borepin/Borepin.iOS/CNFC/Hardware.cs @@ -0,0 +1,24 @@ +using System; +using CoreNFC; +using NFC; + +namespace Borepin.iOS.CNFC +{ + public class Hardware : IHardware + { + public bool IsAvailable() + { + return NFCReaderSession.ReadingAvailable; + } + + public String[] GetReaders() + { + return new String[] { "main" }; + } + + public IReader OpenReader(String readerID) + { + return new Reader(); + } + } +} diff --git a/Borepin/Borepin.iOS/CNFC/Reader.cs b/Borepin/Borepin.iOS/CNFC/Reader.cs new file mode 100644 index 0000000..2623290 --- /dev/null +++ b/Borepin/Borepin.iOS/CNFC/Reader.cs @@ -0,0 +1,67 @@ +using System; +using CoreFoundation; +using CoreNFC; +using Foundation; +using NFC; + +namespace Borepin.iOS.CNFC +{ + public class Reader : NFCTagReaderSessionDelegate, IReader + { + public event ReaderEventHandler CardDiscovered; + public event ReaderEventHandler CardLost; + + private NFCReaderSession _session = null; + private DispatchQueue _queue; + + public void Start() + { + _queue = new DispatchQueue("NFC Reader Queue", true); + + // sessions cannot be reused + _session = new NFCTagReaderSession(NFCPollingOption.Iso14443, this, _queue) + { + AlertMessage = "TODO", + }; + + if (_session == null) + { + Console.WriteLine("Oh no! The session is null!"); + } + + _session.BeginSession(); + } + + public void Stop() + { + _session?.InvalidateSession(); + _session = null; + } + + public override void DidDetectTags(NFCTagReaderSession session, INFCTag[] tags) + { + Console.WriteLine("Did detect tags"); + + Console.WriteLine(tags[0].Type); + + //INFCIso7816Tag tag = tags[0].GetNFCIso7816Tag(); + INFCMiFareTag tag = tags[0].GetNFCMiFareTag(); + if (tag != null) + { + Console.WriteLine("Card ist valid"); + CardDiscovered?.Invoke(this, new Card(session, tag)); + } + else + { + Console.WriteLine("Card is not ISO7816"); + } + } + + public override void DidInvalidate(NFCTagReaderSession session, NSError error) + { + // TODO: decide what to do + Console.WriteLine("reader session invalidated"); + } + + } +} diff --git a/NFC/NFC.csproj b/NFC/NFC.csproj index 3c87e5e..519a331 100644 --- a/NFC/NFC.csproj +++ b/NFC/NFC.csproj @@ -1,12 +1,11 @@ - - - - netcoreapp3.1 - - - - - - - - + + + + netstandard2.1 + + + + + + + From 04a41322e6ff3ede24a079f060aebdf309a569d9 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Fri, 25 Sep 2020 20:23:33 +0200 Subject: [PATCH 05/21] BackUp --- NFC/Mifare DESFire/MifareDESFire.cs | 184 ++++++++++++++++++++++++++-- NFC_Test/MifareDESFire_Commands.cs | 33 +++++ NFC_Test/REAL_Windows.cs | 77 ++++++++++++ 3 files changed, 286 insertions(+), 8 deletions(-) create mode 100644 NFC_Test/MifareDESFire_Commands.cs diff --git a/NFC/Mifare DESFire/MifareDESFire.cs b/NFC/Mifare DESFire/MifareDESFire.cs index f6b5287..2a1ab65 100644 --- a/NFC/Mifare DESFire/MifareDESFire.cs +++ b/NFC/Mifare DESFire/MifareDESFire.cs @@ -70,18 +70,34 @@ namespace NFC.Mifare_DESFire 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 + }; + } + /// - /// Select Application by ID + /// Delete Application by ID /// /// 3 Byte ID - public APDUCommand CreateApplication(UInt32 id) + public APDUCommand DeleteApplication(UInt32 id) { byte[] id_byte = BitConverter.GetBytes(id); APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) { CLA = 0x90, - INS = (byte)APDUInstructions.CREATE_APPLICATION, + INS = (byte)APDUInstructions.DELETE_APPLICATION, Data = new byte[] { id_byte[0], @@ -94,18 +110,170 @@ namespace NFC.Mifare_DESFire return cmd; } - public byte GenerateKeySetting1() + /// + /// Select Application by ID + /// + /// 3 Byte ID + public APDUCommand CreateApplication(UInt32 id, byte keysetting1, byte keysetting2) { - return 0x00; + 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 enum ChangeKey : byte + 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, } } } diff --git a/NFC_Test/MifareDESFire_Commands.cs b/NFC_Test/MifareDESFire_Commands.cs new file mode 100644 index 0000000..79207bd --- /dev/null +++ b/NFC_Test/MifareDESFire_Commands.cs @@ -0,0 +1,33 @@ +using NFC; +using NFC.Mifare_DESFire; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC_Test +{ + [TestFixture] + public class MifareDESFire_Commands + { + private MifareDESFire _MifareDESFire; + + [SetUp] + public void SetUp() + { + _MifareDESFire = new MifareDESFire(); + } + + [Test] + public void GetApplicationIDs() + { + + } + + [Test] + public void GenerateKeySetting1() + { + Assert.AreEqual(0xEF, _MifareDESFire.GenerateKeySetting1(MifareDESFire.ChangeApplicationKey.SAMEKEY, MifareDESFire.ChangeMasterKeySettings.WITHMASTERKEY, MifareDESFire.CreateDeleteFile.NOKEY, MifareDESFire.FileDirectoryAccess.NOKEY, MifareDESFire.ChangeMasterKey.CHANGEABLE)); + } + } +} diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index fdb6f2f..1ec7d56 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -134,5 +134,82 @@ namespace NFC_Test reader.Stop(); reader.CardDiscovered -= handler; } + + [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xC0FFEE)] + public void DeleteApplication(string readerID, UInt32 applicationID) + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MifareDESFire desfire = new MifareDESFire(); + + APDUCommand cmd = desfire.DeleteApplication(applicationID); + + cmd.ToArray(); + + APDUResponse response = card.Transmit(cmd); + + if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) + { + transmit_successfully = true; + } + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xC0FFEE)] + public void CreateApplication(string readerID, UInt32 applicationID) + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MifareDESFire desfire = new MifareDESFire(); + + byte keysetting1 = desfire.GenerateKeySetting1(MifareDESFire.ChangeApplicationKey.SAMEKEY, MifareDESFire.ChangeMasterKeySettings.WITHMASTERKEY, MifareDESFire.CreateDeleteFile.NOKEY, MifareDESFire.FileDirectoryAccess.NOKEY, MifareDESFire.ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(MifareDESFire.CryptoOperations.AES, MifareDESFire.FileIdentifies.NOTUSED, 0x01); + + APDUCommand cmd = desfire.CreateApplication(applicationID, keysetting1, keysetting2); + + Console.WriteLine(cmd.ToArray()); + + APDUResponse response = card.Transmit(cmd); + + if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) + { + transmit_successfully = true; + } + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } } } From b9708da23413d680c91c46f1280709097555e823 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Sat, 26 Sep 2020 18:02:44 +0200 Subject: [PATCH 06/21] Added: Card Actions in Test --- NFC/Mifare DESFire/Enums/AccessRights.cs | 8 + .../Enums/ChangeApplicationKey.cs | 21 ++ NFC/Mifare DESFire/Enums/ChangeMasterKey.cs | 18 ++ .../Enums/ChangeMasterKeySettings.cs | 19 ++ NFC/Mifare DESFire/Enums/CreateDeleteFile.cs | 18 ++ .../Enums/CryptoOperationsType.cs | 12 ++ .../{ => Enums}/FileCommunication.cs | 4 +- .../Enums/FileDirectoryAccess.cs | 18 ++ NFC/Mifare DESFire/Enums/FileIdentifies.cs | 11 + NFC/Mifare DESFire/MifareDESFire.cs | 170 +++++----------- NFC_Test/REAL_Windows.cs | 13 +- NFC_Test/REAL_Windows_CardSetUp.cs | 191 ++++++++++++++++++ 12 files changed, 377 insertions(+), 126 deletions(-) create mode 100644 NFC/Mifare DESFire/Enums/AccessRights.cs create mode 100644 NFC/Mifare DESFire/Enums/ChangeApplicationKey.cs create mode 100644 NFC/Mifare DESFire/Enums/ChangeMasterKey.cs create mode 100644 NFC/Mifare DESFire/Enums/ChangeMasterKeySettings.cs create mode 100644 NFC/Mifare DESFire/Enums/CreateDeleteFile.cs create mode 100644 NFC/Mifare DESFire/Enums/CryptoOperationsType.cs rename NFC/Mifare DESFire/{ => Enums}/FileCommunication.cs (82%) create mode 100644 NFC/Mifare DESFire/Enums/FileDirectoryAccess.cs create mode 100644 NFC/Mifare DESFire/Enums/FileIdentifies.cs create mode 100644 NFC_Test/REAL_Windows_CardSetUp.cs diff --git a/NFC/Mifare DESFire/Enums/AccessRights.cs b/NFC/Mifare DESFire/Enums/AccessRights.cs new file mode 100644 index 0000000..0c91aa1 --- /dev/null +++ b/NFC/Mifare DESFire/Enums/AccessRights.cs @@ -0,0 +1,8 @@ +namespace NFC.Mifare_DESFire.Enums +{ + public enum AccessRights : byte + { + FREE = 0x0E, + NEVER = 0x0F + } +} diff --git a/NFC/Mifare DESFire/Enums/ChangeApplicationKey.cs b/NFC/Mifare DESFire/Enums/ChangeApplicationKey.cs new file mode 100644 index 0000000..18305e1 --- /dev/null +++ b/NFC/Mifare DESFire/Enums/ChangeApplicationKey.cs @@ -0,0 +1,21 @@ +namespace NFC.Mifare_DESFire.Enums +{ + /// + /// 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 + } +} diff --git a/NFC/Mifare DESFire/Enums/ChangeMasterKey.cs b/NFC/Mifare DESFire/Enums/ChangeMasterKey.cs new file mode 100644 index 0000000..ae16dd8 --- /dev/null +++ b/NFC/Mifare DESFire/Enums/ChangeMasterKey.cs @@ -0,0 +1,18 @@ +namespace NFC.Mifare_DESFire.Enums +{ + /// + /// 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, + } +} diff --git a/NFC/Mifare DESFire/Enums/ChangeMasterKeySettings.cs b/NFC/Mifare DESFire/Enums/ChangeMasterKeySettings.cs new file mode 100644 index 0000000..75bae21 --- /dev/null +++ b/NFC/Mifare DESFire/Enums/ChangeMasterKeySettings.cs @@ -0,0 +1,19 @@ +namespace NFC.Mifare_DESFire.Enums +{ + /// + /// 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 + } +} diff --git a/NFC/Mifare DESFire/Enums/CreateDeleteFile.cs b/NFC/Mifare DESFire/Enums/CreateDeleteFile.cs new file mode 100644 index 0000000..b50b7b8 --- /dev/null +++ b/NFC/Mifare DESFire/Enums/CreateDeleteFile.cs @@ -0,0 +1,18 @@ +namespace NFC.Mifare_DESFire.Enums +{ + /// + /// 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, + } +} diff --git a/NFC/Mifare DESFire/Enums/CryptoOperationsType.cs b/NFC/Mifare DESFire/Enums/CryptoOperationsType.cs new file mode 100644 index 0000000..d395466 --- /dev/null +++ b/NFC/Mifare DESFire/Enums/CryptoOperationsType.cs @@ -0,0 +1,12 @@ +namespace NFC.Mifare_DESFire.Enums +{ + /// + /// Crypto method of the application + /// + public enum CryptoOperationsType : byte + { + TDES = 0x00, + TKTDES = 0x40, + AES = 0x80, + } +} \ No newline at end of file diff --git a/NFC/Mifare DESFire/FileCommunication.cs b/NFC/Mifare DESFire/Enums/FileCommunication.cs similarity index 82% rename from NFC/Mifare DESFire/FileCommunication.cs rename to NFC/Mifare DESFire/Enums/FileCommunication.cs index efce035..47e976c 100644 --- a/NFC/Mifare DESFire/FileCommunication.cs +++ b/NFC/Mifare DESFire/Enums/FileCommunication.cs @@ -1,6 +1,6 @@ -namespace NFC.Mifare_DESFire +namespace NFC.Mifare_DESFire.Enums { - enum FileCommunication : byte + public enum FileCommunication : byte { /// /// "Plain communication" diff --git a/NFC/Mifare DESFire/Enums/FileDirectoryAccess.cs b/NFC/Mifare DESFire/Enums/FileDirectoryAccess.cs new file mode 100644 index 0000000..e2e9db4 --- /dev/null +++ b/NFC/Mifare DESFire/Enums/FileDirectoryAccess.cs @@ -0,0 +1,18 @@ +namespace NFC.Mifare_DESFire.Enums +{ + /// + /// 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, + } +} diff --git a/NFC/Mifare DESFire/Enums/FileIdentifies.cs b/NFC/Mifare DESFire/Enums/FileIdentifies.cs new file mode 100644 index 0000000..25873f1 --- /dev/null +++ b/NFC/Mifare DESFire/Enums/FileIdentifies.cs @@ -0,0 +1,11 @@ +namespace NFC.Mifare_DESFire.Enums +{ + /// + /// Indicates use of 2 byte ISO/IEC 7816-4 File Identifies for files within the Application + /// + public enum FileIdentifies : byte + { + NOTUSED = 0x00, + USED = 0x20 + } +} diff --git a/NFC/Mifare DESFire/MifareDESFire.cs b/NFC/Mifare DESFire/MifareDESFire.cs index 2a1ab65..14dd282 100644 --- a/NFC/Mifare DESFire/MifareDESFire.cs +++ b/NFC/Mifare DESFire/MifareDESFire.cs @@ -1,4 +1,5 @@ -using PCSC.Iso7816; +using NFC.Mifare_DESFire.Enums; +using PCSC.Iso7816; using System; using System.Collections.Generic; using System.Text; @@ -7,6 +8,13 @@ namespace NFC.Mifare_DESFire { public class MifareDESFire { + private ICard _Card; + + public MifareDESFire(ICard card) + { + _Card = card; + } + /// /// Create new Application with AID /// @@ -46,6 +54,16 @@ namespace NFC.Mifare_DESFire return applicationIDs.ToArray(); } + public void Format() + { + throw new NotImplementedException(); + } + + public void Authenticate(int v, byte[] aPP_MasterKey) + { + throw new NotImplementedException(); + } + /// /// Select Application by ID /// @@ -70,20 +88,9 @@ namespace NFC.Mifare_DESFire return cmd; } - public APDUCommand Authenticate_GetChallenge(byte keyid) + public void ChangeApplicationMasterKey(byte[] aPP_MasterKey) { - 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 - }; + throw new NotImplementedException(); } /// @@ -110,6 +117,11 @@ namespace NFC.Mifare_DESFire return cmd; } + public void ChangeApplicationKey(int v, byte[] aPP_Key_1) + { + throw new NotImplementedException(); + } + /// /// Select Application by ID /// @@ -136,6 +148,31 @@ namespace NFC.Mifare_DESFire return cmd; } + 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(); + } + /// /// Genearte KeySetting1 for Application Settings or PICC Setting /// @@ -163,7 +200,7 @@ namespace NFC.Mifare_DESFire /// /// Number of keys that can be stored within the application (0x01-0x0D) /// - public byte GenerateKeySetting2(CryptoOperations cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys) + public byte GenerateKeySetting2(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys) { if(numberOfKeys < 0x01 || numberOfKeys >= 0x0D) { @@ -172,108 +209,5 @@ namespace NFC.Mifare_DESFire 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, - } } } diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index 1ec7d56..12f9701 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -6,6 +6,7 @@ using NFC; using NFC.Readers.PCSC; using System.Threading; using NFC.Mifare_DESFire; +using NFC.Mifare_DESFire.Enums; namespace NFC_Test { @@ -68,7 +69,7 @@ namespace NFC_Test { card.Connect(); - MifareDESFire desfire = new MifareDESFire(); + MifareDESFire desfire = new MifareDESFire(card); APDUCommand cmd = desfire.GetApplicationIDs(); @@ -110,7 +111,7 @@ namespace NFC_Test { card.Connect(); - MifareDESFire desfire = new MifareDESFire(); + MifareDESFire desfire = new MifareDESFire(card); APDUCommand cmd = desfire.SelectApplication(applicationID); @@ -147,7 +148,7 @@ namespace NFC_Test { card.Connect(); - MifareDESFire desfire = new MifareDESFire(); + MifareDESFire desfire = new MifareDESFire(card); APDUCommand cmd = desfire.DeleteApplication(applicationID); @@ -184,10 +185,10 @@ namespace NFC_Test { card.Connect(); - MifareDESFire desfire = new MifareDESFire(); + MifareDESFire desfire = new MifareDESFire(card); - byte keysetting1 = desfire.GenerateKeySetting1(MifareDESFire.ChangeApplicationKey.SAMEKEY, MifareDESFire.ChangeMasterKeySettings.WITHMASTERKEY, MifareDESFire.CreateDeleteFile.NOKEY, MifareDESFire.FileDirectoryAccess.NOKEY, MifareDESFire.ChangeMasterKey.CHANGEABLE); - byte keysetting2 = desfire.GenerateKeySetting2(MifareDESFire.CryptoOperations.AES, MifareDESFire.FileIdentifies.NOTUSED, 0x01); + byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.SAMEKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x01); APDUCommand cmd = desfire.CreateApplication(applicationID, keysetting1, keysetting2); diff --git a/NFC_Test/REAL_Windows_CardSetUp.cs b/NFC_Test/REAL_Windows_CardSetUp.cs new file mode 100644 index 0000000..67b9061 --- /dev/null +++ b/NFC_Test/REAL_Windows_CardSetUp.cs @@ -0,0 +1,191 @@ +using NFC; +using NFC.Mifare_DESFire; +using NFC.Mifare_DESFire.Enums; +using NFC.Readers.PCSC; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC_Test +{ + [TestFixture] + public class REAL_Windows_CardSetUp + { + public static UInt32 FabAccessAID = 0x001100; + public static string CardReaderID = "ACS ACR122U PICC Interface 0"; + public static byte[] PICC_MasterKey = new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + public static byte[] APP_MasterKey = new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + public static byte[] APP_Key_1 = new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + public static byte[] APP_Key_2 = new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + public static byte[] Empty_Key = new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + }; + + public static byte FabAccessIdentFileID = 0x01; + public static string UserDomain = "user1@fabaccess.org"; + + [Test] + public void ResetCard() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(CardReaderID); + + bool connected_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MifareDESFire mifareDESFire = new MifareDESFire(card); + + mifareDESFire.Authenticate(0x01, APP_MasterKey); + + mifareDESFire.Format(); + + connected_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, connected_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test] + public void ProvisionCard() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(CardReaderID); + + bool connected_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MifareDESFire mifareDESFire = new MifareDESFire(card); + + mifareDESFire.Authenticate(0x01, APP_MasterKey); + mifareDESFire.CreateApplication(FabAccessAID); + mifareDESFire.SelectApplication(FabAccessAID); + + mifareDESFire.Authenticate(0x00, Empty_Key); + mifareDESFire.ChangeApplicationMasterKey(APP_MasterKey); + + mifareDESFire.Authenticate(0x00, APP_MasterKey); + mifareDESFire.ChangeApplicationKey(0x01, APP_Key_1); + + connected_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, connected_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + + [Test] + public void SetUpUserCard() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(CardReaderID); + + bool connected_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MifareDESFire mifareDESFire = new MifareDESFire(card); + + mifareDESFire.SelectApplication(FabAccessAID); + mifareDESFire.Authenticate(0x00, Empty_Key); + UInt16 fileAccessRight = mifareDESFire.GenerateFileAccessRight(AccessRights.FREE, 0x00, 0x00, 0x00); + mifareDESFire.CreateFile(FabAccessIdentFileID, FileCommunication.PLAIN, fileAccessRight, (UInt32)0x90); + + System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + + mifareDESFire.WirteData(FabAccessIdentFileID, 0x00000000, 0x00000000, enc.GetBytes(UserDomain)); + + connected_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, connected_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test] + public void AuthenticateCard() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(CardReaderID); + + bool connected_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MifareDESFire mifareDESFire = new MifareDESFire(card); + + mifareDESFire.SelectApplication(FabAccessAID); + byte[] filedata = mifareDESFire.ReadData(FabAccessIdentFileID, 0x00000000, 0x00000000); + + System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + string userdomain = enc.GetString(filedata); + + Console.WriteLine(userdomain); + + mifareDESFire.Authenticate(0x01, APP_Key_1); + + connected_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, connected_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + } +} From c943a51d9ce18dc18b20509297f2be4fa30aada1 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Thu, 1 Oct 2020 19:06:09 +0200 Subject: [PATCH 07/21] BackUp DES --- NFC/Crypto/DES.cs | 45 ++++++++++ NFC/Crypto/TripleDES.cs | 45 ++++++++++ NFC/Mifare DESFire/MifareDESFire.cs | 127 ++++++++++++++++++++++++++- NFC/NFC.csproj | 3 +- NFC_Test/AuthCrypto_Test.cs | 129 ++++++++++++++++++++++++++++ NFC_Test/MifareDESFire_Commands.cs | 5 +- NFC_Test/NFC_Test.csproj | 1 + NFC_Test/REAL_Windows.cs | 44 ++++++++++ NFC_Test/REAL_Windows_CardSetUp.cs | 2 +- 9 files changed, 393 insertions(+), 8 deletions(-) create mode 100644 NFC/Crypto/DES.cs create mode 100644 NFC/Crypto/TripleDES.cs create mode 100644 NFC_Test/AuthCrypto_Test.cs diff --git a/NFC/Crypto/DES.cs b/NFC/Crypto/DES.cs new file mode 100644 index 0000000..db9356a --- /dev/null +++ b/NFC/Crypto/DES.cs @@ -0,0 +1,45 @@ +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; + +namespace NFC.Crypto +{ + public class DES + { + public byte[] Encrypt(byte[] data, byte[] key, byte[] iv) + { + DesEngine engine = new DesEngine(); + CbcBlockCipher blockCipher = new CbcBlockCipher(engine); + BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); + KeyParameter keyParam = new KeyParameter(key); + ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv); + + // Encrypt + cipher.Init(true, keyParamWithIV); + byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)]; + int length = cipher.ProcessBytes(data, outputBytes, 0); + cipher.DoFinal(outputBytes, length); + + return outputBytes; + } + + public byte[] Decrypt(byte[] data, byte[] key, byte[] iv) + { + DesEngine engine = new DesEngine(); + CbcBlockCipher blockCipher = new CbcBlockCipher(engine); + BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); + KeyParameter keyParam = new KeyParameter(key); + ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv); + + // Decrypt + cipher.Init(false, keyParamWithIV); + byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)]; + int length = cipher.ProcessBytes(data, outputBytes, 0); + cipher.DoFinal(outputBytes, length); + + return outputBytes; + } + } +} diff --git a/NFC/Crypto/TripleDES.cs b/NFC/Crypto/TripleDES.cs new file mode 100644 index 0000000..bf4c4fe --- /dev/null +++ b/NFC/Crypto/TripleDES.cs @@ -0,0 +1,45 @@ +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; + +namespace NFC.Crypto +{ + public class TripleDES + { + public byte[] Encrypt(byte[] data, byte[] key, byte[] iv) + { + DesEngine engine = new DesEdeEngine(); + CbcBlockCipher blockCipher = new CbcBlockCipher(engine); + BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); + KeyParameter keyParam = new KeyParameter(key); + ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv); + + // Encrypt + cipher.Init(true, keyParamWithIV); + byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)]; + int length = cipher.ProcessBytes(data, outputBytes, 0); + cipher.DoFinal(outputBytes, length); + + return outputBytes; + } + + public byte[] Decrypt(byte[] data, byte[] key, byte[] iv) + { + DesEngine engine = new DesEdeEngine(); + CbcBlockCipher blockCipher = new CbcBlockCipher(engine); + BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); + KeyParameter keyParam = new KeyParameter(key); + ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv); + + // Decrypt + cipher.Init(false, keyParamWithIV); + byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)]; + int length = cipher.ProcessBytes(data, outputBytes, 0); + cipher.DoFinal(outputBytes, length); + + return outputBytes; + } + } +} diff --git a/NFC/Mifare DESFire/MifareDESFire.cs b/NFC/Mifare DESFire/MifareDESFire.cs index 14dd282..c6617b7 100644 --- a/NFC/Mifare DESFire/MifareDESFire.cs +++ b/NFC/Mifare DESFire/MifareDESFire.cs @@ -1,13 +1,28 @@ -using NFC.Mifare_DESFire.Enums; +using NFC.Crypto; +using NFC.Mifare_DESFire.Enums; using PCSC.Iso7816; using System; using System.Collections.Generic; +using System.IO; +using System.Net.Http; using System.Text; namespace NFC.Mifare_DESFire { + public class MifareDESFire { + public byte[] GenerateDefaultKey(int size) + { + List key = new List(); + for (int i = 0; i < size; i++) + { + key.Add(0); + } + + return key.ToArray(); + } + private ICard _Card; public MifareDESFire(ICard card) @@ -59,9 +74,113 @@ namespace NFC.Mifare_DESFire throw new NotImplementedException(); } - public void Authenticate(int v, byte[] aPP_MasterKey) + /// + /// Authenticate to Card + /// + /// 0x01 - 0x0D + /// + public void Authenticate(byte key_id, byte[] key) { - throw new NotImplementedException(); + APDUCommand cmd_getchallange = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)0x1A, + Data = new byte[] + { + key_id + } + }; + APDUResponse response = _Card.Transmit(cmd_getchallange); + + byte[] challenge = response.Body; + Console.WriteLine("Challange: {0}", toHexString(challenge)); + + byte[] rndA = new byte[] + { + 0x92, 0x31, 0x34, 0x8B, 0x66, 0x35, 0xA8, 0xAF + }; + Console.WriteLine("rndA: {0}", toHexString(rndA)); + + TripleDES des = new TripleDES(); + byte[] rndB = des.Decrypt(challenge, key, GenerateDefaultKey(8)); + Console.WriteLine("rndB: {0}", toHexString(rndB)); + + byte[] leftRotatedRndB = rotateLeft(rndB); + Console.WriteLine("leftRotatedRndB: {0}", toHexString(leftRotatedRndB)); + + byte[] rndA_rndB = concatenate(rndA, leftRotatedRndB); + Console.WriteLine("rndA_rndB: {0}", toHexString(rndA_rndB)); + + byte[] challengeAnswer = des.Encrypt(rndA_rndB, key, GenerateDefaultKey(8)); + Console.WriteLine("challengeAnswer: {0}", toHexString(challengeAnswer)); + + APDUCommand cmd_answerchallange = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)0xAF, + Data = challengeAnswer + }; + Console.WriteLine("cmd_answerchallange: {0}", toHexString(cmd_answerchallange.ToArray())); + + response = _Card.Transmit(cmd_answerchallange); + + byte[] encryptedRndAFromCard = response.Body; + Console.WriteLine("encryptedRndAFromCard: {0}", toHexString(encryptedRndAFromCard)); + + byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, GenerateDefaultKey(8)); + Console.WriteLine("rotatedRndAFromCard: {0}", toHexString(rotatedRndAFromCard)); + + byte[] rndAFromCard = rotateRight(rotatedRndAFromCard); + Console.WriteLine("rndAFromCard: {0}", toHexString(rndAFromCard)); + + if (!rndA.Equals(rndAFromCard)) + { + throw new Exception("???"); + } + } + + private String toHexString(byte[] data) + { + return BitConverter.ToString(data).Replace("-", string.Empty); + } + + public byte[] rotateLeft(byte[] data) + { + byte[] rotate = new byte[data.Length]; + data.CopyTo(rotate, 0); + + byte temp = rotate[0]; + for (var i = 0; i < rotate.Length - 1; i++) + { + rotate[i] = rotate[i + 1]; + } + rotate[rotate.Length - 1] = temp; + + return rotate; + } + + public byte[] rotateRight(byte[] data) + { + byte[] rotate = new byte[data.Length]; + data.CopyTo(rotate, 0); + + byte temp = rotate[rotate.Length - 1]; + for (var i = rotate.Length - 1; i > 1; i--) + { + rotate[i] = rotate[i - 1]; + } + rotate[0] = temp; + + return rotate; + } + + public byte[] concatenate(byte[] a, byte[] b) + { + byte[] c = new byte[a.Length + b.Length]; + a.CopyTo(c, 0); + b.CopyTo(c, a.Length); + + return c; } /// @@ -148,7 +267,7 @@ namespace NFC.Mifare_DESFire return cmd; } - public void CreateFile(byte fabAccessIdentFileID, FileCommunication pLAIN, ushort fileAccessRight, int v) + public void CreateFile(byte fabAccessIdentFileID, FileCommunication pLAIN, ushort fileAccessRight, UInt32 v) { throw new NotImplementedException(); } diff --git a/NFC/NFC.csproj b/NFC/NFC.csproj index 519a331..59bc652 100644 --- a/NFC/NFC.csproj +++ b/NFC/NFC.csproj @@ -1,4 +1,4 @@ - + netstandard2.1 @@ -7,5 +7,6 @@ + diff --git a/NFC_Test/AuthCrypto_Test.cs b/NFC_Test/AuthCrypto_Test.cs new file mode 100644 index 0000000..04d2856 --- /dev/null +++ b/NFC_Test/AuthCrypto_Test.cs @@ -0,0 +1,129 @@ +using NFC; +using NFC.Crypto; +using NFC.Mifare_DESFire; +using NSubstitute; +using NUnit.Framework; +using PCSC.Iso7816; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC_Test +{ + public class AuthCrypto_Test + { + public byte[] GenerateDefaultKey(int size) + { + List key = new List(); + for (int i = 0; i < size; i++) + { + key.Add(0); + } + + return key.ToArray(); + } + + [Test] + // https://www.linkedin.com/pulse/mifare-desfire-introduction-david-coelho + public void AuthExample() + { + DES des = new DES(); + + byte[] challenge = new byte[] + { + 0x93 ,0x9d ,0x2c ,0x2e ,0xa1 ,0x65 ,0x75 ,0xd5 + }; + + byte[] key = GenerateDefaultKey(8); + byte[] iv = GenerateDefaultKey(8); + + byte[] rndA = new byte[] + { + 0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07 + }; + + byte[] rndB = des.Decrypt(challenge, key, iv); + + byte[] rndB_expected = new byte[] + { + 0xea ,0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67 + }; + + Assert.AreEqual(rndB_expected, rndB); + } + + [Test] + public void concatenate() + { + MifareDESFire mifareDESFire = new MifareDESFire(null); + + byte[] rndA = new byte[] + { + 0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07 + }; + + byte[] rndB = new byte[] + { + 0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67 ,0xea + }; + + byte[] rndA_rndB_expected = new byte[] + { + 0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07, 0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67 ,0xea + }; + + byte[] rndA_rndB = mifareDESFire.concatenate(rndA, rndB); + + Assert.AreEqual(rndA_rndB_expected, rndA_rndB); + } + + [Test] + public void Auth() + { + APDUCommand cmd_getchallange = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)0x1A, + Data = new byte[] + { + 0x00 + } + }; + + APDUCommand cmd_answerchallange = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)0xAF, + Data = new byte[] + { + 0x69, 0x17, 0x8b, 0x93, 0x8c, 0x03, 0xed, 0xf1, 0x86, 0xd3, 0x05, 0x6b, 0xed, 0xc8, 0xd6, 0xcf + } + }; + + APDUResponse response = new APDUResponse() + { + Body = new byte[] + { + 0xB8, 0x90, 0x04, 0x7F, 0x2D, 0xC8, 0xD6, 0x8B + } + }; + + APDUResponse response2 = new APDUResponse() + { + Body = new byte[] + { + 0x04, 0x79, 0xed, 0x6c, 0x4f, 0x74, 0xda, 0x4a + } + }; + + ICard card = Substitute.For(); + + card.Transmit(cmd_getchallange).ReturnsForAnyArgs(response); + card.Transmit(cmd_answerchallange).Returns(response2); + + MifareDESFire mifareDESFire = new MifareDESFire(card); + + mifareDESFire.Authenticate(0x00, mifareDESFire.GenerateDefaultKey(16)); + } + } +} diff --git a/NFC_Test/MifareDESFire_Commands.cs b/NFC_Test/MifareDESFire_Commands.cs index 79207bd..436d92d 100644 --- a/NFC_Test/MifareDESFire_Commands.cs +++ b/NFC_Test/MifareDESFire_Commands.cs @@ -1,5 +1,6 @@ using NFC; using NFC.Mifare_DESFire; +using NFC.Mifare_DESFire.Enums; using NUnit.Framework; using System; using System.Collections.Generic; @@ -15,7 +16,7 @@ namespace NFC_Test [SetUp] public void SetUp() { - _MifareDESFire = new MifareDESFire(); + //_MifareDESFire = new MifareDESFire(); } [Test] @@ -27,7 +28,7 @@ namespace NFC_Test [Test] public void GenerateKeySetting1() { - Assert.AreEqual(0xEF, _MifareDESFire.GenerateKeySetting1(MifareDESFire.ChangeApplicationKey.SAMEKEY, MifareDESFire.ChangeMasterKeySettings.WITHMASTERKEY, MifareDESFire.CreateDeleteFile.NOKEY, MifareDESFire.FileDirectoryAccess.NOKEY, MifareDESFire.ChangeMasterKey.CHANGEABLE)); + Assert.AreEqual(0xEF, _MifareDESFire.GenerateKeySetting1(ChangeApplicationKey.SAMEKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE)); } } } diff --git a/NFC_Test/NFC_Test.csproj b/NFC_Test/NFC_Test.csproj index df2e516..d420e5c 100644 --- a/NFC_Test/NFC_Test.csproj +++ b/NFC_Test/NFC_Test.csproj @@ -6,6 +6,7 @@ + diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index 12f9701..85ffafb 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -212,5 +212,49 @@ namespace NFC_Test reader.Stop(); reader.CardDiscovered -= handler; } + + public byte[] GenerateDefaultKey(int size) + { + List key = new List(); + for(int i = 0; i < size; i++) + { + key.Add(0); + } + + return key.ToArray(); + } + /// + /// Used Default PICC Key with PICC authenticate + /// + /// + [TestCase("ACS ACR122U PICC Interface 0")] + public void Authenticate(string readerID) + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MifareDESFire desfire = new MifareDESFire(card); + + desfire.Authenticate(0x00, GenerateDefaultKey(8)); + + transmit_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } } } diff --git a/NFC_Test/REAL_Windows_CardSetUp.cs b/NFC_Test/REAL_Windows_CardSetUp.cs index 67b9061..bb8c7e0 100644 --- a/NFC_Test/REAL_Windows_CardSetUp.cs +++ b/NFC_Test/REAL_Windows_CardSetUp.cs @@ -56,7 +56,7 @@ namespace NFC_Test MifareDESFire mifareDESFire = new MifareDESFire(card); - mifareDESFire.Authenticate(0x01, APP_MasterKey); + mifareDESFire.Authenticate(0x01, PICC_MasterKey); mifareDESFire.Format(); From 6a5f5218002e09d5771854537bd21a23df7a0aff Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Thu, 1 Oct 2020 23:47:47 +0200 Subject: [PATCH 08/21] Added: Authenticate --- NFC/Mifare DESFire/MifareDESFire.cs | 76 ++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 24 deletions(-) diff --git a/NFC/Mifare DESFire/MifareDESFire.cs b/NFC/Mifare DESFire/MifareDESFire.cs index c6617b7..0b38925 100644 --- a/NFC/Mifare DESFire/MifareDESFire.cs +++ b/NFC/Mifare DESFire/MifareDESFire.cs @@ -4,6 +4,7 @@ using PCSC.Iso7816; using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Net.Http; using System.Text; @@ -81,7 +82,7 @@ namespace NFC.Mifare_DESFire /// public void Authenticate(byte key_id, byte[] key) { - APDUCommand cmd_getchallange = new APDUCommand(IsoCase.Case4Short) + APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short) { CLA = 0x90, INS = (byte)0x1A, @@ -90,56 +91,83 @@ namespace NFC.Mifare_DESFire key_id } }; - APDUResponse response = _Card.Transmit(cmd_getchallange); + APDUResponse response = _Card.Transmit(cmd_challange_request); - byte[] challenge = response.Body; - Console.WriteLine("Challange: {0}", toHexString(challenge)); + byte[] rndB_enc = response.Body; + Console.WriteLine("rndB_enc: {0}", toHexString(rndB_enc)); + + DES des = new DES(); + byte[] rndB = des.Decrypt(rndB_enc, key, GenerateDefaultKey(8)); + Console.WriteLine("rndB: {0}", toHexString(rndB)); + + byte[] iv = new byte[8]; + rndB.CopyTo(iv, 0); + + byte[] rndB_rl = rotateLeft(rndB); + Console.WriteLine("rndB_enc: {0}", toHexString(rndB_rl)); byte[] rndA = new byte[] { - 0x92, 0x31, 0x34, 0x8B, 0x66, 0x35, 0xA8, 0xAF + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; Console.WriteLine("rndA: {0}", toHexString(rndA)); - TripleDES des = new TripleDES(); - byte[] rndB = des.Decrypt(challenge, key, GenerateDefaultKey(8)); - Console.WriteLine("rndB: {0}", toHexString(rndB)); + byte[] rndAB = concatenate(rndA, rndB_rl); + Console.WriteLine("rndAB: {0}", toHexString(rndAB)); - byte[] leftRotatedRndB = rotateLeft(rndB); - Console.WriteLine("leftRotatedRndB: {0}", toHexString(leftRotatedRndB)); + byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc); + Console.WriteLine("rndA_rndB_enc: {0}", toHexString(rndAB_enc)); + iv = lastBlock(rndAB_enc); - byte[] rndA_rndB = concatenate(rndA, leftRotatedRndB); - Console.WriteLine("rndA_rndB: {0}", toHexString(rndA_rndB)); - - byte[] challengeAnswer = des.Encrypt(rndA_rndB, key, GenerateDefaultKey(8)); - Console.WriteLine("challengeAnswer: {0}", toHexString(challengeAnswer)); - - APDUCommand cmd_answerchallange = new APDUCommand(IsoCase.Case4Short) + APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) { CLA = 0x90, INS = (byte)0xAF, - Data = challengeAnswer + Data = rndAB_enc }; - Console.WriteLine("cmd_answerchallange: {0}", toHexString(cmd_answerchallange.ToArray())); + Console.WriteLine("cmd_challange_response: {0}", toHexString(cmd_challange_response.ToArray())); - response = _Card.Transmit(cmd_answerchallange); + response = _Card.Transmit(cmd_challange_response); byte[] encryptedRndAFromCard = response.Body; Console.WriteLine("encryptedRndAFromCard: {0}", toHexString(encryptedRndAFromCard)); - byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, GenerateDefaultKey(8)); + byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv); Console.WriteLine("rotatedRndAFromCard: {0}", toHexString(rotatedRndAFromCard)); byte[] rndAFromCard = rotateRight(rotatedRndAFromCard); Console.WriteLine("rndAFromCard: {0}", toHexString(rndAFromCard)); - if (!rndA.Equals(rndAFromCard)) + if (!rndA.SequenceEqual(rndAFromCard)) { throw new Exception("???"); } } - private String toHexString(byte[] data) + public byte[] lastBlock(byte[] data) + { + byte[] block = new byte[8]; + + for(int i = 0; i < block.Length; i++) + { + block[i] = data[data.Length - block.Length + i]; + } + + return block; + } + public byte[] exclusiveOR(byte[] a, byte[] b) + { + byte[] c = new byte[a.Length]; + + for (int i = 0; i < a.Length; i++) + { + c[i] = (byte)(a[i] ^ b[i]); + } + + return c; + } + + private String toHexString(byte[] data) { return BitConverter.ToString(data).Replace("-", string.Empty); } @@ -165,7 +193,7 @@ namespace NFC.Mifare_DESFire data.CopyTo(rotate, 0); byte temp = rotate[rotate.Length - 1]; - for (var i = rotate.Length - 1; i > 1; i--) + for (var i = rotate.Length - 1; i > 0; i--) { rotate[i] = rotate[i - 1]; } From d601e9afb3efc3826c78e9d6230e443eb4dad55e Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Mon, 5 Oct 2020 18:39:45 +0200 Subject: [PATCH 09/21] Backup --- NFC/APDUCommand.cs | 13 - NFC/IReader.cs | 1 + NFC/ISO7816-4/APDUCommand.cs | 47 +++ NFC/{ => ISO7816-4}/APDUResponse.cs | 57 +-- NFC/{ => ISO7816-4}/APDUStatusWords.cs | 2 - .../APDUInstructions.cs | 0 .../APDUStatusCodes.cs | 0 .../CryptoOperations.cs | 0 .../Enums/AccessRights.cs | 0 .../Enums/ChangeApplicationKey.cs | 0 .../Enums/ChangeMasterKey.cs | 0 .../Enums/ChangeMasterKeySettings.cs | 0 .../Enums/CreateDeleteFile.cs | 0 .../Enums/CryptoOperationsType.cs | 0 .../Enums/FileCommunication.cs | 0 .../Enums/FileDirectoryAccess.cs | 0 .../Enums/FileIdentifies.cs | 0 .../FileTypes.cs | 0 .../MIFARE_DESFire.cs} | 371 +++++++++++------- NFC/Readers/PCSC/Card.cs | 1 + NFC_Test/AuthCrypto_Test.cs | 6 +- NFC_Test/MifareDESFire_Commands.cs | 2 +- NFC_Test/REAL_Windows.cs | 12 +- NFC_Test/REAL_Windows_CardSetUp.cs | 20 +- 24 files changed, 319 insertions(+), 213 deletions(-) delete mode 100644 NFC/APDUCommand.cs create mode 100644 NFC/ISO7816-4/APDUCommand.cs rename NFC/{ => ISO7816-4}/APDUResponse.cs (90%) rename NFC/{ => ISO7816-4}/APDUStatusWords.cs (99%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/APDUInstructions.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/APDUStatusCodes.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/CryptoOperations.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/Enums/AccessRights.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/Enums/ChangeApplicationKey.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/Enums/ChangeMasterKey.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/Enums/ChangeMasterKeySettings.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/Enums/CreateDeleteFile.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/Enums/CryptoOperationsType.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/Enums/FileCommunication.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/Enums/FileDirectoryAccess.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/Enums/FileIdentifies.cs (100%) rename NFC/{Mifare DESFire => NXP MIFARE DESFire}/FileTypes.cs (100%) rename NFC/{Mifare DESFire/MifareDESFire.cs => NXP MIFARE DESFire/MIFARE_DESFire.cs} (64%) diff --git a/NFC/APDUCommand.cs b/NFC/APDUCommand.cs deleted file mode 100644 index 7a22e30..0000000 --- a/NFC/APDUCommand.cs +++ /dev/null @@ -1,13 +0,0 @@ -using PCSC; -using PCSC.Iso7816; - -namespace NFC -{ - public class APDUCommand : CommandApdu - { - public APDUCommand(IsoCase isoCase) : base(isoCase, SCardProtocol.Any) - { - - } - } -} diff --git a/NFC/IReader.cs b/NFC/IReader.cs index 447a543..b130cc6 100644 --- a/NFC/IReader.cs +++ b/NFC/IReader.cs @@ -1,4 +1,5 @@ using System; +using NFC.ISO7816_4; namespace NFC { diff --git a/NFC/ISO7816-4/APDUCommand.cs b/NFC/ISO7816-4/APDUCommand.cs new file mode 100644 index 0000000..bf60034 --- /dev/null +++ b/NFC/ISO7816-4/APDUCommand.cs @@ -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.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(); + } + } +} diff --git a/NFC/APDUResponse.cs b/NFC/ISO7816-4/APDUResponse.cs similarity index 90% rename from NFC/APDUResponse.cs rename to NFC/ISO7816-4/APDUResponse.cs index bc4f810..6b01ab7 100644 --- a/NFC/APDUResponse.cs +++ b/NFC/ISO7816-4/APDUResponse.cs @@ -1,42 +1,44 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Linq; using NFC.Mifare_DESFire; -namespace NFC +namespace NFC.ISO7816_4 { public class APDUResponse { - /// - /// ISO 7816 - Body - Body - /// - public byte[] Body { get; set; } - - /// - /// ISO 7816 - SW1 - Status Word 1 - /// - public byte SW1 { get; set; } - - /// - /// ISO 7816 - SW2 - Status Word 2 - /// - public byte SW2 { get; set; } - - /// - /// Creates a new APDUResponse from the raw received data. - /// - public APDUResponse(byte[] raw) { - Body = raw.Take(raw.Length-1).ToArray(); - SW1 = raw[raw.Length - 2]; - SW2 = raw[raw.Length - 3]; - } - + #region constructor public APDUResponse() { } + /// + /// Creates a new APDUResponse from the raw received data. + /// + public APDUResponse(byte[] raw) + { + Body = raw.Take(raw.Length - 1).ToArray(); + SW1 = raw[raw.Length - 2]; + SW2 = raw[raw.Length - 3]; + } + #endregion + + #region Properties + /// + /// ISO 7816-4-4 - Body - Body + /// + public byte[] Body { get; set; } + + /// + /// ISO 7816-4 - SW1 - Status Word 1 + /// + public byte SW1 { get; set; } + + /// + /// ISO 7816-4 - SW2 - Status Word 2 + /// + public byte SW2 { get; set; } + public APDUStatusWords StatusWord { get @@ -104,5 +106,6 @@ namespace NFC return SW2; } } + #endregion } } diff --git a/NFC/APDUStatusWords.cs b/NFC/ISO7816-4/APDUStatusWords.cs similarity index 99% rename from NFC/APDUStatusWords.cs rename to NFC/ISO7816-4/APDUStatusWords.cs index a9c4bd8..c6db0cb 100644 --- a/NFC/APDUStatusWords.cs +++ b/NFC/ISO7816-4/APDUStatusWords.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace NFC.Mifare_DESFire { diff --git a/NFC/Mifare DESFire/APDUInstructions.cs b/NFC/NXP MIFARE DESFire/APDUInstructions.cs similarity index 100% rename from NFC/Mifare DESFire/APDUInstructions.cs rename to NFC/NXP MIFARE DESFire/APDUInstructions.cs diff --git a/NFC/Mifare DESFire/APDUStatusCodes.cs b/NFC/NXP MIFARE DESFire/APDUStatusCodes.cs similarity index 100% rename from NFC/Mifare DESFire/APDUStatusCodes.cs rename to NFC/NXP MIFARE DESFire/APDUStatusCodes.cs diff --git a/NFC/Mifare DESFire/CryptoOperations.cs b/NFC/NXP MIFARE DESFire/CryptoOperations.cs similarity index 100% rename from NFC/Mifare DESFire/CryptoOperations.cs rename to NFC/NXP MIFARE DESFire/CryptoOperations.cs diff --git a/NFC/Mifare DESFire/Enums/AccessRights.cs b/NFC/NXP MIFARE DESFire/Enums/AccessRights.cs similarity index 100% rename from NFC/Mifare DESFire/Enums/AccessRights.cs rename to NFC/NXP MIFARE DESFire/Enums/AccessRights.cs diff --git a/NFC/Mifare DESFire/Enums/ChangeApplicationKey.cs b/NFC/NXP MIFARE DESFire/Enums/ChangeApplicationKey.cs similarity index 100% rename from NFC/Mifare DESFire/Enums/ChangeApplicationKey.cs rename to NFC/NXP MIFARE DESFire/Enums/ChangeApplicationKey.cs diff --git a/NFC/Mifare DESFire/Enums/ChangeMasterKey.cs b/NFC/NXP MIFARE DESFire/Enums/ChangeMasterKey.cs similarity index 100% rename from NFC/Mifare DESFire/Enums/ChangeMasterKey.cs rename to NFC/NXP MIFARE DESFire/Enums/ChangeMasterKey.cs diff --git a/NFC/Mifare DESFire/Enums/ChangeMasterKeySettings.cs b/NFC/NXP MIFARE DESFire/Enums/ChangeMasterKeySettings.cs similarity index 100% rename from NFC/Mifare DESFire/Enums/ChangeMasterKeySettings.cs rename to NFC/NXP MIFARE DESFire/Enums/ChangeMasterKeySettings.cs diff --git a/NFC/Mifare DESFire/Enums/CreateDeleteFile.cs b/NFC/NXP MIFARE DESFire/Enums/CreateDeleteFile.cs similarity index 100% rename from NFC/Mifare DESFire/Enums/CreateDeleteFile.cs rename to NFC/NXP MIFARE DESFire/Enums/CreateDeleteFile.cs diff --git a/NFC/Mifare DESFire/Enums/CryptoOperationsType.cs b/NFC/NXP MIFARE DESFire/Enums/CryptoOperationsType.cs similarity index 100% rename from NFC/Mifare DESFire/Enums/CryptoOperationsType.cs rename to NFC/NXP MIFARE DESFire/Enums/CryptoOperationsType.cs diff --git a/NFC/Mifare DESFire/Enums/FileCommunication.cs b/NFC/NXP MIFARE DESFire/Enums/FileCommunication.cs similarity index 100% rename from NFC/Mifare DESFire/Enums/FileCommunication.cs rename to NFC/NXP MIFARE DESFire/Enums/FileCommunication.cs diff --git a/NFC/Mifare DESFire/Enums/FileDirectoryAccess.cs b/NFC/NXP MIFARE DESFire/Enums/FileDirectoryAccess.cs similarity index 100% rename from NFC/Mifare DESFire/Enums/FileDirectoryAccess.cs rename to NFC/NXP MIFARE DESFire/Enums/FileDirectoryAccess.cs diff --git a/NFC/Mifare DESFire/Enums/FileIdentifies.cs b/NFC/NXP MIFARE DESFire/Enums/FileIdentifies.cs similarity index 100% rename from NFC/Mifare DESFire/Enums/FileIdentifies.cs rename to NFC/NXP MIFARE DESFire/Enums/FileIdentifies.cs diff --git a/NFC/Mifare DESFire/FileTypes.cs b/NFC/NXP MIFARE DESFire/FileTypes.cs similarity index 100% rename from NFC/Mifare DESFire/FileTypes.cs rename to NFC/NXP MIFARE DESFire/FileTypes.cs diff --git a/NFC/Mifare DESFire/MifareDESFire.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs similarity index 64% rename from NFC/Mifare DESFire/MifareDESFire.cs rename to NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs index 0b38925..c079087 100644 --- a/NFC/Mifare DESFire/MifareDESFire.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs @@ -1,35 +1,223 @@ using NFC.Crypto; +using NFC.ISO7816_4; using NFC.Mifare_DESFire.Enums; +using Org.BouncyCastle.Asn1.Crmf; using PCSC.Iso7816; using System; using System.Collections.Generic; -using System.IO; +using System.Data; using System.Linq; -using System.Net.Http; -using System.Text; namespace NFC.Mifare_DESFire { - public class MifareDESFire + public class MIFARE_DESFire { - public byte[] GenerateDefaultKey(int size) - { - List key = new List(); - for (int i = 0; i < size; i++) - { - key.Add(0); - } + // Docs https://hackmd.io/qATu8uYdRnOC40aFrB9afg - return key.ToArray(); - } - - private ICard _Card; - - public MifareDESFire(ICard card) + #region Contructors + /// + /// Construct MIFRARE_DESFire Object with ICard Interface + /// + /// Implementation of ICard, only transmit is used + public MIFARE_DESFire(ICard card) { _Card = card; } + #endregion + + #region Properties + /// + /// ICard Implementation used to transmit APDUCommands and recive APDUResponses + /// + private ICard _Card; + #endregion + + #region Methods + /// + /// Generate Byte Array filled with 0 + /// + /// Size of Array + public byte[] GenerateDefaultKey(uint size) + { + byte[] key = new byte[size]; + for (int i = 0; i < size; i++) + { + key.[i] = 0; + } + + return key; + } + + /// + /// Converts byte[] to string with HEX Code + /// No 0x is created + /// + /// Data + public string ConvertToHexString(byte[] data) + { + return BitConverter.ToString(data).Replace("-", string.Empty); + } + + public void CheckAPDUResponse(APDUResponse response) + { + + } + + #region Methods for Crypto Operation + /// + /// Return a copy of the last Block of data + /// + /// Data compatible to blocksize + /// Size of Block, default is 8 + public byte[] GetLastBlock(byte[] data, uint blocksize = 8) + { + if(data.Length % blocksize != 0) + { + throw new ArgumentException(string.Format("Data is not compatible with blocksize(data(length):{0}, blocksize:{1}", data.Length, blocksize)); + } + + byte[] block = new byte[blocksize]; + + for (int i = 0; i < blocksize; i++) + { + block[i] = data[data.Length - blocksize + i]; + } + + return block; + } + + /// + /// Rotates Array to the left + /// + /// Data + /// Copy of data + public byte[] rotateLeft(byte[] data) + { + byte[] rotate = new byte[data.Length]; + data.CopyTo(rotate, 0); + + byte tmp = rotate[0]; + for (var i = 0; i < rotate.Length - 1; i++) + { + rotate[i] = rotate[i + 1]; + } + rotate[rotate.Length - 1] = tmp; + + return rotate; + } + + /// + /// Rotates Array to the right + /// + /// Data + /// Copy of data + public byte[] rotateRight(byte[] data) + { + byte[] rotate = new byte[data.Length]; + data.CopyTo(rotate, 0); + + byte tmp = rotate[rotate.Length - 1]; + for (var i = rotate.Length - 1; i > 0; i--) + { + rotate[i] = rotate[i - 1]; + } + rotate[0] = tmp; + + return rotate; + } + + /// + /// Concatenates two Arrays, Array A start at index 0 + /// + /// Array A + /// Array B + /// Copy of Data + public byte[] concatenate(byte[] a, byte[] b) + { + byte[] c = new byte[a.Length + b.Length]; + a.CopyTo(c, 0); + b.CopyTo(c, a.Length); + + return c; + } + #endregion + + #endregion + + #region DESFire Commands + /// + /// Get Application IDs from Card + /// + /// AIDs as Array + public UInt32[] GetApplicationIDs() + { + APDUCommand cmd = new APDUCommand(IsoCase.Case2Short) + { + CLA = 0x90, + INS = (byte)APDUInstructions.GET_APPLICATION_IDS + }; + + APDUResponse response = _Card.Transmit(cmd); + + CheckAPDUResponse(response); + + if (response.Body.Length % 3 != 0) + { + throw new Exception(string.Format("Invalid body length (was: {0}).", response.Body.Length)); + } + + if(response.Body.Length == 0) + { + throw new Exception("Missing PICC Entry 0x000000."); + } + + 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 AID + /// + /// 3 Byte AID + public void SelectApplication(UInt32 aid) + { + byte[] id_byte = BitConverter.GetBytes(aid); + + APDUCommand cmd = new APDUCommand(IsoCase.Case3Short) + { + CLA = 0x90, + INS = (byte)APDUInstructions.SELECT_APPLICATION, + Data = new byte[] + { + id_byte[0], + id_byte[1], + id_byte[2] + }, + Le = 0x00 + }; + + APDUResponse response = _Card.Transmit(cmd); + + CheckAPDUResponse(response); + } + #endregion + + + + + + + + /// /// Create new Application with AID @@ -40,36 +228,6 @@ namespace NFC.Mifare_DESFire 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(); - } - public void Format() { throw new NotImplementedException(); @@ -80,7 +238,9 @@ namespace NFC.Mifare_DESFire /// /// 0x01 - 0x0D /// - public void Authenticate(byte key_id, byte[] key) + + // TODO + public void AuthenticateDES(byte key_id, byte[] key) { APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short) { @@ -94,30 +254,30 @@ namespace NFC.Mifare_DESFire APDUResponse response = _Card.Transmit(cmd_challange_request); byte[] rndB_enc = response.Body; - Console.WriteLine("rndB_enc: {0}", toHexString(rndB_enc)); + Console.WriteLine("rndB_enc: {0}", ConvertToHexString(rndB_enc)); DES des = new DES(); byte[] rndB = des.Decrypt(rndB_enc, key, GenerateDefaultKey(8)); - Console.WriteLine("rndB: {0}", toHexString(rndB)); + Console.WriteLine("rndB: {0}", ConvertToHexString(rndB)); byte[] iv = new byte[8]; rndB.CopyTo(iv, 0); byte[] rndB_rl = rotateLeft(rndB); - Console.WriteLine("rndB_enc: {0}", toHexString(rndB_rl)); + Console.WriteLine("rndB_enc: {0}", ConvertToHexString(rndB_rl)); byte[] rndA = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; - Console.WriteLine("rndA: {0}", toHexString(rndA)); + Console.WriteLine("rndA: {0}", ConvertToHexString(rndA)); byte[] rndAB = concatenate(rndA, rndB_rl); - Console.WriteLine("rndAB: {0}", toHexString(rndAB)); + Console.WriteLine("rndAB: {0}", ConvertToHexString(rndAB)); byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc); - Console.WriteLine("rndA_rndB_enc: {0}", toHexString(rndAB_enc)); - iv = lastBlock(rndAB_enc); + Console.WriteLine("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc)); + iv = GetLastBlock(rndAB_enc); APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) { @@ -125,116 +285,25 @@ namespace NFC.Mifare_DESFire INS = (byte)0xAF, Data = rndAB_enc }; - Console.WriteLine("cmd_challange_response: {0}", toHexString(cmd_challange_response.ToArray())); + Console.WriteLine("cmd_challange_response: {0}", ConvertToHexString(cmd_challange_response.ToArray())); response = _Card.Transmit(cmd_challange_response); byte[] encryptedRndAFromCard = response.Body; - Console.WriteLine("encryptedRndAFromCard: {0}", toHexString(encryptedRndAFromCard)); + Console.WriteLine("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard)); byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv); - Console.WriteLine("rotatedRndAFromCard: {0}", toHexString(rotatedRndAFromCard)); + Console.WriteLine("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard)); byte[] rndAFromCard = rotateRight(rotatedRndAFromCard); - Console.WriteLine("rndAFromCard: {0}", toHexString(rndAFromCard)); + Console.WriteLine("rndAFromCard: {0}", ConvertToHexString(rndAFromCard)); if (!rndA.SequenceEqual(rndAFromCard)) { - throw new Exception("???"); + throw new Exception("PICC Challenge is not correct answered."); } } - public byte[] lastBlock(byte[] data) - { - byte[] block = new byte[8]; - - for(int i = 0; i < block.Length; i++) - { - block[i] = data[data.Length - block.Length + i]; - } - - return block; - } - public byte[] exclusiveOR(byte[] a, byte[] b) - { - byte[] c = new byte[a.Length]; - - for (int i = 0; i < a.Length; i++) - { - c[i] = (byte)(a[i] ^ b[i]); - } - - return c; - } - - private String toHexString(byte[] data) - { - return BitConverter.ToString(data).Replace("-", string.Empty); - } - - public byte[] rotateLeft(byte[] data) - { - byte[] rotate = new byte[data.Length]; - data.CopyTo(rotate, 0); - - byte temp = rotate[0]; - for (var i = 0; i < rotate.Length - 1; i++) - { - rotate[i] = rotate[i + 1]; - } - rotate[rotate.Length - 1] = temp; - - return rotate; - } - - public byte[] rotateRight(byte[] data) - { - byte[] rotate = new byte[data.Length]; - data.CopyTo(rotate, 0); - - byte temp = rotate[rotate.Length - 1]; - for (var i = rotate.Length - 1; i > 0; i--) - { - rotate[i] = rotate[i - 1]; - } - rotate[0] = temp; - - return rotate; - } - - public byte[] concatenate(byte[] a, byte[] b) - { - byte[] c = new byte[a.Length + b.Length]; - a.CopyTo(c, 0); - b.CopyTo(c, a.Length); - - return c; - } - - /// - /// 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 void ChangeApplicationMasterKey(byte[] aPP_MasterKey) { throw new NotImplementedException(); diff --git a/NFC/Readers/PCSC/Card.cs b/NFC/Readers/PCSC/Card.cs index 4b38a7a..83ae2e9 100644 --- a/NFC/Readers/PCSC/Card.cs +++ b/NFC/Readers/PCSC/Card.cs @@ -1,5 +1,6 @@ using PCSC; using PCSC.Iso7816; +using NFC.ISO7816_4; namespace NFC.Readers.PCSC { diff --git a/NFC_Test/AuthCrypto_Test.cs b/NFC_Test/AuthCrypto_Test.cs index 04d2856..f429834 100644 --- a/NFC_Test/AuthCrypto_Test.cs +++ b/NFC_Test/AuthCrypto_Test.cs @@ -55,7 +55,7 @@ namespace NFC_Test [Test] public void concatenate() { - MifareDESFire mifareDESFire = new MifareDESFire(null); + MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(null); byte[] rndA = new byte[] { @@ -121,9 +121,9 @@ namespace NFC_Test card.Transmit(cmd_getchallange).ReturnsForAnyArgs(response); card.Transmit(cmd_answerchallange).Returns(response2); - MifareDESFire mifareDESFire = new MifareDESFire(card); + MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - mifareDESFire.Authenticate(0x00, mifareDESFire.GenerateDefaultKey(16)); + mifareDESFire.AuthenticateDES(0x00, mifareDESFire.GenerateDefaultKey(16)); } } } diff --git a/NFC_Test/MifareDESFire_Commands.cs b/NFC_Test/MifareDESFire_Commands.cs index 436d92d..504b25a 100644 --- a/NFC_Test/MifareDESFire_Commands.cs +++ b/NFC_Test/MifareDESFire_Commands.cs @@ -11,7 +11,7 @@ namespace NFC_Test [TestFixture] public class MifareDESFire_Commands { - private MifareDESFire _MifareDESFire; + private MIFARE_DESFire _MifareDESFire; [SetUp] public void SetUp() diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index 85ffafb..bb2ebfb 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -69,7 +69,7 @@ namespace NFC_Test { card.Connect(); - MifareDESFire desfire = new MifareDESFire(card); + MIFARE_DESFire desfire = new MIFARE_DESFire(card); APDUCommand cmd = desfire.GetApplicationIDs(); @@ -111,7 +111,7 @@ namespace NFC_Test { card.Connect(); - MifareDESFire desfire = new MifareDESFire(card); + MIFARE_DESFire desfire = new MIFARE_DESFire(card); APDUCommand cmd = desfire.SelectApplication(applicationID); @@ -148,7 +148,7 @@ namespace NFC_Test { card.Connect(); - MifareDESFire desfire = new MifareDESFire(card); + MIFARE_DESFire desfire = new MIFARE_DESFire(card); APDUCommand cmd = desfire.DeleteApplication(applicationID); @@ -185,7 +185,7 @@ namespace NFC_Test { card.Connect(); - MifareDESFire desfire = new MifareDESFire(card); + MIFARE_DESFire desfire = new MIFARE_DESFire(card); byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.SAMEKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x01); @@ -239,9 +239,9 @@ namespace NFC_Test { card.Connect(); - MifareDESFire desfire = new MifareDESFire(card); + MIFARE_DESFire desfire = new MIFARE_DESFire(card); - desfire.Authenticate(0x00, GenerateDefaultKey(8)); + desfire.AuthenticateDES(0x00, GenerateDefaultKey(8)); transmit_successfully = true; diff --git a/NFC_Test/REAL_Windows_CardSetUp.cs b/NFC_Test/REAL_Windows_CardSetUp.cs index bb8c7e0..652913b 100644 --- a/NFC_Test/REAL_Windows_CardSetUp.cs +++ b/NFC_Test/REAL_Windows_CardSetUp.cs @@ -54,9 +54,9 @@ namespace NFC_Test { card.Connect(); - MifareDESFire mifareDESFire = new MifareDESFire(card); + MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - mifareDESFire.Authenticate(0x01, PICC_MasterKey); + mifareDESFire.AuthenticateDES(0x01, PICC_MasterKey); mifareDESFire.Format(); @@ -86,16 +86,16 @@ namespace NFC_Test { card.Connect(); - MifareDESFire mifareDESFire = new MifareDESFire(card); + MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - mifareDESFire.Authenticate(0x01, APP_MasterKey); + mifareDESFire.AuthenticateDES(0x01, APP_MasterKey); mifareDESFire.CreateApplication(FabAccessAID); mifareDESFire.SelectApplication(FabAccessAID); - mifareDESFire.Authenticate(0x00, Empty_Key); + mifareDESFire.AuthenticateDES(0x00, Empty_Key); mifareDESFire.ChangeApplicationMasterKey(APP_MasterKey); - mifareDESFire.Authenticate(0x00, APP_MasterKey); + mifareDESFire.AuthenticateDES(0x00, APP_MasterKey); mifareDESFire.ChangeApplicationKey(0x01, APP_Key_1); connected_successfully = true; @@ -125,10 +125,10 @@ namespace NFC_Test { card.Connect(); - MifareDESFire mifareDESFire = new MifareDESFire(card); + MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); mifareDESFire.SelectApplication(FabAccessAID); - mifareDESFire.Authenticate(0x00, Empty_Key); + mifareDESFire.AuthenticateDES(0x00, Empty_Key); UInt16 fileAccessRight = mifareDESFire.GenerateFileAccessRight(AccessRights.FREE, 0x00, 0x00, 0x00); mifareDESFire.CreateFile(FabAccessIdentFileID, FileCommunication.PLAIN, fileAccessRight, (UInt32)0x90); @@ -162,7 +162,7 @@ namespace NFC_Test { card.Connect(); - MifareDESFire mifareDESFire = new MifareDESFire(card); + MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); mifareDESFire.SelectApplication(FabAccessAID); byte[] filedata = mifareDESFire.ReadData(FabAccessIdentFileID, 0x00000000, 0x00000000); @@ -172,7 +172,7 @@ namespace NFC_Test Console.WriteLine(userdomain); - mifareDESFire.Authenticate(0x01, APP_Key_1); + mifareDESFire.AuthenticateDES(0x01, APP_Key_1); connected_successfully = true; From f5dffcec5b75f18f0de150cac187d3e27052a8a4 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Tue, 6 Oct 2020 15:59:53 +0200 Subject: [PATCH 10/21] BackUp --- Borepin/Borepin.iOS/CNFC/Card.cs | 1 + NFC/Crypto/CRC32.cs | 44 +++++ NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs | 213 ++++++++++++++++++++++- NFC_Test/AuthCrypto_Test.cs | 1 + NFC_Test/REAL_Windows.cs | 146 ++++++++++------ 5 files changed, 338 insertions(+), 67 deletions(-) create mode 100644 NFC/Crypto/CRC32.cs diff --git a/Borepin/Borepin.iOS/CNFC/Card.cs b/Borepin/Borepin.iOS/CNFC/Card.cs index 1758062..34a573f 100644 --- a/Borepin/Borepin.iOS/CNFC/Card.cs +++ b/Borepin/Borepin.iOS/CNFC/Card.cs @@ -3,6 +3,7 @@ using System.Threading; using CoreNFC; using Foundation; using NFC; +using NFC.ISO7816_4; namespace Borepin.iOS.CNFC { diff --git a/NFC/Crypto/CRC32.cs b/NFC/Crypto/CRC32.cs new file mode 100644 index 0000000..6593d6e --- /dev/null +++ b/NFC/Crypto/CRC32.cs @@ -0,0 +1,44 @@ +using System; + +namespace NFC.Crypto +{ + public class CRC32 + { + public byte[] Calculate(byte[] data) + { + UInt32 crc32 = 0xFFFFFFFF; + + crc32 = Calculate(data, crc32); + + return BitConverter.GetBytes(crc32); + } + + public byte[] Calculate(byte[] cmd, byte[] data) + { + UInt32 crc32 = 0xFFFFFFFF; + + crc32 = Calculate(cmd, crc32); + crc32 = Calculate(data, crc32); + + return BitConverter.GetBytes(crc32); + } + + public UInt32 Calculate(byte[] data, UInt32 crc32) + { + for (int i = 0; i < data.Length; i++) + { + crc32 ^= data[i]; + for (int b = 0; b < 8; b++) + { + bool b_Bit = (crc32 & 0x01) > 0; + crc32 >>= 1; + if (b_Bit) + { + crc32 ^= 0xEDB88320; + } + } + } + return crc32; + } + } +} diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs index c079087..4fbe232 100644 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs @@ -1,16 +1,13 @@ using NFC.Crypto; using NFC.ISO7816_4; using NFC.Mifare_DESFire.Enums; -using Org.BouncyCastle.Asn1.Crmf; using PCSC.Iso7816; using System; using System.Collections.Generic; -using System.Data; using System.Linq; namespace NFC.Mifare_DESFire { - public class MIFARE_DESFire { // Docs https://hackmd.io/qATu8uYdRnOC40aFrB9afg @@ -31,6 +28,9 @@ namespace NFC.Mifare_DESFire /// ICard Implementation used to transmit APDUCommands and recive APDUResponses /// private ICard _Card; + + public byte[] _SessionKey; + public byte[] _IV; #endregion #region Methods @@ -43,7 +43,7 @@ namespace NFC.Mifare_DESFire byte[] key = new byte[size]; for (int i = 0; i < size; i++) { - key.[i] = 0; + key[i] = 0; } return key; @@ -64,6 +64,63 @@ namespace NFC.Mifare_DESFire } + public bool CheckKey(byte[] key) + { + try + { + GetKeyTypeDES(key); + return true; + } + catch + { + return false; + } + } + + /// + /// Key Types used for DESFire Cards + /// + public enum KeyType + { + /// + /// DES Key - 8 Byte - 64 Bit + /// + DES, + + /// + /// Triple DES Key with two DES Keys - 16 Byte - 128 Bit + /// + TDES_2K, + + /// + /// Triple DES Key with three DES Keys - 24 Byte - 192 Bit + /// + TDES_3K, + + /// + /// AES Key - 16 Byte - 128 Bit + /// + AES + } + + /// + /// Check the Key Length to get Type of DES/3DES Key + /// + public KeyType GetKeyTypeDES(byte[] key) + { + switch(key.Length) + { + case 8: + return KeyType.DES; + case 16: + return KeyType.TDES_2K; + case 24: + return KeyType.TDES_3K; + default: + throw new ArgumentException(string.Format("No valid DES/3DES Key Size({0})", key.Length)); + } + } + #region Methods for Crypto Operation /// /// Return a copy of the last Block of data @@ -141,6 +198,23 @@ namespace NFC.Mifare_DESFire return c; } + + public byte[] xor(byte[] a, byte[] b) + { + if(a.Length != b.Length) + { + throw new ArgumentException("Array are not same Length"); + } + + byte[] c = new byte[a.Length]; + + for(int i = 0; i < a.Length; i++) + { + c[i] = (byte)(a[i] ^ b[i]); + } + + return c; + } #endregion #endregion @@ -192,7 +266,7 @@ namespace NFC.Mifare_DESFire { byte[] id_byte = BitConverter.GetBytes(aid); - APDUCommand cmd = new APDUCommand(IsoCase.Case3Short) + APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) { CLA = 0x90, INS = (byte)APDUInstructions.SELECT_APPLICATION, @@ -201,8 +275,7 @@ namespace NFC.Mifare_DESFire id_byte[0], id_byte[1], id_byte[2] - }, - Le = 0x00 + } }; APDUResponse response = _Card.Transmit(cmd); @@ -211,7 +284,76 @@ namespace NFC.Mifare_DESFire } #endregion + /// + /// Expand Array to Block Size + /// + /// + /// + public byte[] expandToBlockSize(byte[] data, int bocksize) + { + int diff = data.Length % bocksize; + if (diff == 0) + { + return data; + } + byte[] expand = new byte[data.Length + diff]; + + data.CopyTo(expand, 0); + + for(int i = expand.Length - 1; i > data.Length - 1; i--) + { + expand[i] = 0x00; + } + + return expand; + } + + public void ChangeKeyDES(byte key_no, byte[] key_new, byte[] key_current) + { + if(!CheckKey(key_new)) + { + throw new ArgumentException("key_new is invalid"); + } + + if (!CheckKey(key_current)) + { + throw new ArgumentException("key_new is invalid"); + } + + if(GetKeyTypeDES(key_new) != GetKeyTypeDES(key_current)) + { + throw new ArgumentException("key_new and key_current are not same KeyType"); + } + + byte[] keys_xor = xor(key_new, key_current); + + keys_xor = concatenate(keys_xor, keys_xor); + + CRC32 crc32 = new CRC32(); + byte[] crc = crc32.Calculate(new byte[] { (byte)APDUInstructions.CHANGE_KEY, key_no }, keys_xor); + + byte[] key_xor_crc = concatenate(keys_xor, crc); + + byte[] key_xor_crc_block = expandToBlockSize(key_xor_crc, 8); + + + DES des = new DES(); + + byte[] key_xor_crc_block_enc = des.Encrypt(key_xor_crc_block, _SessionKey, _IV); + + APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)APDUInstructions.CHANGE_KEY, + Data = key_xor_crc_block_enc, + Le = 0x00 + }; + + APDUResponse response = _Card.Transmit(cmd); + + CheckAPDUResponse(response); + } @@ -302,6 +444,58 @@ namespace NFC.Mifare_DESFire { throw new Exception("PICC Challenge is not correct answered."); } + + _SessionKey = GenerateDESSesionKey(rndA, rndB); + _IV = GenerateDefaultKey(8); + } + + private byte[] GenerateDESSesionKey(byte[] rndA, byte[] rndB) + { + byte[] sesssionkey = new byte[8]; + + for(int i = 0; i < sesssionkey.Length; i++) + { + if(i < 4) + { + sesssionkey[i] = rndA[i]; + } + else + { + sesssionkey[i] = rndB[i - 4]; + } + } + + // Set Key Verion of Key to 0x55 to LSB + // TODO + byte[] key_version = SetKeyVersion(sesssionkey, 0x55); + + return concatenate(key_version, key_version); + } + + public byte[] SetKeyVersion(byte[] key, byte keyversion) + { + byte[] pow2 = new byte[] + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 + }; + + byte[] new_key = new byte[key.Length]; + key.CopyTo(new_key, 0); + + + for(int i = 0; i < 8; i++) + { + if((keyversion & pow2[i]) > 0) + { + new_key[i] = (byte)(new_key[5] | 0x01); + } + else + { + new_key[i] = (byte)(new_key[5] & 0x7F); + } + } + + return new_key; } public void ChangeApplicationMasterKey(byte[] aPP_MasterKey) @@ -313,7 +507,7 @@ namespace NFC.Mifare_DESFire /// Delete Application by ID /// /// 3 Byte ID - public APDUCommand DeleteApplication(UInt32 id) + public void DeleteApplication(UInt32 id) { byte[] id_byte = BitConverter.GetBytes(id); @@ -330,7 +524,8 @@ namespace NFC.Mifare_DESFire Le = 0x00 }; - return cmd; + APDUResponse response = _Card.Transmit(cmd); + CheckAPDUResponse(response); } public void ChangeApplicationKey(int v, byte[] aPP_Key_1) diff --git a/NFC_Test/AuthCrypto_Test.cs b/NFC_Test/AuthCrypto_Test.cs index f429834..49fde2b 100644 --- a/NFC_Test/AuthCrypto_Test.cs +++ b/NFC_Test/AuthCrypto_Test.cs @@ -1,5 +1,6 @@ using NFC; using NFC.Crypto; +using NFC.ISO7816_4; using NFC.Mifare_DESFire; using NSubstitute; using NUnit.Framework; diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index bb2ebfb..e6118b8 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -7,6 +7,7 @@ using NFC.Readers.PCSC; using System.Threading; using NFC.Mifare_DESFire; using NFC.Mifare_DESFire.Enums; +using NFC.ISO7816_4; namespace NFC_Test { @@ -71,21 +72,21 @@ namespace NFC_Test MIFARE_DESFire desfire = new MIFARE_DESFire(card); - APDUCommand cmd = desfire.GetApplicationIDs(); + //APDUCommand cmd = desfire.GetApplicationIDs(); - APDUResponse response = card.Transmit(cmd); + //APDUResponse response = card.Transmit(cmd); - if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) - { - UInt32[] ApplicationIDs = desfire.ConvertApplicationIDs(response); + //if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) + //{ + // UInt32[] ApplicationIDs = desfire.ConvertApplicationIDs(response); - foreach(UInt32 id in ApplicationIDs) - { - Console.WriteLine("0x{0:X3}", id); - } + // foreach(UInt32 id in ApplicationIDs) + // { + // Console.WriteLine("0x{0:X3}", id); + // } - transmit_successfully = true; - } + // transmit_successfully = true; + //} card.Disconnect(); }; @@ -111,18 +112,18 @@ namespace NFC_Test { card.Connect(); - MIFARE_DESFire desfire = new MIFARE_DESFire(card); + //MIFARE_DESFire desfire = new MIFARE_DESFire(card); - APDUCommand cmd = desfire.SelectApplication(applicationID); + //APDUCommand cmd = desfire.SelectApplication(applicationID); - cmd.ToArray(); + //cmd.ToArray(); - APDUResponse response = card.Transmit(cmd); + //APDUResponse response = card.Transmit(cmd); - if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) - { - transmit_successfully = true; - } + //if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) + //{ + // transmit_successfully = true; + //} card.Disconnect(); }; @@ -136,44 +137,7 @@ namespace NFC_Test reader.CardDiscovered -= handler; } - [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xC0FFEE)] - public void DeleteApplication(string readerID, UInt32 applicationID) - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); - - bool transmit_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - APDUCommand cmd = desfire.DeleteApplication(applicationID); - - cmd.ToArray(); - - APDUResponse response = card.Transmit(cmd); - - if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) - { - transmit_successfully = true; - } - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, transmit_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xC0FFEE)] + [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)] public void CreateApplication(string readerID, UInt32 applicationID) { IHardware hardware = new Hardware(); @@ -188,7 +152,7 @@ namespace NFC_Test MIFARE_DESFire desfire = new MIFARE_DESFire(card); byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.SAMEKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); - byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x01); + byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.TDES, FileIdentifies.NOTUSED, 0x03); APDUCommand cmd = desfire.CreateApplication(applicationID, keysetting1, keysetting2); @@ -213,6 +177,38 @@ namespace NFC_Test reader.CardDiscovered -= handler; } + [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)] + public void DeleteApplication(string readerID, UInt32 applicationID) + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + desfire.AuthenticateDES(0x00, GenerateDefaultKey(8)); + desfire.DeleteApplication(applicationID); + + transmit_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + public byte[] GenerateDefaultKey(int size) { List key = new List(); @@ -223,6 +219,7 @@ namespace NFC_Test return key.ToArray(); } + /// /// Used Default PICC Key with PICC authenticate /// @@ -241,6 +238,7 @@ namespace NFC_Test MIFARE_DESFire desfire = new MIFARE_DESFire(card); + desfire.SelectApplication(0x000000); desfire.AuthenticateDES(0x00, GenerateDefaultKey(8)); transmit_successfully = true; @@ -256,5 +254,37 @@ namespace NFC_Test reader.Stop(); reader.CardDiscovered -= handler; } + + [TestCase("ACS ACR122U PICC Interface 0")] + public void ChangeKey(string readerID) + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0xAAFFEE); + desfire.AuthenticateDES(0x00, GenerateDefaultKey(8)); + desfire.ChangeKeyDES(0x01, GenerateDefaultKey(8), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }); + + transmit_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } } } From 7381341d3754e6478c9efbbc743d461981be9dcb Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Wed, 7 Oct 2020 19:25:51 +0200 Subject: [PATCH 11/21] Added: DESFire Class V2 --- NFC/Crypto/AES.cs | 45 ++ NFC/Crypto/CRC16.cs | 44 ++ NFC/Crypto/CRC32.cs | 1 + NFC/ISO7816-4/APDUResponse.cs | 23 + NFC/NFC.csproj | 1 + .../AuthenticationDelayException.cs | 26 + .../AuthenticationErrorException.cs | 26 + .../Exceptions/BoundaryErrorException.cs | 26 + .../Exceptions/CommandAbortedException.cs | 26 + .../Exceptions/DuplicateErrorException.cs | 26 + .../Exceptions/FileNotFoundException.cs | 26 + .../Exceptions/IllegalCommandCodeException.cs | 26 + .../Exceptions/IntegrityErrorException.cs | 26 + .../Exceptions/LengthErrorException.cs | 26 + .../Exceptions/NoSuchKeyException.cs | 26 + .../Exceptions/ParameterErrorException.cs | 26 + .../Exceptions/PermissionDeniedException.cs | 26 + NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs | 85 +-- NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs | 575 ++++++++++++++++++ NFC_Test/AuthCrypto_Test.cs | 81 +++ NFC_Test/MIFARE_DESFire_V2_Test.cs | 551 +++++++++++++++++ NFC_Test/NamespaceSetUp.cs | 18 + NFC_Test/OTA.cs | 60 ++ NFC_Test/REAL_Windows.cs | 90 ++- 24 files changed, 1806 insertions(+), 80 deletions(-) create mode 100644 NFC/Crypto/AES.cs create mode 100644 NFC/Crypto/CRC16.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/AuthenticationDelayException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/AuthenticationErrorException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/BoundaryErrorException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/CommandAbortedException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/DuplicateErrorException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/FileNotFoundException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/IllegalCommandCodeException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/IntegrityErrorException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/LengthErrorException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/NoSuchKeyException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/ParameterErrorException.cs create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/PermissionDeniedException.cs create mode 100644 NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs create mode 100644 NFC_Test/MIFARE_DESFire_V2_Test.cs create mode 100644 NFC_Test/NamespaceSetUp.cs create mode 100644 NFC_Test/OTA.cs diff --git a/NFC/Crypto/AES.cs b/NFC/Crypto/AES.cs new file mode 100644 index 0000000..4c5be9a --- /dev/null +++ b/NFC/Crypto/AES.cs @@ -0,0 +1,45 @@ +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Paddings; +using Org.BouncyCastle.Crypto.Parameters; + +namespace NFC.Crypto +{ + public class AES + { + public byte[] Encrypt(byte[] data, byte[] key, byte[] iv) + { + AesEngine engine = new AesEngine(); + CbcBlockCipher blockCipher = new CbcBlockCipher(engine); + BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); + KeyParameter keyParam = new KeyParameter(key); + ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv); + + // Encrypt + cipher.Init(true, keyParamWithIV); + byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)]; + int length = cipher.ProcessBytes(data, outputBytes, 0); + cipher.DoFinal(outputBytes, length); + + return outputBytes; + } + + public byte[] Decrypt(byte[] data, byte[] key, byte[] iv) + { + AesEngine engine = new AesEngine(); + CbcBlockCipher blockCipher = new CbcBlockCipher(engine); + BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); + KeyParameter keyParam = new KeyParameter(key); + ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv); + + // Decrypt + cipher.Init(false, keyParamWithIV); + byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)]; + int length = cipher.ProcessBytes(data, outputBytes, 0); + cipher.DoFinal(outputBytes, length); + + return outputBytes; + } + } +} diff --git a/NFC/Crypto/CRC16.cs b/NFC/Crypto/CRC16.cs new file mode 100644 index 0000000..25f2a22 --- /dev/null +++ b/NFC/Crypto/CRC16.cs @@ -0,0 +1,44 @@ +using System; + +namespace NFC.Crypto +{ + public class CRC16 + { + public byte[] Calculate(byte[] data) + { + UInt16 crc16 = 0x6363; + + crc16 = Calculate(data, crc16); + + return BitConverter.GetBytes(crc16); + } + + public byte[] Calculate(byte[] cmd, byte[] data) + { + UInt16 crc16 = 0x6363; + + crc16 = Calculate(cmd, crc16); + crc16 = Calculate(data, crc16); + + return BitConverter.GetBytes(crc16); + } + + public UInt16 Calculate(byte[] data, UInt16 crc16) + { + for (int i = 0; i < data.Length; i++) + { + crc16 ^= data[i]; + for (int b = 0; b < 8; b++) + { + bool b_Bit = (crc16 & 0x01) > 0; + crc16 >>= 1; + if (b_Bit) + { + crc16 ^= 0x8408; + } + } + } + return crc16; + } + } +} diff --git a/NFC/Crypto/CRC32.cs b/NFC/Crypto/CRC32.cs index 6593d6e..e3e6f1d 100644 --- a/NFC/Crypto/CRC32.cs +++ b/NFC/Crypto/CRC32.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; namespace NFC.Crypto { diff --git a/NFC/ISO7816-4/APDUResponse.cs b/NFC/ISO7816-4/APDUResponse.cs index 6b01ab7..a52d62b 100644 --- a/NFC/ISO7816-4/APDUResponse.cs +++ b/NFC/ISO7816-4/APDUResponse.cs @@ -107,5 +107,28 @@ namespace NFC.ISO7816_4 } } #endregion + + #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; + } + #endregion } } diff --git a/NFC/NFC.csproj b/NFC/NFC.csproj index 59bc652..fdcc319 100644 --- a/NFC/NFC.csproj +++ b/NFC/NFC.csproj @@ -5,6 +5,7 @@ + diff --git a/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationDelayException.cs b/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationDelayException.cs new file mode 100644 index 0000000..160eceb --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationDelayException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Currently not allowed to authenticate. Keeptrying until full delay is spent. + /// 0x91AD + /// + public class AuthenticationDelayException : Exception + { + public AuthenticationDelayException() + { + + } + + public AuthenticationDelayException(string message) : base(message) + { + + } + + public AuthenticationDelayException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationErrorException.cs b/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationErrorException.cs new file mode 100644 index 0000000..368e0eb --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationErrorException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Current authentication status does not allow there- quested command. + /// 0x91AE + /// + public class AuthenticationErrorException : Exception + { + public AuthenticationErrorException() + { + + } + + public AuthenticationErrorException(string message) : base(message) + { + + } + + public AuthenticationErrorException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/BoundaryErrorException.cs b/NFC/NXP MIFARE DESFire/Exceptions/BoundaryErrorException.cs new file mode 100644 index 0000000..f46e5ea --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/BoundaryErrorException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Attempt toread/write data from/to beyond thefile’s/record’s limits. Attempt to exceed the limitsof a value file. + /// 0x91BE + /// + public class BoundaryErrorException : Exception + { + public BoundaryErrorException() + { + + } + + public BoundaryErrorException(string message) : base(message) + { + + } + + public BoundaryErrorException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/CommandAbortedException.cs b/NFC/NXP MIFARE DESFire/Exceptions/CommandAbortedException.cs new file mode 100644 index 0000000..34e1534 --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/CommandAbortedException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Previous Command was not fully completed.Not all Frames were requested or provided bythe PCD. + /// 0x91CA + /// + public class CommandAbortedException : Exception + { + public CommandAbortedException() + { + + } + + public CommandAbortedException(string message) : base(message) + { + + } + + public CommandAbortedException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/DuplicateErrorException.cs b/NFC/NXP MIFARE DESFire/Exceptions/DuplicateErrorException.cs new file mode 100644 index 0000000..8b09b29 --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/DuplicateErrorException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Creation of file/application failed because file/application with same number already exists + /// 0x91DE + /// + public class DuplicateErrorException : Exception + { + public DuplicateErrorException() + { + + } + + public DuplicateErrorException(string message) : base(message) + { + + } + + public DuplicateErrorException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/FileNotFoundException.cs b/NFC/NXP MIFARE DESFire/Exceptions/FileNotFoundException.cs new file mode 100644 index 0000000..1de1e7c --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/FileNotFoundException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Specified file number does not exist. + /// 0x91F0 + /// + public class FileNotFoundException : Exception + { + public FileNotFoundException() + { + + } + + public FileNotFoundException(string message) : base(message) + { + + } + + public FileNotFoundException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/IllegalCommandCodeException.cs b/NFC/NXP MIFARE DESFire/Exceptions/IllegalCommandCodeException.cs new file mode 100644 index 0000000..18f4992 --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/IllegalCommandCodeException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Command code not supported. + /// 0x911C + /// + public class IllegalCommandCodeException : Exception + { + public IllegalCommandCodeException() + { + + } + + public IllegalCommandCodeException(string message) : base(message) + { + + } + + public IllegalCommandCodeException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/IntegrityErrorException.cs b/NFC/NXP MIFARE DESFire/Exceptions/IntegrityErrorException.cs new file mode 100644 index 0000000..6dce4f3 --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/IntegrityErrorException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// CRC or MAC does not match data. Paddingbytes not valid. + /// 0x911E + /// + public class IntegrityErrorException : Exception + { + public IntegrityErrorException() + { + + } + + public IntegrityErrorException(string message) : base(message) + { + + } + + public IntegrityErrorException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/LengthErrorException.cs b/NFC/NXP MIFARE DESFire/Exceptions/LengthErrorException.cs new file mode 100644 index 0000000..b817242 --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/LengthErrorException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Length of command string invalid. + /// 0x917E + /// + public class LengthErrorException : Exception + { + public LengthErrorException() + { + + } + + public LengthErrorException(string message) : base(message) + { + + } + + public LengthErrorException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/NoSuchKeyException.cs b/NFC/NXP MIFARE DESFire/Exceptions/NoSuchKeyException.cs new file mode 100644 index 0000000..d534bbc --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/NoSuchKeyException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Invalid key number specified. + /// 0x9140 + /// + public class NoSuchKeyException : Exception + { + public NoSuchKeyException() + { + + } + + public NoSuchKeyException(string message) : base(message) + { + + } + + public NoSuchKeyException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/ParameterErrorException.cs b/NFC/NXP MIFARE DESFire/Exceptions/ParameterErrorException.cs new file mode 100644 index 0000000..c4e3d3f --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/ParameterErrorException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Value of the parameter(s) invalid. + /// 0x919E + /// + public class ParameterErrorException : Exception + { + public ParameterErrorException() + { + + } + + public ParameterErrorException(string message) : base(message) + { + + } + + public ParameterErrorException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/Exceptions/PermissionDeniedException.cs b/NFC/NXP MIFARE DESFire/Exceptions/PermissionDeniedException.cs new file mode 100644 index 0000000..12a0928 --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/PermissionDeniedException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Current configuration / status does not allow the requested command. + /// 0x919D + /// + public class PermissionDeniedException : Exception + { + public PermissionDeniedException() + { + + } + + public PermissionDeniedException(string message) : base(message) + { + + } + + public PermissionDeniedException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs index 4fbe232..2c3840e 100644 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs @@ -56,9 +56,10 @@ namespace NFC.Mifare_DESFire /// Data public string ConvertToHexString(byte[] data) { - return BitConverter.ToString(data).Replace("-", string.Empty); + return BitConverter.ToString(data).Replace("-", " "); } + public void CheckAPDUResponse(APDUResponse response) { @@ -297,7 +298,7 @@ namespace NFC.Mifare_DESFire return data; } - byte[] expand = new byte[data.Length + diff]; + byte[] expand = new byte[data.Length + bocksize - diff]; data.CopyTo(expand, 0); @@ -311,44 +312,43 @@ namespace NFC.Mifare_DESFire public void ChangeKeyDES(byte key_no, byte[] key_new, byte[] key_current) { - if(!CheckKey(key_new)) + Console.WriteLine("key_new: {0}", ConvertToHexString(key_new)); + key_new = concatenate(key_new, key_new); + Console.WriteLine("key_new_double: {0}", ConvertToHexString(key_new)); + + byte[] header = new byte[] { - throw new ArgumentException("key_new is invalid"); - } + 0xC4, key_no + }; + Console.WriteLine("header: {0}", ConvertToHexString(header)); - if (!CheckKey(key_current)) - { - throw new ArgumentException("key_new is invalid"); - } + byte[] cmd_ = concatenate(header, key_new); + Console.WriteLine("cmd_: {0}", ConvertToHexString(cmd_)); - if(GetKeyTypeDES(key_new) != GetKeyTypeDES(key_current)) - { - throw new ArgumentException("key_new and key_current are not same KeyType"); - } - - byte[] keys_xor = xor(key_new, key_current); - - keys_xor = concatenate(keys_xor, keys_xor); - - CRC32 crc32 = new CRC32(); - byte[] crc = crc32.Calculate(new byte[] { (byte)APDUInstructions.CHANGE_KEY, key_no }, keys_xor); - - byte[] key_xor_crc = concatenate(keys_xor, crc); - - byte[] key_xor_crc_block = expandToBlockSize(key_xor_crc, 8); + CRC32 crc = new CRC32(); + byte[] cmd_crc = crc.Calculate(cmd_); + Console.WriteLine("cmd_crc: {0}", ConvertToHexString(cmd_crc)); + byte[] cryptogram = concatenate(key_new, cmd_crc); + Console.WriteLine("cryptogram: {0}", ConvertToHexString(cryptogram)); + byte[] cryptogram_block = expandToBlockSize(cryptogram, 8); + Console.WriteLine("cryptogram_block: {0}", ConvertToHexString(cryptogram_block)); DES des = new DES(); - byte[] key_xor_crc_block_enc = des.Encrypt(key_xor_crc_block, _SessionKey, _IV); + byte[] cryptogram_block_enc = des.Encrypt(cryptogram_block, _SessionKey, _IV); + Console.WriteLine("cryptogram_block_enc: {0}", ConvertToHexString(cryptogram_block_enc)); + + byte[] data = concatenate(new byte[] { key_no }, cryptogram_block_enc); + Console.WriteLine("data: {0}", ConvertToHexString(data)); APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) { CLA = 0x90, - INS = (byte)APDUInstructions.CHANGE_KEY, - Data = key_xor_crc_block_enc, - Le = 0x00 + INS = 0xC4, + Data = data }; + Console.WriteLine("cmd: {0}", ConvertToHexString(cmd.ToArray())); APDUResponse response = _Card.Transmit(cmd); @@ -592,33 +592,6 @@ namespace NFC.Mifare_DESFire 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(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys) - { - if(numberOfKeys < 0x01 || numberOfKeys >= 0x0D) - { - throw new ArgumentOutOfRangeException(); - } - - return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys); - } + } } diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs new file mode 100644 index 0000000..6222665 --- /dev/null +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs @@ -0,0 +1,575 @@ +using log4net.Repository.Hierarchy; +using NFC.Crypto; +using NFC.ISO7816_4; +using NFC.Mifare_DESFire.Enums; +using NFC.NXP_MIFARE_DESFire.Exceptions; +using PCSC.Iso7816; +using System; +using System.Linq; + +namespace NFC.Mifare_DESFire +{ + public class MIFARE_DESFire_V2 + { + // Docs https://hackmd.io/qATu8uYdRnOC40aFrB9afg + + #region Log + private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + #endregion + + #region Contructors + /// + /// Construct MIFRARE_DESFire Object with ICard Interface + /// + /// Implementation of ICard, only transmit is used + public MIFARE_DESFire_V2(ICard card) + { + _Card = card; + } + #endregion + + #region Properties + /// + /// ICard Implementation used to transmit APDUCommands and recive APDUResponses + /// + private ICard _Card; + + /// + /// SessionKey, is set after Successfull Authentication + /// + public byte[] _SessionKey; + + /// + /// Initialation Vector for CBC Encryption + /// Is 0 bytes after Successfull Authentication + /// + public byte[] _IV; + #endregion + + #region Methods + #region Helper Methods + /// + /// Generate Byte Array filled with 0 + /// + /// Size of Array + public byte[] GenerateEmptyKey(uint size) + { + byte[] key = new byte[size]; + for (int i = 0; i < size; i++) + { + key[i] = 0; + } + + return key; + } + + /// + /// Converts byte[] to string with HEX Code + /// No 0x is created + /// + /// Data + public string ConvertToHexString(byte[] data) + { + return BitConverter.ToString(data).Replace("-", " "); + } + + /// + /// Converts string with HEX Code to byte[] + /// No 0x is requiered + /// + /// Data + public byte[] ConvertFromHexString(string data) + { + if (data.Length % 2 == 1) + throw new Exception("Data Length is uneven."); + + byte[] arr = new byte[data.Length >> 1]; + + for (int i = 0; i < data.Length >> 1; ++i) + { + arr[i] = (byte)((GetHexVal(data[i << 1]) << 4) + (GetHexVal(data[(i << 1) + 1]))); + } + + return arr; + } + + private int GetHexVal(char hex) + { + int val = (int)hex; + //For uppercase A-F letters: + //return val - (val < 58 ? 48 : 55); + //For lowercase a-f letters: + //return val - (val < 58 ? 48 : 87); + //Or the two combined, but a bit slower: + return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); + } + + /// + /// Check APDU Response for DESFire Error Codes + /// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf + /// Section: 11.3 + /// + public void CheckAPDUResponse(APDUResponse response) + { + if (response == null) + { + throw new ArgumentNullException("Response cannot be null."); + } + + if (response.SW1 == 0x91) + { + switch (response.SW2) + { + case 0x00: // OPERATION_OK + return; + case 0x0C: // NO_CHANGES + return; + case 0x1C: // ILLEGAL_COMMAND_CODE + throw new IllegalCommandCodeException(); + case 0x1E: // INTEGRITY_ERROR + throw new IntegrityErrorException(); + case 0x40: // NO_SUCH_KEY + throw new NoSuchKeyException(); + case 0x7E: // LENGTH_ERROR + throw new LengthErrorException(); + case 0x9D: // PERMISSION_DENIED + throw new PermissionDeniedException(); + case 0x9E: // PARAMETER_ERROR + throw new ParameterErrorException(); + case 0xAD: // AUTHENTICATION_DELAY + throw new AuthenticationDelayException(); + case 0xAE: // AUTHENTICATION_ERROR + throw new AuthenticationErrorException(); + case 0xAF: // ADDITIONAL_FRAME + return; + case 0xBE: // BOUNDARY_ERROR + throw new BoundaryErrorException(); + case 0xCA: // COMMAND_ABORTED + throw new CommandAbortedException(); + case 0xDE: // DUPLICATE_ERROR + throw new DuplicateErrorException(); + case 0xF0: // FILE_NOT_FOUND + throw new FileNotFoundException(); + default: + break; + } + } + + throw new Exception(string.Format("Unknown Response Code: 0x{0}.", BitConverter.ToString(new byte[] { response.SW1, response.SW2 }).Replace("-", string.Empty))); + } + #endregion + + #region Crypto Operation + /// + /// Return a copy of the last Block of data + /// + /// Data compatible to blocksize + /// in byte + public byte[] ExtractLastBlock(byte[] data, uint blocksize) + { + if (data == null) + { + throw new ArgumentNullException("Data cannot be null."); + } + + if (data.Length % blocksize != 0) + { + throw new ArgumentException(string.Format("Data is not compatible with blocksize(data(length):{0}, blocksize:{1}.", data.Length, blocksize)); + } + + byte[] lastblock = new byte[blocksize]; + + for (int i = 0; i < blocksize; i++) + { + lastblock[i] = data[data.Length - blocksize + i]; + } + + return lastblock; + } + + /// + /// Rotates Array to the left + /// + /// Data + /// Copy of data + public byte[] RotateLeft(byte[] data) + { + if (data == null) + { + throw new ArgumentNullException("Data cannot be null."); + } + + byte[] rotate = new byte[data.Length]; + data.CopyTo(rotate, 0); + + byte tmp = rotate[0]; + for (var i = 0; i < rotate.Length - 1; i++) + { + rotate[i] = rotate[i + 1]; + } + rotate[rotate.Length - 1] = tmp; + + return rotate; + } + + /// + /// Rotates Array to the right + /// + /// Data + /// Copy of data + public byte[] RotateRight(byte[] data) + { + if (data == null) + { + throw new ArgumentNullException("Data cannot be null."); + } + + byte[] rotate = new byte[data.Length]; + data.CopyTo(rotate, 0); + + byte tmp = rotate[rotate.Length - 1]; + for (var i = rotate.Length - 1; i > 0; i--) + { + rotate[i] = rotate[i - 1]; + } + rotate[0] = tmp; + + return rotate; + } + + /// + /// Concatenates two Arrays, Array A start at index 0 + /// + /// Array A + /// Array B + /// Copy of Data (a.Size + b.Size) + public byte[] Concatenate(byte[] a, byte[] b) + { + if (a == null) + { + throw new ArgumentNullException("Array A cannot be null."); + } + + if (b == null) + { + throw new ArgumentNullException("Array B cannot be null."); + } + + byte[] c = new byte[a.Length + b.Length]; + a.CopyTo(c, 0); + b.CopyTo(c, a.Length); + + return c; + } + + /// + /// Boolean Operation XOR on all Bytes + /// + /// Array A + /// Array B + /// Copy of Data + public byte[] XOR(byte[] a, byte[] b) + { + if (a == null) + { + throw new ArgumentNullException("Array A cannot be null."); + } + + if (b == null) + { + throw new ArgumentNullException("Array B cannot be null."); + } + + if (a.Length != b.Length) + { + throw new ArgumentException(string.Format("Arrays are not same Length(Length A:{0}, Lenght B:{1})", a.Length, b.Length)); + } + + byte[] c = new byte[a.Length]; + + for(int i = 0; i < a.Length; i++) + { + c[i] = (byte)(a[i] ^ b[i]); + } + + return c; + } + + /// + /// Generates SessionKey for DES Authentification + /// + /// 16Byte SessionKey + private byte[] GenerateSesionKey_DES(byte[] rndA, byte[] rndB) + { + byte[] sesssionkey = new byte[8]; + + for (int i = 0; i < sesssionkey.Length; i++) + { + if (i < 4) + { + sesssionkey[i] = rndA[i]; + } + else + { + sesssionkey[i] = rndB[i - 4]; + } + } + + // DES SessionKey is a double DES Key + return Concatenate(sesssionkey, sesssionkey); + } + + /// + /// Set KeyVersion in DES Key + /// KeyVersion is stored in LSB of the first 8 Bytes of the DES Key + /// + public byte[] SetKeyVersion(byte[] key, byte keyversion) + { + byte[] pow2 = new byte[] + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 + }; + + byte[] new_key = new byte[key.Length]; + key.CopyTo(new_key, 0); + + for (int i = 0; i < 8; i++) + { + if ((keyversion & pow2[i]) > 0) + { + new_key[i] = (byte)(new_key[5] | 0x01); + } + else + { + new_key[i] = (byte)(new_key[5] & 0x7F); + } + } + + return new_key; + } + #endregion + + #region DESFire Commands + /// + /// Authenticate to PICC, with ISO Authenticate + /// + /// 0x01 - 0x0D + /// + /// !!! WARNING For Testing only !!! + /// Retry after short Time + public void AuthenticateISO_DES(byte key_id, byte[] key, byte[] rndA = null) + { + _Log.Debug("Start AuthenticateISO_DES"); + + // Sepearte InitialisationVector for Authentication + byte[] iv = new byte[8]; + + APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0x1A, + Data = new byte[] + { + key_id + } + }; + _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_challange_request); + _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + byte[] rndB_enc = response.Body; + _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc)); + + DES des = new DES(); + byte[] rndB = des.Decrypt(rndB_enc, key, GenerateEmptyKey(8)); + _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB)); + + rndB.CopyTo(iv, 0); + + byte[] rndB_rl = RotateLeft(rndB); + _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl)); + + if(rndA == null) + { + Random rnd = new Random(); + rndA = new byte[8]; + rnd.NextBytes(rndA); + } + _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA)); + + byte[] rndAB = Concatenate(rndA, rndB_rl); + _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB)); + + byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc); + _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc)); + iv = ExtractLastBlock(rndAB_enc, 8); + + APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xAF, + Data = rndAB_enc + }; + _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + + response = _Card.Transmit(cmd_challange_response); + _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + + CheckAPDUResponse(response); + + byte[] encryptedRndAFromCard = response.Body; + _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard)); + + byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv); + _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard)); + + byte[] rndAFromCard = RotateRight(rotatedRndAFromCard); + _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard)); + + if (!rndA.SequenceEqual(rndAFromCard)) + { + throw new Exception("Authentication failed, PICC Challenge is not corret"); + } + + _SessionKey = GenerateSesionKey_DES(rndA, rndB); + _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey)); + + _IV = GenerateEmptyKey(8); + _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); + + _Log.Debug("End AuthenticateISO_DES"); + } + + /// + /// Format PICC + /// + public void Format() + { + _Log.Debug("Start Format"); + + APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short) + { + CLA = 0x90, + INS = 0xFC, + }; + _Log.DebugFormat("APDU_CMD(cmd_format): {0}", ConvertToHexString(cmd_format.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_format); + _Log.DebugFormat("APDU_RES(cmd_format): {0}", ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + _Log.Debug("End Format"); + } + + /// + /// Create Application for ID + /// + /// 3 Byte ID + public void CreateApplication(UInt32 aid, byte keysetting1, byte keysetting2) + { + _Log.Debug("Start CreateApplication"); + + byte[] id_byte = BitConverter.GetBytes(aid); + _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray())); + + APDUCommand cmd_CreateApplication = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xCA, + Data = new byte[] + { + id_byte[0], + id_byte[1], + id_byte[2], + keysetting1, + keysetting2 + } + }; + _Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", ConvertToHexString(cmd_CreateApplication.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_CreateApplication); + _Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + _Log.Debug("End CreateApplication"); + } + + /// + /// Select Application by AID + /// + /// 3 Byte AID + public void SelectApplication(UInt32 aid) + { + _Log.Debug("Start SelectApplication"); + + byte[] id_byte = BitConverter.GetBytes(aid); + _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray())); + + APDUCommand cmd_SelectApplication = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)APDUInstructions.SELECT_APPLICATION, + Data = new byte[] + { + id_byte[0], + id_byte[1], + id_byte[2] + } + }; + _Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", ConvertToHexString(cmd_SelectApplication.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_SelectApplication); + _Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + _Log.Debug("End SelectApplication"); + } + #endregion + + #region Configuration Generator + /// + /// 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(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys) + { + if (numberOfKeys < 0x01 || numberOfKeys >= 0x0D) + { + throw new ArgumentOutOfRangeException(); + } + + return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys); + } + #endregion + #endregion + } +} diff --git a/NFC_Test/AuthCrypto_Test.cs b/NFC_Test/AuthCrypto_Test.cs index 49fde2b..58e6b6f 100644 --- a/NFC_Test/AuthCrypto_Test.cs +++ b/NFC_Test/AuthCrypto_Test.cs @@ -126,5 +126,86 @@ namespace NFC_Test mifareDESFire.AuthenticateDES(0x00, mifareDESFire.GenerateDefaultKey(16)); } + + [Test] + public void ChangeKey() + { + ICard card = Substitute.For(); + MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); + + mifareDESFire._SessionKey = new byte[] + { + 0xDC, 0xB0, 0x96, 0xC2, 0xA4, 0x0E, 0x78, 0xE0, 0xA0, 0xE4, 0x7A, 0x96, 0xF4, 0x2E, 0x62, 0xAE + }; + mifareDESFire._IV = new byte[] + { + 0x33, 0x45 , 0xAA , 0x95 , 0xF2 , 0xD9 , 0x56 , 0xCF + }; + + mifareDESFire.ChangeKeyDES(0x00, GenerateDefaultKey(16), GenerateDefaultKey(16)); + } + + [Test] + public void CRC() + { + byte[] data = StringToByteArrayFastest("c40045eeb8338ae8f49a032e85bb1114353010"); + + CRC32 crc32 = new CRC32(); + + byte[] crc = crc32.Calculate(data); + + MIFARE_DESFire dESFire = new MIFARE_DESFire(null); + + Console.WriteLine("data: {0}", dESFire.ConvertToHexString(data)); + Console.WriteLine("crc: {0}", dESFire.ConvertToHexString(crc)); + + byte[] data_crc = dESFire.concatenate(data, crc); + Console.WriteLine("data_crc: {0}", dESFire.ConvertToHexString(data_crc)); + } + + public static byte[] StringToByteArrayFastest(string hex) + { + if (hex.Length % 2 == 1) + throw new Exception("The binary key cannot have an odd number of digits"); + + byte[] arr = new byte[hex.Length >> 1]; + + for (int i = 0; i < hex.Length >> 1; ++i) + { + arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1]))); + } + + return arr; + } + + public static int GetHexVal(char hex) + { + int val = (int)hex; + //For uppercase A-F letters: + //return val - (val < 58 ? 48 : 55); + //For lowercase a-f letters: + //return val - (val < 58 ? 48 : 87); + //Or the two combined, but a bit slower: + return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); + } + + [Test] + public void AES() + { + byte[] data = StringToByteArrayFastest("45eeb8338ae8f49a032e85bb111435301095c3894b0000000000000000000000"); + byte[] key = StringToByteArrayFastest("d99aca2b5b4de3a949fa2cf12b0eb673"); + byte[] iv = StringToByteArrayFastest("00000000000000000000000000000000"); + + MIFARE_DESFire dESFire = new MIFARE_DESFire(null); + + Console.WriteLine("data: {0}", dESFire.ConvertToHexString(data)); + Console.WriteLine("key: {0}", dESFire.ConvertToHexString(key)); + Console.WriteLine("iv: {0}", dESFire.ConvertToHexString(iv)); + + AES aes = new AES(); + + byte[] data_enc = aes.Encrypt(data, key, iv); + Console.WriteLine("data_enc: {0}", dESFire.ConvertToHexString(data_enc)); + } } } diff --git a/NFC_Test/MIFARE_DESFire_V2_Test.cs b/NFC_Test/MIFARE_DESFire_V2_Test.cs new file mode 100644 index 0000000..8ddbe05 --- /dev/null +++ b/NFC_Test/MIFARE_DESFire_V2_Test.cs @@ -0,0 +1,551 @@ +using NFC; +using NFC.ISO7816_4; +using NFC.Mifare_DESFire; +using NFC.NXP_MIFARE_DESFire.Exceptions; +using NSubstitute; +using NUnit.Framework; +using System; +using System.Net; + +namespace NFC_Test +{ + [TestFixture] + public class MIFARE_DESFire_V2_Test + { + #region Helper Methods + [Test] + public void GenerateDefaultKey() + { + uint i = 16; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + byte[] data = desfire.GenerateEmptyKey(i); + + for(int e = 0; e < i; e++) + { + if(data[e] != 0x00) + { + Assert.Fail("Data is not 0x00"); + } + } + } + + [Test] + public void CheckAPDUResponse__NULL() + { + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(null); + }); + } + + [Test] + public void CheckAPDUResponse__UNKNOWN() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x00, + SW2 = 0x00 + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + [Test] + public void CheckAPDUResponse__OPERATION_OK() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00 + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + desfire.CheckAPDUResponse(response); + } + + [Test] + public void CheckAPDUResponse__NO_CHANGES() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x0C + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + desfire.CheckAPDUResponse(response); + } + + [Test] + public void CheckAPDUResponse__ILLEGAL_COMMAND_CODE() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x1C + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + [Test] + public void CheckAPDUResponse__INTEGRITY_ERROR() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x1E + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + [Test] + public void CheckAPDUResponse__NO_SUCH_KEY() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x40 + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + [Test] + public void CheckAPDUResponse__LENGTH_ERROR() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x7E + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + [Test] + public void CheckAPDUResponse__PERMISSION_DENIED() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x9D + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + + [Test] + public void CheckAPDUResponse__PARAMETER_ERROR() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x9E + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + + [Test] + public void CheckAPDUResponse__AUTHENTICATION_DELAY() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0xAD + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + [Test] + public void CheckAPDUResponse__AUTHENTICATION_ERROR() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0xAE + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + [Test] + public void CheckAPDUResponse__ADDITIONAL_FRAME() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0xAF + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + desfire.CheckAPDUResponse(response); + } + + [Test] + public void CheckAPDUResponse__BOUNDARY_ERROR() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0xBE + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + [Test] + public void CheckAPDUResponse__COMMAND_ABORTED() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0xCA + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + [Test] + public void CheckAPDUResponse__DUPLICATE_ERROR() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0xDE + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + + [Test] + public void CheckAPDUResponse__FILE_NOT_FOUND() + { + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0xF0 + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + desfire.CheckAPDUResponse(response); + }); + } + #endregion + + #region Crypto Operation + [Test] + public void ExtractLastBlock() + { + byte[] data = new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + }; + + byte[] expected_lastblock = new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + byte[] lastblock = desfire.ExtractLastBlock(data, 8); + + Assert.AreEqual(expected_lastblock, lastblock); + } + + [Test] + public void ExtractLastBlock_WrongBlocksize() + { + byte[] data = new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + byte[] lastblock = desfire.ExtractLastBlock(data, 7); + }); + } + + [Test] + public void ExtractLastBlock_Null() + { + byte[] data = null; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + byte[] lastblock = desfire.ExtractLastBlock(data, 7); + }); + } + + [Test] + public void RotateLeft() + { + byte[] data = new byte[] + { + 0x01, 0x02, 0x03, 0x04 + }; + + byte[] expected_data_left = new byte[] + { + 0x02, 0x03, 0x04, 0x01 + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + byte[] data_left = desfire.RotateLeft(data); + + Assert.AreEqual(expected_data_left, data_left); + } + + [Test] + public void RotateLeft_Null() + { + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + byte[] lastblock = desfire.RotateLeft(null); + }); + } + + [Test] + public void RotateRight() + { + byte[] data = new byte[] + { + 0x01, 0x02, 0x03, 0x04 + }; + + byte[] expected_data_left = new byte[] + { + 0x04, 0x01, 0x02, 0x03 + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + byte[] data_left = desfire.RotateRight(data); + + Assert.AreEqual(expected_data_left, data_left); + } + + [Test] + public void RotateRight_Null() + { + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + byte[] lastblock = desfire.RotateRight(null); + }); + } + + [Test] + public void Concatenate() + { + byte[] data_a = new byte[] + { + 0x01, 0x02, 0x03, 0x04 + }; + + byte[] data_b = new byte[] + { + 0x05, 0x06, 0x07, 0x08 + }; + + byte[] expected_data_c = new byte[] + { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + byte[] data_c = desfire.Concatenate(data_a, data_b); + + Assert.AreEqual(expected_data_c, data_c); + } + + [Test] + public void Concatenate_Null() + { + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + byte[] lastblock = desfire.Concatenate(null, null); + }); + } + + [Test] + public void XOR() + { + byte[] data_a = new byte[] + { + 0x00, 0xF0, 0x00, 0xF0 + }; + + byte[] data_b = new byte[] + { + 0x0F, 0x00, 0x0F, 0x00 + }; + + byte[] expected_data_c = new byte[] + { + 0x0F, 0xF0, 0x0F, 0xF0 + }; + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + byte[] data_c = desfire.XOR(data_a, data_b); + + Assert.AreEqual(expected_data_c, data_c); + } + + [Test] + public void XOR_null() + { + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + Assert.Throws( + delegate + { + byte[] lastblock = desfire.XOR(null, null); + }); + } + #endregion + + #region DESFire Commands + [Test] + public void AuthenticateISO_DES() + { + ICard card = Substitute.For(); + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + + APDUResponse response_challenge_request = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0xAF, + Body = desfire.ConvertFromHexString("5D994CE085F24089") + }; + + APDUResponse response_challenge_response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00, + Body = desfire.ConvertFromHexString("913C6DED84221C41") + }; + + byte[] rndA = desfire.ConvertFromHexString("849B36C5F8BF4A09"); + byte[] key = desfire.ConvertFromHexString("00000000000000000000000000000000"); + + card.Transmit(Arg.Is(x => x.INS == 0x1A)).Returns(response_challenge_request); + card.Transmit(Arg.Is(x => x.INS == 0xAF)).Returns(response_challenge_response); + + desfire.AuthenticateISO_DES(0x00, key, rndA); + + byte[] expected_sessionkey = desfire.ConvertFromHexString("849B36C54FD1B759849B36C54FD1B759"); + byte[] expected_iv = desfire.GenerateEmptyKey(8); + + Assert.AreEqual(expected_sessionkey, desfire._SessionKey); + Assert.AreEqual(expected_iv, desfire._IV); + } + #endregion + } +} diff --git a/NFC_Test/NamespaceSetUp.cs b/NFC_Test/NamespaceSetUp.cs new file mode 100644 index 0000000..4cb85ab --- /dev/null +++ b/NFC_Test/NamespaceSetUp.cs @@ -0,0 +1,18 @@ +using log4net; +using log4net.Config; +using NUnit.Framework; +using System; + +namespace NFC_Test +{ + [SetUpFixture] + public class NamespaceSetUp + { + private static readonly ILog log = LogManager.GetLogger(typeof(NamespaceSetUp)); + [OneTimeSetUp] + public void OneTimeSetUp() + { + BasicConfigurator.Configure(); + } + } +} diff --git a/NFC_Test/OTA.cs b/NFC_Test/OTA.cs new file mode 100644 index 0000000..8ff2752 --- /dev/null +++ b/NFC_Test/OTA.cs @@ -0,0 +1,60 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Text; +using NFC; +using NFC.Readers.PCSC; +using System.Threading; +using NFC.Mifare_DESFire; +using NFC.Mifare_DESFire.Enums; +using NFC.ISO7816_4; +using PCSC.Iso7816; +using log4net.Config; + +namespace NFC_Test +{ + [TestFixture, Explicit] + public class OTA + { + private string _ReaderID = "ACS ACR122U PICC Interface 0"; + + [Test] + public void Init() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(_ReaderID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + + desfire.AuthenticateISO_DES(0x00, desfire.GenerateEmptyKey(16)); + desfire.Format(); + + desfire.AuthenticateISO_DES(0x00, desfire.GenerateEmptyKey(16)); + + byte keySetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + byte keySetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x03); + desfire.CreateApplication(0xAAFFEE, keySetting1, keySetting2); + + desfire.SelectApplication(0xAAFFEE); + + transmit_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + } +} diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index e6118b8..0e35f12 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -8,6 +8,7 @@ using System.Threading; using NFC.Mifare_DESFire; using NFC.Mifare_DESFire.Enums; using NFC.ISO7816_4; +using PCSC.Iso7816; namespace NFC_Test { @@ -140,41 +141,41 @@ namespace NFC_Test [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)] public void CreateApplication(string readerID, UInt32 applicationID) { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); + //IHardware hardware = new Hardware(); + //IReader reader = hardware.OpenReader(readerID); - bool transmit_successfully = false; + //bool transmit_successfully = false; - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); + //ReaderEventHandler handler = (sender, card) => + //{ + // card.Connect(); - MIFARE_DESFire desfire = new MIFARE_DESFire(card); + // MIFARE_DESFire desfire = new MIFARE_DESFire(card); - byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.SAMEKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); - byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.TDES, FileIdentifies.NOTUSED, 0x03); + // byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + // byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.TDES, FileIdentifies.NOTUSED, 0x03); - APDUCommand cmd = desfire.CreateApplication(applicationID, keysetting1, keysetting2); + // APDUCommand cmd = desfire.CreateApplication(applicationID, keysetting1, keysetting2); - Console.WriteLine(cmd.ToArray()); + // Console.WriteLine(cmd.ToArray()); - APDUResponse response = card.Transmit(cmd); + // APDUResponse response = card.Transmit(cmd); - if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) - { - transmit_successfully = true; - } + // if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) + // { + // transmit_successfully = true; + // } - card.Disconnect(); - }; + // card.Disconnect(); + //}; - reader.CardDiscovered += handler; - reader.Start(); + //reader.CardDiscovered += handler; + //reader.Start(); - Assert.AreEqual(true, transmit_successfully); + //Assert.AreEqual(true, transmit_successfully); - reader.Stop(); - reader.CardDiscovered -= handler; + //reader.Stop(); + //reader.CardDiscovered -= handler; } [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)] @@ -271,7 +272,48 @@ namespace NFC_Test desfire.SelectApplication(0xAAFFEE); desfire.AuthenticateDES(0x00, GenerateDefaultKey(8)); - desfire.ChangeKeyDES(0x01, GenerateDefaultKey(8), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }); + desfire.ChangeKeyDES(0x00, GenerateDefaultKey(8), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }); + + transmit_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [TestCase("ACS ACR122U PICC Interface 0")] + public void ChangeKey_Test(string readerID) + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0xAAFFEE); + desfire.AuthenticateDES(0x00, GenerateDefaultKey(8)); + + APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xC4, + Data = GenerateDefaultKey(1 + 16 + 4 + 4) + // KEY_NO, KEY, CRC32, PADDING + }; + + card.Transmit(cmd); transmit_successfully = true; From 307bd609251f3e8b95f5f3557a2800baaa3542c4 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Thu, 8 Oct 2020 17:23:48 +0200 Subject: [PATCH 12/21] Added: ChangeKey AES Same Key --- NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs | 198 +++++++++++++++++++- NFC_Test/MIFARE_DESFire_V2_Test.cs | 83 ++++++++ NFC_Test/OTA.cs | 44 ++++- 3 files changed, 322 insertions(+), 3 deletions(-) diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs index 6222665..df5fbe2 100644 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs @@ -299,7 +299,7 @@ namespace NFC.Mifare_DESFire /// Generates SessionKey for DES Authentification /// /// 16Byte SessionKey - private byte[] GenerateSesionKey_DES(byte[] rndA, byte[] rndB) + public byte[] GenerateSesionKey_DES(byte[] rndA, byte[] rndB) { byte[] sesssionkey = new byte[8]; @@ -319,6 +319,37 @@ namespace NFC.Mifare_DESFire return Concatenate(sesssionkey, sesssionkey); } + /// + /// Generates SessionKey for AES Authentification + /// + /// 16Byte SessionKey + public byte[] GenerateSesionKey_AES(byte[] rndA, byte[] rndB) + { + byte[] sesssionkey = new byte[16]; + + for (int i = 0; i < sesssionkey.Length; i++) + { + if (i < 4) + { + sesssionkey[i] = rndA[i]; + } + else if(i >= 4 && i < 8) + { + sesssionkey[i] = rndB[i - 4]; + } + else if (i >= 8 && i < 12) + { + sesssionkey[i] = rndA[i + 4]; + } + else + { + sesssionkey[i] = rndB[i]; + } + } + + return sesssionkey; + } + /// /// Set KeyVersion in DES Key /// KeyVersion is stored in LSB of the first 8 Bytes of the DES Key @@ -347,6 +378,30 @@ namespace NFC.Mifare_DESFire return new_key; } + + /// + /// Expand Array to Block Size, fill with 0x00 + /// + /// + public byte[] ExpandToBlockSize(byte[] data, uint bocksize) + { + int diff = data.Length % (int)bocksize; + if (diff == 0) + { + return data; + } + + byte[] expand = new byte[data.Length + bocksize - diff]; + + data.CopyTo(expand, 0); + + for (int i = expand.Length - 1; i > data.Length - 1; i--) + { + expand[i] = 0x00; + } + + return expand; + } #endregion #region DESFire Commands @@ -530,6 +585,147 @@ namespace NFC.Mifare_DESFire _Log.Debug("End SelectApplication"); } + + /// + /// Authenticate to PICC, with ISO Authenticate + /// + /// 0x01 - 0x0D + /// + /// !!! WARNING For Testing only !!! + /// Retry after short Time + public void AuthenticateISO_AES(byte key_id, byte[] key, byte[] rndA = null) + { + _Log.Debug("Start AuthenticateISO_AES"); + + // Sepearte InitialisationVector for Authentication + byte[] iv = new byte[16]; + + APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xAA, + Data = new byte[] + { + key_id + } + }; + _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_challange_request); + _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + byte[] rndB_enc = response.Body; + _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc)); + + AES aes = new AES(); + byte[] rndB = aes.Decrypt(rndB_enc, key, GenerateEmptyKey(16)); + _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB)); + + rndB.CopyTo(iv, 0); + + byte[] rndB_rl = RotateLeft(rndB); + _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl)); + + if (rndA == null) + { + Random rnd = new Random(); + rndA = new byte[16]; + rnd.NextBytes(rndA); + } + _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA)); + + byte[] rndAB = Concatenate(rndA, rndB_rl); + _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB)); + + byte[] rndAB_enc = aes.Encrypt(rndAB, key, rndB_enc); + _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc)); + iv = ExtractLastBlock(rndAB_enc, 16); + + APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xAF, + Data = rndAB_enc + }; + _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + + response = _Card.Transmit(cmd_challange_response); + _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + + CheckAPDUResponse(response); + + byte[] encryptedRndAFromCard = response.Body; + _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard)); + + byte[] rotatedRndAFromCard = aes.Decrypt(encryptedRndAFromCard, key, iv); + _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard)); + + byte[] rndAFromCard = RotateRight(rotatedRndAFromCard); + _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard)); + + if (!rndA.SequenceEqual(rndAFromCard)) + { + throw new Exception("Authentication failed, PICC Challenge is not corret"); + } + + _SessionKey = GenerateSesionKey_AES(rndA, rndB); + _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey)); + + _IV = GenerateEmptyKey(16); + _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); + + _Log.Debug("End AuthenticateISO_DES"); + } + + public void ChangeKey_AES(byte key_id, byte[] new_key, byte key_version) + { + _Log.Debug("Start ChangeKey_AES"); + + byte[] header = new byte[] + { + 0xC4, key_id + }; + _Log.DebugFormat("header: {0}", ConvertToHexString(header)); + + // AES Key Version is Append to Key + byte[] key_and_version = Concatenate(new_key, new byte[] { key_version }); + 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)); + + AES aes = new AES(); + byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV); + _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc)); + + 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"); + } #endregion #region Configuration Generator diff --git a/NFC_Test/MIFARE_DESFire_V2_Test.cs b/NFC_Test/MIFARE_DESFire_V2_Test.cs index 8ddbe05..2b7a7c2 100644 --- a/NFC_Test/MIFARE_DESFire_V2_Test.cs +++ b/NFC_Test/MIFARE_DESFire_V2_Test.cs @@ -3,8 +3,11 @@ using NFC.ISO7816_4; using NFC.Mifare_DESFire; using NFC.NXP_MIFARE_DESFire.Exceptions; using NSubstitute; +using NSubstitute.Core; using NUnit.Framework; +using PCSC.Iso7816; using System; +using System.Collections.Generic; using System.Net; namespace NFC_Test @@ -508,6 +511,24 @@ namespace NFC_Test byte[] lastblock = desfire.XOR(null, null); }); } + + [Test] + public void GenerateSessionKey_AES() + { + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + byte[] rndA = desfire.ConvertFromHexString("bc14dfde20074617e45a8822f06fdd91"); + Console.WriteLine(desfire.ConvertToHexString(rndA)); + byte[] rndB = desfire.ConvertFromHexString("482ddc54426e6dee560413b8d95471f5"); + Console.WriteLine(desfire.ConvertToHexString(rndB)); + + byte[] expected_sessionkey = desfire.ConvertFromHexString("bc14dfde482ddc54f06fdd91d95471f5"); + Console.WriteLine(desfire.ConvertToHexString(expected_sessionkey)); + + byte[] sessionkey = desfire.GenerateSesionKey_AES(rndA, rndB); + Console.WriteLine(desfire.ConvertToHexString(sessionkey)); + Assert.AreEqual(expected_sessionkey, sessionkey); + } #endregion #region DESFire Commands @@ -546,6 +567,68 @@ namespace NFC_Test Assert.AreEqual(expected_sessionkey, desfire._SessionKey); Assert.AreEqual(expected_iv, desfire._IV); } + + [Test] + public void AuthenticateISO_AES() + { + ICard card = Substitute.For(); + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + + APDUResponse response_challenge_request = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0xAF, + Body = desfire.ConvertFromHexString("43a28e28c653df83cd85039714bccb51") + }; + + APDUResponse response_challenge_response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00, + Body = desfire.ConvertFromHexString("d8f70a0f9a43f522f775a56f5688592f") + }; + + byte[] rndA = desfire.ConvertFromHexString("8a8b3c15e576ae3a21c2b18e6aead1f1"); + byte[] key = desfire.ConvertFromHexString("00000000000000000000000000000000"); + + card.Transmit(Arg.Is(x => x.INS == 0xAA)).Returns(response_challenge_request); + card.Transmit(Arg.Is(x => x.INS == 0xAF)).Returns(response_challenge_response); + + desfire.AuthenticateISO_AES(0x00, key, rndA); + + byte[] expected_sessionkey = desfire.ConvertFromHexString("8a8b3c15c71d0cf46aead1f148f27703"); + byte[] expected_iv = desfire.GenerateEmptyKey(16); + + Assert.AreEqual(expected_sessionkey, desfire._SessionKey); + Assert.AreEqual(expected_iv, desfire._IV); + } + + [Test] + public void ChangeKey_AES() + { + ICard card = Substitute.For(); + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00 + }; + + byte[] new_key = desfire.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); + + byte[] sessionkey = desfire.ConvertFromHexString("2f96515262e1beb0129de2df3e97feb3"); + byte[] iv = desfire.ConvertFromHexString("00000000000000000000000000000000"); + + desfire._SessionKey = sessionkey; + desfire._IV = iv; + + card.Transmit(null).ReturnsForAnyArgs(response); + + desfire.ChangeKey_AES(0x00, new_key, 0x10); + } #endregion } } diff --git a/NFC_Test/OTA.cs b/NFC_Test/OTA.cs index 8ff2752..b5eb63f 100644 --- a/NFC_Test/OTA.cs +++ b/NFC_Test/OTA.cs @@ -39,9 +39,49 @@ namespace NFC_Test byte keySetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); byte keySetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x03); - desfire.CreateApplication(0xAAFFEE, keySetting1, keySetting2); + desfire.CreateApplication(0xC0FFEE, keySetting1, keySetting2); - desfire.SelectApplication(0xAAFFEE); + desfire.SelectApplication(0xC0FFEE); + desfire.AuthenticateISO_AES(0x00, desfire.GenerateEmptyKey(16)); + + byte[] new_key = desfire.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); + + desfire.ChangeKey_AES(0x00, new_key, 0x10); + + transmit_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test] + public void ChangeKey() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(_ReaderID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + + desfire.SelectApplication(0xC0FFEE); + desfire.AuthenticateISO_AES(0x00, desfire.GenerateEmptyKey(16)); + + byte[] new_key = desfire.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); + + desfire.ChangeKey_AES(0x00, new_key, 0x10); transmit_successfully = true; From b52a976098bfc72180d3c88c69919d21690ccb39 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Fri, 9 Oct 2020 10:48:07 +0200 Subject: [PATCH 13/21] Added: Change Other Key --- NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs | 73 ++++++++++++++++++++- NFC_Test/AES_Test.cs | 26 ++++++++ NFC_Test/MIFARE_DESFire_V2_Test.cs | 27 ++++++++ NFC_Test/OTA.cs | 52 +++------------ 4 files changed, 134 insertions(+), 44 deletions(-) create mode 100644 NFC_Test/AES_Test.cs diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs index df5fbe2..dbb7a2c 100644 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs @@ -70,7 +70,7 @@ namespace NFC.Mifare_DESFire /// Data public string ConvertToHexString(byte[] data) { - return BitConverter.ToString(data).Replace("-", " "); + return BitConverter.ToString(data).Replace("-", "").ToLower(); } /// @@ -679,6 +679,12 @@ namespace NFC.Mifare_DESFire _Log.Debug("End AuthenticateISO_DES"); } + /// + /// Change Same AES key as Authenticated + /// + /// + /// + /// public void ChangeKey_AES(byte key_id, byte[] new_key, byte key_version) { _Log.Debug("Start ChangeKey_AES"); @@ -708,6 +714,9 @@ namespace NFC.Mifare_DESFire byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV); _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc)); + _IV = ExtractLastBlock(cryptogram_enc, 16); + _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); + byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc); _Log.DebugFormat("data: {0}", ConvertToHexString(data)); @@ -726,6 +735,68 @@ namespace NFC.Mifare_DESFire _Log.Debug("End ChangeKey_AES"); } + + /// + /// Change other AES key as Authenticated + /// + /// + /// + /// + public void ChangeOtherKey_AES(byte key_id, byte[] new_key, byte[] old_key, byte key_version) + { + _Log.Debug("Start ChangeOtherKey_AES"); + + byte[] header = new byte[] + { + 0xC4, key_id + }; + _Log.DebugFormat("header: {0}", ConvertToHexString(header)); + + byte[] key_xor = XOR(new_key, old_key); + + // AES Key Version is Append to Key + byte[] key_and_version = Concatenate(key_xor, new byte[] { key_version }); + byte[] command = Concatenate(header, key_and_version); + _Log.DebugFormat("command: {0}", ConvertToHexString(command)); + + CRC32 crc32 = new CRC32(); + byte[] crc_cmd = crc32.Calculate(command); + _Log.DebugFormat("crc_cmd: {0}", ConvertToHexString(crc_cmd)); + byte[] crc_key = crc32.Calculate(new_key); + _Log.DebugFormat("crc_key: {0}", ConvertToHexString(crc_key)); + + byte[] cryptogram = Concatenate(key_and_version, crc_cmd); + cryptogram = Concatenate(cryptogram, crc_key); + _Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram)); + + byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16); + _Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block)); + + AES aes = new AES(); + byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV); + _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc)); + + _IV = ExtractLastBlock(cryptogram_enc, 16); + _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 ChangeOtherKey_AES"); + } #endregion #region Configuration Generator diff --git a/NFC_Test/AES_Test.cs b/NFC_Test/AES_Test.cs new file mode 100644 index 0000000..b35fee2 --- /dev/null +++ b/NFC_Test/AES_Test.cs @@ -0,0 +1,26 @@ +using NFC.Crypto; +using NFC.Mifare_DESFire; +using NUnit.Framework; + +namespace NFC_Test +{ + [TestFixture] + public class AES_Test + { + [Test] + public void Encrypt() + { + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + + byte[] data = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12104a3b07e8eb77a7ac00000000000000"); + byte[] key = desfire.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b"); + byte[] iv = desfire.ConvertFromHexString("00000000000000000000000000000000"); + + AES aes = new AES(); + byte[] data_enc = aes.Encrypt(data, key, iv); + + byte[] data_enc_expected = desfire.ConvertFromHexString("3c79d74a4969ba7123e5d8f6df24493112d221fd131a4617d0eda5d92ccc1b46"); + Assert.AreEqual(data_enc_expected, data_enc); + } + } +} \ No newline at end of file diff --git a/NFC_Test/MIFARE_DESFire_V2_Test.cs b/NFC_Test/MIFARE_DESFire_V2_Test.cs index 2b7a7c2..a3a8a2b 100644 --- a/NFC_Test/MIFARE_DESFire_V2_Test.cs +++ b/NFC_Test/MIFARE_DESFire_V2_Test.cs @@ -629,6 +629,33 @@ namespace NFC_Test desfire.ChangeKey_AES(0x00, new_key, 0x10); } + + [Test] + public void ChangeOtherKey_AES() + { + ICard card = Substitute.For(); + + MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00 + }; + + byte[] new_key = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12"); + byte[] old_key = desfire.ConvertFromHexString("00000000000000000000000000000000"); + + byte[] sessionkey = desfire.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b"); + byte[] iv = desfire.ConvertFromHexString("00000000000000000000000000000000"); + + desfire._SessionKey = sessionkey; + desfire._IV = iv; + + card.Transmit(null).ReturnsForAnyArgs(response); + + desfire.ChangeOtherKey_AES(0x01, new_key, old_key, 0x10); + } #endregion } } diff --git a/NFC_Test/OTA.cs b/NFC_Test/OTA.cs index b5eb63f..217efa4 100644 --- a/NFC_Test/OTA.cs +++ b/NFC_Test/OTA.cs @@ -1,15 +1,8 @@ using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Text; using NFC; using NFC.Readers.PCSC; -using System.Threading; using NFC.Mifare_DESFire; using NFC.Mifare_DESFire.Enums; -using NFC.ISO7816_4; -using PCSC.Iso7816; -using log4net.Config; namespace NFC_Test { @@ -32,6 +25,7 @@ namespace NFC_Test MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + desfire.SelectApplication(0x000000); desfire.AuthenticateISO_DES(0x00, desfire.GenerateEmptyKey(16)); desfire.Format(); @@ -44,44 +38,16 @@ namespace NFC_Test desfire.SelectApplication(0xC0FFEE); desfire.AuthenticateISO_AES(0x00, desfire.GenerateEmptyKey(16)); - byte[] new_key = desfire.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); + byte[] key_master = desfire.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); + byte[] key_1 = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12"); + byte[] key_2 = desfire.ConvertFromHexString("77611d170c449df6f294c48581ab315d"); + desfire.ChangeKey_AES(0x00, key_master, 0x10); - desfire.ChangeKey_AES(0x00, new_key, 0x10); + desfire.AuthenticateISO_AES(0x00, key_master); + desfire.ChangeOtherKey_AES(0x01, key_1, desfire.GenerateEmptyKey(16), 0x10); - transmit_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, transmit_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [Test] - public void ChangeKey() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(_ReaderID); - - bool transmit_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); - - desfire.SelectApplication(0xC0FFEE); - desfire.AuthenticateISO_AES(0x00, desfire.GenerateEmptyKey(16)); - - byte[] new_key = desfire.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); - - desfire.ChangeKey_AES(0x00, new_key, 0x10); + desfire.AuthenticateISO_AES(0x00, key_master); + desfire.ChangeOtherKey_AES(0x02, key_2, desfire.GenerateEmptyKey(16), 0x10); transmit_successfully = true; From 2c0db72f55513c022a5533f54ea2396c677dd2c5 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Sat, 10 Oct 2020 12:39:36 +0200 Subject: [PATCH 14/21] BackUp --- NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs index dbb7a2c..b0bda50 100644 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs @@ -797,6 +797,8 @@ namespace NFC.Mifare_DESFire _Log.Debug("End ChangeOtherKey_AES"); } + + public void CreateFile_STD() #endregion #region Configuration Generator From 2049e7eba336933872621a875ec2723bc440b370 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Wed, 14 Oct 2020 00:26:23 +0200 Subject: [PATCH 15/21] Added: Create STD File, ReadData, WriteData --- Borepin/Borepin.iOS/CNFC/Reader.cs | 1 - NFC/Crypto/{ => CRC}/CRC16.cs | 36 +- NFC/Crypto/{ => CRC}/CRC32.cs | 37 +- NFC/Crypto/{ => Cipher}/AES.cs | 7 +- NFC/Crypto/Cipher/TDES.cs | 49 + .../{TripleDES.cs => Cipher/TDES_2K.cs} | 7 +- NFC/Crypto/{DES.cs => Cipher/TDES_3K.cs} | 11 +- NFC/Crypto/CipherKey.cs | 171 +++ NFC/Crypto/CipherType.cs | 25 + NFC/Crypto/ICipher.cs | 32 + NFC/HexConverter.cs | 51 + NFC/ISO7816-4/APDUCommand.cs | 42 +- NFC/NXP MIFARE DESFire/APDUInstructions.cs | 2 +- NFC/NXP MIFARE DESFire/CMAC.cs | 106 ++ .../{AccessRights.cs => FileAccessRights.cs} | 2 +- .../{ => Enums}/FileTypes.cs | 2 +- .../AuthenticationMissingException.cs | 26 + NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs | 1208 ++++++++++++----- NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs | 844 ------------ NFC_Test/AuthCrypto_Test.cs | 211 --- NFC_Test/{ => Crypto}/AES_Test.cs | 4 +- NFC_Test/Crypto/CRC16_Test.cs | 23 + NFC_Test/Crypto/CRC32_Test.cs | 22 + NFC_Test/Crypto/TDES_Test.cs | 61 + NFC_Test/ISO7816-4/APDUCommand_Test.cs | 119 ++ NFC_Test/MifareDESFire_Commands.cs | 34 - NFC_Test/NFC_Test.csproj | 2 +- .../MIFARE_DESFire_Test.cs} | 162 ++- NFC_Test/NamespaceSetUp.cs | 7 +- NFC_Test/OTA.cs | 13 +- NFC_Test/REAL_Windows.cs | 270 ---- NFC_Test/REAL_Windows_CardSetUp.cs | 250 ++-- 32 files changed, 1867 insertions(+), 1970 deletions(-) rename NFC/Crypto/{ => CRC}/CRC16.cs (59%) rename NFC/Crypto/{ => CRC}/CRC32.cs (57%) rename NFC/Crypto/{ => Cipher}/AES.cs (93%) create mode 100644 NFC/Crypto/Cipher/TDES.cs rename NFC/Crypto/{TripleDES.cs => Cipher/TDES_2K.cs} (92%) rename NFC/Crypto/{DES.cs => Cipher/TDES_3K.cs} (87%) create mode 100644 NFC/Crypto/CipherKey.cs create mode 100644 NFC/Crypto/CipherType.cs create mode 100644 NFC/Crypto/ICipher.cs create mode 100644 NFC/HexConverter.cs create mode 100644 NFC/NXP MIFARE DESFire/CMAC.cs rename NFC/NXP MIFARE DESFire/Enums/{AccessRights.cs => FileAccessRights.cs} (70%) rename NFC/NXP MIFARE DESFire/{ => Enums}/FileTypes.cs (93%) create mode 100644 NFC/NXP MIFARE DESFire/Exceptions/AuthenticationMissingException.cs delete mode 100644 NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs delete mode 100644 NFC_Test/AuthCrypto_Test.cs rename NFC_Test/{ => Crypto}/AES_Test.cs (89%) create mode 100644 NFC_Test/Crypto/CRC16_Test.cs create mode 100644 NFC_Test/Crypto/CRC32_Test.cs create mode 100644 NFC_Test/Crypto/TDES_Test.cs create mode 100644 NFC_Test/ISO7816-4/APDUCommand_Test.cs delete mode 100644 NFC_Test/MifareDESFire_Commands.cs rename NFC_Test/{MIFARE_DESFire_V2_Test.cs => NXP MIFARE DESFire/MIFARE_DESFire_Test.cs} (73%) diff --git a/Borepin/Borepin.iOS/CNFC/Reader.cs b/Borepin/Borepin.iOS/CNFC/Reader.cs index 2623290..992eb5e 100644 --- a/Borepin/Borepin.iOS/CNFC/Reader.cs +++ b/Borepin/Borepin.iOS/CNFC/Reader.cs @@ -62,6 +62,5 @@ namespace Borepin.iOS.CNFC // TODO: decide what to do Console.WriteLine("reader session invalidated"); } - } } diff --git a/NFC/Crypto/CRC16.cs b/NFC/Crypto/CRC/CRC16.cs similarity index 59% rename from NFC/Crypto/CRC16.cs rename to NFC/Crypto/CRC/CRC16.cs index 25f2a22..1530396 100644 --- a/NFC/Crypto/CRC16.cs +++ b/NFC/Crypto/CRC/CRC16.cs @@ -2,26 +2,14 @@ namespace NFC.Crypto { + /// + /// CRC16 for DESFire Card + /// public class CRC16 { - public byte[] Calculate(byte[] data) - { - UInt16 crc16 = 0x6363; + public UInt16 Polynomial { get; } = 0x8408; - crc16 = Calculate(data, crc16); - - return BitConverter.GetBytes(crc16); - } - - public byte[] Calculate(byte[] cmd, byte[] data) - { - UInt16 crc16 = 0x6363; - - crc16 = Calculate(cmd, crc16); - crc16 = Calculate(data, crc16); - - return BitConverter.GetBytes(crc16); - } + public UInt16 InitValue { get; } = 0x6363; public UInt16 Calculate(byte[] data, UInt16 crc16) { @@ -34,11 +22,23 @@ namespace NFC.Crypto crc16 >>= 1; if (b_Bit) { - crc16 ^= 0x8408; + crc16 ^= Polynomial; } } } return crc16; } + + public byte[] Calculate(params byte[][] data) + { + UInt16 crc16 = InitValue; + + foreach(byte[] d in data) + { + crc16 = Calculate(d, crc16); + } + + return BitConverter.GetBytes(crc16); + } } } diff --git a/NFC/Crypto/CRC32.cs b/NFC/Crypto/CRC/CRC32.cs similarity index 57% rename from NFC/Crypto/CRC32.cs rename to NFC/Crypto/CRC/CRC32.cs index e3e6f1d..1d1c45a 100644 --- a/NFC/Crypto/CRC32.cs +++ b/NFC/Crypto/CRC/CRC32.cs @@ -1,28 +1,15 @@ using System; -using System.Linq; namespace NFC.Crypto { + /// + /// CRC32 for DESFire Card + /// public class CRC32 { - public byte[] Calculate(byte[] data) - { - UInt32 crc32 = 0xFFFFFFFF; + public UInt32 Polynomial { get; } = 0xEDB88320; - crc32 = Calculate(data, crc32); - - return BitConverter.GetBytes(crc32); - } - - public byte[] Calculate(byte[] cmd, byte[] data) - { - UInt32 crc32 = 0xFFFFFFFF; - - crc32 = Calculate(cmd, crc32); - crc32 = Calculate(data, crc32); - - return BitConverter.GetBytes(crc32); - } + public UInt32 InitValue { get; } = 0xFFFFFFFF; public UInt32 Calculate(byte[] data, UInt32 crc32) { @@ -35,11 +22,23 @@ namespace NFC.Crypto crc32 >>= 1; if (b_Bit) { - crc32 ^= 0xEDB88320; + crc32 ^= Polynomial; } } } return crc32; } + + public byte[] Calculate(params byte[][] data) + { + UInt32 crc32 = InitValue; + + foreach(byte[] d in data) + { + crc32 = Calculate(d, crc32); + } + + return BitConverter.GetBytes(crc32); + } } } diff --git a/NFC/Crypto/AES.cs b/NFC/Crypto/Cipher/AES.cs similarity index 93% rename from NFC/Crypto/AES.cs rename to NFC/Crypto/Cipher/AES.cs index 4c5be9a..83a7676 100644 --- a/NFC/Crypto/AES.cs +++ b/NFC/Crypto/Cipher/AES.cs @@ -1,13 +1,16 @@ using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Modes; -using Org.BouncyCastle.Crypto.Paddings; using Org.BouncyCastle.Crypto.Parameters; namespace NFC.Crypto { - public class AES + public class AES : ICipher { + public uint BlockSize { get; } = 16; + + public uint KeySize { get; } = 16; + public byte[] Encrypt(byte[] data, byte[] key, byte[] iv) { AesEngine engine = new AesEngine(); diff --git a/NFC/Crypto/Cipher/TDES.cs b/NFC/Crypto/Cipher/TDES.cs new file mode 100644 index 0000000..59e591e --- /dev/null +++ b/NFC/Crypto/Cipher/TDES.cs @@ -0,0 +1,49 @@ +using Org.BouncyCastle.Crypto; +using Org.BouncyCastle.Crypto.Engines; +using Org.BouncyCastle.Crypto.Modes; +using Org.BouncyCastle.Crypto.Parameters; + +namespace NFC.Crypto +{ + public class TDES : ICipher + { + public uint BlockSize { get; } = 8; + + // Two times the DES Key + public uint KeySize { get; } = 16; + + public byte[] Encrypt(byte[] data, byte[] key, byte[] iv) + { + DesEngine engine = new DesEdeEngine(); + CbcBlockCipher blockCipher = new CbcBlockCipher(engine); + BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); + KeyParameter keyParam = new KeyParameter(key); + ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv); + + // Encrypt + cipher.Init(true, keyParamWithIV); + byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)]; + int length = cipher.ProcessBytes(data, outputBytes, 0); + cipher.DoFinal(outputBytes, length); + + return outputBytes; + } + + public byte[] Decrypt(byte[] data, byte[] key, byte[] iv) + { + DesEngine engine = new DesEdeEngine(); + CbcBlockCipher blockCipher = new CbcBlockCipher(engine); + BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); + KeyParameter keyParam = new KeyParameter(key); + ParametersWithIV keyParamWithIV = new ParametersWithIV(keyParam, iv); + + // Decrypt + cipher.Init(false, keyParamWithIV); + byte[] outputBytes = new byte[cipher.GetOutputSize(data.Length)]; + int length = cipher.ProcessBytes(data, outputBytes, 0); + cipher.DoFinal(outputBytes, length); + + return outputBytes; + } + } +} diff --git a/NFC/Crypto/TripleDES.cs b/NFC/Crypto/Cipher/TDES_2K.cs similarity index 92% rename from NFC/Crypto/TripleDES.cs rename to NFC/Crypto/Cipher/TDES_2K.cs index bf4c4fe..142f6cc 100644 --- a/NFC/Crypto/TripleDES.cs +++ b/NFC/Crypto/Cipher/TDES_2K.cs @@ -1,13 +1,16 @@ using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Modes; -using Org.BouncyCastle.Crypto.Paddings; using Org.BouncyCastle.Crypto.Parameters; namespace NFC.Crypto { - public class TripleDES + public class TDES_2K : ICipher { + public uint BlockSize { get; } = 8; + + public uint KeySize { get; } = 16; + public byte[] Encrypt(byte[] data, byte[] key, byte[] iv) { DesEngine engine = new DesEdeEngine(); diff --git a/NFC/Crypto/DES.cs b/NFC/Crypto/Cipher/TDES_3K.cs similarity index 87% rename from NFC/Crypto/DES.cs rename to NFC/Crypto/Cipher/TDES_3K.cs index db9356a..87a3bf5 100644 --- a/NFC/Crypto/DES.cs +++ b/NFC/Crypto/Cipher/TDES_3K.cs @@ -1,16 +1,19 @@ using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Engines; using Org.BouncyCastle.Crypto.Modes; -using Org.BouncyCastle.Crypto.Paddings; using Org.BouncyCastle.Crypto.Parameters; namespace NFC.Crypto { - public class DES + public class TDES_3K : ICipher { + public uint BlockSize { get; } = 8; + + public uint KeySize { get; } = 24; + public byte[] Encrypt(byte[] data, byte[] key, byte[] iv) { - DesEngine engine = new DesEngine(); + DesEngine engine = new DesEdeEngine(); CbcBlockCipher blockCipher = new CbcBlockCipher(engine); BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); KeyParameter keyParam = new KeyParameter(key); @@ -27,7 +30,7 @@ namespace NFC.Crypto public byte[] Decrypt(byte[] data, byte[] key, byte[] iv) { - DesEngine engine = new DesEngine(); + DesEngine engine = new DesEdeEngine(); CbcBlockCipher blockCipher = new CbcBlockCipher(engine); BufferedBlockCipher cipher = new BufferedBlockCipher(blockCipher); KeyParameter keyParam = new KeyParameter(key); diff --git a/NFC/Crypto/CipherKey.cs b/NFC/Crypto/CipherKey.cs new file mode 100644 index 0000000..519ab2a --- /dev/null +++ b/NFC/Crypto/CipherKey.cs @@ -0,0 +1,171 @@ +using System; + +namespace NFC.Crypto +{ + /// + /// Key for DESFire Card + /// + public class CipherKey + { + #region Constructors + /// + /// Creates Key from Array + /// + /// Key + /// Cipher for Key + /// Version of Key + public CipherKey(byte[] key, CipherType cipher, byte keyVersion) + { + _Cipher = cipher; + + if (cipher == CipherType.AES && keyVersion < 0x10) + { + throw new ArgumentOutOfRangeException("KeyVersion is to low for AES Key (Minimum = 0x10)"); + } + _KeyVersion = keyVersion; + + if (!CheckKey(key, cipher)) + { + throw new ArgumentException("Key is not vaild for CipherType"); + } + + if (cipher == CipherType.TDES || cipher == CipherType.TDES_2K || cipher == CipherType.TDES_3K) + { + _Key = SetKeyVersion(key, keyVersion); + } + else + { + _Key = key; + } + } + + /// + /// Generates Empty Key + /// + /// Cipher for Key + /// + public CipherKey(CipherType cipher) + { + _Cipher = cipher; + _Key = GenerateEmptyKey(cipher); + + if (cipher == CipherType.AES) + { + _KeyVersion = 0x10; + } + else + { + _KeyVersion = 0x00; + } + } + #endregion + + #region Properties + /// + /// Key as Array + /// + public byte[] _Key { get; private set; } + + /// + /// CipherType of Key + /// + public CipherType _Cipher { get; private set; } + + /// + /// KeyVersion of Key + /// For AES 0x10 is minimum + /// + public byte _KeyVersion { get; private set; } + #endregion + + #region Methods + /// + /// Generate Empty Key for CipherType + /// + /// Type of Cipher + public byte[] GenerateEmptyKey(CipherType cipher) + { + uint size = GetKeySize(cipher); + + byte[] key = new byte[size]; + for (int i = 0; i < size; i++) + { + key[i] = 0; + } + + return key; + } + + /// + /// Check Key Array + /// + /// Key + /// Cipher Type of Key + public bool CheckKey(byte[] key, CipherType cipher) + { + if (key.Length != GetKeySize(cipher)) + { + return false; + } + else + { + return true; + } + } + + /// + /// Get KeySize for CipherType + /// + /// Type of Cipher + public uint GetKeySize(CipherType cipher) + { + switch (cipher) + { + case CipherType.TDES: + return 8; + case CipherType.TDES_2K: + return 16; + case CipherType.TDES_3K: + return 24; + case CipherType.AES: + return 16; + default: + throw new ArgumentOutOfRangeException("Unknown CipherType."); + } + } + + /// + /// Set Key Version for DES/TDES Keys + /// KeyVersion is stored in the LSBits of the first 8 Bytes + /// Parity Bits are not used from DESFire Cars + /// + /// + /// + /// + public byte[] SetKeyVersion(byte[] key, byte version) + { + byte[] pow2 = new byte[] + { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 + }; + + byte[] new_key = new byte[key.Length]; + key.CopyTo(new_key, 0); + + for (int i = 0; i < 8; i++) + { + if ((version & pow2[i]) > 0) + { + new_key[i] = (byte)(new_key[5] | 0x01); + } + else + { + new_key[i] = (byte)(new_key[5] & 0x7F); + } + } + + return new_key; + } + #endregion + } +} \ No newline at end of file diff --git a/NFC/Crypto/CipherType.cs b/NFC/Crypto/CipherType.cs new file mode 100644 index 0000000..c0b7dfa --- /dev/null +++ b/NFC/Crypto/CipherType.cs @@ -0,0 +1,25 @@ +namespace NFC.Crypto +{ + public enum CipherType + { + /// + /// DES / Triple DES + /// + TDES, + + /// + /// Triple DES with 2 DES Keys + /// + TDES_2K, + + /// + /// Triple DES with 3 DES Keys + /// + TDES_3K, + + /// + /// AES + /// + AES + } +} diff --git a/NFC/Crypto/ICipher.cs b/NFC/Crypto/ICipher.cs new file mode 100644 index 0000000..84583a4 --- /dev/null +++ b/NFC/Crypto/ICipher.cs @@ -0,0 +1,32 @@ +namespace NFC.Crypto +{ + public interface ICipher + { + /// + /// Size of Cipher Block in Byte + /// + public uint BlockSize { get; } + + /// + /// Size of Key in Byte + /// + public uint KeySize { get; } + + /// + /// Encrypt Data + /// + /// Data in BlockSize + /// Key + /// Initialisation Vector + /// + public byte[] Encrypt(byte[] data, byte[] key, byte[] IV); + + /// + /// Decrypt Data + /// + /// Data in BlockSize + /// Key + /// Initialisation Vector + public byte[] Decrypt(byte[] data, byte[] key, byte[] IV); + } +} diff --git a/NFC/HexConverter.cs b/NFC/HexConverter.cs new file mode 100644 index 0000000..b6e07a7 --- /dev/null +++ b/NFC/HexConverter.cs @@ -0,0 +1,51 @@ +using System; + +namespace NFC +{ + /// + /// Converts to and from Byte Array from and to String + /// + public static class HexConverter + { + /// + /// Converts byte[] to string with HEX Code + /// No 0x is created + /// + /// Data + public static string ConvertToHexString(byte[] data) + { + return BitConverter.ToString(data).Replace("-", "").ToLower(); + } + + /// + /// Converts string with HEX Code to byte[] + /// No 0x is requiered + /// + /// Data + public static byte[] ConvertFromHexString(string data) + { + if (data.Length % 2 == 1) + throw new Exception("Data Length is uneven."); + + byte[] arr = new byte[data.Length >> 1]; + + for (int i = 0; i < data.Length >> 1; ++i) + { + arr[i] = (byte)((GetHexVal(data[i << 1]) << 4) + (GetHexVal(data[(i << 1) + 1]))); + } + + return arr; + } + + private static int GetHexVal(char hex) + { + int val = (int)hex; + //For uppercase A-F letters: + //return val - (val < 58 ? 48 : 55); + //For lowercase a-f letters: + //return val - (val < 58 ? 48 : 87); + //Or the two combined, but a bit slower: + return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); + } + } +} diff --git a/NFC/ISO7816-4/APDUCommand.cs b/NFC/ISO7816-4/APDUCommand.cs index bf60034..ef6a5e3 100644 --- a/NFC/ISO7816-4/APDUCommand.cs +++ b/NFC/ISO7816-4/APDUCommand.cs @@ -1,7 +1,7 @@ using PCSC; using PCSC.Iso7816; using System; -using System.Collections.Generic; +using System.Linq; namespace NFC.ISO7816_4 { @@ -13,7 +13,7 @@ namespace NFC.ISO7816_4 } public override bool Equals(object obj) - { + { return obj is APDUCommand command && Case == command.Case && Protocol == command.Protocol && @@ -21,7 +21,8 @@ namespace NFC.ISO7816_4 INS == command.INS && P1 == command.P1 && P2 == command.P2 && - EqualityComparer.Default.Equals(Data, command.Data); + Data.SequenceEqual(command.Data) && + Le == command.Le; } public override int GetHashCode() @@ -43,5 +44,40 @@ namespace NFC.ISO7816_4 hash.Add(IsValid); return hash.ToHashCode(); } + + public static bool operator ==(APDUCommand obj1, APDUCommand obj2) + { + return obj1.Equals(obj2); + } + + public static bool operator !=(APDUCommand obj1, APDUCommand obj2) + { + return !(obj1.Equals(obj2)); + } + + public override string ToString() + { + string pattern_case1 = "(CASE: 1) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x}"; + string pattern_case2 = "(CASE: 2) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x} | LE: 0x{4:x} |"; + string pattern_case3 = "(CASE: 3) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x} | LC: 0x{4:x} | Data: {5:x}"; + string pattern_case4 = "(CASE: 4) CLA: 0x{0:x} | INS: 0x{1:x} | P1: 0x{2:x} | P2: 0x{3:x} | LC: 0x{4:x} | Data: {5:x} | LE: 0x{6:x} |"; + + switch (Case) + { + case IsoCase.Case1: + return string.Format(pattern_case1, CLA, INS, P1, P2); + case IsoCase.Case2Short: + case IsoCase.Case2Extended: + return string.Format(pattern_case2, CLA, INS, P1, P2, Le); + case IsoCase.Case3Short: + case IsoCase.Case3Extended: + return string.Format(pattern_case3, CLA, INS, P1, P2, Lc, BitConverter.ToString(Data).Replace("-", " ")); + case IsoCase.Case4Short: + case IsoCase.Case4Extended: + return string.Format(pattern_case4, CLA, INS, P1, P2, Lc, BitConverter.ToString(Data).Replace("-", " "), Le); + default: + throw new Exception("Unknown IsoCase"); + } + } } } diff --git a/NFC/NXP MIFARE DESFire/APDUInstructions.cs b/NFC/NXP MIFARE DESFire/APDUInstructions.cs index dd3025c..934c08d 100644 --- a/NFC/NXP MIFARE DESFire/APDUInstructions.cs +++ b/NFC/NXP MIFARE DESFire/APDUInstructions.cs @@ -28,7 +28,7 @@ CREATE_CYCLIC_RECORD_FILE = 0xC0, DELETE_FILE = 0xDF, GET_ISO_FILE_IDS = 0x61, - READ_DATA = 0x8D, + READ_DATA = 0xBD, WRITE_DATA = 0x3D, GET_VALUE = 0x6C, CREDIT = 0x0C, diff --git a/NFC/NXP MIFARE DESFire/CMAC.cs b/NFC/NXP MIFARE DESFire/CMAC.cs new file mode 100644 index 0000000..532aa23 --- /dev/null +++ b/NFC/NXP MIFARE DESFire/CMAC.cs @@ -0,0 +1,106 @@ +using NFC.Crypto; +using System; + +namespace NFC.NXP_MIFARE_DESFire +{ + public class CMAC + { + #region Contructors + public CMAC(CipherType cipher) + { + switch(cipher) + { + case(CipherType.TDES): + _Cipher = new TDES(); + break; + case(CipherType.TDES_2K): + _Cipher = new TDES_2K(); + break; + case(CipherType.TDES_3K): + _Cipher = new TDES_3K(); + break; + case (CipherType.AES): + _Cipher = new AES(); + break; + default: + throw new ArgumentException("Unkown Cipher Type."); + } + } + + public CMAC(ICipher cipher) + { + _Cipher = cipher ?? throw new ArgumentNullException(); + } + #endregion + + #region Properties + private ICipher _Cipher; + #endregion + + #region Methods + /// + /// Generate Key with all Zeros, in KeySize + /// + public byte[] GenerateEmpytKey() + { + byte[] key = new byte[_Cipher.KeySize]; + for (int i = 0; i < _Cipher.KeySize; i++) + { + key[i] = 0; + } + + return key; + } + + /// + /// Generate IV with all Zeros, in KeySize + /// + public byte[] GenerateEmpytIV() + { + byte[] key = new byte[_Cipher.BlockSize]; + for (int i = 0; i < _Cipher.BlockSize; i++) + { + key[i] = 0; + } + + return key; + } + + /// + /// Encrypt Data + /// + public byte[] Encrypt(byte[] data) + { + throw new NotImplementedException(); + } + + /// + /// Decrypt Data + /// + public byte[] Decrypt(byte[] data) + { + throw new NotImplementedException(); + } + + /// + /// + /// + /// Two Keys + public byte[][] GenerateSubKey() + { + throw new NotImplementedException(); + } + + /// + /// + /// + /// + /// + public byte[] Digest(byte[] data) + { + throw new NotImplementedException(); + } + + #endregion + } +} diff --git a/NFC/NXP MIFARE DESFire/Enums/AccessRights.cs b/NFC/NXP MIFARE DESFire/Enums/FileAccessRights.cs similarity index 70% rename from NFC/NXP MIFARE DESFire/Enums/AccessRights.cs rename to NFC/NXP MIFARE DESFire/Enums/FileAccessRights.cs index 0c91aa1..fd91f3a 100644 --- a/NFC/NXP MIFARE DESFire/Enums/AccessRights.cs +++ b/NFC/NXP MIFARE DESFire/Enums/FileAccessRights.cs @@ -1,6 +1,6 @@ namespace NFC.Mifare_DESFire.Enums { - public enum AccessRights : byte + public enum FileAccessRights : byte { FREE = 0x0E, NEVER = 0x0F diff --git a/NFC/NXP MIFARE DESFire/FileTypes.cs b/NFC/NXP MIFARE DESFire/Enums/FileTypes.cs similarity index 93% rename from NFC/NXP MIFARE DESFire/FileTypes.cs rename to NFC/NXP MIFARE DESFire/Enums/FileTypes.cs index 9c1fb13..0a18ea3 100644 --- a/NFC/NXP MIFARE DESFire/FileTypes.cs +++ b/NFC/NXP MIFARE DESFire/Enums/FileTypes.cs @@ -1,4 +1,4 @@ -namespace NFC.Mifare_DESFire +namespace NFC.Mifare_DESFire.Enums { enum FileTypes : byte { diff --git a/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationMissingException.cs b/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationMissingException.cs new file mode 100644 index 0000000..04c19cd --- /dev/null +++ b/NFC/NXP MIFARE DESFire/Exceptions/AuthenticationMissingException.cs @@ -0,0 +1,26 @@ +using System; + +namespace NFC.NXP_MIFARE_DESFire.Exceptions +{ + /// + /// Current authentication status does not allow there- quested command. + /// 0x91AE + /// + public class AuthenticationMissingException : Exception + { + public AuthenticationMissingException() + { + + } + + public AuthenticationMissingException(string message) : base(message) + { + + } + + public AuthenticationMissingException(string message, Exception inner) : base(message, inner) + { + + } + } +} diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs index 2c3840e..149d04e 100644 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs @@ -1,6 +1,8 @@ -using NFC.Crypto; +using log4net.Repository.Hierarchy; +using NFC.Crypto; using NFC.ISO7816_4; using NFC.Mifare_DESFire.Enums; +using NFC.NXP_MIFARE_DESFire.Exceptions; using PCSC.Iso7816; using System; using System.Collections.Generic; @@ -12,6 +14,10 @@ namespace NFC.Mifare_DESFire { // Docs https://hackmd.io/qATu8uYdRnOC40aFrB9afg + #region Log + private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + #endregion + #region Contructors /// /// Construct MIFRARE_DESFire Object with ICard Interface @@ -29,16 +35,25 @@ namespace NFC.Mifare_DESFire /// private ICard _Card; + /// + /// SessionKey, is set after Successfull Authentication + /// public byte[] _SessionKey; + + /// + /// Initialation Vector for CBC Encryption + /// Is 0 bytes after Successfull Authentication + /// public byte[] _IV; #endregion #region Methods + #region Helper Methods /// /// Generate Byte Array filled with 0 /// /// Size of Array - public byte[] GenerateDefaultKey(uint size) + public byte[] GenerateEmptyKey(uint size) { byte[] key = new byte[size]; for (int i = 0; i < size; i++) @@ -56,93 +71,121 @@ namespace NFC.Mifare_DESFire /// Data public string ConvertToHexString(byte[] data) { - return BitConverter.ToString(data).Replace("-", " "); + return BitConverter.ToString(data).Replace("-", "").ToLower(); } + /// + /// Converts string with HEX Code to byte[] + /// No 0x is requiered + /// + /// Data + public byte[] ConvertFromHexString(string data) + { + if (data.Length % 2 == 1) + throw new Exception("Data Length is uneven."); + byte[] arr = new byte[data.Length >> 1]; + + for (int i = 0; i < data.Length >> 1; ++i) + { + arr[i] = (byte)((GetHexVal(data[i << 1]) << 4) + (GetHexVal(data[(i << 1) + 1]))); + } + + return arr; + } + + private int GetHexVal(char hex) + { + int val = (int)hex; + //For uppercase A-F letters: + //return val - (val < 58 ? 48 : 55); + //For lowercase a-f letters: + //return val - (val < 58 ? 48 : 87); + //Or the two combined, but a bit slower: + return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); + } + + /// + /// Check APDU Response for DESFire Error Codes + /// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf + /// Section: 11.3 + /// public void CheckAPDUResponse(APDUResponse response) { - - } - - public bool CheckKey(byte[] key) - { - try + if (response == null) { - GetKeyTypeDES(key); - return true; + throw new ArgumentNullException("Response cannot be null."); } - catch + + if (response.SW1 == 0x91) { - return false; + switch (response.SW2) + { + case 0x00: // OPERATION_OK + return; + case 0x0C: // NO_CHANGES + return; + case 0x1C: // ILLEGAL_COMMAND_CODE + throw new IllegalCommandCodeException(); + case 0x1E: // INTEGRITY_ERROR + throw new IntegrityErrorException(); + case 0x40: // NO_SUCH_KEY + throw new NoSuchKeyException(); + case 0x7E: // LENGTH_ERROR + throw new LengthErrorException(); + case 0x9D: // PERMISSION_DENIED + throw new PermissionDeniedException(); + case 0x9E: // PARAMETER_ERROR + throw new ParameterErrorException(); + case 0xAD: // AUTHENTICATION_DELAY + throw new AuthenticationDelayException(); + case 0xAE: // AUTHENTICATION_ERROR + throw new AuthenticationErrorException(); + case 0xAF: // ADDITIONAL_FRAME + return; + case 0xBE: // BOUNDARY_ERROR + throw new BoundaryErrorException(); + case 0xCA: // COMMAND_ABORTED + throw new CommandAbortedException(); + case 0xDE: // DUPLICATE_ERROR + throw new DuplicateErrorException(); + case 0xF0: // FILE_NOT_FOUND + throw new FileNotFoundException(); + default: + break; + } } + + throw new Exception(string.Format("Unknown Response Code: 0x{0}.", BitConverter.ToString(new byte[] { response.SW1, response.SW2 }).Replace("-", string.Empty))); } + #endregion - /// - /// Key Types used for DESFire Cards - /// - public enum KeyType - { - /// - /// DES Key - 8 Byte - 64 Bit - /// - DES, - - /// - /// Triple DES Key with two DES Keys - 16 Byte - 128 Bit - /// - TDES_2K, - - /// - /// Triple DES Key with three DES Keys - 24 Byte - 192 Bit - /// - TDES_3K, - - /// - /// AES Key - 16 Byte - 128 Bit - /// - AES - } - - /// - /// Check the Key Length to get Type of DES/3DES Key - /// - public KeyType GetKeyTypeDES(byte[] key) - { - switch(key.Length) - { - case 8: - return KeyType.DES; - case 16: - return KeyType.TDES_2K; - case 24: - return KeyType.TDES_3K; - default: - throw new ArgumentException(string.Format("No valid DES/3DES Key Size({0})", key.Length)); - } - } - - #region Methods for Crypto Operation + #region Crypto Operation /// /// Return a copy of the last Block of data /// /// Data compatible to blocksize - /// Size of Block, default is 8 - public byte[] GetLastBlock(byte[] data, uint blocksize = 8) + /// in byte + public byte[] ExtractLastBlock(byte[] data, uint blocksize) { - if(data.Length % blocksize != 0) + if (data == null) { - throw new ArgumentException(string.Format("Data is not compatible with blocksize(data(length):{0}, blocksize:{1}", data.Length, blocksize)); + throw new ArgumentNullException("Data cannot be null."); } - byte[] block = new byte[blocksize]; + if (data.Length % blocksize != 0) + { + throw new ArgumentException(string.Format("Data is not compatible with blocksize(data(length):{0}, blocksize:{1}.", data.Length, blocksize)); + } + + byte[] lastblock = new byte[blocksize]; for (int i = 0; i < blocksize; i++) { - block[i] = data[data.Length - blocksize + i]; + lastblock[i] = data[data.Length - blocksize + i]; } - return block; + return lastblock; } /// @@ -150,8 +193,13 @@ namespace NFC.Mifare_DESFire /// /// Data /// Copy of data - public byte[] rotateLeft(byte[] data) + public byte[] RotateLeft(byte[] data) { + if (data == null) + { + throw new ArgumentNullException("Data cannot be null."); + } + byte[] rotate = new byte[data.Length]; data.CopyTo(rotate, 0); @@ -170,8 +218,13 @@ namespace NFC.Mifare_DESFire /// /// Data /// Copy of data - public byte[] rotateRight(byte[] data) + public byte[] RotateRight(byte[] data) { + if (data == null) + { + throw new ArgumentNullException("Data cannot be null."); + } + byte[] rotate = new byte[data.Length]; data.CopyTo(rotate, 0); @@ -186,25 +239,47 @@ namespace NFC.Mifare_DESFire } /// - /// Concatenates two Arrays, Array A start at index 0 + /// Concatenates Arrays + /// + /// List of Byte Array + public byte[] Concatenate(params byte[][] data) + { + if (data == null) + { + throw new ArgumentNullException("Data cannot be null."); + } + + List cat = new List(); + + foreach(byte[] d in data) + { + cat.AddRange(d); + } + + return cat.ToArray(); + } + + /// + /// Boolean Operation XOR on all Bytes /// /// Array A /// Array B /// Copy of Data - public byte[] concatenate(byte[] a, byte[] b) + public byte[] XOR(byte[] a, byte[] b) { - byte[] c = new byte[a.Length + b.Length]; - a.CopyTo(c, 0); - b.CopyTo(c, a.Length); - - return c; - } - - public byte[] xor(byte[] a, byte[] b) - { - if(a.Length != b.Length) + if (a == null) { - throw new ArgumentException("Array are not same Length"); + throw new ArgumentNullException("Array A cannot be null."); + } + + if (b == null) + { + throw new ArgumentNullException("Array B cannot be null."); + } + + if (a.Length != b.Length) + { + throw new ArgumentException(string.Format("Arrays are not same Length(Length A:{0}, Lenght B:{1})", a.Length, b.Length)); } byte[] c = new byte[a.Length]; @@ -216,246 +291,18 @@ namespace NFC.Mifare_DESFire return c; } - #endregion - - #endregion - - #region DESFire Commands - /// - /// Get Application IDs from Card - /// - /// AIDs as Array - public UInt32[] GetApplicationIDs() - { - APDUCommand cmd = new APDUCommand(IsoCase.Case2Short) - { - CLA = 0x90, - INS = (byte)APDUInstructions.GET_APPLICATION_IDS - }; - - APDUResponse response = _Card.Transmit(cmd); - - CheckAPDUResponse(response); - - if (response.Body.Length % 3 != 0) - { - throw new Exception(string.Format("Invalid body length (was: {0}).", response.Body.Length)); - } - - if(response.Body.Length == 0) - { - throw new Exception("Missing PICC Entry 0x000000."); - } - - 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 AID + /// Generates SessionKey for DES Authentification /// - /// 3 Byte AID - public void SelectApplication(UInt32 aid) - { - byte[] id_byte = BitConverter.GetBytes(aid); - - 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] - } - }; - - APDUResponse response = _Card.Transmit(cmd); - - CheckAPDUResponse(response); - } - #endregion - - /// - /// Expand Array to Block Size - /// - /// - /// - public byte[] expandToBlockSize(byte[] data, int bocksize) - { - int diff = data.Length % bocksize; - if (diff == 0) - { - return data; - } - - byte[] expand = new byte[data.Length + bocksize - diff]; - - data.CopyTo(expand, 0); - - for(int i = expand.Length - 1; i > data.Length - 1; i--) - { - expand[i] = 0x00; - } - - return expand; - } - - public void ChangeKeyDES(byte key_no, byte[] key_new, byte[] key_current) - { - Console.WriteLine("key_new: {0}", ConvertToHexString(key_new)); - key_new = concatenate(key_new, key_new); - Console.WriteLine("key_new_double: {0}", ConvertToHexString(key_new)); - - byte[] header = new byte[] - { - 0xC4, key_no - }; - Console.WriteLine("header: {0}", ConvertToHexString(header)); - - byte[] cmd_ = concatenate(header, key_new); - Console.WriteLine("cmd_: {0}", ConvertToHexString(cmd_)); - - CRC32 crc = new CRC32(); - byte[] cmd_crc = crc.Calculate(cmd_); - Console.WriteLine("cmd_crc: {0}", ConvertToHexString(cmd_crc)); - byte[] cryptogram = concatenate(key_new, cmd_crc); - Console.WriteLine("cryptogram: {0}", ConvertToHexString(cryptogram)); - - byte[] cryptogram_block = expandToBlockSize(cryptogram, 8); - Console.WriteLine("cryptogram_block: {0}", ConvertToHexString(cryptogram_block)); - - DES des = new DES(); - - byte[] cryptogram_block_enc = des.Encrypt(cryptogram_block, _SessionKey, _IV); - Console.WriteLine("cryptogram_block_enc: {0}", ConvertToHexString(cryptogram_block_enc)); - - byte[] data = concatenate(new byte[] { key_no }, cryptogram_block_enc); - Console.WriteLine("data: {0}", ConvertToHexString(data)); - - APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = 0xC4, - Data = data - }; - Console.WriteLine("cmd: {0}", ConvertToHexString(cmd.ToArray())); - - APDUResponse response = _Card.Transmit(cmd); - - CheckAPDUResponse(response); - } - - - - - - - - /// - /// Create new Application with AID - /// - /// Appilication ID - public APDUCommand CreateApplication(UInt64 aid) - { - throw new NotImplementedException(); - } - - public void Format() - { - throw new NotImplementedException(); - } - - /// - /// Authenticate to Card - /// - /// 0x01 - 0x0D - /// - - // TODO - public void AuthenticateDES(byte key_id, byte[] key) - { - APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = (byte)0x1A, - Data = new byte[] - { - key_id - } - }; - APDUResponse response = _Card.Transmit(cmd_challange_request); - - byte[] rndB_enc = response.Body; - Console.WriteLine("rndB_enc: {0}", ConvertToHexString(rndB_enc)); - - DES des = new DES(); - byte[] rndB = des.Decrypt(rndB_enc, key, GenerateDefaultKey(8)); - Console.WriteLine("rndB: {0}", ConvertToHexString(rndB)); - - byte[] iv = new byte[8]; - rndB.CopyTo(iv, 0); - - byte[] rndB_rl = rotateLeft(rndB); - Console.WriteLine("rndB_enc: {0}", ConvertToHexString(rndB_rl)); - - byte[] rndA = new byte[] - { - 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 - }; - Console.WriteLine("rndA: {0}", ConvertToHexString(rndA)); - - byte[] rndAB = concatenate(rndA, rndB_rl); - Console.WriteLine("rndAB: {0}", ConvertToHexString(rndAB)); - - byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc); - Console.WriteLine("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc)); - iv = GetLastBlock(rndAB_enc); - - APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = (byte)0xAF, - Data = rndAB_enc - }; - Console.WriteLine("cmd_challange_response: {0}", ConvertToHexString(cmd_challange_response.ToArray())); - - response = _Card.Transmit(cmd_challange_response); - - byte[] encryptedRndAFromCard = response.Body; - Console.WriteLine("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard)); - - byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv); - Console.WriteLine("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard)); - - byte[] rndAFromCard = rotateRight(rotatedRndAFromCard); - Console.WriteLine("rndAFromCard: {0}", ConvertToHexString(rndAFromCard)); - - if (!rndA.SequenceEqual(rndAFromCard)) - { - throw new Exception("PICC Challenge is not correct answered."); - } - - _SessionKey = GenerateDESSesionKey(rndA, rndB); - _IV = GenerateDefaultKey(8); - } - - private byte[] GenerateDESSesionKey(byte[] rndA, byte[] rndB) + /// 16Byte SessionKey + public byte[] GenerateSesionKey_DES(byte[] rndA, byte[] rndB) { byte[] sesssionkey = new byte[8]; - for(int i = 0; i < sesssionkey.Length; i++) + for (int i = 0; i < sesssionkey.Length; i++) { - if(i < 4) + if (i < 4) { sesssionkey[i] = rndA[i]; } @@ -465,13 +312,45 @@ namespace NFC.Mifare_DESFire } } - // Set Key Verion of Key to 0x55 to LSB - // TODO - byte[] key_version = SetKeyVersion(sesssionkey, 0x55); - - return concatenate(key_version, key_version); + // DES SessionKey is a double DES Key + return Concatenate(sesssionkey, sesssionkey); } + /// + /// Generates SessionKey for AES Authentification + /// + /// 16Byte SessionKey + public byte[] GenerateSesionKey_AES(byte[] rndA, byte[] rndB) + { + byte[] sesssionkey = new byte[16]; + + for (int i = 0; i < sesssionkey.Length; i++) + { + if (i < 4) + { + sesssionkey[i] = rndA[i]; + } + else if(i >= 4 && i < 8) + { + sesssionkey[i] = rndB[i - 4]; + } + else if (i >= 8 && i < 12) + { + sesssionkey[i] = rndA[i + 4]; + } + else + { + sesssionkey[i] = rndB[i]; + } + } + + return sesssionkey; + } + + /// + /// Set KeyVersion in DES Key + /// KeyVersion is stored in LSB of the first 8 Bytes of the DES Key + /// public byte[] SetKeyVersion(byte[] key, byte keyversion) { byte[] pow2 = new byte[] @@ -482,10 +361,9 @@ namespace NFC.Mifare_DESFire byte[] new_key = new byte[key.Length]; key.CopyTo(new_key, 0); - - for(int i = 0; i < 8; i++) + for (int i = 0; i < 8; i++) { - if((keyversion & pow2[i]) > 0) + if ((keyversion & pow2[i]) > 0) { new_key[i] = (byte)(new_key[5] | 0x01); } @@ -498,53 +376,162 @@ namespace NFC.Mifare_DESFire return new_key; } - public void ChangeApplicationMasterKey(byte[] aPP_MasterKey) - { - throw new NotImplementedException(); - } - /// - /// Delete Application by ID + /// Expand Array to Block Size, fill with 0x00 /// - /// 3 Byte ID - public void DeleteApplication(UInt32 id) + /// + public byte[] ExpandToBlockSize(byte[] data, uint bocksize) { - byte[] id_byte = BitConverter.GetBytes(id); + int diff = data.Length % (int)bocksize; + if (diff == 0) + { + return data; + } - APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) + byte[] expand = new byte[data.Length + bocksize - diff]; + + data.CopyTo(expand, 0); + + for (int i = expand.Length - 1; i > data.Length - 1; i--) + { + expand[i] = 0x00; + } + + return expand; + } + #endregion + + #region DESFire Commands + /// + /// Authenticate to PICC, with ISO Authenticate + /// + /// 0x01 - 0x0D + /// + /// !!! WARNING For Testing only !!! + /// Retry after short Time + public void AuthenticateISO_DES(byte key_id, byte[] key, byte[] rndA = null) + { + _Log.Debug("Start AuthenticateISO_DES"); + + // Sepearte InitialisationVector for Authentication + byte[] iv = new byte[8]; + + APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short) { CLA = 0x90, - INS = (byte)APDUInstructions.DELETE_APPLICATION, + INS = 0x1A, Data = new byte[] { - id_byte[0], - id_byte[1], - id_byte[2] - }, - Le = 0x00 + key_id + } }; + _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_challange_request); + _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray())); - APDUResponse response = _Card.Transmit(cmd); CheckAPDUResponse(response); - } - public void ChangeApplicationKey(int v, byte[] aPP_Key_1) - { - throw new NotImplementedException(); + byte[] rndB_enc = response.Body; + _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc)); + + TDES des = new TDES(); + byte[] rndB = des.Decrypt(rndB_enc, key, GenerateEmptyKey(8)); + _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB)); + + rndB.CopyTo(iv, 0); + + byte[] rndB_rl = RotateLeft(rndB); + _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl)); + + if(rndA == null) + { + Random rnd = new Random(); + rndA = new byte[8]; + rnd.NextBytes(rndA); + } + _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA)); + + byte[] rndAB = Concatenate(rndA, rndB_rl); + _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB)); + + byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc); + _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc)); + iv = ExtractLastBlock(rndAB_enc, 8); + + APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xAF, + Data = rndAB_enc + }; + _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + + response = _Card.Transmit(cmd_challange_response); + _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + + CheckAPDUResponse(response); + + byte[] encryptedRndAFromCard = response.Body; + _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard)); + + byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv); + _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard)); + + byte[] rndAFromCard = RotateRight(rotatedRndAFromCard); + _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard)); + + if (!rndA.SequenceEqual(rndAFromCard)) + { + throw new Exception("Authentication failed, PICC Challenge is not corret"); + } + + _SessionKey = GenerateSesionKey_DES(rndA, rndB); + _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey)); + + _IV = GenerateEmptyKey(8); + _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); + + _Log.Debug("End AuthenticateISO_DES"); } /// - /// Select Application by ID + /// Format PICC /// - /// 3 Byte ID - public APDUCommand CreateApplication(UInt32 id, byte keysetting1, byte keysetting2) + public void Format() { - byte[] id_byte = BitConverter.GetBytes(id); + _Log.Debug("Start Format"); - APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) + APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short) { CLA = 0x90, - INS = (byte)APDUInstructions.CREATE_APPLICATION, + INS = 0xFC, + }; + _Log.DebugFormat("APDU_CMD(cmd_format): {0}", ConvertToHexString(cmd_format.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_format); + _Log.DebugFormat("APDU_RES(cmd_format): {0}", ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + _Log.Debug("End Format"); + } + + /// + /// Create Application for ID + /// + /// 3 Byte ID + public void CreateApplication(UInt32 aid, byte keysetting1, byte keysetting2) + { + _Log.Debug("Start CreateApplication"); + + byte[] id_byte = BitConverter.GetBytes(aid); + _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray())); + + APDUCommand cmd_CreateApplication = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xCA, Data = new byte[] { id_byte[0], @@ -552,38 +539,476 @@ namespace NFC.Mifare_DESFire id_byte[2], keysetting1, keysetting2 - }, - Le = 0x00 + } + }; + _Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", ConvertToHexString(cmd_CreateApplication.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_CreateApplication); + _Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + _Log.Debug("End CreateApplication"); + } + + /// + /// Select Application by AID + /// + /// 3 Byte AID + public void SelectApplication(UInt32 aid) + { + _Log.Debug("Start SelectApplication"); + + byte[] id_byte = BitConverter.GetBytes(aid); + _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray())); + + APDUCommand cmd_SelectApplication = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)APDUInstructions.SELECT_APPLICATION, + Data = new byte[] + { + id_byte[0], + id_byte[1], + id_byte[2] + } + }; + _Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", ConvertToHexString(cmd_SelectApplication.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_SelectApplication); + _Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + _Log.Debug("End SelectApplication"); + } + + /// + /// Authenticate to PICC, with ISO Authenticate + /// + /// 0x01 - 0x0D + /// + /// !!! WARNING For Testing only !!! + /// Retry after short Time + public void AuthenticateISO_AES(byte key_id, byte[] key, byte[] rndA = null) + { + _Log.Debug("Start AuthenticateISO_AES"); + + // Sepearte InitialisationVector for Authentication + byte[] iv = new byte[16]; + + APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xAA, + Data = new byte[] + { + key_id + } + }; + _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_challange_request); + _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + byte[] rndB_enc = response.Body; + _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc)); + + AES aes = new AES(); + byte[] rndB = aes.Decrypt(rndB_enc, key, GenerateEmptyKey(16)); + _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB)); + + rndB.CopyTo(iv, 0); + + byte[] rndB_rl = RotateLeft(rndB); + _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl)); + + if (rndA == null) + { + Random rnd = new Random(); + rndA = new byte[16]; + rnd.NextBytes(rndA); + } + _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA)); + + byte[] rndAB = Concatenate(rndA, rndB_rl); + _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB)); + + byte[] rndAB_enc = aes.Encrypt(rndAB, key, rndB_enc); + _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc)); + iv = ExtractLastBlock(rndAB_enc, 16); + + APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xAF, + Data = rndAB_enc + }; + _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + + response = _Card.Transmit(cmd_challange_response); + _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + + CheckAPDUResponse(response); + + byte[] encryptedRndAFromCard = response.Body; + _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard)); + + byte[] rotatedRndAFromCard = aes.Decrypt(encryptedRndAFromCard, key, iv); + _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard)); + + byte[] rndAFromCard = RotateRight(rotatedRndAFromCard); + _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard)); + + if (!rndA.SequenceEqual(rndAFromCard)) + { + throw new Exception("Authentication failed, PICC Challenge is not corret"); + } + + _SessionKey = GenerateSesionKey_AES(rndA, rndB); + _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey)); + + _IV = GenerateEmptyKey(16); + _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); + + _Log.Debug("End AuthenticateISO_DES"); + } + + /// + /// Change Same AES key as Authenticated + /// + /// + /// + /// + public void ChangeKey_AES(byte key_id, byte[] new_key, byte key_version) + { + _Log.Debug("Start ChangeKey_AES"); + + byte[] header = new byte[] + { + 0xC4, key_id + }; + _Log.DebugFormat("header: {0}", ConvertToHexString(header)); + + // AES Key Version is Append to Key + byte[] key_and_version = Concatenate(new_key, new byte[] { key_version }); + 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)); + + AES aes = new AES(); + byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV); + _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc)); + + _IV = ExtractLastBlock(cryptogram_enc, 16); + _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"); + } + + /// + /// Change other AES key as Authenticated + /// + /// + /// + /// + public void ChangeOtherKey_AES(byte key_id, byte[] new_key, byte[] old_key, byte key_version) + { + _Log.Debug("Start ChangeOtherKey_AES"); + + byte[] header = new byte[] + { + 0xC4, key_id + }; + _Log.DebugFormat("header: {0}", ConvertToHexString(header)); + + byte[] key_xor = XOR(new_key, old_key); + + // AES Key Version is Append to Key + byte[] key_and_version = Concatenate(key_xor, new byte[] { key_version }); + byte[] command = Concatenate(header, key_and_version); + _Log.DebugFormat("command: {0}", ConvertToHexString(command)); + + CRC32 crc32 = new CRC32(); + byte[] crc_cmd = crc32.Calculate(command); + _Log.DebugFormat("crc_cmd: {0}", ConvertToHexString(crc_cmd)); + byte[] crc_key = crc32.Calculate(new_key); + _Log.DebugFormat("crc_key: {0}", ConvertToHexString(crc_key)); + + byte[] cryptogram = Concatenate(key_and_version, crc_cmd); + cryptogram = Concatenate(cryptogram, crc_key); + _Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram)); + + byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16); + _Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block)); + + AES aes = new AES(); + byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV); + _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc)); + + _IV = ExtractLastBlock(cryptogram_enc, 16); + _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 ChangeOtherKey_AES"); + } + + /// + /// Create Standard Data File + /// + /// ID of File (0x01 - 0x10) + /// Type of File Communicaton + /// Access Rights for File + /// Size of File in Bytes + public void CreateFile_Standard(byte file_id, FileCommunication communication, UInt16 accessRights, UInt32 size) + { + _Log.Debug("Start CreateFile_Standard"); + + _Log.DebugFormat("FID: {0}", file_id); + + byte[] accessRights_byte = BitConverter.GetBytes(accessRights); + byte[] size_byte_tolong = BitConverter.GetBytes(size); + // Use only 3 Bytes + byte[] size_byte = new byte[] + { + size_byte_tolong[0], + size_byte_tolong[1], + size_byte_tolong[2], }; - return cmd; + byte[] data = new byte[] + { + file_id, + (byte)communication + }; + + APDUCommand cmd_CreateFile_Standard = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)APDUInstructions.CREATE_STDDATAFILE, + Data = Concatenate(data, accessRights_byte, size_byte) + }; + _Log.DebugFormat("APDU_CMD(cmd_CreateFile_Standard): {0}", ConvertToHexString(cmd_CreateFile_Standard.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_CreateFile_Standard); + _Log.DebugFormat("APDU_RES(cmd_CreateFile_Standard): {0}", ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + _Log.Debug("End CreateFile_Standard"); } - public void CreateFile(byte fabAccessIdentFileID, FileCommunication pLAIN, ushort fileAccessRight, UInt32 v) + /// + /// Read Data from File + /// + /// ID of File (0x01 - 0x10) + /// Offset for File + /// Lenght of Data + public byte[] ReadData(byte file_id, UInt32 offset, UInt32 length) { - throw new NotImplementedException(); + _Log.Debug("Start ReadData"); + + byte[] data = new byte[] + { + file_id + }; + + byte[] offset_byte_tolong = BitConverter.GetBytes(offset); + // 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], + }; + + 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); + + _Log.Debug("End ReadData"); + + return response.Body; } - public ushort GenerateFileAccessRight(AccessRights fREE, int v1, int v2, int v3) + /// + /// Write Data to File + /// + /// ID of File (0x01 - 0x10) + /// Offset for File + /// Data to write + public void WriteData(byte file_id, UInt32 offset, byte[] data) { - throw new NotImplementedException(); + _Log.Debug("Start WriteData"); + + byte[] file_id_array = new byte[] + { + file_id + }; + + byte[] offset_byte_tolong = BitConverter.GetBytes(offset); + // Use only 3 Bytes + byte[] offset_byte = new byte[] + { + offset_byte_tolong[0], + offset_byte_tolong[1], + offset_byte_tolong[2], + }; + + byte[] lenght_byte_tolong = BitConverter.GetBytes(data.Length); + // Use only 3 Bytes + byte[] lenght_byte = new byte[] + { + lenght_byte_tolong[0], + lenght_byte_tolong[1], + lenght_byte_tolong[2], + }; + + APDUCommand cmd_WriteData = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = (byte)APDUInstructions.WRITE_DATA, + Data = Concatenate(file_id_array, offset_byte, lenght_byte, data) + }; + _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"); } - public void WirteData(byte fabAccessIdentFileID, int v1, int v2, byte[] vs) - { - throw new NotImplementedException(); - } + /// + /// Get all ApplicationIDS from PICC + /// + /// AIDs (3 Byte) as Array + //public UInt32[] GetApplicationIDs() + //{ + // _Log.Debug("Start GetApplicationIDs"); - public void CreateFile(byte fabAccessIdentFileID, object plain, AccessRights fREE, int v1, int v2, int v3) - { - throw new NotImplementedException(); - } + // APDUCommand cmd = new APDUCommand(IsoCase.Case2Short) + // { + // CLA = 0x90, + // INS = (byte)APDUInstructions.GET_APPLICATION_IDS + // }; - public byte[] ReadData(byte identFileID, int v1, int v2) - { - throw new NotImplementedException(); - } + // APDUResponse response = _Card.Transmit(cmd); + // CheckAPDUResponse(response); + + // if (response.Body.Length % 3 != 0) + // { + // throw new Exception(string.Format("Invalid body length (was: {0}).", response.Body.Length)); + // } + + // if (response.Body.Length == 0) + // { + // throw new Exception("Missing PICC Entry 0x000000."); + // } + + // 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); + // } + + // _Log.Debug("End GetApplicationIDs"); + + // return applicationIDs.ToArray(); + //} + + /// + /// Delete Application by ID + /// + /// 3 Byte ID + //public void 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 + // }; + + // APDUResponse response = _Card.Transmit(cmd); + // CheckAPDUResponse(response); + //} + #endregion + + #region Configuration Generator /// /// Genearte KeySetting1 for Application Settings or PICC Setting /// @@ -592,6 +1017,53 @@ namespace NFC.Mifare_DESFire 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(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys) + { + if (numberOfKeys < 0x01 || numberOfKeys >= 0x0D) + { + throw new ArgumentOutOfRangeException(); + } + + return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys); + } + + /// + /// Generate FileAccess Rights for File Settings + /// Use enum AccesRights for Free or Never Option + /// + /// KeyID for Read Access + /// KeyID for Write Access + /// KeyID for Read and Write Access + /// KeyID for Configuration Access + public UInt16 GenerateFileAccessRights(byte read, byte write, byte read_write, byte configure) + { + if(read > 0x0F || write > 0x0F || read_write > 0x0F || configure > 0x0F) + { + throw new ArgumentOutOfRangeException("One KeyID is not valid"); + } + + return (UInt16)((read << 12) | (write << 8) | (read_write << 4) | configure); + } + #endregion + #endregion } } diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs deleted file mode 100644 index b0bda50..0000000 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire_V2.cs +++ /dev/null @@ -1,844 +0,0 @@ -using log4net.Repository.Hierarchy; -using NFC.Crypto; -using NFC.ISO7816_4; -using NFC.Mifare_DESFire.Enums; -using NFC.NXP_MIFARE_DESFire.Exceptions; -using PCSC.Iso7816; -using System; -using System.Linq; - -namespace NFC.Mifare_DESFire -{ - public class MIFARE_DESFire_V2 - { - // Docs https://hackmd.io/qATu8uYdRnOC40aFrB9afg - - #region Log - private static readonly log4net.ILog _Log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - #endregion - - #region Contructors - /// - /// Construct MIFRARE_DESFire Object with ICard Interface - /// - /// Implementation of ICard, only transmit is used - public MIFARE_DESFire_V2(ICard card) - { - _Card = card; - } - #endregion - - #region Properties - /// - /// ICard Implementation used to transmit APDUCommands and recive APDUResponses - /// - private ICard _Card; - - /// - /// SessionKey, is set after Successfull Authentication - /// - public byte[] _SessionKey; - - /// - /// Initialation Vector for CBC Encryption - /// Is 0 bytes after Successfull Authentication - /// - public byte[] _IV; - #endregion - - #region Methods - #region Helper Methods - /// - /// Generate Byte Array filled with 0 - /// - /// Size of Array - public byte[] GenerateEmptyKey(uint size) - { - byte[] key = new byte[size]; - for (int i = 0; i < size; i++) - { - key[i] = 0; - } - - return key; - } - - /// - /// Converts byte[] to string with HEX Code - /// No 0x is created - /// - /// Data - public string ConvertToHexString(byte[] data) - { - return BitConverter.ToString(data).Replace("-", "").ToLower(); - } - - /// - /// Converts string with HEX Code to byte[] - /// No 0x is requiered - /// - /// Data - public byte[] ConvertFromHexString(string data) - { - if (data.Length % 2 == 1) - throw new Exception("Data Length is uneven."); - - byte[] arr = new byte[data.Length >> 1]; - - for (int i = 0; i < data.Length >> 1; ++i) - { - arr[i] = (byte)((GetHexVal(data[i << 1]) << 4) + (GetHexVal(data[(i << 1) + 1]))); - } - - return arr; - } - - private int GetHexVal(char hex) - { - int val = (int)hex; - //For uppercase A-F letters: - //return val - (val < 58 ? 48 : 55); - //For lowercase a-f letters: - //return val - (val < 58 ? 48 : 87); - //Or the two combined, but a bit slower: - return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); - } - - /// - /// Check APDU Response for DESFire Error Codes - /// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf - /// Section: 11.3 - /// - public void CheckAPDUResponse(APDUResponse response) - { - if (response == null) - { - throw new ArgumentNullException("Response cannot be null."); - } - - if (response.SW1 == 0x91) - { - switch (response.SW2) - { - case 0x00: // OPERATION_OK - return; - case 0x0C: // NO_CHANGES - return; - case 0x1C: // ILLEGAL_COMMAND_CODE - throw new IllegalCommandCodeException(); - case 0x1E: // INTEGRITY_ERROR - throw new IntegrityErrorException(); - case 0x40: // NO_SUCH_KEY - throw new NoSuchKeyException(); - case 0x7E: // LENGTH_ERROR - throw new LengthErrorException(); - case 0x9D: // PERMISSION_DENIED - throw new PermissionDeniedException(); - case 0x9E: // PARAMETER_ERROR - throw new ParameterErrorException(); - case 0xAD: // AUTHENTICATION_DELAY - throw new AuthenticationDelayException(); - case 0xAE: // AUTHENTICATION_ERROR - throw new AuthenticationErrorException(); - case 0xAF: // ADDITIONAL_FRAME - return; - case 0xBE: // BOUNDARY_ERROR - throw new BoundaryErrorException(); - case 0xCA: // COMMAND_ABORTED - throw new CommandAbortedException(); - case 0xDE: // DUPLICATE_ERROR - throw new DuplicateErrorException(); - case 0xF0: // FILE_NOT_FOUND - throw new FileNotFoundException(); - default: - break; - } - } - - throw new Exception(string.Format("Unknown Response Code: 0x{0}.", BitConverter.ToString(new byte[] { response.SW1, response.SW2 }).Replace("-", string.Empty))); - } - #endregion - - #region Crypto Operation - /// - /// Return a copy of the last Block of data - /// - /// Data compatible to blocksize - /// in byte - public byte[] ExtractLastBlock(byte[] data, uint blocksize) - { - if (data == null) - { - throw new ArgumentNullException("Data cannot be null."); - } - - if (data.Length % blocksize != 0) - { - throw new ArgumentException(string.Format("Data is not compatible with blocksize(data(length):{0}, blocksize:{1}.", data.Length, blocksize)); - } - - byte[] lastblock = new byte[blocksize]; - - for (int i = 0; i < blocksize; i++) - { - lastblock[i] = data[data.Length - blocksize + i]; - } - - return lastblock; - } - - /// - /// Rotates Array to the left - /// - /// Data - /// Copy of data - public byte[] RotateLeft(byte[] data) - { - if (data == null) - { - throw new ArgumentNullException("Data cannot be null."); - } - - byte[] rotate = new byte[data.Length]; - data.CopyTo(rotate, 0); - - byte tmp = rotate[0]; - for (var i = 0; i < rotate.Length - 1; i++) - { - rotate[i] = rotate[i + 1]; - } - rotate[rotate.Length - 1] = tmp; - - return rotate; - } - - /// - /// Rotates Array to the right - /// - /// Data - /// Copy of data - public byte[] RotateRight(byte[] data) - { - if (data == null) - { - throw new ArgumentNullException("Data cannot be null."); - } - - byte[] rotate = new byte[data.Length]; - data.CopyTo(rotate, 0); - - byte tmp = rotate[rotate.Length - 1]; - for (var i = rotate.Length - 1; i > 0; i--) - { - rotate[i] = rotate[i - 1]; - } - rotate[0] = tmp; - - return rotate; - } - - /// - /// Concatenates two Arrays, Array A start at index 0 - /// - /// Array A - /// Array B - /// Copy of Data (a.Size + b.Size) - public byte[] Concatenate(byte[] a, byte[] b) - { - if (a == null) - { - throw new ArgumentNullException("Array A cannot be null."); - } - - if (b == null) - { - throw new ArgumentNullException("Array B cannot be null."); - } - - byte[] c = new byte[a.Length + b.Length]; - a.CopyTo(c, 0); - b.CopyTo(c, a.Length); - - return c; - } - - /// - /// Boolean Operation XOR on all Bytes - /// - /// Array A - /// Array B - /// Copy of Data - public byte[] XOR(byte[] a, byte[] b) - { - if (a == null) - { - throw new ArgumentNullException("Array A cannot be null."); - } - - if (b == null) - { - throw new ArgumentNullException("Array B cannot be null."); - } - - if (a.Length != b.Length) - { - throw new ArgumentException(string.Format("Arrays are not same Length(Length A:{0}, Lenght B:{1})", a.Length, b.Length)); - } - - byte[] c = new byte[a.Length]; - - for(int i = 0; i < a.Length; i++) - { - c[i] = (byte)(a[i] ^ b[i]); - } - - return c; - } - - /// - /// Generates SessionKey for DES Authentification - /// - /// 16Byte SessionKey - public byte[] GenerateSesionKey_DES(byte[] rndA, byte[] rndB) - { - byte[] sesssionkey = new byte[8]; - - for (int i = 0; i < sesssionkey.Length; i++) - { - if (i < 4) - { - sesssionkey[i] = rndA[i]; - } - else - { - sesssionkey[i] = rndB[i - 4]; - } - } - - // DES SessionKey is a double DES Key - return Concatenate(sesssionkey, sesssionkey); - } - - /// - /// Generates SessionKey for AES Authentification - /// - /// 16Byte SessionKey - public byte[] GenerateSesionKey_AES(byte[] rndA, byte[] rndB) - { - byte[] sesssionkey = new byte[16]; - - for (int i = 0; i < sesssionkey.Length; i++) - { - if (i < 4) - { - sesssionkey[i] = rndA[i]; - } - else if(i >= 4 && i < 8) - { - sesssionkey[i] = rndB[i - 4]; - } - else if (i >= 8 && i < 12) - { - sesssionkey[i] = rndA[i + 4]; - } - else - { - sesssionkey[i] = rndB[i]; - } - } - - return sesssionkey; - } - - /// - /// Set KeyVersion in DES Key - /// KeyVersion is stored in LSB of the first 8 Bytes of the DES Key - /// - public byte[] SetKeyVersion(byte[] key, byte keyversion) - { - byte[] pow2 = new byte[] - { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 - }; - - byte[] new_key = new byte[key.Length]; - key.CopyTo(new_key, 0); - - for (int i = 0; i < 8; i++) - { - if ((keyversion & pow2[i]) > 0) - { - new_key[i] = (byte)(new_key[5] | 0x01); - } - else - { - new_key[i] = (byte)(new_key[5] & 0x7F); - } - } - - return new_key; - } - - /// - /// Expand Array to Block Size, fill with 0x00 - /// - /// - public byte[] ExpandToBlockSize(byte[] data, uint bocksize) - { - int diff = data.Length % (int)bocksize; - if (diff == 0) - { - return data; - } - - byte[] expand = new byte[data.Length + bocksize - diff]; - - data.CopyTo(expand, 0); - - for (int i = expand.Length - 1; i > data.Length - 1; i--) - { - expand[i] = 0x00; - } - - return expand; - } - #endregion - - #region DESFire Commands - /// - /// Authenticate to PICC, with ISO Authenticate - /// - /// 0x01 - 0x0D - /// - /// !!! WARNING For Testing only !!! - /// Retry after short Time - public void AuthenticateISO_DES(byte key_id, byte[] key, byte[] rndA = null) - { - _Log.Debug("Start AuthenticateISO_DES"); - - // Sepearte InitialisationVector for Authentication - byte[] iv = new byte[8]; - - APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = 0x1A, - Data = new byte[] - { - key_id - } - }; - _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray())); - - APDUResponse response = _Card.Transmit(cmd_challange_request); - _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray())); - - CheckAPDUResponse(response); - - byte[] rndB_enc = response.Body; - _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc)); - - DES des = new DES(); - byte[] rndB = des.Decrypt(rndB_enc, key, GenerateEmptyKey(8)); - _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB)); - - rndB.CopyTo(iv, 0); - - byte[] rndB_rl = RotateLeft(rndB); - _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl)); - - if(rndA == null) - { - Random rnd = new Random(); - rndA = new byte[8]; - rnd.NextBytes(rndA); - } - _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA)); - - byte[] rndAB = Concatenate(rndA, rndB_rl); - _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB)); - - byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc); - _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc)); - iv = ExtractLastBlock(rndAB_enc, 8); - - APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = 0xAF, - Data = rndAB_enc - }; - _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); - - response = _Card.Transmit(cmd_challange_response); - _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); - - CheckAPDUResponse(response); - - byte[] encryptedRndAFromCard = response.Body; - _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard)); - - byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv); - _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard)); - - byte[] rndAFromCard = RotateRight(rotatedRndAFromCard); - _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard)); - - if (!rndA.SequenceEqual(rndAFromCard)) - { - throw new Exception("Authentication failed, PICC Challenge is not corret"); - } - - _SessionKey = GenerateSesionKey_DES(rndA, rndB); - _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey)); - - _IV = GenerateEmptyKey(8); - _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); - - _Log.Debug("End AuthenticateISO_DES"); - } - - /// - /// Format PICC - /// - public void Format() - { - _Log.Debug("Start Format"); - - APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short) - { - CLA = 0x90, - INS = 0xFC, - }; - _Log.DebugFormat("APDU_CMD(cmd_format): {0}", ConvertToHexString(cmd_format.ToArray())); - - APDUResponse response = _Card.Transmit(cmd_format); - _Log.DebugFormat("APDU_RES(cmd_format): {0}", ConvertToHexString(response.ToArray())); - - CheckAPDUResponse(response); - - _Log.Debug("End Format"); - } - - /// - /// Create Application for ID - /// - /// 3 Byte ID - public void CreateApplication(UInt32 aid, byte keysetting1, byte keysetting2) - { - _Log.Debug("Start CreateApplication"); - - byte[] id_byte = BitConverter.GetBytes(aid); - _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray())); - - APDUCommand cmd_CreateApplication = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = 0xCA, - Data = new byte[] - { - id_byte[0], - id_byte[1], - id_byte[2], - keysetting1, - keysetting2 - } - }; - _Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", ConvertToHexString(cmd_CreateApplication.ToArray())); - - APDUResponse response = _Card.Transmit(cmd_CreateApplication); - _Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", ConvertToHexString(response.ToArray())); - - CheckAPDUResponse(response); - - _Log.Debug("End CreateApplication"); - } - - /// - /// Select Application by AID - /// - /// 3 Byte AID - public void SelectApplication(UInt32 aid) - { - _Log.Debug("Start SelectApplication"); - - byte[] id_byte = BitConverter.GetBytes(aid); - _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray())); - - APDUCommand cmd_SelectApplication = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = (byte)APDUInstructions.SELECT_APPLICATION, - Data = new byte[] - { - id_byte[0], - id_byte[1], - id_byte[2] - } - }; - _Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", ConvertToHexString(cmd_SelectApplication.ToArray())); - - APDUResponse response = _Card.Transmit(cmd_SelectApplication); - _Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", ConvertToHexString(response.ToArray())); - - CheckAPDUResponse(response); - - _Log.Debug("End SelectApplication"); - } - - /// - /// Authenticate to PICC, with ISO Authenticate - /// - /// 0x01 - 0x0D - /// - /// !!! WARNING For Testing only !!! - /// Retry after short Time - public void AuthenticateISO_AES(byte key_id, byte[] key, byte[] rndA = null) - { - _Log.Debug("Start AuthenticateISO_AES"); - - // Sepearte InitialisationVector for Authentication - byte[] iv = new byte[16]; - - APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = 0xAA, - Data = new byte[] - { - key_id - } - }; - _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray())); - - APDUResponse response = _Card.Transmit(cmd_challange_request); - _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray())); - - CheckAPDUResponse(response); - - byte[] rndB_enc = response.Body; - _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc)); - - AES aes = new AES(); - byte[] rndB = aes.Decrypt(rndB_enc, key, GenerateEmptyKey(16)); - _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB)); - - rndB.CopyTo(iv, 0); - - byte[] rndB_rl = RotateLeft(rndB); - _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl)); - - if (rndA == null) - { - Random rnd = new Random(); - rndA = new byte[16]; - rnd.NextBytes(rndA); - } - _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA)); - - byte[] rndAB = Concatenate(rndA, rndB_rl); - _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB)); - - byte[] rndAB_enc = aes.Encrypt(rndAB, key, rndB_enc); - _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc)); - iv = ExtractLastBlock(rndAB_enc, 16); - - APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = 0xAF, - Data = rndAB_enc - }; - _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); - - response = _Card.Transmit(cmd_challange_response); - _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); - - CheckAPDUResponse(response); - - byte[] encryptedRndAFromCard = response.Body; - _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard)); - - byte[] rotatedRndAFromCard = aes.Decrypt(encryptedRndAFromCard, key, iv); - _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard)); - - byte[] rndAFromCard = RotateRight(rotatedRndAFromCard); - _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard)); - - if (!rndA.SequenceEqual(rndAFromCard)) - { - throw new Exception("Authentication failed, PICC Challenge is not corret"); - } - - _SessionKey = GenerateSesionKey_AES(rndA, rndB); - _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey)); - - _IV = GenerateEmptyKey(16); - _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); - - _Log.Debug("End AuthenticateISO_DES"); - } - - /// - /// Change Same AES key as Authenticated - /// - /// - /// - /// - public void ChangeKey_AES(byte key_id, byte[] new_key, byte key_version) - { - _Log.Debug("Start ChangeKey_AES"); - - byte[] header = new byte[] - { - 0xC4, key_id - }; - _Log.DebugFormat("header: {0}", ConvertToHexString(header)); - - // AES Key Version is Append to Key - byte[] key_and_version = Concatenate(new_key, new byte[] { key_version }); - 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)); - - AES aes = new AES(); - byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV); - _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc)); - - _IV = ExtractLastBlock(cryptogram_enc, 16); - _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"); - } - - /// - /// Change other AES key as Authenticated - /// - /// - /// - /// - public void ChangeOtherKey_AES(byte key_id, byte[] new_key, byte[] old_key, byte key_version) - { - _Log.Debug("Start ChangeOtherKey_AES"); - - byte[] header = new byte[] - { - 0xC4, key_id - }; - _Log.DebugFormat("header: {0}", ConvertToHexString(header)); - - byte[] key_xor = XOR(new_key, old_key); - - // AES Key Version is Append to Key - byte[] key_and_version = Concatenate(key_xor, new byte[] { key_version }); - byte[] command = Concatenate(header, key_and_version); - _Log.DebugFormat("command: {0}", ConvertToHexString(command)); - - CRC32 crc32 = new CRC32(); - byte[] crc_cmd = crc32.Calculate(command); - _Log.DebugFormat("crc_cmd: {0}", ConvertToHexString(crc_cmd)); - byte[] crc_key = crc32.Calculate(new_key); - _Log.DebugFormat("crc_key: {0}", ConvertToHexString(crc_key)); - - byte[] cryptogram = Concatenate(key_and_version, crc_cmd); - cryptogram = Concatenate(cryptogram, crc_key); - _Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram)); - - byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16); - _Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block)); - - AES aes = new AES(); - byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV); - _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc)); - - _IV = ExtractLastBlock(cryptogram_enc, 16); - _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 ChangeOtherKey_AES"); - } - - public void CreateFile_STD() - #endregion - - #region Configuration Generator - /// - /// 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(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys) - { - if (numberOfKeys < 0x01 || numberOfKeys >= 0x0D) - { - throw new ArgumentOutOfRangeException(); - } - - return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys); - } - #endregion - #endregion - } -} diff --git a/NFC_Test/AuthCrypto_Test.cs b/NFC_Test/AuthCrypto_Test.cs deleted file mode 100644 index 58e6b6f..0000000 --- a/NFC_Test/AuthCrypto_Test.cs +++ /dev/null @@ -1,211 +0,0 @@ -using NFC; -using NFC.Crypto; -using NFC.ISO7816_4; -using NFC.Mifare_DESFire; -using NSubstitute; -using NUnit.Framework; -using PCSC.Iso7816; -using System; -using System.Collections.Generic; -using System.Text; - -namespace NFC_Test -{ - public class AuthCrypto_Test - { - public byte[] GenerateDefaultKey(int size) - { - List key = new List(); - for (int i = 0; i < size; i++) - { - key.Add(0); - } - - return key.ToArray(); - } - - [Test] - // https://www.linkedin.com/pulse/mifare-desfire-introduction-david-coelho - public void AuthExample() - { - DES des = new DES(); - - byte[] challenge = new byte[] - { - 0x93 ,0x9d ,0x2c ,0x2e ,0xa1 ,0x65 ,0x75 ,0xd5 - }; - - byte[] key = GenerateDefaultKey(8); - byte[] iv = GenerateDefaultKey(8); - - byte[] rndA = new byte[] - { - 0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07 - }; - - byte[] rndB = des.Decrypt(challenge, key, iv); - - byte[] rndB_expected = new byte[] - { - 0xea ,0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67 - }; - - Assert.AreEqual(rndB_expected, rndB); - } - - [Test] - public void concatenate() - { - MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(null); - - byte[] rndA = new byte[] - { - 0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07 - }; - - byte[] rndB = new byte[] - { - 0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67 ,0xea - }; - - byte[] rndA_rndB_expected = new byte[] - { - 0x00 ,0x01 ,0x02 ,0x03 ,0x04 ,0x05 ,0x06 ,0x07, 0x48 ,0x50 ,0x13 ,0xd8 ,0x0a ,0x05 ,0x67 ,0xea - }; - - byte[] rndA_rndB = mifareDESFire.concatenate(rndA, rndB); - - Assert.AreEqual(rndA_rndB_expected, rndA_rndB); - } - - [Test] - public void Auth() - { - APDUCommand cmd_getchallange = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = (byte)0x1A, - Data = new byte[] - { - 0x00 - } - }; - - APDUCommand cmd_answerchallange = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = (byte)0xAF, - Data = new byte[] - { - 0x69, 0x17, 0x8b, 0x93, 0x8c, 0x03, 0xed, 0xf1, 0x86, 0xd3, 0x05, 0x6b, 0xed, 0xc8, 0xd6, 0xcf - } - }; - - APDUResponse response = new APDUResponse() - { - Body = new byte[] - { - 0xB8, 0x90, 0x04, 0x7F, 0x2D, 0xC8, 0xD6, 0x8B - } - }; - - APDUResponse response2 = new APDUResponse() - { - Body = new byte[] - { - 0x04, 0x79, 0xed, 0x6c, 0x4f, 0x74, 0xda, 0x4a - } - }; - - ICard card = Substitute.For(); - - card.Transmit(cmd_getchallange).ReturnsForAnyArgs(response); - card.Transmit(cmd_answerchallange).Returns(response2); - - MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - - mifareDESFire.AuthenticateDES(0x00, mifareDESFire.GenerateDefaultKey(16)); - } - - [Test] - public void ChangeKey() - { - ICard card = Substitute.For(); - MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - - mifareDESFire._SessionKey = new byte[] - { - 0xDC, 0xB0, 0x96, 0xC2, 0xA4, 0x0E, 0x78, 0xE0, 0xA0, 0xE4, 0x7A, 0x96, 0xF4, 0x2E, 0x62, 0xAE - }; - mifareDESFire._IV = new byte[] - { - 0x33, 0x45 , 0xAA , 0x95 , 0xF2 , 0xD9 , 0x56 , 0xCF - }; - - mifareDESFire.ChangeKeyDES(0x00, GenerateDefaultKey(16), GenerateDefaultKey(16)); - } - - [Test] - public void CRC() - { - byte[] data = StringToByteArrayFastest("c40045eeb8338ae8f49a032e85bb1114353010"); - - CRC32 crc32 = new CRC32(); - - byte[] crc = crc32.Calculate(data); - - MIFARE_DESFire dESFire = new MIFARE_DESFire(null); - - Console.WriteLine("data: {0}", dESFire.ConvertToHexString(data)); - Console.WriteLine("crc: {0}", dESFire.ConvertToHexString(crc)); - - byte[] data_crc = dESFire.concatenate(data, crc); - Console.WriteLine("data_crc: {0}", dESFire.ConvertToHexString(data_crc)); - } - - public static byte[] StringToByteArrayFastest(string hex) - { - if (hex.Length % 2 == 1) - throw new Exception("The binary key cannot have an odd number of digits"); - - byte[] arr = new byte[hex.Length >> 1]; - - for (int i = 0; i < hex.Length >> 1; ++i) - { - arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1]))); - } - - return arr; - } - - public static int GetHexVal(char hex) - { - int val = (int)hex; - //For uppercase A-F letters: - //return val - (val < 58 ? 48 : 55); - //For lowercase a-f letters: - //return val - (val < 58 ? 48 : 87); - //Or the two combined, but a bit slower: - return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); - } - - [Test] - public void AES() - { - byte[] data = StringToByteArrayFastest("45eeb8338ae8f49a032e85bb111435301095c3894b0000000000000000000000"); - byte[] key = StringToByteArrayFastest("d99aca2b5b4de3a949fa2cf12b0eb673"); - byte[] iv = StringToByteArrayFastest("00000000000000000000000000000000"); - - MIFARE_DESFire dESFire = new MIFARE_DESFire(null); - - Console.WriteLine("data: {0}", dESFire.ConvertToHexString(data)); - Console.WriteLine("key: {0}", dESFire.ConvertToHexString(key)); - Console.WriteLine("iv: {0}", dESFire.ConvertToHexString(iv)); - - AES aes = new AES(); - - byte[] data_enc = aes.Encrypt(data, key, iv); - Console.WriteLine("data_enc: {0}", dESFire.ConvertToHexString(data_enc)); - } - } -} diff --git a/NFC_Test/AES_Test.cs b/NFC_Test/Crypto/AES_Test.cs similarity index 89% rename from NFC_Test/AES_Test.cs rename to NFC_Test/Crypto/AES_Test.cs index b35fee2..a4a2cf0 100644 --- a/NFC_Test/AES_Test.cs +++ b/NFC_Test/Crypto/AES_Test.cs @@ -2,7 +2,7 @@ using NFC.Mifare_DESFire; using NUnit.Framework; -namespace NFC_Test +namespace NFC_Test.Crypto { [TestFixture] public class AES_Test @@ -10,7 +10,7 @@ namespace NFC_Test [Test] public void Encrypt() { - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); byte[] data = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12104a3b07e8eb77a7ac00000000000000"); byte[] key = desfire.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b"); diff --git a/NFC_Test/Crypto/CRC16_Test.cs b/NFC_Test/Crypto/CRC16_Test.cs new file mode 100644 index 0000000..d174e05 --- /dev/null +++ b/NFC_Test/Crypto/CRC16_Test.cs @@ -0,0 +1,23 @@ +using NFC; +using NFC.Crypto; +using NUnit.Framework; + +namespace NFC_Test.Crypto +{ + [TestFixture] + public class CRC16_Test + { + [Test] + [Ignore("Unknown Expected Data")] + public void Caluclate() + { + byte[] data = HexConverter.ConvertFromHexString(""); + byte[] crc_expected = HexConverter.ConvertFromHexString(""); + + CRC16 crc16 = new CRC16(); + byte[] crc = crc16.Calculate(data); + + Assert.AreEqual(crc_expected, crc); + } + } +} diff --git a/NFC_Test/Crypto/CRC32_Test.cs b/NFC_Test/Crypto/CRC32_Test.cs new file mode 100644 index 0000000..aa14248 --- /dev/null +++ b/NFC_Test/Crypto/CRC32_Test.cs @@ -0,0 +1,22 @@ +using NFC; +using NFC.Crypto; +using NUnit.Framework; + +namespace NFC_Test.Crypto +{ + [TestFixture] + public class CRC32_Test + { + [Test] + public void Caluclate() + { + byte[] data = HexConverter.ConvertFromHexString("c40045eeb8338ae8f49a032e85bb1114353010"); + byte[] crc_expected = HexConverter.ConvertFromHexString("95c3894b"); + + CRC32 crc32 = new CRC32(); + byte[] crc = crc32.Calculate(data); + + Assert.AreEqual(crc_expected, crc); + } + } +} diff --git a/NFC_Test/Crypto/TDES_Test.cs b/NFC_Test/Crypto/TDES_Test.cs new file mode 100644 index 0000000..3789040 --- /dev/null +++ b/NFC_Test/Crypto/TDES_Test.cs @@ -0,0 +1,61 @@ +using NFC.Crypto; +using NFC.Mifare_DESFire; +using NUnit.Framework; + +namespace NFC_Test.Crypto +{ + [TestFixture] + public class TDES_Test + { + [Test] + [Ignore("Unknown Expected Data")] + public void Encrypt_TDES() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + byte[] data = desfire.ConvertFromHexString(""); + byte[] key = desfire.ConvertFromHexString(""); + byte[] iv = desfire.ConvertFromHexString("0000000000000000"); + + TDES des = new TDES(); + byte[] data_enc = des.Encrypt(data, key, iv); + + byte[] data_enc_expected = desfire.ConvertFromHexString(""); + Assert.AreEqual(data_enc_expected, data_enc); + } + + [Test] + [Ignore("Unknown Expected Data")] + public void Encrypt_TDES_2K() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + byte[] data = desfire.ConvertFromHexString(""); + byte[] key = desfire.ConvertFromHexString(""); + byte[] iv = desfire.ConvertFromHexString("0000000000000000"); + + TDES_2K des = new TDES_2K(); + byte[] data_enc = des.Encrypt(data, key, iv); + + byte[] data_enc_expected = desfire.ConvertFromHexString(""); + Assert.AreEqual(data_enc_expected, data_enc); + } + + [Test] + [Ignore("Unknown Expected Data")] + public void Encrypt_TDES_3K() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + byte[] data = desfire.ConvertFromHexString(""); + byte[] key = desfire.ConvertFromHexString(""); + byte[] iv = desfire.ConvertFromHexString("0000000000000000"); + + TDES_3K des = new TDES_3K(); + byte[] data_enc = des.Encrypt(data, key, iv); + + byte[] data_enc_expected = desfire.ConvertFromHexString(""); + Assert.AreEqual(data_enc_expected, data_enc); + } + } +} \ No newline at end of file diff --git a/NFC_Test/ISO7816-4/APDUCommand_Test.cs b/NFC_Test/ISO7816-4/APDUCommand_Test.cs new file mode 100644 index 0000000..28c68e1 --- /dev/null +++ b/NFC_Test/ISO7816-4/APDUCommand_Test.cs @@ -0,0 +1,119 @@ +using System; +using NFC.ISO7816_4; +using NUnit.Framework; +using PCSC.Iso7816; + +namespace NFC_Test.ISO7816_4 +{ + [TestFixture] + public class APDUCommand_Test + { + [Test] + public void Compare() + { + APDUCommand command1 = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xAA, + Data = new byte[] + { + 0x01, 0x02, 0x03 + } + }; + + APDUCommand command2 = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xAA, + Data = new byte[] + { + 0x01, 0x02, 0x03 + } + }; + + Assert.IsTrue(command1 == command2); + } + + [Test] + public void Compare_Diff() + { + APDUCommand command1 = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0xAA, + Data = new byte[] + { + 0x01, 0x02, 0x03 + } + }; + + APDUCommand command2 = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0x1A, + Data = new byte[] + { + 0x01, 0x02, 0x03 + } + }; + + Assert.IsFalse(command1 == command2); + } + + [Test] + public void ToString_Case1() + { + APDUCommand command = new APDUCommand(IsoCase.Case1) + { + CLA = 0x90, + INS = 0x1A + }; + + Console.WriteLine(command.ToString()); + } + + [Test] + public void ToString_Case2() + { + APDUCommand command = new APDUCommand(IsoCase.Case2Short) + { + CLA = 0x90, + INS = 0x1A + }; + + Console.WriteLine(command.ToString()); + } + + [Test] + public void ToString_Case3() + { + APDUCommand command = new APDUCommand(IsoCase.Case3Short) + { + CLA = 0x90, + INS = 0x1A, + Data = new byte[] + { + 0x01, 0x02, 0x03 + } + }; + + Console.WriteLine(command.ToString()); + } + + [Test] + public void ToString_Case4() + { + APDUCommand command = new APDUCommand(IsoCase.Case4Short) + { + CLA = 0x90, + INS = 0x1A, + Data = new byte[] + { + 0x01, 0x02, 0x03 + } + }; + + Console.WriteLine(command.ToString()); + } + } +} diff --git a/NFC_Test/MifareDESFire_Commands.cs b/NFC_Test/MifareDESFire_Commands.cs deleted file mode 100644 index 504b25a..0000000 --- a/NFC_Test/MifareDESFire_Commands.cs +++ /dev/null @@ -1,34 +0,0 @@ -using NFC; -using NFC.Mifare_DESFire; -using NFC.Mifare_DESFire.Enums; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Text; - -namespace NFC_Test -{ - [TestFixture] - public class MifareDESFire_Commands - { - private MIFARE_DESFire _MifareDESFire; - - [SetUp] - public void SetUp() - { - //_MifareDESFire = new MifareDESFire(); - } - - [Test] - public void GetApplicationIDs() - { - - } - - [Test] - public void GenerateKeySetting1() - { - Assert.AreEqual(0xEF, _MifareDESFire.GenerateKeySetting1(ChangeApplicationKey.SAMEKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE)); - } - } -} diff --git a/NFC_Test/NFC_Test.csproj b/NFC_Test/NFC_Test.csproj index d420e5c..28d0baf 100644 --- a/NFC_Test/NFC_Test.csproj +++ b/NFC_Test/NFC_Test.csproj @@ -1,4 +1,4 @@ - + netcoreapp3.1 diff --git a/NFC_Test/MIFARE_DESFire_V2_Test.cs b/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs similarity index 73% rename from NFC_Test/MIFARE_DESFire_V2_Test.cs rename to NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs index a3a8a2b..0a1b6d5 100644 --- a/NFC_Test/MIFARE_DESFire_V2_Test.cs +++ b/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs @@ -3,17 +3,13 @@ using NFC.ISO7816_4; using NFC.Mifare_DESFire; using NFC.NXP_MIFARE_DESFire.Exceptions; using NSubstitute; -using NSubstitute.Core; using NUnit.Framework; -using PCSC.Iso7816; using System; -using System.Collections.Generic; -using System.Net; -namespace NFC_Test +namespace NFC_Test.NXP_MIFARE_DESFire { [TestFixture] - public class MIFARE_DESFire_V2_Test + public class MIFARE_DESFire_Test { #region Helper Methods [Test] @@ -21,7 +17,7 @@ namespace NFC_Test { uint i = 16; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); byte[] data = desfire.GenerateEmptyKey(i); @@ -37,7 +33,7 @@ namespace NFC_Test [Test] public void CheckAPDUResponse__NULL() { - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate { @@ -54,7 +50,7 @@ namespace NFC_Test SW2 = 0x00 }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate { @@ -71,7 +67,7 @@ namespace NFC_Test SW2 = 0x00 }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); desfire.CheckAPDUResponse(response); } @@ -85,7 +81,7 @@ namespace NFC_Test SW2 = 0x0C }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); desfire.CheckAPDUResponse(response); } @@ -98,7 +94,7 @@ namespace NFC_Test SW2 = 0x1C }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -116,7 +112,7 @@ namespace NFC_Test SW2 = 0x1E }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -134,7 +130,7 @@ namespace NFC_Test SW2 = 0x40 }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -152,7 +148,7 @@ namespace NFC_Test SW2 = 0x7E }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -170,7 +166,7 @@ namespace NFC_Test SW2 = 0x9D }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -189,7 +185,7 @@ namespace NFC_Test SW2 = 0x9E }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -208,7 +204,7 @@ namespace NFC_Test SW2 = 0xAD }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -226,7 +222,7 @@ namespace NFC_Test SW2 = 0xAE }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -244,7 +240,7 @@ namespace NFC_Test SW2 = 0xAF }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); desfire.CheckAPDUResponse(response); } @@ -258,7 +254,7 @@ namespace NFC_Test SW2 = 0xBE }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -276,7 +272,7 @@ namespace NFC_Test SW2 = 0xCA }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -294,7 +290,7 @@ namespace NFC_Test SW2 = 0xDE }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -312,7 +308,7 @@ namespace NFC_Test SW2 = 0xF0 }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -336,7 +332,7 @@ namespace NFC_Test 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); byte[] lastblock = desfire.ExtractLastBlock(data, 8); @@ -351,7 +347,7 @@ namespace NFC_Test 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -365,7 +361,7 @@ namespace NFC_Test { byte[] data = null; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -387,7 +383,7 @@ namespace NFC_Test 0x02, 0x03, 0x04, 0x01 }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); byte[] data_left = desfire.RotateLeft(data); @@ -397,7 +393,7 @@ namespace NFC_Test [Test] public void RotateLeft_Null() { - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -419,7 +415,7 @@ namespace NFC_Test 0x04, 0x01, 0x02, 0x03 }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); byte[] data_left = desfire.RotateRight(data); @@ -429,7 +425,7 @@ namespace NFC_Test [Test] public void RotateRight_Null() { - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -456,17 +452,47 @@ namespace NFC_Test 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); byte[] data_c = desfire.Concatenate(data_a, data_b); Assert.AreEqual(expected_data_c, data_c); } + [Test] + public void Concatenate_ABC() + { + byte[] data_a = new byte[] + { + 0x01, 0x02, 0x03, 0x04 + }; + + byte[] data_b = new byte[] + { + 0x05, 0x06, 0x07, 0x08 + }; + + byte[] data_c = new byte[] + { + 0x09, 0xA0, 0xB0, 0xC0 + }; + + byte[] expected_data_d = new byte[] + { + 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xA0, 0xB0, 0xC0 + }; + + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + byte[] data_d = desfire.Concatenate(data_a, data_b, data_c); + + Assert.AreEqual(expected_data_d, data_d); + } + [Test] public void Concatenate_Null() { - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -493,7 +519,7 @@ namespace NFC_Test 0x0F, 0xF0, 0x0F, 0xF0 }; - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); byte[] data_c = desfire.XOR(data_a, data_b); @@ -503,7 +529,7 @@ namespace NFC_Test [Test] public void XOR_null() { - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); Assert.Throws( delegate @@ -515,7 +541,7 @@ namespace NFC_Test [Test] public void GenerateSessionKey_AES() { - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(null); + MIFARE_DESFire desfire = new MIFARE_DESFire(null); byte[] rndA = desfire.ConvertFromHexString("bc14dfde20074617e45a8822f06fdd91"); Console.WriteLine(desfire.ConvertToHexString(rndA)); @@ -537,31 +563,31 @@ namespace NFC_Test { ICard card = Substitute.For(); - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + MIFARE_DESFire desfire = new MIFARE_DESFire(card); APDUResponse response_challenge_request = new APDUResponse() { SW1 = 0x91, SW2 = 0xAF, - Body = desfire.ConvertFromHexString("5D994CE085F24089") + Body = HexConverter.ConvertFromHexString("5D994CE085F24089") }; APDUResponse response_challenge_response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, - Body = desfire.ConvertFromHexString("913C6DED84221C41") + Body = HexConverter.ConvertFromHexString("913C6DED84221C41") }; - byte[] rndA = desfire.ConvertFromHexString("849B36C5F8BF4A09"); - byte[] key = desfire.ConvertFromHexString("00000000000000000000000000000000"); + byte[] rndA = HexConverter.ConvertFromHexString("849B36C5F8BF4A09"); + byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); card.Transmit(Arg.Is(x => x.INS == 0x1A)).Returns(response_challenge_request); card.Transmit(Arg.Is(x => x.INS == 0xAF)).Returns(response_challenge_response); desfire.AuthenticateISO_DES(0x00, key, rndA); - byte[] expected_sessionkey = desfire.ConvertFromHexString("849B36C54FD1B759849B36C54FD1B759"); + byte[] expected_sessionkey = HexConverter.ConvertFromHexString("849B36C54FD1B759849B36C54FD1B759"); byte[] expected_iv = desfire.GenerateEmptyKey(8); Assert.AreEqual(expected_sessionkey, desfire._SessionKey); @@ -573,31 +599,31 @@ namespace NFC_Test { ICard card = Substitute.For(); - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + MIFARE_DESFire desfire = new MIFARE_DESFire(card); APDUResponse response_challenge_request = new APDUResponse() { SW1 = 0x91, SW2 = 0xAF, - Body = desfire.ConvertFromHexString("43a28e28c653df83cd85039714bccb51") + Body = HexConverter.ConvertFromHexString("43a28e28c653df83cd85039714bccb51") }; APDUResponse response_challenge_response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, - Body = desfire.ConvertFromHexString("d8f70a0f9a43f522f775a56f5688592f") + Body = HexConverter.ConvertFromHexString("d8f70a0f9a43f522f775a56f5688592f") }; - byte[] rndA = desfire.ConvertFromHexString("8a8b3c15e576ae3a21c2b18e6aead1f1"); - byte[] key = desfire.ConvertFromHexString("00000000000000000000000000000000"); + byte[] rndA = HexConverter.ConvertFromHexString("8a8b3c15e576ae3a21c2b18e6aead1f1"); + byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); card.Transmit(Arg.Is(x => x.INS == 0xAA)).Returns(response_challenge_request); card.Transmit(Arg.Is(x => x.INS == 0xAF)).Returns(response_challenge_response); desfire.AuthenticateISO_AES(0x00, key, rndA); - byte[] expected_sessionkey = desfire.ConvertFromHexString("8a8b3c15c71d0cf46aead1f148f27703"); + byte[] expected_sessionkey = HexConverter.ConvertFromHexString("8a8b3c15c71d0cf46aead1f148f27703"); byte[] expected_iv = desfire.GenerateEmptyKey(16); Assert.AreEqual(expected_sessionkey, desfire._SessionKey); @@ -609,7 +635,7 @@ namespace NFC_Test { ICard card = Substitute.For(); - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + MIFARE_DESFire desfire = new MIFARE_DESFire(card); APDUResponse response = new APDUResponse() { @@ -617,10 +643,10 @@ namespace NFC_Test SW2 = 0x00 }; - byte[] new_key = desfire.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); + byte[] new_key = HexConverter.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); - byte[] sessionkey = desfire.ConvertFromHexString("2f96515262e1beb0129de2df3e97feb3"); - byte[] iv = desfire.ConvertFromHexString("00000000000000000000000000000000"); + byte[] sessionkey = HexConverter.ConvertFromHexString("2f96515262e1beb0129de2df3e97feb3"); + byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); desfire._SessionKey = sessionkey; desfire._IV = iv; @@ -635,7 +661,7 @@ namespace NFC_Test { ICard card = Substitute.For(); - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + MIFARE_DESFire desfire = new MIFARE_DESFire(card); APDUResponse response = new APDUResponse() { @@ -643,11 +669,11 @@ namespace NFC_Test SW2 = 0x00 }; - byte[] new_key = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12"); - byte[] old_key = desfire.ConvertFromHexString("00000000000000000000000000000000"); + byte[] new_key = HexConverter.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12"); + byte[] old_key = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); - byte[] sessionkey = desfire.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b"); - byte[] iv = desfire.ConvertFromHexString("00000000000000000000000000000000"); + byte[] sessionkey = HexConverter.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b"); + byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); desfire._SessionKey = sessionkey; desfire._IV = iv; @@ -657,5 +683,27 @@ namespace NFC_Test desfire.ChangeOtherKey_AES(0x01, new_key, old_key, 0x10); } #endregion + + #region Configuration Generator + [Test] + public void GenerateFileAccessRights() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.AreEqual(0x1234, desfire.GenerateFileAccessRights(0x01, 0x02, 0x03, 0x04)); + } + + [Test] + public void GenerateFileAccessRights_OutOfRange() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + desfire.GenerateFileAccessRights(0x10, 0x00, 0x00, 0x00); + }); + } + #endregion } } diff --git a/NFC_Test/NamespaceSetUp.cs b/NFC_Test/NamespaceSetUp.cs index 4cb85ab..eb86856 100644 --- a/NFC_Test/NamespaceSetUp.cs +++ b/NFC_Test/NamespaceSetUp.cs @@ -1,14 +1,11 @@ -using log4net; -using log4net.Config; +using log4net.Config; using NUnit.Framework; -using System; namespace NFC_Test { [SetUpFixture] public class NamespaceSetUp - { - private static readonly ILog log = LogManager.GetLogger(typeof(NamespaceSetUp)); + { [OneTimeSetUp] public void OneTimeSetUp() { diff --git a/NFC_Test/OTA.cs b/NFC_Test/OTA.cs index 217efa4..9e1cd36 100644 --- a/NFC_Test/OTA.cs +++ b/NFC_Test/OTA.cs @@ -3,6 +3,8 @@ using NFC; using NFC.Readers.PCSC; using NFC.Mifare_DESFire; using NFC.Mifare_DESFire.Enums; +using System; +using System.Text; namespace NFC_Test { @@ -23,7 +25,7 @@ namespace NFC_Test { card.Connect(); - MIFARE_DESFire_V2 desfire = new MIFARE_DESFire_V2(card); + MIFARE_DESFire desfire = new MIFARE_DESFire(card); desfire.SelectApplication(0x000000); desfire.AuthenticateISO_DES(0x00, desfire.GenerateEmptyKey(16)); @@ -49,6 +51,15 @@ namespace NFC_Test desfire.AuthenticateISO_AES(0x00, key_master); desfire.ChangeOtherKey_AES(0x02, key_2, desfire.GenerateEmptyKey(16), 0x10); + UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00); + desfire.CreateFile_Standard(0x01, FileCommunication.PLAIN, accesRights, 0x100); + + desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes("user@domain.org")); + + byte[] data = desfire.ReadData(0x01, 0, 32); + + Console.WriteLine(Encoding.ASCII.GetString(data)); + transmit_successfully = true; card.Disconnect(); diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index 0e35f12..0951e4b 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -58,275 +58,5 @@ namespace NFC_Test reader.Stop(); reader.CardDiscovered -= handler; } - - [TestCase("ACS ACR122U PICC Interface 0")] - public void GetApplicationIDs(string readerID) - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); - - bool transmit_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - //APDUCommand cmd = desfire.GetApplicationIDs(); - - //APDUResponse response = card.Transmit(cmd); - - //if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) - //{ - // UInt32[] ApplicationIDs = desfire.ConvertApplicationIDs(response); - - // foreach(UInt32 id in ApplicationIDs) - // { - // Console.WriteLine("0x{0:X3}", id); - // } - - // transmit_successfully = true; - //} - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, transmit_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xC0FFEE)] - public void SelectApplication(string readerID, UInt32 applicationID) - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); - - bool transmit_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - //MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - //APDUCommand cmd = desfire.SelectApplication(applicationID); - - //cmd.ToArray(); - - //APDUResponse response = card.Transmit(cmd); - - //if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) - //{ - // transmit_successfully = true; - //} - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, transmit_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)] - public void CreateApplication(string readerID, UInt32 applicationID) - { - //IHardware hardware = new Hardware(); - //IReader reader = hardware.OpenReader(readerID); - - //bool transmit_successfully = false; - - //ReaderEventHandler handler = (sender, card) => - //{ - // card.Connect(); - - // MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - // byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); - // byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.TDES, FileIdentifies.NOTUSED, 0x03); - - // APDUCommand cmd = desfire.CreateApplication(applicationID, keysetting1, keysetting2); - - // Console.WriteLine(cmd.ToArray()); - - // APDUResponse response = card.Transmit(cmd); - - // if (response.StatusWord == NFC.Mifare_DESFire.APDUStatusWords.OK) - // { - // transmit_successfully = true; - // } - - // card.Disconnect(); - //}; - - //reader.CardDiscovered += handler; - //reader.Start(); - - //Assert.AreEqual(true, transmit_successfully); - - //reader.Stop(); - //reader.CardDiscovered -= handler; - } - - [TestCase("ACS ACR122U PICC Interface 0", (UInt32)0xAAFFEE)] - public void DeleteApplication(string readerID, UInt32 applicationID) - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); - - bool transmit_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(0x000000); - desfire.AuthenticateDES(0x00, GenerateDefaultKey(8)); - desfire.DeleteApplication(applicationID); - - transmit_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, transmit_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - public byte[] GenerateDefaultKey(int size) - { - List key = new List(); - for(int i = 0; i < size; i++) - { - key.Add(0); - } - - return key.ToArray(); - } - - /// - /// Used Default PICC Key with PICC authenticate - /// - /// - [TestCase("ACS ACR122U PICC Interface 0")] - public void Authenticate(string readerID) - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); - - bool transmit_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(0x000000); - desfire.AuthenticateDES(0x00, GenerateDefaultKey(8)); - - transmit_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, transmit_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [TestCase("ACS ACR122U PICC Interface 0")] - public void ChangeKey(string readerID) - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); - - bool transmit_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(0xAAFFEE); - desfire.AuthenticateDES(0x00, GenerateDefaultKey(8)); - desfire.ChangeKeyDES(0x00, GenerateDefaultKey(8), new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }); - - transmit_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, transmit_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [TestCase("ACS ACR122U PICC Interface 0")] - public void ChangeKey_Test(string readerID) - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); - - bool transmit_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(0xAAFFEE); - desfire.AuthenticateDES(0x00, GenerateDefaultKey(8)); - - APDUCommand cmd = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = 0xC4, - Data = GenerateDefaultKey(1 + 16 + 4 + 4) - // KEY_NO, KEY, CRC32, PADDING - }; - - card.Transmit(cmd); - - transmit_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, transmit_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } } } diff --git a/NFC_Test/REAL_Windows_CardSetUp.cs b/NFC_Test/REAL_Windows_CardSetUp.cs index 652913b..931a17a 100644 --- a/NFC_Test/REAL_Windows_CardSetUp.cs +++ b/NFC_Test/REAL_Windows_CardSetUp.cs @@ -9,183 +9,183 @@ using System.Text; namespace NFC_Test { - [TestFixture] - public class REAL_Windows_CardSetUp - { - public static UInt32 FabAccessAID = 0x001100; - public static string CardReaderID = "ACS ACR122U PICC Interface 0"; - public static byte[] PICC_MasterKey = new byte[] - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; + //[TestFixture] + //public class REAL_Windows_CardSetUp + //{ + // public static UInt32 FabAccessAID = 0x001100; + // public static string CardReaderID = "ACS ACR122U PICC Interface 0"; + // public static byte[] PICC_MasterKey = new byte[] + // { + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + // }; - public static byte[] APP_MasterKey = new byte[] - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; + // public static byte[] APP_MasterKey = new byte[] + // { + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + // }; - public static byte[] APP_Key_1 = new byte[] - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; + // public static byte[] APP_Key_1 = new byte[] + // { + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + // }; - public static byte[] APP_Key_2 = new byte[] - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; + // public static byte[] APP_Key_2 = new byte[] + // { + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + // }; - public static byte[] Empty_Key = new byte[] - { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; + // public static byte[] Empty_Key = new byte[] + // { + // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + // }; - public static byte FabAccessIdentFileID = 0x01; - public static string UserDomain = "user1@fabaccess.org"; + // public static byte FabAccessIdentFileID = 0x01; + // public static string UserDomain = "user1@fabaccess.org"; - [Test] - public void ResetCard() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(CardReaderID); + // [Test] + // public void ResetCard() + // { + // IHardware hardware = new Hardware(); + // IReader reader = hardware.OpenReader(CardReaderID); - bool connected_successfully = false; + // bool connected_successfully = false; - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); + // ReaderEventHandler handler = (sender, card) => + // { + // card.Connect(); - MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); + // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - mifareDESFire.AuthenticateDES(0x01, PICC_MasterKey); + // mifareDESFire.AuthenticateISO_DES(0x01, PICC_MasterKey); - mifareDESFire.Format(); + // mifareDESFire.Format(); - connected_successfully = true; + // connected_successfully = true; - card.Disconnect(); - }; + // card.Disconnect(); + // }; - reader.CardDiscovered += handler; - reader.Start(); + // reader.CardDiscovered += handler; + // reader.Start(); - Assert.AreEqual(true, connected_successfully); + // Assert.AreEqual(true, connected_successfully); - reader.Stop(); - reader.CardDiscovered -= handler; - } + // reader.Stop(); + // reader.CardDiscovered -= handler; + // } - [Test] - public void ProvisionCard() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(CardReaderID); + // [Test] + // public void ProvisionCard() + // { + // IHardware hardware = new Hardware(); + // IReader reader = hardware.OpenReader(CardReaderID); - bool connected_successfully = false; + // bool connected_successfully = false; - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); + // ReaderEventHandler handler = (sender, card) => + // { + // card.Connect(); - MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); + // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - mifareDESFire.AuthenticateDES(0x01, APP_MasterKey); - mifareDESFire.CreateApplication(FabAccessAID); - mifareDESFire.SelectApplication(FabAccessAID); + // mifareDESFire.AuthenticateISO_DES(0x01, APP_MasterKey); + // mifareDESFire.CreateApplication(FabAccessAID); + // mifareDESFire.SelectApplication(FabAccessAID); - mifareDESFire.AuthenticateDES(0x00, Empty_Key); - mifareDESFire.ChangeApplicationMasterKey(APP_MasterKey); + // mifareDESFire.AuthenticateDES(0x00, Empty_Key); + // mifareDESFire.ChangeApplicationMasterKey(APP_MasterKey); - mifareDESFire.AuthenticateDES(0x00, APP_MasterKey); - mifareDESFire.ChangeApplicationKey(0x01, APP_Key_1); + // mifareDESFire.AuthenticateDES(0x00, APP_MasterKey); + // mifareDESFire.ChangeApplicationKey(0x01, APP_Key_1); - connected_successfully = true; + // connected_successfully = true; - card.Disconnect(); - }; + // card.Disconnect(); + // }; - reader.CardDiscovered += handler; - reader.Start(); + // reader.CardDiscovered += handler; + // reader.Start(); - Assert.AreEqual(true, connected_successfully); + // Assert.AreEqual(true, connected_successfully); - reader.Stop(); - reader.CardDiscovered -= handler; - } + // reader.Stop(); + // reader.CardDiscovered -= handler; + // } - [Test] - public void SetUpUserCard() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(CardReaderID); + // [Test] + // public void SetUpUserCard() + // { + // IHardware hardware = new Hardware(); + // IReader reader = hardware.OpenReader(CardReaderID); - bool connected_successfully = false; + // bool connected_successfully = false; - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); + // ReaderEventHandler handler = (sender, card) => + // { + // card.Connect(); - MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); + // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - mifareDESFire.SelectApplication(FabAccessAID); - mifareDESFire.AuthenticateDES(0x00, Empty_Key); - UInt16 fileAccessRight = mifareDESFire.GenerateFileAccessRight(AccessRights.FREE, 0x00, 0x00, 0x00); - mifareDESFire.CreateFile(FabAccessIdentFileID, FileCommunication.PLAIN, fileAccessRight, (UInt32)0x90); + // mifareDESFire.SelectApplication(FabAccessAID); + // mifareDESFire.AuthenticateDES(0x00, Empty_Key); + // UInt16 fileAccessRight = mifareDESFire.GenerateFileAccessRight(AccessRights.FREE, 0x00, 0x00, 0x00); + // mifareDESFire.CreateFile(FabAccessIdentFileID, FileCommunication.PLAIN, fileAccessRight, (UInt32)0x90); - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + // System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); - mifareDESFire.WirteData(FabAccessIdentFileID, 0x00000000, 0x00000000, enc.GetBytes(UserDomain)); + // mifareDESFire.WirteData(FabAccessIdentFileID, 0x00000000, 0x00000000, enc.GetBytes(UserDomain)); - connected_successfully = true; + // connected_successfully = true; - card.Disconnect(); - }; + // card.Disconnect(); + // }; - reader.CardDiscovered += handler; - reader.Start(); + // reader.CardDiscovered += handler; + // reader.Start(); - Assert.AreEqual(true, connected_successfully); + // Assert.AreEqual(true, connected_successfully); - reader.Stop(); - reader.CardDiscovered -= handler; - } + // reader.Stop(); + // reader.CardDiscovered -= handler; + // } - [Test] - public void AuthenticateCard() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(CardReaderID); + // [Test] + // public void AuthenticateCard() + // { + // IHardware hardware = new Hardware(); + // IReader reader = hardware.OpenReader(CardReaderID); - bool connected_successfully = false; + // bool connected_successfully = false; - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); + // ReaderEventHandler handler = (sender, card) => + // { + // card.Connect(); - MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); + // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - mifareDESFire.SelectApplication(FabAccessAID); - byte[] filedata = mifareDESFire.ReadData(FabAccessIdentFileID, 0x00000000, 0x00000000); + // mifareDESFire.SelectApplication(FabAccessAID); + // byte[] filedata = mifareDESFire.ReadData(FabAccessIdentFileID, 0x00000000, 0x00000000); - System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); - string userdomain = enc.GetString(filedata); + // System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + // string userdomain = enc.GetString(filedata); - Console.WriteLine(userdomain); + // Console.WriteLine(userdomain); - mifareDESFire.AuthenticateDES(0x01, APP_Key_1); + // mifareDESFire.AuthenticateDES(0x01, APP_Key_1); - connected_successfully = true; + // connected_successfully = true; - card.Disconnect(); - }; + // card.Disconnect(); + // }; - reader.CardDiscovered += handler; - reader.Start(); + // reader.CardDiscovered += handler; + // reader.Start(); - Assert.AreEqual(true, connected_successfully); + // Assert.AreEqual(true, connected_successfully); - reader.Stop(); - reader.CardDiscovered -= handler; - } - } + // reader.Stop(); + // reader.CardDiscovered -= handler; + // } + //} } From 4004413af76f9e3928b44085911c8bd7a916a2a7 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Wed, 4 Nov 2020 00:41:19 +0100 Subject: [PATCH 16/21] BackUp --- NFC/Crypto/CipherKey.cs | 13 +- NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs | 27 +- NFC_Test/FabAccess_OTA.cs | 131 ++++++++ NFC_Test/HexConverter_Test.cs | 34 ++ .../NXP MIFARE DESFire/Command_Card_Test.cs | 308 ++++++++++++++++++ NFC_Test/NXP MIFARE DESFire/Command_Test.cs | 10 + NFC_Test/OTA.cs | 77 ----- 7 files changed, 517 insertions(+), 83 deletions(-) create mode 100644 NFC_Test/FabAccess_OTA.cs create mode 100644 NFC_Test/HexConverter_Test.cs create mode 100644 NFC_Test/NXP MIFARE DESFire/Command_Card_Test.cs create mode 100644 NFC_Test/NXP MIFARE DESFire/Command_Test.cs delete mode 100644 NFC_Test/OTA.cs diff --git a/NFC/Crypto/CipherKey.cs b/NFC/Crypto/CipherKey.cs index 519ab2a..3280381 100644 --- a/NFC/Crypto/CipherKey.cs +++ b/NFC/Crypto/CipherKey.cs @@ -39,6 +39,17 @@ namespace NFC.Crypto } } + /// + /// Creates Key from String + /// + /// Key + /// Cipher for Key + /// Version of Key + public CipherKey(string key, CipherType cipher, byte keyVersion) : this(HexConverter.ConvertFromHexString(key), cipher, keyVersion) + { + + } + /// /// Generates Empty Key /// @@ -122,7 +133,7 @@ namespace NFC.Crypto switch (cipher) { case CipherType.TDES: - return 8; + return 16; case CipherType.TDES_2K: return 16; case CipherType.TDES_3K: diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs index 149d04e..5b053c3 100644 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs @@ -7,6 +7,7 @@ using PCSC.Iso7816; using System; using System.Collections.Generic; using System.Linq; +using System.Reflection; namespace NFC.Mifare_DESFire { @@ -879,16 +880,32 @@ namespace NFC.Mifare_DESFire 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())); + APDUResponse response; + List read_data = new List(); - CheckAPDUResponse(response); + 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) + { + read_data.AddRange(response.Body); + } + else + { + CheckAPDUResponse(response); + } + + cmd_ReadData.INS = 0xAF; + } while (response.SW1 == 0x91 && response.SW2 == 0xAF); + _Log.Debug("End ReadData"); - return response.Body; + return read_data.ToArray(); } /// diff --git a/NFC_Test/FabAccess_OTA.cs b/NFC_Test/FabAccess_OTA.cs new file mode 100644 index 0000000..80e580b --- /dev/null +++ b/NFC_Test/FabAccess_OTA.cs @@ -0,0 +1,131 @@ +using NUnit.Framework; +using NFC; +using NFC.Readers.PCSC; +using NFC.Mifare_DESFire; +using NFC.Mifare_DESFire.Enums; +using System; +using System.Text; +using NFC.Crypto; +using System.Runtime.CompilerServices; +using System.Drawing.Printing; + +namespace NFC_Test +{ + [TestFixture, Explicit] + public class FabAccess_OTA + { + private string _ReaderID = "ACS ACR122U PICC Interface 0"; + private UInt32 _FabAccess_AID = 0x2A472D; + private byte _FabAccess_FID = 0x01; + private UInt32 _FabAccess_FSize = 0xF0; + + private CipherKey _FabAccess_Card_MasterKey = new CipherKey("294A404E635266556A576E5A72347537", CipherType.AES, 0x10); + private CipherKey _FabAccess_Application_MasterKey = new CipherKey("50645367566B59703273357638792F42", CipherType.AES, 0x10); + private CipherKey _FabAccess_Application_AuthKey = new CipherKey("6D5A7134743677397A24432646294A40", CipherType.AES, 0x10); + + private string _FabAccess_UserDomain = "thejoklla@fvm.fab-access.org"; + private string _FabAccess_Domain = "fvm.fab-access.org"; + + private CipherKey _Default_DESKey = new CipherKey(CipherType.TDES); + private CipherKey _Default_AESKey = new CipherKey(CipherType.AES); + + [Test] + public void Init_EmptyCard() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(_ReaderID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + desfire.AuthenticateISO_DES(0x00, _Default_DESKey._Key); + desfire.Format(); + + desfire.AuthenticateISO_DES(0x00, _Default_DESKey._Key); + + byte keySetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + byte keySetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x02); + desfire.CreateApplication(_FabAccess_AID, keySetting1, keySetting2); + + desfire.SelectApplication(_FabAccess_AID); + desfire.AuthenticateISO_AES(0x00, _Default_DESKey._Key); + + desfire.ChangeKey_AES(0x00, _FabAccess_Application_MasterKey._Key, _FabAccess_Application_MasterKey._KeyVersion); + + desfire.AuthenticateISO_AES(0x00, _FabAccess_Application_MasterKey._Key); + desfire.ChangeOtherKey_AES(0x01, _FabAccess_Application_AuthKey._Key, _Default_AESKey._Key, _FabAccess_Application_AuthKey._KeyVersion); + + UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00); + desfire.CreateFile_Standard(_FabAccess_FID, FileCommunication.PLAIN, accesRights, _FabAccess_FSize); + + desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes(_FabAccess_UserDomain)); + + transmit_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test] + public void Authenticate() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(_ReaderID); + + bool transmit_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(_FabAccess_AID); + byte[] card_data = desfire.ReadData(_FabAccess_FID, 0x00, _FabAccess_FSize); + string userdomain = Encoding.ASCII.GetString(card_data).Replace("\u0000", ""); + + string domain = userdomain.Split('@')[1]; + if(domain != _FabAccess_Domain) + { + throw new Exception("Incorrect Domain"); + } + + desfire.SelectApplication(_FabAccess_AID); + desfire.AuthenticateISO_AES(0x01, _FabAccess_Application_AuthKey._Key); + + byte[] card_data_auth = desfire.ReadData(_FabAccess_FID, 0x00, _FabAccess_FSize); + string userdomain_auth = Encoding.ASCII.GetString(card_data).Replace("\u0000", ""); + if(card_data_auth != card_data) + { + throw new Exception("Authentication failed"); + } + + transmit_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, transmit_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + } +} diff --git a/NFC_Test/HexConverter_Test.cs b/NFC_Test/HexConverter_Test.cs new file mode 100644 index 0000000..fba4be6 --- /dev/null +++ b/NFC_Test/HexConverter_Test.cs @@ -0,0 +1,34 @@ +using NFC; +using NUnit.Framework; + +namespace NFC_Test +{ + public class HexConverter_Test + { + [Test] + public void ConvertFromHexString() + { + string s = "0180ff0a"; + + byte[] expected_s = + { + 0x01, 0x80, 0xFF, 0x0A + }; + + Assert.AreEqual(expected_s, HexConverter.ConvertFromHexString(s)); + } + + [Test] + public void ConvertToHexString() + { + byte[] s = + { + 0x01, 0x80, 0xFF, 0x0A + }; + + string expected_s = "0180ff0a"; + + Assert.AreEqual(expected_s, HexConverter.ConvertToHexString(s)); + } + } +} diff --git a/NFC_Test/NXP MIFARE DESFire/Command_Card_Test.cs b/NFC_Test/NXP MIFARE DESFire/Command_Card_Test.cs new file mode 100644 index 0000000..92e2c21 --- /dev/null +++ b/NFC_Test/NXP MIFARE DESFire/Command_Card_Test.cs @@ -0,0 +1,308 @@ +using NFC; +using NFC.Crypto; +using NFC.Mifare_DESFire; +using NFC.Readers.PCSC; +using NUnit.Framework; +using NUnit.Framework.Constraints; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC_Test.NXP_MIFARE_DESFire +{ + /// + /// Test all DESFire Commands with empty Card + /// + [Description("Test with real DESFire Card")] + [Explicit] + public class Command_Card_Test + { + public readonly string ReaderID = ""; + public readonly UInt32 AID = 0xAAFFEE; + public readonly string AES_Key_Master = "25432A462D4A614E645267556B587032"; + public readonly string AES_Key_1 = "50645367566B59703373367638792F42"; + + /// + /// Get ReaderIDs form PC/SC API + /// + [Test] + public void GetReaderIDs() + { + IHardware hardware = new Hardware(); + string[] readers = hardware.GetReaders(); + + Console.WriteLine("Readers detected: {0}", readers.Length); + + if (readers.Length > 0) + { + Console.WriteLine("List of ReaderIDs:"); + foreach (string readerID in readers) + { + Console.WriteLine("{0}", readerID); + } + } + } + + [Test] + public void Connect() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool connected_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + connected_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, connected_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test] + public void Format() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.Format(); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test] + public void SelectApplication() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test] + public void Authenticate_DES() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + + [Test] + public void CreateApplication() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + byte keysetting1 = desfire.GenerateKeySetting1(NFC.Mifare_DESFire.Enums.ChangeApplicationKey.ALLKEYS, NFC.Mifare_DESFire.Enums.ChangeMasterKeySettings.WITHMASTERKEY, NFC.Mifare_DESFire.Enums.CreateDeleteFile.NOKEY, NFC.Mifare_DESFire.Enums.FileDirectoryAccess.NOKEY, NFC.Mifare_DESFire.Enums.ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(NFC.Mifare_DESFire.Enums.CryptoOperationsType.AES, NFC.Mifare_DESFire.Enums.FileIdentifies.NOTUSED, 2); + + desfire.CreateApplication(AID, keysetting1, keysetting2); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test] + public void Authenticate_AES() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(AID); + + CipherKey key = new CipherKey(CipherType.AES); + desfire.AuthenticateISO_AES(0x00, key._Key); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test] + public void ChangeApplicationMasterKey() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(AID); + + CipherKey key_default = new CipherKey(CipherType.AES); + desfire.AuthenticateISO_AES(0x00, key_default._Key); + + CipherKey key = new CipherKey(AES_Key_Master, CipherType.AES, 0x10); + desfire.ChangeKey_AES(0x00, key._Key, key._KeyVersion); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test] + public void ChangeApplicationKey_1() + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(AID); + + CipherKey key_master = new CipherKey(AES_Key_Master, CipherType.AES, 0x10); + desfire.AuthenticateISO_AES(0x00, key_master._Key); + + CipherKey key_old = new CipherKey(AES_Key_1, CipherType.AES, 0x10); + CipherKey key_new = new CipherKey(AES_Key_1, CipherType.AES, 0x10); + desfire.ChangeOtherKey_AES(0x01, key_new._Key, key_old._Key, key_new._KeyVersion); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + } +} diff --git a/NFC_Test/NXP MIFARE DESFire/Command_Test.cs b/NFC_Test/NXP MIFARE DESFire/Command_Test.cs new file mode 100644 index 0000000..f154e3f --- /dev/null +++ b/NFC_Test/NXP MIFARE DESFire/Command_Test.cs @@ -0,0 +1,10 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC_Test.NXP_MIFARE_DESFire +{ + class Command_Test + { + } +} diff --git a/NFC_Test/OTA.cs b/NFC_Test/OTA.cs deleted file mode 100644 index 9e1cd36..0000000 --- a/NFC_Test/OTA.cs +++ /dev/null @@ -1,77 +0,0 @@ -using NUnit.Framework; -using NFC; -using NFC.Readers.PCSC; -using NFC.Mifare_DESFire; -using NFC.Mifare_DESFire.Enums; -using System; -using System.Text; - -namespace NFC_Test -{ - [TestFixture, Explicit] - public class OTA - { - private string _ReaderID = "ACS ACR122U PICC Interface 0"; - - [Test] - public void Init() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(_ReaderID); - - bool transmit_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(0x000000); - desfire.AuthenticateISO_DES(0x00, desfire.GenerateEmptyKey(16)); - desfire.Format(); - - desfire.AuthenticateISO_DES(0x00, desfire.GenerateEmptyKey(16)); - - byte keySetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.NOKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); - byte keySetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x03); - desfire.CreateApplication(0xC0FFEE, keySetting1, keySetting2); - - desfire.SelectApplication(0xC0FFEE); - desfire.AuthenticateISO_AES(0x00, desfire.GenerateEmptyKey(16)); - - byte[] key_master = desfire.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); - byte[] key_1 = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12"); - byte[] key_2 = desfire.ConvertFromHexString("77611d170c449df6f294c48581ab315d"); - desfire.ChangeKey_AES(0x00, key_master, 0x10); - - desfire.AuthenticateISO_AES(0x00, key_master); - desfire.ChangeOtherKey_AES(0x01, key_1, desfire.GenerateEmptyKey(16), 0x10); - - desfire.AuthenticateISO_AES(0x00, key_master); - desfire.ChangeOtherKey_AES(0x02, key_2, desfire.GenerateEmptyKey(16), 0x10); - - UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00); - desfire.CreateFile_Standard(0x01, FileCommunication.PLAIN, accesRights, 0x100); - - desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes("user@domain.org")); - - byte[] data = desfire.ReadData(0x01, 0, 32); - - Console.WriteLine(Encoding.ASCII.GetString(data)); - - transmit_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, transmit_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - } -} From 872aeccee70a003c8588ccea0cdcb19220b20689 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Fri, 6 Nov 2020 21:36:37 +0100 Subject: [PATCH 17/21] BackUp --- .../Borepin.Android/Borepin.Android.csproj | 2 +- .../Resources/Resource.designer.cs | 539 +++++++++--------- Borepin/Borepin.GTK/Borepin.GTK.csproj | 22 +- Borepin/Borepin.GTK/app.config | 2 +- Borepin/Borepin.GTK/packages.config | 6 +- Borepin/Borepin.UWP/Borepin.UWP.csproj | 2 +- Borepin/Borepin.iOS/Borepin.iOS.csproj | 2 +- Borepin/Borepin.macOS/Borepin.macOS.csproj | 51 +- Borepin/Borepin.macOS/packages.config | 2 +- Borepin/Borepin/Borepin.csproj | 2 +- NFC/NFC.csproj | 4 +- NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs | 230 ++++++-- NFC_Test/FabAccess_OTA.cs | 4 +- NFC_Test/REAL_Windows.cs | 67 +++ 14 files changed, 597 insertions(+), 338 deletions(-) diff --git a/Borepin/Borepin.Android/Borepin.Android.csproj b/Borepin/Borepin.Android/Borepin.Android.csproj index afcad44..70d8c2f 100644 --- a/Borepin/Borepin.Android/Borepin.Android.csproj +++ b/Borepin/Borepin.Android/Borepin.Android.csproj @@ -53,7 +53,7 @@ - + diff --git a/Borepin/Borepin.Android/Resources/Resource.designer.cs b/Borepin/Borepin.Android/Resources/Resource.designer.cs index 1bc81a8..9ef43e5 100644 --- a/Borepin/Borepin.Android/Resources/Resource.designer.cs +++ b/Borepin/Borepin.Android/Resources/Resource.designer.cs @@ -575,6 +575,7 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimAnimationDuration = global::Borepin.Droid.Resource.Attribute.scrimAnimationDuration; global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimBackground = global::Borepin.Droid.Resource.Attribute.scrimBackground; global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimVisibleHeightTrigger = global::Borepin.Droid.Resource.Attribute.scrimVisibleHeightTrigger; + global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrollViewStyle = global::Borepin.Droid.Resource.Attribute.scrollViewStyle; global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchHintIcon = global::Borepin.Droid.Resource.Attribute.searchHintIcon; global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchIcon = global::Borepin.Droid.Resource.Attribute.searchIcon; global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchViewStyle = global::Borepin.Droid.Resource.Attribute.searchViewStyle; @@ -1717,7 +1718,6 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Android.Resource.Style.CardView = global::Borepin.Droid.Resource.Style.CardView; global::Xamarin.Forms.Platform.Android.Resource.Style.CardView_Dark = global::Borepin.Droid.Resource.Style.CardView_Dark; global::Xamarin.Forms.Platform.Android.Resource.Style.CardView_Light = global::Borepin.Droid.Resource.Style.CardView_Light; - global::Xamarin.Forms.Platform.Android.Resource.Style.collectionViewScrollBars = global::Borepin.Droid.Resource.Style.collectionViewScrollBars; global::Xamarin.Forms.Platform.Android.Resource.Style.collectionViewTheme = global::Borepin.Droid.Resource.Style.collectionViewTheme; global::Xamarin.Forms.Platform.Android.Resource.Style.MainTheme = global::Borepin.Droid.Resource.Style.MainTheme; global::Xamarin.Forms.Platform.Android.Resource.Style.MainTheme_Base = global::Borepin.Droid.Resource.Style.MainTheme_Base; @@ -1752,6 +1752,8 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text = global::Borepin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text; global::Xamarin.Forms.Platform.Android.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton = global::Borepin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton; global::Xamarin.Forms.Platform.Android.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = global::Borepin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow; + global::Xamarin.Forms.Platform.Android.Resource.Style.scrollViewScrollBars = global::Borepin.Droid.Resource.Style.scrollViewScrollBars; + global::Xamarin.Forms.Platform.Android.Resource.Style.scrollViewTheme = global::Borepin.Droid.Resource.Style.scrollViewTheme; global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat; global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Body1 = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat_Body1; global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Body2 = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat_Body2; @@ -2601,6 +2603,8 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground = global::Borepin.Droid.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground; global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollingViewBehavior_Layout = global::Borepin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout; global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop = global::Borepin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollViewRendererTheme = global::Borepin.Droid.Resource.Styleable.ScrollViewRendererTheme; + global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle = global::Borepin.Droid.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle; global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView = global::Borepin.Droid.Resource.Styleable.SearchView; global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_focusable = global::Borepin.Droid.Resource.Styleable.SearchView_android_focusable; global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_imeOptions = global::Borepin.Droid.Resource.Styleable.SearchView_android_imeOptions; @@ -3145,6 +3149,7 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Resource.Attribute.scrimAnimationDuration = global::Borepin.Droid.Resource.Attribute.scrimAnimationDuration; global::Xamarin.Forms.Platform.Resource.Attribute.scrimBackground = global::Borepin.Droid.Resource.Attribute.scrimBackground; global::Xamarin.Forms.Platform.Resource.Attribute.scrimVisibleHeightTrigger = global::Borepin.Droid.Resource.Attribute.scrimVisibleHeightTrigger; + global::Xamarin.Forms.Platform.Resource.Attribute.scrollViewStyle = global::Borepin.Droid.Resource.Attribute.scrollViewStyle; global::Xamarin.Forms.Platform.Resource.Attribute.searchHintIcon = global::Borepin.Droid.Resource.Attribute.searchHintIcon; global::Xamarin.Forms.Platform.Resource.Attribute.searchIcon = global::Borepin.Droid.Resource.Attribute.searchIcon; global::Xamarin.Forms.Platform.Resource.Attribute.searchViewStyle = global::Borepin.Droid.Resource.Attribute.searchViewStyle; @@ -4287,7 +4292,6 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Resource.Style.CardView = global::Borepin.Droid.Resource.Style.CardView; global::Xamarin.Forms.Platform.Resource.Style.CardView_Dark = global::Borepin.Droid.Resource.Style.CardView_Dark; global::Xamarin.Forms.Platform.Resource.Style.CardView_Light = global::Borepin.Droid.Resource.Style.CardView_Light; - global::Xamarin.Forms.Platform.Resource.Style.collectionViewScrollBars = global::Borepin.Droid.Resource.Style.collectionViewScrollBars; global::Xamarin.Forms.Platform.Resource.Style.collectionViewTheme = global::Borepin.Droid.Resource.Style.collectionViewTheme; global::Xamarin.Forms.Platform.Resource.Style.MainTheme = global::Borepin.Droid.Resource.Style.MainTheme; global::Xamarin.Forms.Platform.Resource.Style.MainTheme_Base = global::Borepin.Droid.Resource.Style.MainTheme_Base; @@ -4322,6 +4326,8 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text = global::Borepin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text; global::Xamarin.Forms.Platform.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton = global::Borepin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton; global::Xamarin.Forms.Platform.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = global::Borepin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow; + global::Xamarin.Forms.Platform.Resource.Style.scrollViewScrollBars = global::Borepin.Droid.Resource.Style.scrollViewScrollBars; + global::Xamarin.Forms.Platform.Resource.Style.scrollViewTheme = global::Borepin.Droid.Resource.Style.scrollViewTheme; global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat; global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Body1 = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat_Body1; global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Body2 = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat_Body2; @@ -5171,6 +5177,8 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground = global::Borepin.Droid.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground; global::Xamarin.Forms.Platform.Resource.Styleable.ScrollingViewBehavior_Layout = global::Borepin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout; global::Xamarin.Forms.Platform.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop = global::Borepin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop; + global::Xamarin.Forms.Platform.Resource.Styleable.ScrollViewRendererTheme = global::Borepin.Droid.Resource.Styleable.ScrollViewRendererTheme; + global::Xamarin.Forms.Platform.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle = global::Borepin.Droid.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle; global::Xamarin.Forms.Platform.Resource.Styleable.SearchView = global::Borepin.Droid.Resource.Styleable.SearchView; global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_focusable = global::Borepin.Droid.Resource.Styleable.SearchView_android_focusable; global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_imeOptions = global::Borepin.Droid.Resource.Styleable.SearchView_android_imeOptions; @@ -6483,424 +6491,427 @@ namespace Borepin.Droid public const int scrimVisibleHeightTrigger = 2130903377; // aapt resource value: 0x7F030152 - public const int searchHintIcon = 2130903378; + public const int scrollViewStyle = 2130903378; // aapt resource value: 0x7F030153 - public const int searchIcon = 2130903379; + public const int searchHintIcon = 2130903379; // aapt resource value: 0x7F030154 - public const int searchViewStyle = 2130903380; + public const int searchIcon = 2130903380; // aapt resource value: 0x7F030155 - public const int seekBarStyle = 2130903381; + public const int searchViewStyle = 2130903381; // aapt resource value: 0x7F030156 - public const int selectableItemBackground = 2130903382; + public const int seekBarStyle = 2130903382; // aapt resource value: 0x7F030157 - public const int selectableItemBackgroundBorderless = 2130903383; + public const int selectableItemBackground = 2130903383; // aapt resource value: 0x7F030158 - public const int showAsAction = 2130903384; + public const int selectableItemBackgroundBorderless = 2130903384; // aapt resource value: 0x7F030159 - public const int showDividers = 2130903385; + public const int showAsAction = 2130903385; // aapt resource value: 0x7F03015A - public const int showMotionSpec = 2130903386; + public const int showDividers = 2130903386; // aapt resource value: 0x7F03015B - public const int showText = 2130903387; + public const int showMotionSpec = 2130903387; // aapt resource value: 0x7F03015C - public const int showTitle = 2130903388; + public const int showText = 2130903388; // aapt resource value: 0x7F03015D - public const int singleChoiceItemLayout = 2130903389; + public const int showTitle = 2130903389; // aapt resource value: 0x7F03015E - public const int singleLine = 2130903390; + public const int singleChoiceItemLayout = 2130903390; // aapt resource value: 0x7F03015F - public const int singleSelection = 2130903391; + public const int singleLine = 2130903391; // aapt resource value: 0x7F030160 - public const int snackbarButtonStyle = 2130903392; + public const int singleSelection = 2130903392; // aapt resource value: 0x7F030161 - public const int snackbarStyle = 2130903393; + public const int snackbarButtonStyle = 2130903393; // aapt resource value: 0x7F030162 - public const int spanCount = 2130903394; + public const int snackbarStyle = 2130903394; // aapt resource value: 0x7F030163 - public const int spinBars = 2130903395; + public const int spanCount = 2130903395; // aapt resource value: 0x7F030164 - public const int spinnerDropDownItemStyle = 2130903396; + public const int spinBars = 2130903396; // aapt resource value: 0x7F030165 - public const int spinnerStyle = 2130903397; + public const int spinnerDropDownItemStyle = 2130903397; // aapt resource value: 0x7F030166 - public const int splitTrack = 2130903398; + public const int spinnerStyle = 2130903398; // aapt resource value: 0x7F030167 - public const int srcCompat = 2130903399; + public const int splitTrack = 2130903399; // aapt resource value: 0x7F030168 - public const int stackFromEnd = 2130903400; + public const int srcCompat = 2130903400; // aapt resource value: 0x7F030169 - public const int state_above_anchor = 2130903401; + public const int stackFromEnd = 2130903401; // aapt resource value: 0x7F03016A - public const int state_collapsed = 2130903402; + public const int state_above_anchor = 2130903402; // aapt resource value: 0x7F03016B - public const int state_collapsible = 2130903403; + public const int state_collapsed = 2130903403; // aapt resource value: 0x7F03016C - public const int state_liftable = 2130903404; + public const int state_collapsible = 2130903404; // aapt resource value: 0x7F03016D - public const int state_lifted = 2130903405; + public const int state_liftable = 2130903405; // aapt resource value: 0x7F03016E - public const int statusBarBackground = 2130903406; + public const int state_lifted = 2130903406; // aapt resource value: 0x7F03016F - public const int statusBarScrim = 2130903407; + public const int statusBarBackground = 2130903407; // aapt resource value: 0x7F030170 - public const int strokeColor = 2130903408; + public const int statusBarScrim = 2130903408; // aapt resource value: 0x7F030171 - public const int strokeWidth = 2130903409; + public const int strokeColor = 2130903409; // aapt resource value: 0x7F030172 - public const int subMenuArrow = 2130903410; + public const int strokeWidth = 2130903410; // aapt resource value: 0x7F030173 - public const int submitBackground = 2130903411; + public const int subMenuArrow = 2130903411; // aapt resource value: 0x7F030174 - public const int subtitle = 2130903412; + public const int submitBackground = 2130903412; // aapt resource value: 0x7F030175 - public const int subtitleTextAppearance = 2130903413; + public const int subtitle = 2130903413; // aapt resource value: 0x7F030176 - public const int subtitleTextColor = 2130903414; + public const int subtitleTextAppearance = 2130903414; // aapt resource value: 0x7F030177 - public const int subtitleTextStyle = 2130903415; + public const int subtitleTextColor = 2130903415; // aapt resource value: 0x7F030178 - public const int suggestionRowLayout = 2130903416; + public const int subtitleTextStyle = 2130903416; // aapt resource value: 0x7F030179 - public const int switchMinWidth = 2130903417; + public const int suggestionRowLayout = 2130903417; // aapt resource value: 0x7F03017A - public const int switchPadding = 2130903418; + public const int switchMinWidth = 2130903418; // aapt resource value: 0x7F03017B - public const int switchStyle = 2130903419; + public const int switchPadding = 2130903419; // aapt resource value: 0x7F03017C - public const int switchTextAppearance = 2130903420; + public const int switchStyle = 2130903420; // aapt resource value: 0x7F03017D - public const int tabBackground = 2130903421; + public const int switchTextAppearance = 2130903421; // aapt resource value: 0x7F03017E - public const int tabContentStart = 2130903422; + public const int tabBackground = 2130903422; // aapt resource value: 0x7F03017F - public const int tabGravity = 2130903423; + public const int tabContentStart = 2130903423; // aapt resource value: 0x7F030180 - public const int tabIconTint = 2130903424; + public const int tabGravity = 2130903424; // aapt resource value: 0x7F030181 - public const int tabIconTintMode = 2130903425; + public const int tabIconTint = 2130903425; // aapt resource value: 0x7F030182 - public const int tabIndicator = 2130903426; + public const int tabIconTintMode = 2130903426; // aapt resource value: 0x7F030183 - public const int tabIndicatorAnimationDuration = 2130903427; + public const int tabIndicator = 2130903427; // aapt resource value: 0x7F030184 - public const int tabIndicatorColor = 2130903428; + public const int tabIndicatorAnimationDuration = 2130903428; // aapt resource value: 0x7F030185 - public const int tabIndicatorFullWidth = 2130903429; + public const int tabIndicatorColor = 2130903429; // aapt resource value: 0x7F030186 - public const int tabIndicatorGravity = 2130903430; + public const int tabIndicatorFullWidth = 2130903430; // aapt resource value: 0x7F030187 - public const int tabIndicatorHeight = 2130903431; + public const int tabIndicatorGravity = 2130903431; // aapt resource value: 0x7F030188 - public const int tabInlineLabel = 2130903432; + public const int tabIndicatorHeight = 2130903432; // aapt resource value: 0x7F030189 - public const int tabMaxWidth = 2130903433; + public const int tabInlineLabel = 2130903433; // aapt resource value: 0x7F03018A - public const int tabMinWidth = 2130903434; + public const int tabMaxWidth = 2130903434; // aapt resource value: 0x7F03018B - public const int tabMode = 2130903435; + public const int tabMinWidth = 2130903435; // aapt resource value: 0x7F03018C - public const int tabPadding = 2130903436; + public const int tabMode = 2130903436; // aapt resource value: 0x7F03018D - public const int tabPaddingBottom = 2130903437; + public const int tabPadding = 2130903437; // aapt resource value: 0x7F03018E - public const int tabPaddingEnd = 2130903438; + public const int tabPaddingBottom = 2130903438; // aapt resource value: 0x7F03018F - public const int tabPaddingStart = 2130903439; + public const int tabPaddingEnd = 2130903439; // aapt resource value: 0x7F030190 - public const int tabPaddingTop = 2130903440; + public const int tabPaddingStart = 2130903440; // aapt resource value: 0x7F030191 - public const int tabRippleColor = 2130903441; + public const int tabPaddingTop = 2130903441; // aapt resource value: 0x7F030192 - public const int tabSelectedTextColor = 2130903442; + public const int tabRippleColor = 2130903442; // aapt resource value: 0x7F030193 - public const int tabStyle = 2130903443; + public const int tabSelectedTextColor = 2130903443; // aapt resource value: 0x7F030194 - public const int tabTextAppearance = 2130903444; + public const int tabStyle = 2130903444; // aapt resource value: 0x7F030195 - public const int tabTextColor = 2130903445; + public const int tabTextAppearance = 2130903445; // aapt resource value: 0x7F030196 - public const int tabUnboundedRipple = 2130903446; + public const int tabTextColor = 2130903446; // aapt resource value: 0x7F030197 - public const int textAllCaps = 2130903447; + public const int tabUnboundedRipple = 2130903447; // aapt resource value: 0x7F030198 - public const int textAppearanceBody1 = 2130903448; + public const int textAllCaps = 2130903448; // aapt resource value: 0x7F030199 - public const int textAppearanceBody2 = 2130903449; + public const int textAppearanceBody1 = 2130903449; // aapt resource value: 0x7F03019A - public const int textAppearanceButton = 2130903450; + public const int textAppearanceBody2 = 2130903450; // aapt resource value: 0x7F03019B - public const int textAppearanceCaption = 2130903451; + public const int textAppearanceButton = 2130903451; // aapt resource value: 0x7F03019C - public const int textAppearanceHeadline1 = 2130903452; + public const int textAppearanceCaption = 2130903452; // aapt resource value: 0x7F03019D - public const int textAppearanceHeadline2 = 2130903453; + public const int textAppearanceHeadline1 = 2130903453; // aapt resource value: 0x7F03019E - public const int textAppearanceHeadline3 = 2130903454; + public const int textAppearanceHeadline2 = 2130903454; // aapt resource value: 0x7F03019F - public const int textAppearanceHeadline4 = 2130903455; + public const int textAppearanceHeadline3 = 2130903455; // aapt resource value: 0x7F0301A0 - public const int textAppearanceHeadline5 = 2130903456; + public const int textAppearanceHeadline4 = 2130903456; // aapt resource value: 0x7F0301A1 - public const int textAppearanceHeadline6 = 2130903457; + public const int textAppearanceHeadline5 = 2130903457; // aapt resource value: 0x7F0301A2 - public const int textAppearanceLargePopupMenu = 2130903458; + public const int textAppearanceHeadline6 = 2130903458; // aapt resource value: 0x7F0301A3 - public const int textAppearanceListItem = 2130903459; + public const int textAppearanceLargePopupMenu = 2130903459; // aapt resource value: 0x7F0301A4 - public const int textAppearanceListItemSecondary = 2130903460; + public const int textAppearanceListItem = 2130903460; // aapt resource value: 0x7F0301A5 - public const int textAppearanceListItemSmall = 2130903461; + public const int textAppearanceListItemSecondary = 2130903461; // aapt resource value: 0x7F0301A6 - public const int textAppearanceOverline = 2130903462; + public const int textAppearanceListItemSmall = 2130903462; // aapt resource value: 0x7F0301A7 - public const int textAppearancePopupMenuHeader = 2130903463; + public const int textAppearanceOverline = 2130903463; // aapt resource value: 0x7F0301A8 - public const int textAppearanceSearchResultSubtitle = 2130903464; + public const int textAppearancePopupMenuHeader = 2130903464; // aapt resource value: 0x7F0301A9 - public const int textAppearanceSearchResultTitle = 2130903465; + public const int textAppearanceSearchResultSubtitle = 2130903465; // aapt resource value: 0x7F0301AA - public const int textAppearanceSmallPopupMenu = 2130903466; + public const int textAppearanceSearchResultTitle = 2130903466; // aapt resource value: 0x7F0301AB - public const int textAppearanceSubtitle1 = 2130903467; + public const int textAppearanceSmallPopupMenu = 2130903467; // aapt resource value: 0x7F0301AC - public const int textAppearanceSubtitle2 = 2130903468; + public const int textAppearanceSubtitle1 = 2130903468; // aapt resource value: 0x7F0301AD - public const int textColorAlertDialogListItem = 2130903469; + public const int textAppearanceSubtitle2 = 2130903469; // aapt resource value: 0x7F0301AE - public const int textColorSearchUrl = 2130903470; + public const int textColorAlertDialogListItem = 2130903470; // aapt resource value: 0x7F0301AF - public const int textEndPadding = 2130903471; + public const int textColorSearchUrl = 2130903471; // aapt resource value: 0x7F0301B0 - public const int textInputStyle = 2130903472; + public const int textEndPadding = 2130903472; // aapt resource value: 0x7F0301B1 - public const int textStartPadding = 2130903473; + public const int textInputStyle = 2130903473; // aapt resource value: 0x7F0301B2 - public const int theme = 2130903474; + public const int textStartPadding = 2130903474; // aapt resource value: 0x7F0301B3 - public const int thickness = 2130903475; + public const int theme = 2130903475; // aapt resource value: 0x7F0301B4 - public const int thumbTextPadding = 2130903476; + public const int thickness = 2130903476; // aapt resource value: 0x7F0301B5 - public const int thumbTint = 2130903477; + public const int thumbTextPadding = 2130903477; // aapt resource value: 0x7F0301B6 - public const int thumbTintMode = 2130903478; + public const int thumbTint = 2130903478; // aapt resource value: 0x7F0301B7 - public const int tickMark = 2130903479; + public const int thumbTintMode = 2130903479; // aapt resource value: 0x7F0301B8 - public const int tickMarkTint = 2130903480; + public const int tickMark = 2130903480; // aapt resource value: 0x7F0301B9 - public const int tickMarkTintMode = 2130903481; + public const int tickMarkTint = 2130903481; // aapt resource value: 0x7F0301BA - public const int tint = 2130903482; + public const int tickMarkTintMode = 2130903482; // aapt resource value: 0x7F0301BB - public const int tintMode = 2130903483; + public const int tint = 2130903483; // aapt resource value: 0x7F0301BC - public const int title = 2130903484; + public const int tintMode = 2130903484; // aapt resource value: 0x7F0301BD - public const int titleEnabled = 2130903485; + public const int title = 2130903485; // aapt resource value: 0x7F0301BE - public const int titleMargin = 2130903486; + public const int titleEnabled = 2130903486; // aapt resource value: 0x7F0301BF - public const int titleMarginBottom = 2130903487; + public const int titleMargin = 2130903487; // aapt resource value: 0x7F0301C0 - public const int titleMarginEnd = 2130903488; - - // aapt resource value: 0x7F0301C3 - public const int titleMargins = 2130903491; + public const int titleMarginBottom = 2130903488; // aapt resource value: 0x7F0301C1 - public const int titleMarginStart = 2130903489; - - // aapt resource value: 0x7F0301C2 - public const int titleMarginTop = 2130903490; + public const int titleMarginEnd = 2130903489; // aapt resource value: 0x7F0301C4 - public const int titleTextAppearance = 2130903492; + public const int titleMargins = 2130903492; + + // aapt resource value: 0x7F0301C2 + public const int titleMarginStart = 2130903490; + + // aapt resource value: 0x7F0301C3 + public const int titleMarginTop = 2130903491; // aapt resource value: 0x7F0301C5 - public const int titleTextColor = 2130903493; + public const int titleTextAppearance = 2130903493; // aapt resource value: 0x7F0301C6 - public const int titleTextStyle = 2130903494; + public const int titleTextColor = 2130903494; // aapt resource value: 0x7F0301C7 - public const int toolbarId = 2130903495; + public const int titleTextStyle = 2130903495; // aapt resource value: 0x7F0301C8 - public const int toolbarNavigationButtonStyle = 2130903496; + public const int toolbarId = 2130903496; // aapt resource value: 0x7F0301C9 - public const int toolbarStyle = 2130903497; + public const int toolbarNavigationButtonStyle = 2130903497; // aapt resource value: 0x7F0301CA - public const int tooltipForegroundColor = 2130903498; + public const int toolbarStyle = 2130903498; // aapt resource value: 0x7F0301CB - public const int tooltipFrameBackground = 2130903499; + public const int tooltipForegroundColor = 2130903499; // aapt resource value: 0x7F0301CC - public const int tooltipText = 2130903500; + public const int tooltipFrameBackground = 2130903500; // aapt resource value: 0x7F0301CD - public const int track = 2130903501; + public const int tooltipText = 2130903501; // aapt resource value: 0x7F0301CE - public const int trackTint = 2130903502; + public const int track = 2130903502; // aapt resource value: 0x7F0301CF - public const int trackTintMode = 2130903503; + public const int trackTint = 2130903503; // aapt resource value: 0x7F0301D0 - public const int ttcIndex = 2130903504; + public const int trackTintMode = 2130903504; // aapt resource value: 0x7F0301D1 - public const int useCompatPadding = 2130903505; + public const int ttcIndex = 2130903505; // aapt resource value: 0x7F0301D2 - public const int viewInflaterClass = 2130903506; + public const int useCompatPadding = 2130903506; // aapt resource value: 0x7F0301D3 - public const int voiceIcon = 2130903507; + public const int viewInflaterClass = 2130903507; // aapt resource value: 0x7F0301D4 - public const int windowActionBar = 2130903508; + public const int voiceIcon = 2130903508; // aapt resource value: 0x7F0301D5 - public const int windowActionBarOverlay = 2130903509; + public const int windowActionBar = 2130903509; // aapt resource value: 0x7F0301D6 - public const int windowActionModeOverlay = 2130903510; + public const int windowActionBarOverlay = 2130903510; // aapt resource value: 0x7F0301D7 - public const int windowFixedHeightMajor = 2130903511; + public const int windowActionModeOverlay = 2130903511; // aapt resource value: 0x7F0301D8 - public const int windowFixedHeightMinor = 2130903512; + public const int windowFixedHeightMajor = 2130903512; // aapt resource value: 0x7F0301D9 - public const int windowFixedWidthMajor = 2130903513; + public const int windowFixedHeightMinor = 2130903513; // aapt resource value: 0x7F0301DA - public const int windowFixedWidthMinor = 2130903514; + public const int windowFixedWidthMajor = 2130903514; // aapt resource value: 0x7F0301DB - public const int windowMinWidthMajor = 2130903515; + public const int windowFixedWidthMinor = 2130903515; // aapt resource value: 0x7F0301DC - public const int windowMinWidthMinor = 2130903516; + public const int windowMinWidthMajor = 2130903516; // aapt resource value: 0x7F0301DD - public const int windowNoTitle = 2130903517; + public const int windowMinWidthMinor = 2130903517; + + // aapt resource value: 0x7F0301DE + public const int windowNoTitle = 2130903518; static Attribute() { @@ -10124,10 +10135,7 @@ namespace Borepin.Droid public const int CardView_Light = 2131624133; // aapt resource value: 0x7F0E01F7 - public const int collectionViewScrollBars = 2131624439; - - // aapt resource value: 0x7F0E01F8 - public const int collectionViewTheme = 2131624440; + public const int collectionViewTheme = 2131624439; // aapt resource value: 0x7F0E00C6 public const int MainTheme = 2131624134; @@ -10228,6 +10236,12 @@ namespace Borepin.Droid // aapt resource value: 0x7F0E00E6 public const int RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = 2131624166; + // aapt resource value: 0x7F0E01F8 + public const int scrollViewScrollBars = 2131624440; + + // aapt resource value: 0x7F0E01F9 + public const int scrollViewTheme = 2131624441; + // aapt resource value: 0x7F0E00E7 public const int TextAppearance_AppCompat = 2131624167; @@ -11057,7 +11071,7 @@ namespace Borepin.Droid public partial class Styleable { - // aapt resource value: { 0x7F030031,0x7F030032,0x7F030033,0x7F030092,0x7F030093,0x7F030094,0x7F030095,0x7F030096,0x7F030097,0x7F0300A5,0x7F0300AA,0x7F0300AB,0x7F0300B6,0x7F0300E0,0x7F0300E5,0x7F0300EA,0x7F0300EB,0x7F0300ED,0x7F0300F7,0x7F030101,0x7F030124,0x7F030130,0x7F030141,0x7F030145,0x7F030146,0x7F030174,0x7F030177,0x7F0301BC,0x7F0301C6 } + // aapt resource value: { 0x7F030031,0x7F030032,0x7F030033,0x7F030092,0x7F030093,0x7F030094,0x7F030095,0x7F030096,0x7F030097,0x7F0300A5,0x7F0300AA,0x7F0300AB,0x7F0300B6,0x7F0300E0,0x7F0300E5,0x7F0300EA,0x7F0300EB,0x7F0300ED,0x7F0300F7,0x7F030101,0x7F030124,0x7F030130,0x7F030141,0x7F030145,0x7F030146,0x7F030175,0x7F030178,0x7F0301BD,0x7F0301C7 } public static int[] ActionBar = new int[] { 2130903089, 2130903090, @@ -11084,10 +11098,10 @@ namespace Borepin.Droid 2130903361, 2130903365, 2130903366, - 2130903412, - 2130903415, - 2130903484, - 2130903494}; + 2130903413, + 2130903416, + 2130903485, + 2130903495}; // aapt resource value: { 0x10100B3 } public static int[] ActionBarLayout = new int[] { @@ -11194,14 +11208,14 @@ namespace Borepin.Droid public static int[] ActionMenuView = new int[] { -1}; - // aapt resource value: { 0x7F030031,0x7F030032,0x7F03007E,0x7F0300E0,0x7F030177,0x7F0301C6 } + // aapt resource value: { 0x7F030031,0x7F030032,0x7F03007E,0x7F0300E0,0x7F030178,0x7F0301C7 } public static int[] ActionMode = new int[] { 2130903089, 2130903090, 2130903166, 2130903264, - 2130903415, - 2130903494}; + 2130903416, + 2130903495}; // aapt resource value: 0 public const int ActionMode_background = 0; @@ -11232,7 +11246,7 @@ namespace Borepin.Droid // aapt resource value: 1 public const int ActivityChooserView_initialActivityCount = 1; - // aapt resource value: { 0x10100F2,0x7F030052,0x7F030053,0x7F03011B,0x7F03011C,0x7F03012D,0x7F03015C,0x7F03015D } + // aapt resource value: { 0x10100F2,0x7F030052,0x7F030053,0x7F03011B,0x7F03011C,0x7F03012D,0x7F03015D,0x7F03015E } public static int[] AlertDialog = new int[] { 16842994, 2130903122, @@ -11240,8 +11254,8 @@ namespace Borepin.Droid 2130903323, 2130903324, 2130903341, - 2130903388, - 2130903389}; + 2130903389, + 2130903390}; // aapt resource value: 0 public const int AlertDialog_android_layout = 0; @@ -11333,12 +11347,12 @@ namespace Borepin.Droid 2130903228, 2130903318}; - // aapt resource value: { 0x7F03016A,0x7F03016B,0x7F03016C,0x7F03016D } + // aapt resource value: { 0x7F03016B,0x7F03016C,0x7F03016D,0x7F03016E } public static int[] AppBarLayoutStates = new int[] { - 2130903402, 2130903403, 2130903404, - 2130903405}; + 2130903405, + 2130903406}; // aapt resource value: 0 public const int AppBarLayoutStates_state_collapsed = 0; @@ -11381,12 +11395,12 @@ namespace Borepin.Droid // aapt resource value: 5 public const int AppBarLayout_liftOnScroll = 5; - // aapt resource value: { 0x1010119,0x7F030167,0x7F0301BA,0x7F0301BB } + // aapt resource value: { 0x1010119,0x7F030168,0x7F0301BB,0x7F0301BC } public static int[] AppCompatImageView = new int[] { 16843033, - 2130903399, - 2130903482, - 2130903483}; + 2130903400, + 2130903483, + 2130903484}; // aapt resource value: 0 public const int AppCompatImageView_android_src = 0; @@ -11400,12 +11414,12 @@ namespace Borepin.Droid // aapt resource value: 3 public const int AppCompatImageView_tintMode = 3; - // aapt resource value: { 0x1010142,0x7F0301B7,0x7F0301B8,0x7F0301B9 } + // aapt resource value: { 0x1010142,0x7F0301B8,0x7F0301B9,0x7F0301BA } public static int[] AppCompatSeekBar = new int[] { 16843074, - 2130903479, 2130903480, - 2130903481}; + 2130903481, + 2130903482}; // aapt resource value: 0 public const int AppCompatSeekBar_android_thumb = 0; @@ -11450,7 +11464,7 @@ namespace Borepin.Droid // aapt resource value: 0 public const int AppCompatTextHelper_android_textAppearance = 0; - // aapt resource value: { 0x1010034,0x7F03002C,0x7F03002D,0x7F03002E,0x7F03002F,0x7F030030,0x7F0300CF,0x7F0300D2,0x7F030109,0x7F030117,0x7F030197 } + // aapt resource value: { 0x1010034,0x7F03002C,0x7F03002D,0x7F03002E,0x7F03002F,0x7F030030,0x7F0300CF,0x7F0300D2,0x7F030109,0x7F030117,0x7F030198 } public static int[] AppCompatTextView = new int[] { 16842804, 2130903084, @@ -11462,7 +11476,7 @@ namespace Borepin.Droid 2130903250, 2130903305, 2130903319, - 2130903447}; + 2130903448}; // aapt resource value: 0 public const int AppCompatTextView_android_textAppearance = 0; @@ -11497,7 +11511,7 @@ namespace Borepin.Droid // aapt resource value: 10 public const int AppCompatTextView_textAllCaps = 10; - // aapt resource value: { 0x1010057,0x10100AE,0x7F030000,0x7F030001,0x7F030002,0x7F030003,0x7F030004,0x7F030005,0x7F030006,0x7F030007,0x7F030008,0x7F030009,0x7F03000A,0x7F03000B,0x7F03000C,0x7F03000E,0x7F03000F,0x7F030010,0x7F030011,0x7F030012,0x7F030013,0x7F030014,0x7F030015,0x7F030016,0x7F030017,0x7F030018,0x7F030019,0x7F03001A,0x7F03001B,0x7F03001C,0x7F03001D,0x7F03001E,0x7F030021,0x7F030022,0x7F030023,0x7F030024,0x7F030025,0x7F03002B,0x7F03003E,0x7F03004C,0x7F03004D,0x7F03004E,0x7F03004F,0x7F030050,0x7F030054,0x7F030055,0x7F03005F,0x7F030064,0x7F030085,0x7F030086,0x7F030087,0x7F030088,0x7F030089,0x7F03008A,0x7F03008B,0x7F03008C,0x7F03008D,0x7F03008F,0x7F03009E,0x7F0300A7,0x7F0300A8,0x7F0300A9,0x7F0300AC,0x7F0300AE,0x7F0300B1,0x7F0300B2,0x7F0300B3,0x7F0300B4,0x7F0300B5,0x7F0300EA,0x7F0300F6,0x7F030119,0x7F03011A,0x7F03011D,0x7F03011E,0x7F03011F,0x7F030120,0x7F030121,0x7F030122,0x7F030123,0x7F030138,0x7F030139,0x7F03013A,0x7F030140,0x7F030142,0x7F030149,0x7F03014A,0x7F03014B,0x7F03014C,0x7F030154,0x7F030155,0x7F030156,0x7F030157,0x7F030164,0x7F030165,0x7F03017B,0x7F0301A2,0x7F0301A3,0x7F0301A4,0x7F0301A5,0x7F0301A7,0x7F0301A8,0x7F0301A9,0x7F0301AA,0x7F0301AD,0x7F0301AE,0x7F0301C8,0x7F0301C9,0x7F0301CA,0x7F0301CB,0x7F0301D2,0x7F0301D4,0x7F0301D5,0x7F0301D6,0x7F0301D7,0x7F0301D8,0x7F0301D9,0x7F0301DA,0x7F0301DB,0x7F0301DC,0x7F0301DD } + // aapt resource value: { 0x1010057,0x10100AE,0x7F030000,0x7F030001,0x7F030002,0x7F030003,0x7F030004,0x7F030005,0x7F030006,0x7F030007,0x7F030008,0x7F030009,0x7F03000A,0x7F03000B,0x7F03000C,0x7F03000E,0x7F03000F,0x7F030010,0x7F030011,0x7F030012,0x7F030013,0x7F030014,0x7F030015,0x7F030016,0x7F030017,0x7F030018,0x7F030019,0x7F03001A,0x7F03001B,0x7F03001C,0x7F03001D,0x7F03001E,0x7F030021,0x7F030022,0x7F030023,0x7F030024,0x7F030025,0x7F03002B,0x7F03003E,0x7F03004C,0x7F03004D,0x7F03004E,0x7F03004F,0x7F030050,0x7F030054,0x7F030055,0x7F03005F,0x7F030064,0x7F030085,0x7F030086,0x7F030087,0x7F030088,0x7F030089,0x7F03008A,0x7F03008B,0x7F03008C,0x7F03008D,0x7F03008F,0x7F03009E,0x7F0300A7,0x7F0300A8,0x7F0300A9,0x7F0300AC,0x7F0300AE,0x7F0300B1,0x7F0300B2,0x7F0300B3,0x7F0300B4,0x7F0300B5,0x7F0300EA,0x7F0300F6,0x7F030119,0x7F03011A,0x7F03011D,0x7F03011E,0x7F03011F,0x7F030120,0x7F030121,0x7F030122,0x7F030123,0x7F030138,0x7F030139,0x7F03013A,0x7F030140,0x7F030142,0x7F030149,0x7F03014A,0x7F03014B,0x7F03014C,0x7F030155,0x7F030156,0x7F030157,0x7F030158,0x7F030165,0x7F030166,0x7F03017C,0x7F0301A3,0x7F0301A4,0x7F0301A5,0x7F0301A6,0x7F0301A8,0x7F0301A9,0x7F0301AA,0x7F0301AB,0x7F0301AE,0x7F0301AF,0x7F0301C9,0x7F0301CA,0x7F0301CB,0x7F0301CC,0x7F0301D3,0x7F0301D5,0x7F0301D6,0x7F0301D7,0x7F0301D8,0x7F0301D9,0x7F0301DA,0x7F0301DB,0x7F0301DC,0x7F0301DD,0x7F0301DE } public static int[] AppCompatTheme = new int[] { 16842839, 16842926, @@ -11588,29 +11602,28 @@ namespace Borepin.Droid 2130903370, 2130903371, 2130903372, - 2130903380, 2130903381, 2130903382, 2130903383, - 2130903396, + 2130903384, 2130903397, - 2130903419, - 2130903458, + 2130903398, + 2130903420, 2130903459, 2130903460, 2130903461, - 2130903463, + 2130903462, 2130903464, 2130903465, 2130903466, - 2130903469, + 2130903467, 2130903470, - 2130903496, + 2130903471, 2130903497, 2130903498, 2130903499, - 2130903506, - 2130903508, + 2130903500, + 2130903507, 2130903509, 2130903510, 2130903511, @@ -11619,7 +11632,8 @@ namespace Borepin.Droid 2130903514, 2130903515, 2130903516, - 2130903517}; + 2130903517, + 2130903518}; // aapt resource value: 2 public const int AppCompatTheme_actionBarDivider = 2; @@ -12135,7 +12149,7 @@ namespace Borepin.Droid // aapt resource value: 12 public const int CardView_contentPaddingTop = 12; - // aapt resource value: { 0x1010034,0x10100AB,0x101011F,0x101014F,0x10101E5,0x7F030061,0x7F030062,0x7F030063,0x7F030065,0x7F030066,0x7F030067,0x7F030069,0x7F03006A,0x7F03006B,0x7F03006C,0x7F03006D,0x7F03006E,0x7F030073,0x7F030074,0x7F030075,0x7F030077,0x7F030078,0x7F030079,0x7F03007A,0x7F03007B,0x7F03007C,0x7F03007D,0x7F0300E4,0x7F0300EE,0x7F0300F2,0x7F03014E,0x7F03015A,0x7F0301AF,0x7F0301B1 } + // aapt resource value: { 0x1010034,0x10100AB,0x101011F,0x101014F,0x10101E5,0x7F030061,0x7F030062,0x7F030063,0x7F030065,0x7F030066,0x7F030067,0x7F030069,0x7F03006A,0x7F03006B,0x7F03006C,0x7F03006D,0x7F03006E,0x7F030073,0x7F030074,0x7F030075,0x7F030077,0x7F030078,0x7F030079,0x7F03007A,0x7F03007B,0x7F03007C,0x7F03007D,0x7F0300E4,0x7F0300EE,0x7F0300F2,0x7F03014E,0x7F03015B,0x7F0301B0,0x7F0301B2 } public static int[] Chip = new int[] { 16842804, 16842923, @@ -12168,18 +12182,18 @@ namespace Borepin.Droid 2130903278, 2130903282, 2130903374, - 2130903386, - 2130903471, - 2130903473}; + 2130903387, + 2130903472, + 2130903474}; - // aapt resource value: { 0x7F030060,0x7F03006F,0x7F030070,0x7F030071,0x7F03015E,0x7F03015F } + // aapt resource value: { 0x7F030060,0x7F03006F,0x7F030070,0x7F030071,0x7F03015F,0x7F030160 } public static int[] ChipGroup = new int[] { 2130903136, 2130903151, 2130903152, 2130903153, - 2130903390, - 2130903391}; + 2130903391, + 2130903392}; // aapt resource value: 0 public const int ChipGroup_checkedChip = 0; @@ -12301,7 +12315,7 @@ namespace Borepin.Droid // aapt resource value: 33 public const int Chip_textStartPadding = 33; - // aapt resource value: { 0x7F030081,0x7F030082,0x7F03009D,0x7F0300BD,0x7F0300BE,0x7F0300BF,0x7F0300C0,0x7F0300C1,0x7F0300C2,0x7F0300C3,0x7F03014F,0x7F030151,0x7F03016F,0x7F0301BC,0x7F0301BD,0x7F0301C7 } + // aapt resource value: { 0x7F030081,0x7F030082,0x7F03009D,0x7F0300BD,0x7F0300BE,0x7F0300BF,0x7F0300C0,0x7F0300C1,0x7F0300C2,0x7F0300C3,0x7F03014F,0x7F030151,0x7F030170,0x7F0301BD,0x7F0301BE,0x7F0301C8 } public static int[] CollapsingToolbarLayout = new int[] { 2130903169, 2130903170, @@ -12315,10 +12329,10 @@ namespace Borepin.Droid 2130903235, 2130903375, 2130903377, - 2130903407, - 2130903484, + 2130903408, 2130903485, - 2130903495}; + 2130903486, + 2130903496}; // aapt resource value: 0 public const int CollapsingToolbarLayout_collapsedTitleGravity = 0; @@ -12409,10 +12423,10 @@ namespace Borepin.Droid // aapt resource value: 2 public const int CompoundButton_buttonTintMode = 2; - // aapt resource value: { 0x7F030107,0x7F03016E } + // aapt resource value: { 0x7F030107,0x7F03016F } public static int[] CoordinatorLayout = new int[] { 2130903303, - 2130903406}; + 2130903407}; // aapt resource value: 0 public const int CoordinatorLayout_keylines = 0; @@ -12462,7 +12476,7 @@ namespace Borepin.Droid // aapt resource value: 1 public const int DesignTheme_bottomSheetStyle = 1; - // aapt resource value: { 0x7F030029,0x7F03002A,0x7F030036,0x7F030084,0x7F0300AF,0x7F0300DD,0x7F030163,0x7F0301B3 } + // aapt resource value: { 0x7F030029,0x7F03002A,0x7F030036,0x7F030084,0x7F0300AF,0x7F0300DD,0x7F030164,0x7F0301B4 } public static int[] DrawerArrowToggle = new int[] { 2130903081, 2130903082, @@ -12470,8 +12484,8 @@ namespace Borepin.Droid 2130903172, 2130903215, 2130903261, - 2130903395, - 2130903475}; + 2130903396, + 2130903476}; // aapt resource value: 0 public const int DrawerArrowToggle_arrowHeadLength = 0; @@ -12497,7 +12511,7 @@ namespace Borepin.Droid // aapt resource value: 7 public const int DrawerArrowToggle_thickness = 7; - // aapt resource value: { 0x7F030034,0x7F030035,0x7F03003D,0x7F0300B6,0x7F0300C8,0x7F0300C9,0x7F0300E4,0x7F0300EC,0x7F03012A,0x7F030144,0x7F03014E,0x7F03015A,0x7F0301D1 } + // aapt resource value: { 0x7F030034,0x7F030035,0x7F03003D,0x7F0300B6,0x7F0300C8,0x7F0300C9,0x7F0300E4,0x7F0300EC,0x7F03012A,0x7F030144,0x7F03014E,0x7F03015B,0x7F0301D2 } public static int[] FloatingActionButton = new int[] { 2130903092, 2130903093, @@ -12510,8 +12524,8 @@ namespace Borepin.Droid 2130903338, 2130903364, 2130903374, - 2130903386, - 2130903505}; + 2130903387, + 2130903506}; // aapt resource value: 0 public const int FloatingActionButton_backgroundTint = 0; @@ -12579,7 +12593,7 @@ namespace Borepin.Droid 2130903255, 2130903256}; - // aapt resource value: { 0x1010532,0x1010533,0x101053F,0x101056F,0x1010570,0x7F0300D1,0x7F0300D9,0x7F0300DA,0x7F0300DB,0x7F0301D0 } + // aapt resource value: { 0x1010532,0x1010533,0x101053F,0x101056F,0x1010570,0x7F0300D1,0x7F0300D9,0x7F0300DA,0x7F0300DB,0x7F0301D1 } public static int[] FontFamilyFont = new int[] { 16844082, 16844083, @@ -12590,7 +12604,7 @@ namespace Borepin.Droid 2130903257, 2130903258, 2130903259, - 2130903504}; + 2130903505}; // aapt resource value: 0 public const int FontFamilyFont_android_font = 0; @@ -12724,7 +12738,7 @@ namespace Borepin.Droid // aapt resource value: 0 public const int ItemsViewRendererTheme_collectionViewStyle = 0; - // aapt resource value: { 0x10100AF,0x10100C4,0x1010126,0x1010127,0x1010128,0x7F0300AB,0x7F0300AD,0x7F03012B,0x7F030159 } + // aapt resource value: { 0x10100AF,0x10100C4,0x1010126,0x1010127,0x1010128,0x7F0300AB,0x7F0300AD,0x7F03012B,0x7F03015A } public static int[] LinearLayoutCompat = new int[] { 16842927, 16842948, @@ -12734,7 +12748,7 @@ namespace Borepin.Droid 2130903211, 2130903213, 2130903339, - 2130903385}; + 2130903386}; // aapt resource value: 2 public const int LinearLayoutCompat_android_baselineAligned = 2; @@ -12793,7 +12807,7 @@ namespace Borepin.Droid // aapt resource value: 1 public const int ListPopupWindow_android_dropDownVerticalOffset = 1; - // aapt resource value: { 0x10101B7,0x10101B8,0x10101B9,0x10101BA,0x7F030034,0x7F030035,0x7F0300A0,0x7F0300ED,0x7F0300EF,0x7F0300F0,0x7F0300F1,0x7F0300F3,0x7F0300F4,0x7F03014E,0x7F030170,0x7F030171 } + // aapt resource value: { 0x10101B7,0x10101B8,0x10101B9,0x10101BA,0x7F030034,0x7F030035,0x7F0300A0,0x7F0300ED,0x7F0300EF,0x7F0300F0,0x7F0300F1,0x7F0300F3,0x7F0300F4,0x7F03014E,0x7F030171,0x7F030172 } public static int[] MaterialButton = new int[] { 16843191, 16843192, @@ -12809,8 +12823,8 @@ namespace Borepin.Droid 2130903283, 2130903284, 2130903374, - 2130903408, - 2130903409}; + 2130903409, + 2130903410}; // aapt resource value: 3 public const int MaterialButton_android_insetBottom = 3; @@ -12860,10 +12874,10 @@ namespace Borepin.Droid // aapt resource value: 15 public const int MaterialButton_strokeWidth = 15; - // aapt resource value: { 0x7F030170,0x7F030171 } + // aapt resource value: { 0x7F030171,0x7F030172 } public static int[] MaterialCardView = new int[] { - 2130903408, - 2130903409}; + 2130903409, + 2130903410}; // aapt resource value: 0 public const int MaterialCardView_strokeColor = 0; @@ -12871,7 +12885,7 @@ namespace Borepin.Droid // aapt resource value: 1 public const int MaterialCardView_strokeWidth = 1; - // aapt resource value: { 0x7F030041,0x7F030042,0x7F030068,0x7F030072,0x7F030076,0x7F030085,0x7F030086,0x7F03008C,0x7F03008D,0x7F03008E,0x7F0300B5,0x7F0300D0,0x7F030126,0x7F030127,0x7F030131,0x7F030150,0x7F030160,0x7F030193,0x7F030198,0x7F030199,0x7F03019A,0x7F03019B,0x7F03019C,0x7F03019D,0x7F03019E,0x7F03019F,0x7F0301A0,0x7F0301A1,0x7F0301A6,0x7F0301AB,0x7F0301AC,0x7F0301B0 } + // aapt resource value: { 0x7F030041,0x7F030042,0x7F030068,0x7F030072,0x7F030076,0x7F030085,0x7F030086,0x7F03008C,0x7F03008D,0x7F03008E,0x7F0300B5,0x7F0300D0,0x7F030126,0x7F030127,0x7F030131,0x7F030150,0x7F030161,0x7F030194,0x7F030199,0x7F03019A,0x7F03019B,0x7F03019C,0x7F03019D,0x7F03019E,0x7F03019F,0x7F0301A0,0x7F0301A1,0x7F0301A2,0x7F0301A7,0x7F0301AC,0x7F0301AD,0x7F0301B1 } public static int[] MaterialComponentsTheme = new int[] { 2130903105, 2130903106, @@ -12889,9 +12903,8 @@ namespace Borepin.Droid 2130903335, 2130903345, 2130903376, - 2130903392, - 2130903443, - 2130903448, + 2130903393, + 2130903444, 2130903449, 2130903450, 2130903451, @@ -12901,10 +12914,11 @@ namespace Borepin.Droid 2130903455, 2130903456, 2130903457, - 2130903462, - 2130903467, + 2130903458, + 2130903463, 2130903468, - 2130903472}; + 2130903469, + 2130903473}; // aapt resource value: 0 public const int MaterialComponentsTheme_bottomSheetDialogTheme = 0; @@ -13029,7 +13043,7 @@ namespace Borepin.Droid // aapt resource value: 2 public const int MenuGroup_android_visible = 2; - // aapt resource value: { 0x1010002,0x101000E,0x10100D0,0x1010106,0x1010194,0x10101DE,0x10101DF,0x10101E1,0x10101E2,0x10101E3,0x10101E4,0x10101E5,0x101026F,0x7F03000D,0x7F03001F,0x7F030020,0x7F030028,0x7F030091,0x7F0300F3,0x7F0300F4,0x7F030132,0x7F030158,0x7F0301CC } + // aapt resource value: { 0x1010002,0x101000E,0x10100D0,0x1010106,0x1010194,0x10101DE,0x10101DF,0x10101E1,0x10101E2,0x10101E3,0x10101E4,0x10101E5,0x101026F,0x7F03000D,0x7F03001F,0x7F030020,0x7F030028,0x7F030091,0x7F0300F3,0x7F0300F4,0x7F030132,0x7F030159,0x7F0301CD } public static int[] MenuItem = new int[] { 16842754, 16842766, @@ -13052,8 +13066,8 @@ namespace Borepin.Droid 2130903283, 2130903284, 2130903346, - 2130903384, - 2130903500}; + 2130903385, + 2130903501}; // aapt resource value: 13 public const int MenuItem_actionLayout = 13; @@ -13124,7 +13138,7 @@ namespace Borepin.Droid // aapt resource value: 22 public const int MenuItem_tooltipText = 22; - // aapt resource value: { 0x10100AE,0x101012C,0x101012D,0x101012E,0x101012F,0x1010130,0x1010131,0x7F030143,0x7F030172 } + // aapt resource value: { 0x10100AE,0x101012C,0x101012D,0x101012E,0x101012F,0x1010130,0x1010131,0x7F030143,0x7F030173 } public static int[] MenuView = new int[] { 16842926, 16843052, @@ -13134,7 +13148,7 @@ namespace Borepin.Droid 16843056, 16843057, 2130903363, - 2130903410}; + 2130903411}; // aapt resource value: 4 public const int MenuView_android_headerBackground = 4; @@ -13220,9 +13234,9 @@ namespace Borepin.Droid 16843465, 2130903347}; - // aapt resource value: { 0x7F030169 } + // aapt resource value: { 0x7F03016A } public static int[] PopupWindowBackgroundState = new int[] { - 2130903401}; + 2130903402}; // aapt resource value: 0 public const int PopupWindowBackgroundState_state_above_anchor = 0; @@ -13247,7 +13261,7 @@ namespace Borepin.Droid // aapt resource value: 1 public const int RecycleListView_paddingTopNoTitle = 1; - // aapt resource value: { 0x10100C4,0x10100F1,0x7F0300CA,0x7F0300CB,0x7F0300CC,0x7F0300CD,0x7F0300CE,0x7F03010B,0x7F03014D,0x7F030162,0x7F030168 } + // aapt resource value: { 0x10100C4,0x10100F1,0x7F0300CA,0x7F0300CB,0x7F0300CC,0x7F0300CD,0x7F0300CE,0x7F03010B,0x7F03014D,0x7F030163,0x7F030169 } public static int[] RecyclerView = new int[] { 16842948, 16842993, @@ -13258,8 +13272,8 @@ namespace Borepin.Droid 2130903246, 2130903307, 2130903373, - 2130903394, - 2130903400}; + 2130903395, + 2130903401}; // aapt resource value: 1 public const int RecyclerView_android_descendantFocusability = 1; @@ -13308,7 +13322,14 @@ namespace Borepin.Droid // aapt resource value: 0 public const int ScrollingViewBehavior_Layout_behavior_overlapTop = 0; - // aapt resource value: { 0x10100DA,0x101011F,0x1010220,0x1010264,0x7F030077,0x7F030090,0x7F0300A6,0x7F0300DE,0x7F0300F5,0x7F03010A,0x7F030147,0x7F030148,0x7F030152,0x7F030153,0x7F030173,0x7F030178,0x7F0301D3 } + // aapt resource value: { 0x7F030152 } + public static int[] ScrollViewRendererTheme = new int[] { + 2130903378}; + + // aapt resource value: 0 + public const int ScrollViewRendererTheme_scrollViewStyle = 0; + + // aapt resource value: { 0x10100DA,0x101011F,0x1010220,0x1010264,0x7F030077,0x7F030090,0x7F0300A6,0x7F0300DE,0x7F0300F5,0x7F03010A,0x7F030147,0x7F030148,0x7F030153,0x7F030154,0x7F030174,0x7F030179,0x7F0301D4 } public static int[] SearchView = new int[] { 16842970, 16843039, @@ -13322,11 +13343,11 @@ namespace Borepin.Droid 2130903306, 2130903367, 2130903368, - 2130903378, 2130903379, - 2130903411, - 2130903416, - 2130903507}; + 2130903380, + 2130903412, + 2130903417, + 2130903508}; // aapt resource value: 0 public const int SearchView_android_focusable = 0; @@ -13379,10 +13400,10 @@ namespace Borepin.Droid // aapt resource value: 16 public const int SearchView_voiceIcon = 16; - // aapt resource value: { 0x7F030160,0x7F030161 } + // aapt resource value: { 0x7F030161,0x7F030162 } public static int[] Snackbar = new int[] { - 2130903392, - 2130903393}; + 2130903393, + 2130903394}; // aapt resource value: { 0x101011F,0x7F0300B6,0x7F030128 } public static int[] SnackbarLayout = new int[] { @@ -13462,22 +13483,22 @@ namespace Borepin.Droid // aapt resource value: 1 public const int StateListDrawable_android_visible = 1; - // aapt resource value: { 0x1010124,0x1010125,0x1010142,0x7F03015B,0x7F030166,0x7F030179,0x7F03017A,0x7F03017C,0x7F0301B4,0x7F0301B5,0x7F0301B6,0x7F0301CD,0x7F0301CE,0x7F0301CF } + // aapt resource value: { 0x1010124,0x1010125,0x1010142,0x7F03015C,0x7F030167,0x7F03017A,0x7F03017B,0x7F03017D,0x7F0301B5,0x7F0301B6,0x7F0301B7,0x7F0301CE,0x7F0301CF,0x7F0301D0 } public static int[] SwitchCompat = new int[] { 16843044, 16843045, 16843074, - 2130903387, - 2130903398, - 2130903417, + 2130903388, + 2130903399, 2130903418, - 2130903420, - 2130903476, + 2130903419, + 2130903421, 2130903477, 2130903478, - 2130903501, + 2130903479, 2130903502, - 2130903503}; + 2130903503, + 2130903504}; // aapt resource value: 1 public const int SwitchCompat_android_textOff = 1; @@ -13536,9 +13557,8 @@ namespace Borepin.Droid // aapt resource value: 2 public const int TabItem_android_text = 2; - // aapt resource value: { 0x7F03017D,0x7F03017E,0x7F03017F,0x7F030180,0x7F030181,0x7F030182,0x7F030183,0x7F030184,0x7F030185,0x7F030186,0x7F030187,0x7F030188,0x7F030189,0x7F03018A,0x7F03018B,0x7F03018C,0x7F03018D,0x7F03018E,0x7F03018F,0x7F030190,0x7F030191,0x7F030192,0x7F030194,0x7F030195,0x7F030196 } + // aapt resource value: { 0x7F03017E,0x7F03017F,0x7F030180,0x7F030181,0x7F030182,0x7F030183,0x7F030184,0x7F030185,0x7F030186,0x7F030187,0x7F030188,0x7F030189,0x7F03018A,0x7F03018B,0x7F03018C,0x7F03018D,0x7F03018E,0x7F03018F,0x7F030190,0x7F030191,0x7F030192,0x7F030193,0x7F030195,0x7F030196,0x7F030197 } public static int[] TabLayout = new int[] { - 2130903421, 2130903422, 2130903423, 2130903424, @@ -13560,9 +13580,10 @@ namespace Borepin.Droid 2130903440, 2130903441, 2130903442, - 2130903444, + 2130903443, 2130903445, - 2130903446}; + 2130903446, + 2130903447}; // aapt resource value: 0 public const int TabLayout_tabBackground = 0; @@ -13639,7 +13660,7 @@ namespace Borepin.Droid // aapt resource value: 24 public const int TabLayout_tabUnboundedRipple = 24; - // aapt resource value: { 0x1010095,0x1010096,0x1010097,0x1010098,0x101009A,0x101009B,0x1010161,0x1010162,0x1010163,0x1010164,0x10103AC,0x7F0300D2,0x7F030197 } + // aapt resource value: { 0x1010095,0x1010096,0x1010097,0x1010098,0x101009A,0x101009B,0x1010161,0x1010162,0x1010163,0x1010164,0x10103AC,0x7F0300D2,0x7F030198 } public static int[] TextAppearance = new int[] { 16842901, 16842902, @@ -13653,7 +13674,7 @@ namespace Borepin.Droid 16843108, 16843692, 2130903250, - 2130903447}; + 2130903448}; // aapt resource value: 10 public const int TextAppearance_android_fontFamily = 10; @@ -13824,7 +13845,7 @@ namespace Borepin.Droid // aapt resource value: 2 public const int ThemeEnforcement_enforceTextAppearance = 2; - // aapt resource value: { 0x10100AF,0x1010140,0x7F030051,0x7F03007F,0x7F030080,0x7F030092,0x7F030093,0x7F030094,0x7F030095,0x7F030096,0x7F030097,0x7F030124,0x7F030125,0x7F030129,0x7F03012E,0x7F03012F,0x7F030141,0x7F030174,0x7F030175,0x7F030176,0x7F0301BC,0x7F0301BE,0x7F0301BF,0x7F0301C0,0x7F0301C1,0x7F0301C2,0x7F0301C3,0x7F0301C4,0x7F0301C5 } + // aapt resource value: { 0x10100AF,0x1010140,0x7F030051,0x7F03007F,0x7F030080,0x7F030092,0x7F030093,0x7F030094,0x7F030095,0x7F030096,0x7F030097,0x7F030124,0x7F030125,0x7F030129,0x7F03012E,0x7F03012F,0x7F030141,0x7F030175,0x7F030176,0x7F030177,0x7F0301BD,0x7F0301BF,0x7F0301C0,0x7F0301C1,0x7F0301C2,0x7F0301C3,0x7F0301C4,0x7F0301C5,0x7F0301C6 } public static int[] Toolbar = new int[] { 16842927, 16843072, @@ -13843,18 +13864,18 @@ namespace Borepin.Droid 2130903342, 2130903343, 2130903361, - 2130903412, 2130903413, 2130903414, - 2130903484, - 2130903486, + 2130903415, + 2130903485, 2130903487, 2130903488, 2130903489, 2130903490, 2130903491, 2130903492, - 2130903493}; + 2130903493, + 2130903494}; // aapt resource value: 0 public const int Toolbar_android_gravity = 0; @@ -13943,13 +13964,13 @@ namespace Borepin.Droid // aapt resource value: 28 public const int Toolbar_titleTextColor = 28; - // aapt resource value: { 0x1010000,0x10100DA,0x7F030135,0x7F030136,0x7F0301B2 } + // aapt resource value: { 0x1010000,0x10100DA,0x7F030135,0x7F030136,0x7F0301B3 } public static int[] View = new int[] { 16842752, 16842970, 2130903349, 2130903350, - 2130903474}; + 2130903475}; // aapt resource value: { 0x10100D4,0x7F030034,0x7F030035 } public static int[] ViewBackgroundHelper = new int[] { diff --git a/Borepin/Borepin.GTK/Borepin.GTK.csproj b/Borepin/Borepin.GTK/Borepin.GTK.csproj index 56ab842..3e4d45f 100644 --- a/Borepin/Borepin.GTK/Borepin.GTK.csproj +++ b/Borepin/Borepin.GTK/Borepin.GTK.csproj @@ -1,6 +1,6 @@  - + Debug @@ -10,11 +10,12 @@ Properties Borepin.GTK Borepin.GTK - v4.8 + v4.7.2 512 true + true @@ -76,17 +77,20 @@ + + ..\..\packages\Xamarin.Forms.Platform.GTK.4.8.0.1560\lib\net45\webkit-sharp.dll + - ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\netstandard2.0\Xamarin.Forms.Core.dll + ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\netstandard2.0\Xamarin.Forms.Core.dll - ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\netstandard2.0\Xamarin.Forms.Platform.dll + ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\netstandard2.0\Xamarin.Forms.Platform.dll - ..\..\packages\Xamarin.Forms.Platform.GTK.4.8.0.1364\lib\net45\Xamarin.Forms.Platform.GTK.dll + ..\..\packages\Xamarin.Forms.Platform.GTK.4.8.0.1560\lib\net45\Xamarin.Forms.Platform.GTK.dll - ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\netstandard2.0\Xamarin.Forms.Xaml.dll + ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\netstandard2.0\Xamarin.Forms.Xaml.dll @@ -110,8 +114,8 @@ Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". - - + + - + \ No newline at end of file diff --git a/Borepin/Borepin.GTK/app.config b/Borepin/Borepin.GTK/app.config index 3c31098..5c893eb 100644 --- a/Borepin/Borepin.GTK/app.config +++ b/Borepin/Borepin.GTK/app.config @@ -8,4 +8,4 @@ - \ No newline at end of file + diff --git a/Borepin/Borepin.GTK/packages.config b/Borepin/Borepin.GTK/packages.config index 6088e1e..90bea8d 100644 --- a/Borepin/Borepin.GTK/packages.config +++ b/Borepin/Borepin.GTK/packages.config @@ -1,6 +1,6 @@  - - - + + + \ No newline at end of file diff --git a/Borepin/Borepin.UWP/Borepin.UWP.csproj b/Borepin/Borepin.UWP/Borepin.UWP.csproj index cff9dad..d9a65ed 100644 --- a/Borepin/Borepin.UWP/Borepin.UWP.csproj +++ b/Borepin/Borepin.UWP/Borepin.UWP.csproj @@ -143,7 +143,7 @@ - + diff --git a/Borepin/Borepin.iOS/Borepin.iOS.csproj b/Borepin/Borepin.iOS/Borepin.iOS.csproj index 33b6ba5..aac8173 100644 --- a/Borepin/Borepin.iOS/Borepin.iOS.csproj +++ b/Borepin/Borepin.iOS/Borepin.iOS.csproj @@ -130,7 +130,7 @@ - + diff --git a/Borepin/Borepin.macOS/Borepin.macOS.csproj b/Borepin/Borepin.macOS/Borepin.macOS.csproj index 21177a9..7bc19f0 100644 --- a/Borepin/Borepin.macOS/Borepin.macOS.csproj +++ b/Borepin/Borepin.macOS/Borepin.macOS.csproj @@ -1,6 +1,6 @@ - + - + Debug AnyCPU @@ -12,6 +12,8 @@ v2.0 Xamarin.Mac Resources + + true @@ -28,15 +30,19 @@ false true true - - - + + + + + + pdbonly true bin\Release - + + prompt 4 false @@ -47,22 +53,24 @@ true Entitlements.plist SdkOnly - - + + + + + + ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\Xamarin.Mac\Xamarin.Forms.Core.dll + + + ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\Xamarin.Mac\Xamarin.Forms.Platform.dll + + + ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\Xamarin.Mac\Xamarin.Forms.Xaml.dll + - - ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\Xamarin.Mac\Xamarin.Forms.Core.dll - - - ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\Xamarin.Mac\Xamarin.Forms.Platform.dll - - - ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\Xamarin.Mac\Xamarin.Forms.Xaml.dll - @@ -104,5 +112,12 @@ - + + + Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". + + + + + \ No newline at end of file diff --git a/Borepin/Borepin.macOS/packages.config b/Borepin/Borepin.macOS/packages.config index f09afaf..85b5327 100644 --- a/Borepin/Borepin.macOS/packages.config +++ b/Borepin/Borepin.macOS/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Borepin/Borepin/Borepin.csproj b/Borepin/Borepin/Borepin.csproj index 7c81734..16bdb1b 100644 --- a/Borepin/Borepin/Borepin.csproj +++ b/Borepin/Borepin/Borepin.csproj @@ -20,7 +20,7 @@ - + diff --git a/NFC/NFC.csproj b/NFC/NFC.csproj index fdcc319..d823efa 100644 --- a/NFC/NFC.csproj +++ b/NFC/NFC.csproj @@ -5,9 +5,9 @@ - + - + diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs index 5b053c3..092b9d1 100644 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs @@ -95,6 +95,23 @@ namespace NFC.Mifare_DESFire return arr; } + /// + /// Get Range of Array + /// + /// + /// + /// + /// + 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"); } + /// + /// Change Same DES key as Authenticated + /// + /// + /// + /// + 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"); + } + /// /// Change Same AES key as Authenticated /// @@ -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 read_data = new List(); + + 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 read_data = new List(); - - 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"); } + + ///// + ///// Write Data to File + ///// + ///// ID of File (0x01 - 0x10) + ///// Offset for File + ///// Data to write + //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"); + //} + /// /// Get all ApplicationIDS from PICC /// diff --git a/NFC_Test/FabAccess_OTA.cs b/NFC_Test/FabAccess_OTA.cs index 80e580b..353a6bd 100644 --- a/NFC_Test/FabAccess_OTA.cs +++ b/NFC_Test/FabAccess_OTA.cs @@ -62,7 +62,7 @@ namespace NFC_Test desfire.ChangeOtherKey_AES(0x01, _FabAccess_Application_AuthKey._Key, _Default_AESKey._Key, _FabAccess_Application_AuthKey._KeyVersion); UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00); - desfire.CreateFile_Standard(_FabAccess_FID, FileCommunication.PLAIN, accesRights, _FabAccess_FSize); + desfire.CreateFile_Standard(_FabAccess_FID, FileCommunication.MAC, accesRights, _FabAccess_FSize); desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes(_FabAccess_UserDomain)); @@ -95,7 +95,7 @@ namespace NFC_Test MIFARE_DESFire desfire = new MIFARE_DESFire(card); desfire.SelectApplication(_FabAccess_AID); - byte[] card_data = desfire.ReadData(_FabAccess_FID, 0x00, _FabAccess_FSize); + byte[] card_data = desfire.ReadData(_FabAccess_FID, 0x00, 0x0F); string userdomain = Encoding.ASCII.GetString(card_data).Replace("\u0000", ""); string domain = userdomain.Split('@')[1]; diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs index 0951e4b..a754039 100644 --- a/NFC_Test/REAL_Windows.cs +++ b/NFC_Test/REAL_Windows.cs @@ -9,6 +9,7 @@ using NFC.Mifare_DESFire; using NFC.Mifare_DESFire.Enums; using NFC.ISO7816_4; using PCSC.Iso7816; +using NFC.Crypto; namespace NFC_Test { @@ -58,5 +59,71 @@ namespace NFC_Test reader.Stop(); reader.CardDiscovered -= handler; } + + [TestCase("ACS ACR122U PICC Interface 0")] + public void Read(string readerID) + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool connected_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x2A472D); + Console.WriteLine(HexConverter.ConvertToHexString(desfire.ReadData(0x01, 0x00, 0xF0))); + + connected_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, connected_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [TestCase("ACS ACR122U PICC Interface 0")] + public void Write(string readerID) + { + IHardware hardware = new Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool connected_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x2A472D); + + CipherKey _FabAccess_Application_MasterKey = new CipherKey("50645367566B59703273357638792F42", CipherType.AES, 0x10); + + desfire.AuthenticateISO_AES(0x00, _FabAccess_Application_MasterKey._Key); + desfire.WriteData(0x01, 0x00, HexConverter.ConvertFromHexString("7468656a6f6b6c6c")); + + connected_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, connected_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } } } From 6c51e4089107e30916876b59679f4a0f32e4d09c Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Sat, 7 Nov 2020 01:14:51 +0100 Subject: [PATCH 18/21] Added: Complete Real Test --- NFC/ISO7816-4/APDUResponse.cs | 20 + NFC/NXP MIFARE DESFire/APDUStatusCodes.cs | 2 - NFC/NXP MIFARE DESFire/CMAC.cs | 106 ---- NFC/NXP MIFARE DESFire/CryptoOperations.cs | 13 - NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs | 567 +++++++----------- .../PCSC/{Hardware.cs => PCSC_Hardware.cs} | 4 +- .../PCSC/{Reader.cs => PCSC_Reader.cs} | 6 +- NFC_Test/Crypto/AES_Test.cs | 16 +- NFC_Test/Crypto/CRC16_Test.cs | 2 +- NFC_Test/Crypto/CRC32_Test.cs | 2 +- NFC_Test/Crypto/CipherKey_Test.cs | 13 + NFC_Test/Crypto/TDES_Test.cs | 36 +- NFC_Test/HexConverter_Test.cs | 2 +- NFC_Test/ISO7816-4/APDUCommand_Test.cs | 2 +- .../NXP MIFARE DESFire/Command_Card_Test.cs | 308 ---------- NFC_Test/NXP MIFARE DESFire/Command_Test.cs | 10 - .../NXP MIFARE DESFire/MIFARE_DESFire_Test.cs | 193 ++++-- NFC_Test/NamespaceSetUp.cs | 21 +- NFC_Test/REAL_DESFireCommands.cs | 477 +++++++++++++++ ...FabAccess_OTA.cs => REAL_FabAccess_OTA.cs} | 37 +- NFC_Test/REAL_Reader_PCSC.cs | 62 ++ NFC_Test/REAL_Windows.cs | 129 ---- NFC_Test/REAL_Windows_CardSetUp.cs | 191 ------ 23 files changed, 1020 insertions(+), 1199 deletions(-) delete mode 100644 NFC/NXP MIFARE DESFire/CMAC.cs delete mode 100644 NFC/NXP MIFARE DESFire/CryptoOperations.cs rename NFC/Readers/PCSC/{Hardware.cs => PCSC_Hardware.cs} (87%) rename NFC/Readers/PCSC/{Reader.cs => PCSC_Reader.cs} (88%) create mode 100644 NFC_Test/Crypto/CipherKey_Test.cs delete mode 100644 NFC_Test/NXP MIFARE DESFire/Command_Card_Test.cs delete mode 100644 NFC_Test/NXP MIFARE DESFire/Command_Test.cs create mode 100644 NFC_Test/REAL_DESFireCommands.cs rename NFC_Test/{FabAccess_OTA.cs => REAL_FabAccess_OTA.cs} (82%) create mode 100644 NFC_Test/REAL_Reader_PCSC.cs delete mode 100644 NFC_Test/REAL_Windows.cs delete mode 100644 NFC_Test/REAL_Windows_CardSetUp.cs diff --git a/NFC/ISO7816-4/APDUResponse.cs b/NFC/ISO7816-4/APDUResponse.cs index a52d62b..61e8501 100644 --- a/NFC/ISO7816-4/APDUResponse.cs +++ b/NFC/ISO7816-4/APDUResponse.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Linq; using NFC.Mifare_DESFire; @@ -129,6 +130,25 @@ namespace NFC.ISO7816_4 return array; } + + public override bool Equals(object obj) + { + return obj is APDUResponse response && + EqualityComparer.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); + } #endregion } } diff --git a/NFC/NXP MIFARE DESFire/APDUStatusCodes.cs b/NFC/NXP MIFARE DESFire/APDUStatusCodes.cs index a06327b..06fa336 100644 --- a/NFC/NXP MIFARE DESFire/APDUStatusCodes.cs +++ b/NFC/NXP MIFARE DESFire/APDUStatusCodes.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; namespace NFC.Mifare_DESFire { diff --git a/NFC/NXP MIFARE DESFire/CMAC.cs b/NFC/NXP MIFARE DESFire/CMAC.cs deleted file mode 100644 index 532aa23..0000000 --- a/NFC/NXP MIFARE DESFire/CMAC.cs +++ /dev/null @@ -1,106 +0,0 @@ -using NFC.Crypto; -using System; - -namespace NFC.NXP_MIFARE_DESFire -{ - public class CMAC - { - #region Contructors - public CMAC(CipherType cipher) - { - switch(cipher) - { - case(CipherType.TDES): - _Cipher = new TDES(); - break; - case(CipherType.TDES_2K): - _Cipher = new TDES_2K(); - break; - case(CipherType.TDES_3K): - _Cipher = new TDES_3K(); - break; - case (CipherType.AES): - _Cipher = new AES(); - break; - default: - throw new ArgumentException("Unkown Cipher Type."); - } - } - - public CMAC(ICipher cipher) - { - _Cipher = cipher ?? throw new ArgumentNullException(); - } - #endregion - - #region Properties - private ICipher _Cipher; - #endregion - - #region Methods - /// - /// Generate Key with all Zeros, in KeySize - /// - public byte[] GenerateEmpytKey() - { - byte[] key = new byte[_Cipher.KeySize]; - for (int i = 0; i < _Cipher.KeySize; i++) - { - key[i] = 0; - } - - return key; - } - - /// - /// Generate IV with all Zeros, in KeySize - /// - public byte[] GenerateEmpytIV() - { - byte[] key = new byte[_Cipher.BlockSize]; - for (int i = 0; i < _Cipher.BlockSize; i++) - { - key[i] = 0; - } - - return key; - } - - /// - /// Encrypt Data - /// - public byte[] Encrypt(byte[] data) - { - throw new NotImplementedException(); - } - - /// - /// Decrypt Data - /// - public byte[] Decrypt(byte[] data) - { - throw new NotImplementedException(); - } - - /// - /// - /// - /// Two Keys - public byte[][] GenerateSubKey() - { - throw new NotImplementedException(); - } - - /// - /// - /// - /// - /// - public byte[] Digest(byte[] data) - { - throw new NotImplementedException(); - } - - #endregion - } -} diff --git a/NFC/NXP MIFARE DESFire/CryptoOperations.cs b/NFC/NXP MIFARE DESFire/CryptoOperations.cs deleted file mode 100644 index 0ae77af..0000000 --- a/NFC/NXP MIFARE DESFire/CryptoOperations.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace NFC.Mifare_DESFire -{ - enum CryptoOperations : byte - { - TDES = 0x00, - TKTDES = 0x40, - AES = 0x80, - } -} diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs index 092b9d1..185d78c 100644 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs @@ -1,5 +1,4 @@ -using log4net.Repository.Hierarchy; -using NFC.Crypto; +using NFC.Crypto; using NFC.ISO7816_4; using NFC.Mifare_DESFire.Enums; using NFC.NXP_MIFARE_DESFire.Exceptions; @@ -7,7 +6,6 @@ using PCSC.Iso7816; using System; using System.Collections.Generic; using System.Linq; -using System.Reflection; namespace NFC.Mifare_DESFire { @@ -54,7 +52,7 @@ namespace NFC.Mifare_DESFire /// Generate Byte Array filled with 0 /// /// Size of Array - public byte[] GenerateEmptyKey(uint size) + public byte[] GenerateEmptyArray(uint size) { byte[] key = new byte[size]; for (int i = 0; i < size; i++) @@ -66,42 +64,12 @@ namespace NFC.Mifare_DESFire } /// - /// Converts byte[] to string with HEX Code - /// No 0x is created + /// Get Range of Array Elements /// - /// Data - public string ConvertToHexString(byte[] data) - { - return BitConverter.ToString(data).Replace("-", "").ToLower(); - } - - /// - /// Converts string with HEX Code to byte[] - /// No 0x is requiered - /// - /// Data - public byte[] ConvertFromHexString(string data) - { - if (data.Length % 2 == 1) - throw new Exception("Data Length is uneven."); - - byte[] arr = new byte[data.Length >> 1]; - - for (int i = 0; i < data.Length >> 1; ++i) - { - arr[i] = (byte)((GetHexVal(data[i << 1]) << 4) + (GetHexVal(data[(i << 1) + 1]))); - } - - return arr; - } - - /// - /// Get Range of Array - /// - /// - /// - /// - /// + /// Array + /// Offset in Byte + /// Lenght to read in Byte + /// new Array with Range of Array Elements public byte[] GetSubArray(byte[] array, long offset, long length) { byte[] subarray = new byte[length]; @@ -112,17 +80,6 @@ namespace NFC.Mifare_DESFire return subarray; } - private int GetHexVal(char hex) - { - int val = (int)hex; - //For uppercase A-F letters: - //return val - (val < 58 ? 48 : 55); - //For lowercase a-f letters: - //return val - (val < 58 ? 48 : 87); - //Or the two combined, but a bit slower: - return val - (val < 58 ? 48 : (val < 97 ? 55 : 87)); - } - /// /// Check APDU Response for DESFire Error Codes /// https://www.nxp.com/docs/en/data-sheet/MF2DLHX0.pdf @@ -206,6 +163,35 @@ namespace NFC.Mifare_DESFire return lastblock; } + /// + /// Expand Array to Block Size, fill with 0x00 + /// + /// + public byte[] ExpandToBlockSize(byte[] data, uint bocksize) + { + if (data == null) + { + throw new ArgumentNullException("Data cannot be null."); + } + + int diff = data.Length % (int)bocksize; + if (diff == 0) + { + return data; + } + + byte[] expand = new byte[data.Length + bocksize - diff]; + + data.CopyTo(expand, 0); + + for (int i = expand.Length - 1; i > data.Length - 1; i--) + { + expand[i] = 0x00; + } + + return expand; + } + /// /// Rotates Array to the left /// @@ -310,6 +296,7 @@ namespace NFC.Mifare_DESFire return c; } + /// /// Generates SessionKey for DES Authentification /// @@ -364,62 +351,89 @@ namespace NFC.Mifare_DESFire return sesssionkey; } + #endregion + #region Configuration Generator /// - /// Set KeyVersion in DES Key - /// KeyVersion is stored in LSB of the first 8 Bytes of the DES Key + /// Genearte KeySetting1 for Application Settings or PICC Setting /// - public byte[] SetKeyVersion(byte[] key, byte keyversion) + public byte GenerateKeySetting1(ChangeApplicationKey changeKey, ChangeMasterKeySettings changeMasterKeySettings, CreateDeleteFile createDeleteFile, FileDirectoryAccess fileDirectoryAccess, ChangeMasterKey changeMasterKey) { - byte[] pow2 = new byte[] - { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 - }; - - byte[] new_key = new byte[key.Length]; - key.CopyTo(new_key, 0); - - for (int i = 0; i < 8; i++) - { - if ((keyversion & pow2[i]) > 0) - { - new_key[i] = (byte)(new_key[5] | 0x01); - } - else - { - new_key[i] = (byte)(new_key[5] & 0x7F); - } - } - - return new_key; + return (byte)(((byte)changeKey << 4) | (byte)changeMasterKeySettings | (byte)createDeleteFile | (byte)fileDirectoryAccess | (byte)changeMasterKey); } /// - /// Expand Array to Block Size, fill with 0x00 + /// Genearte KeySetting1 for Application Settings or PICC Setting /// - /// - public byte[] ExpandToBlockSize(byte[] data, uint bocksize) + /// ID of Key for changing Application Keys + /// + public byte GenerateKeySetting1(byte changeKey, ChangeMasterKeySettings changeMasterKeySettings, CreateDeleteFile createDeleteFile, FileDirectoryAccess fileDirectoryAccess, ChangeMasterKey changeMasterKey) { - int diff = data.Length % (int)bocksize; - if (diff == 0) + if (changeKey < 0x01 || changeKey >= 0x0E) { - return data; + throw new ArgumentOutOfRangeException(); + } + return GenerateKeySetting1((ChangeApplicationKey)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(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys) + { + if (numberOfKeys < 0x01 || numberOfKeys >= 0x0D) + { + throw new ArgumentOutOfRangeException(); } - byte[] expand = new byte[data.Length + bocksize - diff]; + return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys); + } - data.CopyTo(expand, 0); - - for (int i = expand.Length - 1; i > data.Length - 1; i--) + /// + /// Generate FileAccess Rights for File Settings + /// Use enum AccesRights for Free or Never Option + /// + /// KeyID for Read Access + /// KeyID for Write Access + /// KeyID for Read and Write Access + /// KeyID for Configuration Access + public UInt16 GenerateFileAccessRights(byte read, byte write, byte read_write, byte configure) + { + if (read > 0x0F || write > 0x0F || read_write > 0x0F || configure > 0x0F) { - expand[i] = 0x00; + throw new ArgumentOutOfRangeException("One KeyID is not valid"); } - return expand; + return (UInt16)((read << 12) | (write << 8) | (read_write << 4) | configure); } #endregion #region DESFire Commands + /// + /// Format PICC + /// Works after PICC Authentication + /// + public void Format() + { + _Log.Debug("Start Format"); + + APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short) + { + CLA = 0x90, + INS = 0xFC, + }; + _Log.DebugFormat("APDU_CMD(cmd_format): {0}", HexConverter.ConvertToHexString(cmd_format.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_format); + _Log.DebugFormat("APDU_RES(cmd_format): {0}", HexConverter.ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + + _Log.Debug("End Format"); + } + /// /// Authenticate to PICC, with ISO Authenticate /// @@ -443,24 +457,24 @@ namespace NFC.Mifare_DESFire key_id } }; - _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", HexConverter.ConvertToHexString(cmd_challange_request.ToArray())); APDUResponse response = _Card.Transmit(cmd_challange_request); - _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", HexConverter.ConvertToHexString(response.ToArray())); CheckAPDUResponse(response); byte[] rndB_enc = response.Body; - _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc)); + _Log.DebugFormat("rndB_enc: {0}", HexConverter.ConvertToHexString(rndB_enc)); TDES des = new TDES(); - byte[] rndB = des.Decrypt(rndB_enc, key, GenerateEmptyKey(8)); - _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB)); + byte[] rndB = des.Decrypt(rndB_enc, key, GenerateEmptyArray(8)); + _Log.DebugFormat("rndB: {0}", HexConverter.ConvertToHexString(rndB)); rndB.CopyTo(iv, 0); byte[] rndB_rl = RotateLeft(rndB); - _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl)); + _Log.DebugFormat("rndB_enc: {0}", HexConverter.ConvertToHexString(rndB_rl)); if(rndA == null) { @@ -468,13 +482,13 @@ namespace NFC.Mifare_DESFire rndA = new byte[8]; rnd.NextBytes(rndA); } - _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA)); + _Log.DebugFormat("rndA: {0}", HexConverter.ConvertToHexString(rndA)); byte[] rndAB = Concatenate(rndA, rndB_rl); - _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB)); + _Log.DebugFormat("rndAB: {0}", HexConverter.ConvertToHexString(rndAB)); byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc); - _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc)); + _Log.DebugFormat("rndA_rndB_enc: {0}", HexConverter.ConvertToHexString(rndAB_enc)); iv = ExtractLastBlock(rndAB_enc, 8); APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) @@ -483,21 +497,21 @@ namespace NFC.Mifare_DESFire INS = 0xAF, Data = rndAB_enc }; - _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray())); response = _Card.Transmit(cmd_challange_response); - _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray())); CheckAPDUResponse(response); byte[] encryptedRndAFromCard = response.Body; - _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard)); + _Log.DebugFormat("encryptedRndAFromCard: {0}", HexConverter.ConvertToHexString(encryptedRndAFromCard)); byte[] rotatedRndAFromCard = des.Decrypt(encryptedRndAFromCard, key, iv); - _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard)); + _Log.DebugFormat("rotatedRndAFromCard: {0}", HexConverter.ConvertToHexString(rotatedRndAFromCard)); byte[] rndAFromCard = RotateRight(rotatedRndAFromCard); - _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard)); + _Log.DebugFormat("rndAFromCard: {0}", HexConverter.ConvertToHexString(rndAFromCard)); if (!rndA.SequenceEqual(rndAFromCard)) { @@ -505,36 +519,14 @@ namespace NFC.Mifare_DESFire } _SessionKey = GenerateSesionKey_DES(rndA, rndB); - _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey)); + _Log.DebugFormat("_SessionKey: {0}", HexConverter.ConvertToHexString(_SessionKey)); - _IV = GenerateEmptyKey(8); - _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); + _IV = GenerateEmptyArray(8); + _Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV)); _Log.Debug("End AuthenticateISO_DES"); } - /// - /// Format PICC - /// - public void Format() - { - _Log.Debug("Start Format"); - - APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short) - { - CLA = 0x90, - INS = 0xFC, - }; - _Log.DebugFormat("APDU_CMD(cmd_format): {0}", ConvertToHexString(cmd_format.ToArray())); - - APDUResponse response = _Card.Transmit(cmd_format); - _Log.DebugFormat("APDU_RES(cmd_format): {0}", ConvertToHexString(response.ToArray())); - - CheckAPDUResponse(response); - - _Log.Debug("End Format"); - } - /// /// Create Application for ID /// @@ -544,7 +536,7 @@ namespace NFC.Mifare_DESFire _Log.Debug("Start CreateApplication"); byte[] id_byte = BitConverter.GetBytes(aid); - _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray())); + _Log.DebugFormat("AID: {0}", HexConverter.ConvertToHexString(id_byte.ToArray())); APDUCommand cmd_CreateApplication = new APDUCommand(IsoCase.Case4Short) { @@ -559,10 +551,10 @@ namespace NFC.Mifare_DESFire keysetting2 } }; - _Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", ConvertToHexString(cmd_CreateApplication.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", HexConverter.ConvertToHexString(cmd_CreateApplication.ToArray())); APDUResponse response = _Card.Transmit(cmd_CreateApplication); - _Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", ConvertToHexString(response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", HexConverter.ConvertToHexString(response.ToArray())); CheckAPDUResponse(response); @@ -578,7 +570,7 @@ namespace NFC.Mifare_DESFire _Log.Debug("Start SelectApplication"); byte[] id_byte = BitConverter.GetBytes(aid); - _Log.DebugFormat("AID: {0}", ConvertToHexString(id_byte.ToArray())); + _Log.DebugFormat("AID: {0}", HexConverter.ConvertToHexString(id_byte.ToArray())); APDUCommand cmd_SelectApplication = new APDUCommand(IsoCase.Case4Short) { @@ -591,10 +583,10 @@ namespace NFC.Mifare_DESFire id_byte[2] } }; - _Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", ConvertToHexString(cmd_SelectApplication.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", HexConverter.ConvertToHexString(cmd_SelectApplication.ToArray())); APDUResponse response = _Card.Transmit(cmd_SelectApplication); - _Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", ConvertToHexString(response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", HexConverter.ConvertToHexString(response.ToArray())); CheckAPDUResponse(response); @@ -624,24 +616,24 @@ namespace NFC.Mifare_DESFire key_id } }; - _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", ConvertToHexString(cmd_challange_request.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", HexConverter.ConvertToHexString(cmd_challange_request.ToArray())); APDUResponse response = _Card.Transmit(cmd_challange_request); - _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", ConvertToHexString(response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", HexConverter.ConvertToHexString(response.ToArray())); CheckAPDUResponse(response); byte[] rndB_enc = response.Body; - _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_enc)); + _Log.DebugFormat("rndB_enc: {0}", HexConverter.ConvertToHexString(rndB_enc)); AES aes = new AES(); - byte[] rndB = aes.Decrypt(rndB_enc, key, GenerateEmptyKey(16)); - _Log.DebugFormat("rndB: {0}", ConvertToHexString(rndB)); + byte[] rndB = aes.Decrypt(rndB_enc, key, GenerateEmptyArray(16)); + _Log.DebugFormat("rndB: {0}", HexConverter.ConvertToHexString(rndB)); rndB.CopyTo(iv, 0); byte[] rndB_rl = RotateLeft(rndB); - _Log.DebugFormat("rndB_enc: {0}", ConvertToHexString(rndB_rl)); + _Log.DebugFormat("rndB_enc: {0}", HexConverter.ConvertToHexString(rndB_rl)); if (rndA == null) { @@ -649,13 +641,13 @@ namespace NFC.Mifare_DESFire rndA = new byte[16]; rnd.NextBytes(rndA); } - _Log.DebugFormat("rndA: {0}", ConvertToHexString(rndA)); + _Log.DebugFormat("rndA: {0}", HexConverter.ConvertToHexString(rndA)); byte[] rndAB = Concatenate(rndA, rndB_rl); - _Log.DebugFormat("rndAB: {0}", ConvertToHexString(rndAB)); + _Log.DebugFormat("rndAB: {0}", HexConverter.ConvertToHexString(rndAB)); byte[] rndAB_enc = aes.Encrypt(rndAB, key, rndB_enc); - _Log.DebugFormat("rndA_rndB_enc: {0}", ConvertToHexString(rndAB_enc)); + _Log.DebugFormat("rndA_rndB_enc: {0}", HexConverter.ConvertToHexString(rndAB_enc)); iv = ExtractLastBlock(rndAB_enc, 16); APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) @@ -664,21 +656,21 @@ namespace NFC.Mifare_DESFire INS = 0xAF, Data = rndAB_enc }; - _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray())); response = _Card.Transmit(cmd_challange_response); - _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", ConvertToHexString(cmd_challange_response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray())); CheckAPDUResponse(response); byte[] encryptedRndAFromCard = response.Body; - _Log.DebugFormat("encryptedRndAFromCard: {0}", ConvertToHexString(encryptedRndAFromCard)); + _Log.DebugFormat("encryptedRndAFromCard: {0}", HexConverter.ConvertToHexString(encryptedRndAFromCard)); byte[] rotatedRndAFromCard = aes.Decrypt(encryptedRndAFromCard, key, iv); - _Log.DebugFormat("rotatedRndAFromCard: {0}", ConvertToHexString(rotatedRndAFromCard)); + _Log.DebugFormat("rotatedRndAFromCard: {0}", HexConverter.ConvertToHexString(rotatedRndAFromCard)); byte[] rndAFromCard = RotateRight(rotatedRndAFromCard); - _Log.DebugFormat("rndAFromCard: {0}", ConvertToHexString(rndAFromCard)); + _Log.DebugFormat("rndAFromCard: {0}", HexConverter.ConvertToHexString(rndAFromCard)); if (!rndA.SequenceEqual(rndAFromCard)) { @@ -686,10 +678,10 @@ namespace NFC.Mifare_DESFire } _SessionKey = GenerateSesionKey_AES(rndA, rndB); - _Log.DebugFormat("_SessionKey: {0}", ConvertToHexString(_SessionKey)); + _Log.DebugFormat("_SessionKey: {0}", HexConverter.ConvertToHexString(_SessionKey)); - _IV = GenerateEmptyKey(16); - _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); + _IV = GenerateEmptyArray(16); + _Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV)); _Log.Debug("End AuthenticateISO_DES"); } @@ -708,31 +700,31 @@ namespace NFC.Mifare_DESFire { 0xC4, key_id }; - _Log.DebugFormat("header: {0}", ConvertToHexString(header)); + _Log.DebugFormat("header: {0}", HexConverter.ConvertToHexString(header)); byte[] key_and_version = new_key; byte[] command = Concatenate(header, key_and_version); - _Log.DebugFormat("command: {0}", ConvertToHexString(command)); + _Log.DebugFormat("command: {0}", HexConverter.ConvertToHexString(command)); CRC32 crc32 = new CRC32(); byte[] crc = crc32.Calculate(command); - _Log.DebugFormat("crc: {0}", ConvertToHexString(crc)); + _Log.DebugFormat("crc: {0}", HexConverter.ConvertToHexString(crc)); byte[] cryptogram = Concatenate(key_and_version, crc); - _Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram)); + _Log.DebugFormat("cryptogram: {0}", HexConverter.ConvertToHexString(cryptogram)); byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16); - _Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block)); + _Log.DebugFormat("cryptogram_block: {0}", HexConverter.ConvertToHexString(cryptogram_block)); TDES des = new TDES(); byte[] cryptogram_enc = des.Encrypt(cryptogram_block, _SessionKey, _IV); - _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc)); + _Log.DebugFormat("cryptogram_enc: {0}", HexConverter.ConvertToHexString(cryptogram_enc)); _IV = ExtractLastBlock(cryptogram_enc, 8); - _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); + _Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV)); byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc); - _Log.DebugFormat("data: {0}", ConvertToHexString(data)); + _Log.DebugFormat("data: {0}", HexConverter.ConvertToHexString(data)); APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short) { @@ -740,10 +732,10 @@ namespace NFC.Mifare_DESFire INS = 0xC4, Data = data }; - _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(cmd_ChangeKey.ToArray())); APDUResponse response = _Card.Transmit(cmd_ChangeKey); - _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(response.ToArray())); CheckAPDUResponse(response); @@ -764,32 +756,32 @@ namespace NFC.Mifare_DESFire { 0xC4, key_id }; - _Log.DebugFormat("header: {0}", ConvertToHexString(header)); + _Log.DebugFormat("header: {0}", HexConverter.ConvertToHexString(header)); // AES Key Version is Append to Key byte[] key_and_version = Concatenate(new_key, new byte[] { key_version }); byte[] command = Concatenate(header, key_and_version); - _Log.DebugFormat("command: {0}", ConvertToHexString(command)); + _Log.DebugFormat("command: {0}", HexConverter.ConvertToHexString(command)); CRC32 crc32 = new CRC32(); byte[] crc = crc32.Calculate(command); - _Log.DebugFormat("crc: {0}", ConvertToHexString(crc)); + _Log.DebugFormat("crc: {0}", HexConverter.ConvertToHexString(crc)); byte[] cryptogram = Concatenate(key_and_version, crc); - _Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram)); + _Log.DebugFormat("cryptogram: {0}", HexConverter.ConvertToHexString(cryptogram)); byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16); - _Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block)); + _Log.DebugFormat("cryptogram_block: {0}", HexConverter.ConvertToHexString(cryptogram_block)); AES aes = new AES(); byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV); - _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc)); + _Log.DebugFormat("cryptogram_enc: {0}", HexConverter.ConvertToHexString(cryptogram_enc)); _IV = ExtractLastBlock(cryptogram_enc, 16); - _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); + _Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV)); byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc); - _Log.DebugFormat("data: {0}", ConvertToHexString(data)); + _Log.DebugFormat("data: {0}", HexConverter.ConvertToHexString(data)); APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short) { @@ -797,10 +789,10 @@ namespace NFC.Mifare_DESFire INS = 0xC4, Data = data }; - _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(cmd_ChangeKey.ToArray())); APDUResponse response = _Card.Transmit(cmd_ChangeKey); - _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(response.ToArray())); CheckAPDUResponse(response); @@ -821,37 +813,37 @@ namespace NFC.Mifare_DESFire { 0xC4, key_id }; - _Log.DebugFormat("header: {0}", ConvertToHexString(header)); + _Log.DebugFormat("header: {0}", HexConverter.ConvertToHexString(header)); byte[] key_xor = XOR(new_key, old_key); // AES Key Version is Append to Key byte[] key_and_version = Concatenate(key_xor, new byte[] { key_version }); byte[] command = Concatenate(header, key_and_version); - _Log.DebugFormat("command: {0}", ConvertToHexString(command)); + _Log.DebugFormat("command: {0}", HexConverter.ConvertToHexString(command)); CRC32 crc32 = new CRC32(); byte[] crc_cmd = crc32.Calculate(command); - _Log.DebugFormat("crc_cmd: {0}", ConvertToHexString(crc_cmd)); + _Log.DebugFormat("crc_cmd: {0}", HexConverter.ConvertToHexString(crc_cmd)); byte[] crc_key = crc32.Calculate(new_key); - _Log.DebugFormat("crc_key: {0}", ConvertToHexString(crc_key)); + _Log.DebugFormat("crc_key: {0}", HexConverter.ConvertToHexString(crc_key)); byte[] cryptogram = Concatenate(key_and_version, crc_cmd); cryptogram = Concatenate(cryptogram, crc_key); - _Log.DebugFormat("cryptogram: {0}", ConvertToHexString(cryptogram)); + _Log.DebugFormat("cryptogram: {0}", HexConverter.ConvertToHexString(cryptogram)); byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16); - _Log.DebugFormat("cryptogram_block: {0}", ConvertToHexString(cryptogram_block)); + _Log.DebugFormat("cryptogram_block: {0}", HexConverter.ConvertToHexString(cryptogram_block)); AES aes = new AES(); byte[] cryptogram_enc = aes.Encrypt(cryptogram_block, _SessionKey, _IV); - _Log.DebugFormat("cryptogram_enc: {0}", ConvertToHexString(cryptogram_enc)); + _Log.DebugFormat("cryptogram_enc: {0}", HexConverter.ConvertToHexString(cryptogram_enc)); _IV = ExtractLastBlock(cryptogram_enc, 16); - _Log.DebugFormat("_IV: {0}", ConvertToHexString(_IV)); + _Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV)); byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc); - _Log.DebugFormat("data: {0}", ConvertToHexString(data)); + _Log.DebugFormat("data: {0}", HexConverter.ConvertToHexString(data)); APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short) { @@ -859,10 +851,10 @@ namespace NFC.Mifare_DESFire INS = 0xC4, Data = data }; - _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", ConvertToHexString(cmd_ChangeKey.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(cmd_ChangeKey.ToArray())); APDUResponse response = _Card.Transmit(cmd_ChangeKey); - _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", ConvertToHexString(response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(response.ToArray())); CheckAPDUResponse(response); @@ -904,10 +896,10 @@ namespace NFC.Mifare_DESFire INS = (byte)APDUInstructions.CREATE_STDDATAFILE, Data = Concatenate(data, accessRights_byte, size_byte) }; - _Log.DebugFormat("APDU_CMD(cmd_CreateFile_Standard): {0}", ConvertToHexString(cmd_CreateFile_Standard.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_CreateFile_Standard): {0}", HexConverter.ConvertToHexString(cmd_CreateFile_Standard.ToArray())); APDUResponse response = _Card.Transmit(cmd_CreateFile_Standard); - _Log.DebugFormat("APDU_RES(cmd_CreateFile_Standard): {0}", ConvertToHexString(response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_CreateFile_Standard): {0}", HexConverter.ConvertToHexString(response.ToArray())); CheckAPDUResponse(response); @@ -924,7 +916,7 @@ namespace NFC.Mifare_DESFire { _Log.Debug("Start ReadData"); - int max_read_bytes_pre_transaction = 58; + int max_read_bytes_pre_transaction = 47; long bytes_readed = 0; List read_data = new List(); @@ -973,10 +965,10 @@ namespace NFC.Mifare_DESFire INS = (byte)APDUInstructions.READ_DATA, Data = Concatenate(data, offset_byte, length_byte) }; - _Log.DebugFormat("APDU_CMD(cmd_ReadData): {0}", ConvertToHexString(cmd_ReadData.ToArray())); + _Log.DebugFormat("APDU_CMD(cmd_ReadData): {0}", HexConverter.ConvertToHexString(cmd_ReadData.ToArray())); APDUResponse response = _Card.Transmit(cmd_ReadData); - _Log.DebugFormat("APDU_RES(cmd_ReadData): {0}", ConvertToHexString(response.ToArray())); + _Log.DebugFormat("APDU_RES(cmd_ReadData): {0}", HexConverter.ConvertToHexString(response.ToArray())); CheckAPDUResponse(response); read_data.AddRange(response.Body); @@ -996,119 +988,69 @@ namespace NFC.Mifare_DESFire { _Log.Debug("Start WriteData"); - byte[] file_id_array = new byte[] - { - file_id - }; + int max_write_bytes_pre_transaction = 47; + byte[] write_buffer; - byte[] offset_byte_tolong = BitConverter.GetBytes(offset); - // Use only 3 Bytes - byte[] offset_byte = new byte[] + 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], - }; + }; - byte[] lenght_byte_tolong = BitConverter.GetBytes(data.Length); - // Use only 3 Bytes - byte[] lenght_byte = new byte[] - { - lenght_byte_tolong[0], - lenght_byte_tolong[1], - lenght_byte_tolong[2], - }; + long bytes_towrite = 0; - APDUCommand cmd_WriteData = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = (byte)APDUInstructions.WRITE_DATA, - Data = Concatenate(file_id_array, offset_byte, lenght_byte, data) - }; - _Log.DebugFormat("APDU_CMD(cmd_WriteData): {0}", ConvertToHexString(cmd_WriteData.ToArray())); + if (length - bytes_writed < max_write_bytes_pre_transaction) + { + bytes_towrite = length - bytes_writed; + } + else + { + bytes_towrite = max_write_bytes_pre_transaction; + } - APDUResponse response = _Card.Transmit(cmd_WriteData); - _Log.DebugFormat("APDU_RES(cmd_WriteData): {0}", ConvertToHexString(response.ToArray())); + byte[] length_byte_tolong = BitConverter.GetBytes(bytes_towrite); - CheckAPDUResponse(response); + 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}", HexConverter.ConvertToHexString(cmd_WriteData.ToArray())); + + APDUResponse response = _Card.Transmit(cmd_WriteData); + _Log.DebugFormat("APDU_RES(cmd_WriteData): {0}", HexConverter.ConvertToHexString(response.ToArray())); + + CheckAPDUResponse(response); + } _Log.Debug("End WriteData"); } - - ///// - ///// Write Data to File - ///// - ///// ID of File (0x01 - 0x10) - ///// Offset for File - ///// Data to write - //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"); - //} - /// /// Get all ApplicationIDS from PICC /// @@ -1176,63 +1118,6 @@ namespace NFC.Mifare_DESFire // CheckAPDUResponse(response); //} #endregion - - #region Configuration Generator - /// - /// 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(CryptoOperationsType cryptoOperations, FileIdentifies fileIdentifies, byte numberOfKeys) - { - if (numberOfKeys < 0x01 || numberOfKeys >= 0x0D) - { - throw new ArgumentOutOfRangeException(); - } - - return (byte)((byte)cryptoOperations | (byte)fileIdentifies | numberOfKeys); - } - - /// - /// Generate FileAccess Rights for File Settings - /// Use enum AccesRights for Free or Never Option - /// - /// KeyID for Read Access - /// KeyID for Write Access - /// KeyID for Read and Write Access - /// KeyID for Configuration Access - public UInt16 GenerateFileAccessRights(byte read, byte write, byte read_write, byte configure) - { - if(read > 0x0F || write > 0x0F || read_write > 0x0F || configure > 0x0F) - { - throw new ArgumentOutOfRangeException("One KeyID is not valid"); - } - - return (UInt16)((read << 12) | (write << 8) | (read_write << 4) | configure); - } - #endregion #endregion } } diff --git a/NFC/Readers/PCSC/Hardware.cs b/NFC/Readers/PCSC/PCSC_Hardware.cs similarity index 87% rename from NFC/Readers/PCSC/Hardware.cs rename to NFC/Readers/PCSC/PCSC_Hardware.cs index efc2373..3f86805 100644 --- a/NFC/Readers/PCSC/Hardware.cs +++ b/NFC/Readers/PCSC/PCSC_Hardware.cs @@ -2,7 +2,7 @@ namespace NFC.Readers.PCSC { - public class Hardware : IHardware + public class PCSC_Hardware : IHardware { public string[] GetReaders() { @@ -27,7 +27,7 @@ namespace NFC.Readers.PCSC public IReader OpenReader(string readerID) { - return new Reader(readerID); + return new PCSC_Reader(readerID); } } } diff --git a/NFC/Readers/PCSC/Reader.cs b/NFC/Readers/PCSC/PCSC_Reader.cs similarity index 88% rename from NFC/Readers/PCSC/Reader.cs rename to NFC/Readers/PCSC/PCSC_Reader.cs index dfb440d..c0a399c 100644 --- a/NFC/Readers/PCSC/Reader.cs +++ b/NFC/Readers/PCSC/PCSC_Reader.cs @@ -1,13 +1,11 @@ using PCSC; using PCSC.Iso7816; using System; -using System.Collections.Generic; -using System.Text; namespace NFC.Readers.PCSC { - public class Reader : IReader, IDisposable + public class PCSC_Reader : IReader, IDisposable { private string _ReaderID; private IContextFactory _ContextFactory; @@ -15,7 +13,7 @@ namespace NFC.Readers.PCSC private IsoReader _ISOReader; private ICard _Card; - public Reader(string readerID) + public PCSC_Reader(string readerID) { _ReaderID = readerID; } diff --git a/NFC_Test/Crypto/AES_Test.cs b/NFC_Test/Crypto/AES_Test.cs index a4a2cf0..df41197 100644 --- a/NFC_Test/Crypto/AES_Test.cs +++ b/NFC_Test/Crypto/AES_Test.cs @@ -1,8 +1,8 @@ -using NFC.Crypto; -using NFC.Mifare_DESFire; +using NFC; +using NFC.Crypto; using NUnit.Framework; -namespace NFC_Test.Crypto +namespace NFC_Unit_Test.Crypto { [TestFixture] public class AES_Test @@ -10,16 +10,14 @@ namespace NFC_Test.Crypto [Test] public void Encrypt() { - MIFARE_DESFire desfire = new MIFARE_DESFire(null); - - byte[] data = desfire.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12104a3b07e8eb77a7ac00000000000000"); - byte[] key = desfire.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b"); - byte[] iv = desfire.ConvertFromHexString("00000000000000000000000000000000"); + byte[] data = HexConverter.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12104a3b07e8eb77a7ac00000000000000"); + byte[] key = HexConverter.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b"); + byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); AES aes = new AES(); byte[] data_enc = aes.Encrypt(data, key, iv); - byte[] data_enc_expected = desfire.ConvertFromHexString("3c79d74a4969ba7123e5d8f6df24493112d221fd131a4617d0eda5d92ccc1b46"); + byte[] data_enc_expected = HexConverter.ConvertFromHexString("3c79d74a4969ba7123e5d8f6df24493112d221fd131a4617d0eda5d92ccc1b46"); Assert.AreEqual(data_enc_expected, data_enc); } } diff --git a/NFC_Test/Crypto/CRC16_Test.cs b/NFC_Test/Crypto/CRC16_Test.cs index d174e05..3098f35 100644 --- a/NFC_Test/Crypto/CRC16_Test.cs +++ b/NFC_Test/Crypto/CRC16_Test.cs @@ -2,7 +2,7 @@ using NFC.Crypto; using NUnit.Framework; -namespace NFC_Test.Crypto +namespace NFC_Unit_Test.Crypto { [TestFixture] public class CRC16_Test diff --git a/NFC_Test/Crypto/CRC32_Test.cs b/NFC_Test/Crypto/CRC32_Test.cs index aa14248..f2ce5a8 100644 --- a/NFC_Test/Crypto/CRC32_Test.cs +++ b/NFC_Test/Crypto/CRC32_Test.cs @@ -2,7 +2,7 @@ using NFC.Crypto; using NUnit.Framework; -namespace NFC_Test.Crypto +namespace NFC_Unit_Test.Crypto { [TestFixture] public class CRC32_Test diff --git a/NFC_Test/Crypto/CipherKey_Test.cs b/NFC_Test/Crypto/CipherKey_Test.cs new file mode 100644 index 0000000..492d2d1 --- /dev/null +++ b/NFC_Test/Crypto/CipherKey_Test.cs @@ -0,0 +1,13 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Text; + +namespace NFC_Unit_Test.Crypto +{ + [TestFixture] + public class CipherKey_Test + { + + } +} diff --git a/NFC_Test/Crypto/TDES_Test.cs b/NFC_Test/Crypto/TDES_Test.cs index 3789040..fbf8ba0 100644 --- a/NFC_Test/Crypto/TDES_Test.cs +++ b/NFC_Test/Crypto/TDES_Test.cs @@ -1,8 +1,8 @@ -using NFC.Crypto; -using NFC.Mifare_DESFire; +using NFC; +using NFC.Crypto; using NUnit.Framework; -namespace NFC_Test.Crypto +namespace NFC_Unit_Test.Crypto { [TestFixture] public class TDES_Test @@ -11,16 +11,14 @@ namespace NFC_Test.Crypto [Ignore("Unknown Expected Data")] public void Encrypt_TDES() { - MIFARE_DESFire desfire = new MIFARE_DESFire(null); - - byte[] data = desfire.ConvertFromHexString(""); - byte[] key = desfire.ConvertFromHexString(""); - byte[] iv = desfire.ConvertFromHexString("0000000000000000"); + byte[] data = HexConverter.ConvertFromHexString(""); + byte[] key = HexConverter.ConvertFromHexString(""); + byte[] iv = HexConverter.ConvertFromHexString("0000000000000000"); TDES des = new TDES(); byte[] data_enc = des.Encrypt(data, key, iv); - byte[] data_enc_expected = desfire.ConvertFromHexString(""); + byte[] data_enc_expected = HexConverter.ConvertFromHexString(""); Assert.AreEqual(data_enc_expected, data_enc); } @@ -28,16 +26,14 @@ namespace NFC_Test.Crypto [Ignore("Unknown Expected Data")] public void Encrypt_TDES_2K() { - MIFARE_DESFire desfire = new MIFARE_DESFire(null); - - byte[] data = desfire.ConvertFromHexString(""); - byte[] key = desfire.ConvertFromHexString(""); - byte[] iv = desfire.ConvertFromHexString("0000000000000000"); + byte[] data = HexConverter.ConvertFromHexString(""); + byte[] key = HexConverter.ConvertFromHexString(""); + byte[] iv = HexConverter.ConvertFromHexString("0000000000000000"); TDES_2K des = new TDES_2K(); byte[] data_enc = des.Encrypt(data, key, iv); - byte[] data_enc_expected = desfire.ConvertFromHexString(""); + byte[] data_enc_expected = HexConverter.ConvertFromHexString(""); Assert.AreEqual(data_enc_expected, data_enc); } @@ -45,16 +41,14 @@ namespace NFC_Test.Crypto [Ignore("Unknown Expected Data")] public void Encrypt_TDES_3K() { - MIFARE_DESFire desfire = new MIFARE_DESFire(null); - - byte[] data = desfire.ConvertFromHexString(""); - byte[] key = desfire.ConvertFromHexString(""); - byte[] iv = desfire.ConvertFromHexString("0000000000000000"); + byte[] data = HexConverter.ConvertFromHexString(""); + byte[] key = HexConverter.ConvertFromHexString(""); + byte[] iv = HexConverter.ConvertFromHexString("0000000000000000"); TDES_3K des = new TDES_3K(); byte[] data_enc = des.Encrypt(data, key, iv); - byte[] data_enc_expected = desfire.ConvertFromHexString(""); + byte[] data_enc_expected = HexConverter.ConvertFromHexString(""); Assert.AreEqual(data_enc_expected, data_enc); } } diff --git a/NFC_Test/HexConverter_Test.cs b/NFC_Test/HexConverter_Test.cs index fba4be6..f20669c 100644 --- a/NFC_Test/HexConverter_Test.cs +++ b/NFC_Test/HexConverter_Test.cs @@ -1,7 +1,7 @@ using NFC; using NUnit.Framework; -namespace NFC_Test +namespace NFC_Unit_Test { public class HexConverter_Test { diff --git a/NFC_Test/ISO7816-4/APDUCommand_Test.cs b/NFC_Test/ISO7816-4/APDUCommand_Test.cs index 28c68e1..1688aea 100644 --- a/NFC_Test/ISO7816-4/APDUCommand_Test.cs +++ b/NFC_Test/ISO7816-4/APDUCommand_Test.cs @@ -3,7 +3,7 @@ using NFC.ISO7816_4; using NUnit.Framework; using PCSC.Iso7816; -namespace NFC_Test.ISO7816_4 +namespace NFC_Unit_Test.ISO7816_4 { [TestFixture] public class APDUCommand_Test diff --git a/NFC_Test/NXP MIFARE DESFire/Command_Card_Test.cs b/NFC_Test/NXP MIFARE DESFire/Command_Card_Test.cs deleted file mode 100644 index 92e2c21..0000000 --- a/NFC_Test/NXP MIFARE DESFire/Command_Card_Test.cs +++ /dev/null @@ -1,308 +0,0 @@ -using NFC; -using NFC.Crypto; -using NFC.Mifare_DESFire; -using NFC.Readers.PCSC; -using NUnit.Framework; -using NUnit.Framework.Constraints; -using System; -using System.Collections.Generic; -using System.Text; - -namespace NFC_Test.NXP_MIFARE_DESFire -{ - /// - /// Test all DESFire Commands with empty Card - /// - [Description("Test with real DESFire Card")] - [Explicit] - public class Command_Card_Test - { - public readonly string ReaderID = ""; - public readonly UInt32 AID = 0xAAFFEE; - public readonly string AES_Key_Master = "25432A462D4A614E645267556B587032"; - public readonly string AES_Key_1 = "50645367566B59703373367638792F42"; - - /// - /// Get ReaderIDs form PC/SC API - /// - [Test] - public void GetReaderIDs() - { - IHardware hardware = new Hardware(); - string[] readers = hardware.GetReaders(); - - Console.WriteLine("Readers detected: {0}", readers.Length); - - if (readers.Length > 0) - { - Console.WriteLine("List of ReaderIDs:"); - foreach (string readerID in readers) - { - Console.WriteLine("{0}", readerID); - } - } - } - - [Test] - public void Connect() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(ReaderID); - - bool connected_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - connected_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, connected_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [Test] - public void Format() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(ReaderID); - - bool test_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.Format(); - - test_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, test_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [Test] - public void SelectApplication() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(ReaderID); - - bool test_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(0x000000); - - test_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, test_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [Test] - public void Authenticate_DES() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(ReaderID); - - bool test_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(0x000000); - - CipherKey key = new CipherKey(CipherType.TDES); - desfire.AuthenticateISO_DES(0x00, key._Key); - - test_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, test_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - - [Test] - public void CreateApplication() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(ReaderID); - - bool test_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - CipherKey key = new CipherKey(CipherType.TDES); - desfire.AuthenticateISO_DES(0x00, key._Key); - - byte keysetting1 = desfire.GenerateKeySetting1(NFC.Mifare_DESFire.Enums.ChangeApplicationKey.ALLKEYS, NFC.Mifare_DESFire.Enums.ChangeMasterKeySettings.WITHMASTERKEY, NFC.Mifare_DESFire.Enums.CreateDeleteFile.NOKEY, NFC.Mifare_DESFire.Enums.FileDirectoryAccess.NOKEY, NFC.Mifare_DESFire.Enums.ChangeMasterKey.CHANGEABLE); - byte keysetting2 = desfire.GenerateKeySetting2(NFC.Mifare_DESFire.Enums.CryptoOperationsType.AES, NFC.Mifare_DESFire.Enums.FileIdentifies.NOTUSED, 2); - - desfire.CreateApplication(AID, keysetting1, keysetting2); - - test_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, test_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [Test] - public void Authenticate_AES() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(ReaderID); - - bool test_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(AID); - - CipherKey key = new CipherKey(CipherType.AES); - desfire.AuthenticateISO_AES(0x00, key._Key); - - test_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, test_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [Test] - public void ChangeApplicationMasterKey() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(ReaderID); - - bool test_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(AID); - - CipherKey key_default = new CipherKey(CipherType.AES); - desfire.AuthenticateISO_AES(0x00, key_default._Key); - - CipherKey key = new CipherKey(AES_Key_Master, CipherType.AES, 0x10); - desfire.ChangeKey_AES(0x00, key._Key, key._KeyVersion); - - test_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, test_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [Test] - public void ChangeApplicationKey_1() - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(ReaderID); - - bool test_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(AID); - - CipherKey key_master = new CipherKey(AES_Key_Master, CipherType.AES, 0x10); - desfire.AuthenticateISO_AES(0x00, key_master._Key); - - CipherKey key_old = new CipherKey(AES_Key_1, CipherType.AES, 0x10); - CipherKey key_new = new CipherKey(AES_Key_1, CipherType.AES, 0x10); - desfire.ChangeOtherKey_AES(0x01, key_new._Key, key_old._Key, key_new._KeyVersion); - - test_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, test_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - } -} diff --git a/NFC_Test/NXP MIFARE DESFire/Command_Test.cs b/NFC_Test/NXP MIFARE DESFire/Command_Test.cs deleted file mode 100644 index f154e3f..0000000 --- a/NFC_Test/NXP MIFARE DESFire/Command_Test.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace NFC_Test.NXP_MIFARE_DESFire -{ - class Command_Test - { - } -} diff --git a/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs b/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs index 0a1b6d5..22de52a 100644 --- a/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs +++ b/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs @@ -1,4 +1,5 @@ using NFC; +using NFC.Mifare_DESFire.Enums; using NFC.ISO7816_4; using NFC.Mifare_DESFire; using NFC.NXP_MIFARE_DESFire.Exceptions; @@ -6,30 +7,48 @@ using NSubstitute; using NUnit.Framework; using System; -namespace NFC_Test.NXP_MIFARE_DESFire +namespace NFC_Unit_Test.NXP_MIFARE_DESFire { [TestFixture] public class MIFARE_DESFire_Test { #region Helper Methods [Test] - public void GenerateDefaultKey() + public void GenerateEmptyArray() { uint i = 16; MIFARE_DESFire desfire = new MIFARE_DESFire(null); - byte[] data = desfire.GenerateEmptyKey(i); + byte[] data = desfire.GenerateEmptyArray(i); - for(int e = 0; e < i; e++) + for (int e = 0; e < i; e++) { - if(data[e] != 0x00) + if (data[e] != 0x00) { Assert.Fail("Data is not 0x00"); } } } + [Test] + public void GetSubArray() + { + byte[] array = new byte[] + { + 0x01, 0x02, 0x03, 0x04, 0x05 + }; + + byte[] expected_subarray = new byte[] + { + 0x02, 0x03, 0x04 + }; + + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.AreEqual(expected_subarray, desfire.GetSubArray(array, 1, 3)); + } + [Test] public void CheckAPDUResponse__NULL() { @@ -175,7 +194,6 @@ namespace NFC_Test.NXP_MIFARE_DESFire }); } - [Test] public void CheckAPDUResponse__PARAMETER_ERROR() { @@ -194,7 +212,6 @@ namespace NFC_Test.NXP_MIFARE_DESFire }); } - [Test] public void CheckAPDUResponse__AUTHENTICATION_DELAY() { @@ -370,6 +387,40 @@ namespace NFC_Test.NXP_MIFARE_DESFire }); } + [Test] + public void ExpandToBlockSize() + { + byte[] data = new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 + }; + + byte[] expected_lastblock = new byte[] + { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00 + }; + + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + byte[] lastblock = desfire.ExpandToBlockSize(data, 8); + + Assert.AreEqual(expected_lastblock, lastblock); + } + + [Test] + public void ExpandToBlockSize_Null() + { + byte[] data = null; + + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + byte[] lastblock = desfire.ExpandToBlockSize(data, 8); + }); + } + [Test] public void RotateLeft() { @@ -538,25 +589,113 @@ namespace NFC_Test.NXP_MIFARE_DESFire }); } + [Test] + public void GenerateSessionKey_DES() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + byte[] rndA = HexConverter.ConvertFromHexString("a541a9dc9138df07"); + Console.WriteLine(HexConverter.ConvertToHexString(rndA)); + byte[] rndB = HexConverter.ConvertFromHexString("cbe55aa893b2da25"); + Console.WriteLine(HexConverter.ConvertToHexString(rndB)); + + byte[] expected_sessionkey = HexConverter.ConvertFromHexString("a541a9dccbe55aa8a541a9dccbe55aa8"); + Console.WriteLine(HexConverter.ConvertToHexString(expected_sessionkey)); + + byte[] sessionkey = desfire.GenerateSesionKey_DES(rndA, rndB); + Console.WriteLine(HexConverter.ConvertToHexString(sessionkey)); + Assert.AreEqual(expected_sessionkey, sessionkey); + } + [Test] public void GenerateSessionKey_AES() { MIFARE_DESFire desfire = new MIFARE_DESFire(null); - byte[] rndA = desfire.ConvertFromHexString("bc14dfde20074617e45a8822f06fdd91"); - Console.WriteLine(desfire.ConvertToHexString(rndA)); - byte[] rndB = desfire.ConvertFromHexString("482ddc54426e6dee560413b8d95471f5"); - Console.WriteLine(desfire.ConvertToHexString(rndB)); + byte[] rndA = HexConverter.ConvertFromHexString("bc14dfde20074617e45a8822f06fdd91"); + Console.WriteLine(HexConverter.ConvertToHexString(rndA)); + byte[] rndB = HexConverter.ConvertFromHexString("482ddc54426e6dee560413b8d95471f5"); + Console.WriteLine(HexConverter.ConvertToHexString(rndB)); - byte[] expected_sessionkey = desfire.ConvertFromHexString("bc14dfde482ddc54f06fdd91d95471f5"); - Console.WriteLine(desfire.ConvertToHexString(expected_sessionkey)); + byte[] expected_sessionkey = HexConverter.ConvertFromHexString("bc14dfde482ddc54f06fdd91d95471f5"); + Console.WriteLine(HexConverter.ConvertToHexString(expected_sessionkey)); byte[] sessionkey = desfire.GenerateSesionKey_AES(rndA, rndB); - Console.WriteLine(desfire.ConvertToHexString(sessionkey)); + Console.WriteLine(HexConverter.ConvertToHexString(sessionkey)); Assert.AreEqual(expected_sessionkey, sessionkey); } #endregion + #region Configuration Generator + [Test] + public void GenerateKeySetting1() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.AreEqual(0x0B, desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE)); + } + + [Test] + public void GenerateKeySetting1_ChangeKey() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + Assert.AreEqual(0x1B, desfire.GenerateKeySetting1(0x01, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE)); + } + + [Test] + public void GenerateKeySetting1_Wrong_KeyID() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + desfire.GenerateKeySetting1(0x10, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + }); + } + + [Test] + public void GenerateKeySetting2() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.AreEqual(0x82, desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x02)); + } + + [Test] + public void GenerateKeySetting2_Wrong_KeyNumbers() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 0x10); + }); + } + + + [Test] + public void GenerateFileAccessRights() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.AreEqual(0x1234, desfire.GenerateFileAccessRights(0x01, 0x02, 0x03, 0x04)); + } + + [Test] + public void GenerateFileAccessRights_OutOfRange() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + desfire.GenerateFileAccessRights(0x10, 0x00, 0x00, 0x00); + }); + } + #endregion + #region DESFire Commands [Test] public void AuthenticateISO_DES() @@ -588,7 +727,7 @@ namespace NFC_Test.NXP_MIFARE_DESFire desfire.AuthenticateISO_DES(0x00, key, rndA); byte[] expected_sessionkey = HexConverter.ConvertFromHexString("849B36C54FD1B759849B36C54FD1B759"); - byte[] expected_iv = desfire.GenerateEmptyKey(8); + byte[] expected_iv = HexConverter.ConvertFromHexString("0000000000000000"); Assert.AreEqual(expected_sessionkey, desfire._SessionKey); Assert.AreEqual(expected_iv, desfire._IV); @@ -624,7 +763,7 @@ namespace NFC_Test.NXP_MIFARE_DESFire desfire.AuthenticateISO_AES(0x00, key, rndA); byte[] expected_sessionkey = HexConverter.ConvertFromHexString("8a8b3c15c71d0cf46aead1f148f27703"); - byte[] expected_iv = desfire.GenerateEmptyKey(16); + byte[] expected_iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); Assert.AreEqual(expected_sessionkey, desfire._SessionKey); Assert.AreEqual(expected_iv, desfire._IV); @@ -683,27 +822,5 @@ namespace NFC_Test.NXP_MIFARE_DESFire desfire.ChangeOtherKey_AES(0x01, new_key, old_key, 0x10); } #endregion - - #region Configuration Generator - [Test] - public void GenerateFileAccessRights() - { - MIFARE_DESFire desfire = new MIFARE_DESFire(null); - - Assert.AreEqual(0x1234, desfire.GenerateFileAccessRights(0x01, 0x02, 0x03, 0x04)); - } - - [Test] - public void GenerateFileAccessRights_OutOfRange() - { - MIFARE_DESFire desfire = new MIFARE_DESFire(null); - - Assert.Throws( - delegate - { - desfire.GenerateFileAccessRights(0x10, 0x00, 0x00, 0x00); - }); - } - #endregion } } diff --git a/NFC_Test/NamespaceSetUp.cs b/NFC_Test/NamespaceSetUp.cs index eb86856..64b4adc 100644 --- a/NFC_Test/NamespaceSetUp.cs +++ b/NFC_Test/NamespaceSetUp.cs @@ -1,8 +1,11 @@ using log4net.Config; using NUnit.Framework; -namespace NFC_Test +namespace NFC_Unit_Test { + /// + /// Add log4net Output to Console Out + /// [SetUpFixture] public class NamespaceSetUp { @@ -13,3 +16,19 @@ namespace NFC_Test } } } + +namespace NFC_Real_Test +{ + /// + /// Add log4net Output to Console Out + /// + [SetUpFixture] + public class NamespaceSetUp + { + [OneTimeSetUp] + public void OneTimeSetUp() + { + BasicConfigurator.Configure(); + } + } +} diff --git a/NFC_Test/REAL_DESFireCommands.cs b/NFC_Test/REAL_DESFireCommands.cs new file mode 100644 index 0000000..36bd22f --- /dev/null +++ b/NFC_Test/REAL_DESFireCommands.cs @@ -0,0 +1,477 @@ +using NFC; +using NFC.Crypto; +using NFC.Mifare_DESFire; +using NFC.Mifare_DESFire.Enums; +using NFC.Readers.PCSC; +using NUnit.Framework; +using System; +using System.Text; + +namespace NFC_Real_Test +{ + /// + /// Test all DESFire Commands with an Empty Card + /// The Test are ordered to check the Commands one by one + /// + [TestFixture, Explicit] + public class REAL_DESFireCommands + { + /// + /// Set ReaderID for PCSC Interface + /// You can get the ID from REAL_Reader_PCSC + /// + public readonly string ReaderID = "ACS ACR122U PICC Interface 0"; + + #region Fixed Config Properties + public readonly UInt32 ApplicationID = 0xAAFFEE; + public readonly string ApplicationMasterKey = "25432A462D4A614E645267556B587032"; + public readonly string ApplicationKey_1 = "25432A462D4A614E645267556B587032"; + public readonly byte FileID = 0x01; + public readonly byte FileSize = 0xF0; + #endregion + + [Test, Order(1)] + public void SelectApplication() + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test, Order(2)] + public void Authenticate_DES() + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test, Order(3)] + public void Format() + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + desfire.Format(); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test, Order(4)] + public void CreateApplication() + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + desfire.Format(); + + desfire.AuthenticateISO_DES(0x00, key._Key); + + byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 2); + + desfire.CreateApplication(ApplicationID, keysetting1, keysetting2); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test, Order(5)] + public void Authenticate_AES() + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + desfire.Format(); + + desfire.AuthenticateISO_DES(0x00, key._Key); + + byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 2); + + desfire.CreateApplication(ApplicationID, keysetting1, keysetting2); + + desfire.SelectApplication(ApplicationID); + + CipherKey key_aes = new CipherKey(CipherType.AES); + desfire.AuthenticateISO_AES(0x00, key_aes._Key); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test, Order(6)] + public void ChangeApplicationMasterKey() + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + desfire.Format(); + + desfire.AuthenticateISO_DES(0x00, key._Key); + + byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 2); + + desfire.CreateApplication(ApplicationID, keysetting1, keysetting2); + + desfire.SelectApplication(ApplicationID); + + CipherKey key_aes = new CipherKey(CipherType.AES); + desfire.AuthenticateISO_AES(0x00, key_aes._Key); + + CipherKey key_aes_new = new CipherKey(ApplicationMasterKey, CipherType.AES, 0x10); + desfire.ChangeKey_AES(0x00, key._Key, key._KeyVersion); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test, Order(7)] + public void ChangeApplicationKey_1() + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + desfire.Format(); + + desfire.AuthenticateISO_DES(0x00, key._Key); + + byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 2); + + desfire.CreateApplication(ApplicationID, keysetting1, keysetting2); + + desfire.SelectApplication(ApplicationID); + + CipherKey key_aes = new CipherKey(CipherType.AES); + desfire.AuthenticateISO_AES(0x00, key_aes._Key); + + CipherKey key_new = new CipherKey(ApplicationKey_1, CipherType.AES, 0x10); + desfire.ChangeOtherKey_AES(0x01, key_new._Key, key_aes._Key, key_new._KeyVersion); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test, Order(8)] + public void CreateFile() + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + desfire.Format(); + + desfire.AuthenticateISO_DES(0x00, key._Key); + + byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 2); + + desfire.CreateApplication(ApplicationID, keysetting1, keysetting2); + + desfire.SelectApplication(ApplicationID); + + CipherKey key_aes = new CipherKey(CipherType.AES); + desfire.AuthenticateISO_AES(0x00, key_aes._Key); + + UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00); + desfire.CreateFile_Standard(FileID, FileCommunication.PLAIN, accesRights, FileSize); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test, Order(9)] + public void WriteFile() + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + desfire.Format(); + + desfire.AuthenticateISO_DES(0x00, key._Key); + + byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 2); + + desfire.CreateApplication(ApplicationID, keysetting1, keysetting2); + + desfire.SelectApplication(ApplicationID); + + CipherKey key_aes = new CipherKey(CipherType.AES); + desfire.AuthenticateISO_AES(0x00, key_aes._Key); + + UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00); + desfire.CreateFile_Standard(FileID, FileCommunication.PLAIN, accesRights, FileSize); + + desfire.WriteData(FileID, 0, Encoding.ASCII.GetBytes("Test1234")); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + + [Test, Order(10)] + public void ReadFile() + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(ReaderID); + + bool test_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + desfire.SelectApplication(0x000000); + + CipherKey key = new CipherKey(CipherType.TDES); + desfire.AuthenticateISO_DES(0x00, key._Key); + + desfire.Format(); + + desfire.AuthenticateISO_DES(0x00, key._Key); + + byte keysetting1 = desfire.GenerateKeySetting1(ChangeApplicationKey.MASTERKEY, ChangeMasterKeySettings.WITHMASTERKEY, CreateDeleteFile.ONLYMASTERKEY, FileDirectoryAccess.NOKEY, ChangeMasterKey.CHANGEABLE); + byte keysetting2 = desfire.GenerateKeySetting2(CryptoOperationsType.AES, FileIdentifies.NOTUSED, 2); + + desfire.CreateApplication(ApplicationID, keysetting1, keysetting2); + + desfire.SelectApplication(ApplicationID); + + CipherKey key_aes = new CipherKey(CipherType.AES); + desfire.AuthenticateISO_AES(0x00, key_aes._Key); + + UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00); + desfire.CreateFile_Standard(FileID, FileCommunication.PLAIN, accesRights, FileSize); + + desfire.WriteData(FileID, 0, Encoding.ASCII.GetBytes("Test1234")); + + byte[] data = desfire.ReadData(FileID, 0, FileSize); + Console.WriteLine(Encoding.ASCII.GetString(data).Replace("\u0000", "")); + + test_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, test_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + } +} diff --git a/NFC_Test/FabAccess_OTA.cs b/NFC_Test/REAL_FabAccess_OTA.cs similarity index 82% rename from NFC_Test/FabAccess_OTA.cs rename to NFC_Test/REAL_FabAccess_OTA.cs index 353a6bd..7edc1ab 100644 --- a/NFC_Test/FabAccess_OTA.cs +++ b/NFC_Test/REAL_FabAccess_OTA.cs @@ -6,13 +6,11 @@ using NFC.Mifare_DESFire.Enums; using System; using System.Text; using NFC.Crypto; -using System.Runtime.CompilerServices; -using System.Drawing.Printing; -namespace NFC_Test +namespace NFC_Real_Test { [TestFixture, Explicit] - public class FabAccess_OTA + public class REAL_FabAccess_OTA { private string _ReaderID = "ACS ACR122U PICC Interface 0"; private UInt32 _FabAccess_AID = 0x2A472D; @@ -23,16 +21,19 @@ namespace NFC_Test private CipherKey _FabAccess_Application_MasterKey = new CipherKey("50645367566B59703273357638792F42", CipherType.AES, 0x10); private CipherKey _FabAccess_Application_AuthKey = new CipherKey("6D5A7134743677397A24432646294A40", CipherType.AES, 0x10); - private string _FabAccess_UserDomain = "thejoklla@fvm.fab-access.org"; + private string _FabAccess_UserDomain = "verrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrylooooooooooooooooooongusssssssssssssssssssssssernaaaaaaaaaaaaaaaaaaaaaaaame@fvm.fab-access.org"; private string _FabAccess_Domain = "fvm.fab-access.org"; private CipherKey _Default_DESKey = new CipherKey(CipherType.TDES); private CipherKey _Default_AESKey = new CipherKey(CipherType.AES); - [Test] + /// + /// Create FabAccess Application and UserData File + /// + [Test, Order(1)] public void Init_EmptyCard() { - IHardware hardware = new Hardware(); + IHardware hardware = new PCSC_Hardware(); IReader reader = hardware.OpenReader(_ReaderID); bool transmit_successfully = false; @@ -54,7 +55,7 @@ namespace NFC_Test desfire.CreateApplication(_FabAccess_AID, keySetting1, keySetting2); desfire.SelectApplication(_FabAccess_AID); - desfire.AuthenticateISO_AES(0x00, _Default_DESKey._Key); + desfire.AuthenticateISO_AES(0x00, _Default_AESKey._Key); desfire.ChangeKey_AES(0x00, _FabAccess_Application_MasterKey._Key, _FabAccess_Application_MasterKey._KeyVersion); @@ -62,9 +63,9 @@ namespace NFC_Test desfire.ChangeOtherKey_AES(0x01, _FabAccess_Application_AuthKey._Key, _Default_AESKey._Key, _FabAccess_Application_AuthKey._KeyVersion); UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00); - desfire.CreateFile_Standard(_FabAccess_FID, FileCommunication.MAC, accesRights, _FabAccess_FSize); + desfire.CreateFile_Standard(_FabAccess_FID, FileCommunication.PLAIN, accesRights, _FabAccess_FSize); - desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes(_FabAccess_UserDomain)); + desfire.WriteData(_FabAccess_FID, 0, Encoding.ASCII.GetBytes(_FabAccess_UserDomain)); transmit_successfully = true; @@ -80,10 +81,13 @@ namespace NFC_Test reader.CardDiscovered -= handler; } - [Test] + /// + /// Authenticate with UserData File and AuthKey + /// + [Test, Order(2)] public void Authenticate() { - IHardware hardware = new Hardware(); + IHardware hardware = new PCSC_Hardware(); IReader reader = hardware.OpenReader(_ReaderID); bool transmit_successfully = false; @@ -95,7 +99,7 @@ namespace NFC_Test MIFARE_DESFire desfire = new MIFARE_DESFire(card); desfire.SelectApplication(_FabAccess_AID); - byte[] card_data = desfire.ReadData(_FabAccess_FID, 0x00, 0x0F); + byte[] card_data = desfire.ReadData(_FabAccess_FID, 0x00, _FabAccess_FSize); string userdomain = Encoding.ASCII.GetString(card_data).Replace("\u0000", ""); string domain = userdomain.Split('@')[1]; @@ -107,13 +111,6 @@ namespace NFC_Test desfire.SelectApplication(_FabAccess_AID); desfire.AuthenticateISO_AES(0x01, _FabAccess_Application_AuthKey._Key); - byte[] card_data_auth = desfire.ReadData(_FabAccess_FID, 0x00, _FabAccess_FSize); - string userdomain_auth = Encoding.ASCII.GetString(card_data).Replace("\u0000", ""); - if(card_data_auth != card_data) - { - throw new Exception("Authentication failed"); - } - transmit_successfully = true; card.Disconnect(); diff --git a/NFC_Test/REAL_Reader_PCSC.cs b/NFC_Test/REAL_Reader_PCSC.cs new file mode 100644 index 0000000..9510556 --- /dev/null +++ b/NFC_Test/REAL_Reader_PCSC.cs @@ -0,0 +1,62 @@ +using NFC; +using NFC.Readers.PCSC; +using NUnit.Framework; +using System; + +namespace NFC_Real_Test +{ + [TestFixture, Explicit] + public class REAL_Reader_PCSC + { + /// + /// Print PCSC ReaderIDs to Console Out + /// + [Test] + public void GetReaders() + { + IHardware hardware = new PCSC_Hardware(); + string[] readers = hardware.GetReaders(); + + Console.WriteLine("PCSC Readers detected: {0}", readers.Length); + + if (readers.Length > 0) + { + Console.WriteLine("List of ReaderIDs:"); + foreach (string readerID in readers) + { + Console.WriteLine("{0}", readerID); + } + } + } + + /// + /// Connect to specific PCSC Reader by ReaderID + /// + /// ReaderID from GetReaders + [TestCase("ACS ACR122U PICC Interface 0")] + public void Connect(string readerID) + { + IHardware hardware = new PCSC_Hardware(); + IReader reader = hardware.OpenReader(readerID); + + bool connected_successfully = false; + + ReaderEventHandler handler = (sender, card) => + { + card.Connect(); + + connected_successfully = true; + + card.Disconnect(); + }; + + reader.CardDiscovered += handler; + reader.Start(); + + Assert.AreEqual(true, connected_successfully); + + reader.Stop(); + reader.CardDiscovered -= handler; + } + } +} diff --git a/NFC_Test/REAL_Windows.cs b/NFC_Test/REAL_Windows.cs deleted file mode 100644 index a754039..0000000 --- a/NFC_Test/REAL_Windows.cs +++ /dev/null @@ -1,129 +0,0 @@ -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Text; -using NFC; -using NFC.Readers.PCSC; -using System.Threading; -using NFC.Mifare_DESFire; -using NFC.Mifare_DESFire.Enums; -using NFC.ISO7816_4; -using PCSC.Iso7816; -using NFC.Crypto; - -namespace NFC_Test -{ - [TestFixture, Explicit] - public class REAL_Windows - { - [Test] - public void GetReaders() - { - IHardware hardware = new Hardware(); - string[] readers = hardware.GetReaders(); - - Console.WriteLine("Readers detected: {0}", readers.Length); - - if(readers.Length > 0) - { - Console.WriteLine("List of ReaderIDs:"); - foreach (string readerID in readers) - { - Console.WriteLine("{0}", readerID); - } - } - } - - [TestCase("ACS ACR122U PICC Interface 0")] - public void Connect(string readerID) - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); - - bool connected_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - connected_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, connected_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [TestCase("ACS ACR122U PICC Interface 0")] - public void Read(string readerID) - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); - - bool connected_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(0x2A472D); - Console.WriteLine(HexConverter.ConvertToHexString(desfire.ReadData(0x01, 0x00, 0xF0))); - - connected_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, connected_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - - [TestCase("ACS ACR122U PICC Interface 0")] - public void Write(string readerID) - { - IHardware hardware = new Hardware(); - IReader reader = hardware.OpenReader(readerID); - - bool connected_successfully = false; - - ReaderEventHandler handler = (sender, card) => - { - card.Connect(); - - MIFARE_DESFire desfire = new MIFARE_DESFire(card); - - desfire.SelectApplication(0x2A472D); - - CipherKey _FabAccess_Application_MasterKey = new CipherKey("50645367566B59703273357638792F42", CipherType.AES, 0x10); - - desfire.AuthenticateISO_AES(0x00, _FabAccess_Application_MasterKey._Key); - desfire.WriteData(0x01, 0x00, HexConverter.ConvertFromHexString("7468656a6f6b6c6c")); - - connected_successfully = true; - - card.Disconnect(); - }; - - reader.CardDiscovered += handler; - reader.Start(); - - Assert.AreEqual(true, connected_successfully); - - reader.Stop(); - reader.CardDiscovered -= handler; - } - } -} diff --git a/NFC_Test/REAL_Windows_CardSetUp.cs b/NFC_Test/REAL_Windows_CardSetUp.cs deleted file mode 100644 index 931a17a..0000000 --- a/NFC_Test/REAL_Windows_CardSetUp.cs +++ /dev/null @@ -1,191 +0,0 @@ -using NFC; -using NFC.Mifare_DESFire; -using NFC.Mifare_DESFire.Enums; -using NFC.Readers.PCSC; -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Text; - -namespace NFC_Test -{ - //[TestFixture] - //public class REAL_Windows_CardSetUp - //{ - // public static UInt32 FabAccessAID = 0x001100; - // public static string CardReaderID = "ACS ACR122U PICC Interface 0"; - // public static byte[] PICC_MasterKey = new byte[] - // { - // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - // }; - - // public static byte[] APP_MasterKey = new byte[] - // { - // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - // }; - - // public static byte[] APP_Key_1 = new byte[] - // { - // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - // }; - - // public static byte[] APP_Key_2 = new byte[] - // { - // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - // }; - - // public static byte[] Empty_Key = new byte[] - // { - // 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - // }; - - // public static byte FabAccessIdentFileID = 0x01; - // public static string UserDomain = "user1@fabaccess.org"; - - // [Test] - // public void ResetCard() - // { - // IHardware hardware = new Hardware(); - // IReader reader = hardware.OpenReader(CardReaderID); - - // bool connected_successfully = false; - - // ReaderEventHandler handler = (sender, card) => - // { - // card.Connect(); - - // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - - // mifareDESFire.AuthenticateISO_DES(0x01, PICC_MasterKey); - - // mifareDESFire.Format(); - - // connected_successfully = true; - - // card.Disconnect(); - // }; - - // reader.CardDiscovered += handler; - // reader.Start(); - - // Assert.AreEqual(true, connected_successfully); - - // reader.Stop(); - // reader.CardDiscovered -= handler; - // } - - // [Test] - // public void ProvisionCard() - // { - // IHardware hardware = new Hardware(); - // IReader reader = hardware.OpenReader(CardReaderID); - - // bool connected_successfully = false; - - // ReaderEventHandler handler = (sender, card) => - // { - // card.Connect(); - - // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - - // mifareDESFire.AuthenticateISO_DES(0x01, APP_MasterKey); - // mifareDESFire.CreateApplication(FabAccessAID); - // mifareDESFire.SelectApplication(FabAccessAID); - - // mifareDESFire.AuthenticateDES(0x00, Empty_Key); - // mifareDESFire.ChangeApplicationMasterKey(APP_MasterKey); - - // mifareDESFire.AuthenticateDES(0x00, APP_MasterKey); - // mifareDESFire.ChangeApplicationKey(0x01, APP_Key_1); - - // connected_successfully = true; - - // card.Disconnect(); - // }; - - // reader.CardDiscovered += handler; - // reader.Start(); - - // Assert.AreEqual(true, connected_successfully); - - // reader.Stop(); - // reader.CardDiscovered -= handler; - // } - - - // [Test] - // public void SetUpUserCard() - // { - // IHardware hardware = new Hardware(); - // IReader reader = hardware.OpenReader(CardReaderID); - - // bool connected_successfully = false; - - // ReaderEventHandler handler = (sender, card) => - // { - // card.Connect(); - - // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - - // mifareDESFire.SelectApplication(FabAccessAID); - // mifareDESFire.AuthenticateDES(0x00, Empty_Key); - // UInt16 fileAccessRight = mifareDESFire.GenerateFileAccessRight(AccessRights.FREE, 0x00, 0x00, 0x00); - // mifareDESFire.CreateFile(FabAccessIdentFileID, FileCommunication.PLAIN, fileAccessRight, (UInt32)0x90); - - // System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); - - // mifareDESFire.WirteData(FabAccessIdentFileID, 0x00000000, 0x00000000, enc.GetBytes(UserDomain)); - - // connected_successfully = true; - - // card.Disconnect(); - // }; - - // reader.CardDiscovered += handler; - // reader.Start(); - - // Assert.AreEqual(true, connected_successfully); - - // reader.Stop(); - // reader.CardDiscovered -= handler; - // } - - // [Test] - // public void AuthenticateCard() - // { - // IHardware hardware = new Hardware(); - // IReader reader = hardware.OpenReader(CardReaderID); - - // bool connected_successfully = false; - - // ReaderEventHandler handler = (sender, card) => - // { - // card.Connect(); - - // MIFARE_DESFire mifareDESFire = new MIFARE_DESFire(card); - - // mifareDESFire.SelectApplication(FabAccessAID); - // byte[] filedata = mifareDESFire.ReadData(FabAccessIdentFileID, 0x00000000, 0x00000000); - - // System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); - // string userdomain = enc.GetString(filedata); - - // Console.WriteLine(userdomain); - - // mifareDESFire.AuthenticateDES(0x01, APP_Key_1); - - // connected_successfully = true; - - // card.Disconnect(); - // }; - - // reader.CardDiscovered += handler; - // reader.Start(); - - // Assert.AreEqual(true, connected_successfully); - - // reader.Stop(); - // reader.CardDiscovered -= handler; - // } - //} -} From e4cc1348b8337aaac4b385fcd4617ef203b03140 Mon Sep 17 00:00:00 2001 From: TheJoKlLa Date: Sat, 7 Nov 2020 21:28:55 +0100 Subject: [PATCH 19/21] Finished: NFC Lib v0.9, TODO: CMAC check, Change PICC Key --- NFC/ISO7816-4/APDUCommand.cs | 4 +- NFC/ISO7816-4/APDUResponse.cs | 11 +- NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs | 442 ++++++++---------- .../NXP MIFARE DESFire/MIFARE_DESFire_Test.cs | 349 +++++++++++++- NFC_Test/REAL_DESFireCommands.cs | 2 +- NFC_Test/REAL_FabAccess_OTA.cs | 4 +- 6 files changed, 547 insertions(+), 265 deletions(-) diff --git a/NFC/ISO7816-4/APDUCommand.cs b/NFC/ISO7816-4/APDUCommand.cs index ef6a5e3..a0ffaa4 100644 --- a/NFC/ISO7816-4/APDUCommand.cs +++ b/NFC/ISO7816-4/APDUCommand.cs @@ -71,10 +71,10 @@ namespace NFC.ISO7816_4 return string.Format(pattern_case2, CLA, INS, P1, P2, Le); case IsoCase.Case3Short: case IsoCase.Case3Extended: - return string.Format(pattern_case3, CLA, INS, P1, P2, Lc, BitConverter.ToString(Data).Replace("-", " ")); + return string.Format(pattern_case3, CLA, INS, P1, P2, Lc, BitConverter.ToString(Data).Replace("-", "").ToLower()); case IsoCase.Case4Short: case IsoCase.Case4Extended: - return string.Format(pattern_case4, CLA, INS, P1, P2, Lc, BitConverter.ToString(Data).Replace("-", " "), Le); + return string.Format(pattern_case4, CLA, INS, P1, P2, Lc, BitConverter.ToString(Data).Replace("-", "").ToLower(), Le); default: throw new Exception("Unknown IsoCase"); } diff --git a/NFC/ISO7816-4/APDUResponse.cs b/NFC/ISO7816-4/APDUResponse.cs index 61e8501..d5ef0e3 100644 --- a/NFC/ISO7816-4/APDUResponse.cs +++ b/NFC/ISO7816-4/APDUResponse.cs @@ -146,8 +146,15 @@ namespace NFC.ISO7816_4 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); + if(Body == null) + { + return string.Format("SW1: 0x{0:x} | SW2: 0x{1:x}", SW1, SW2); + } + else + { + return string.Format("SW1: 0x{0:x} | SW2: 0x{1:x} | Body: {2:x}", SW1, SW2, BitConverter.ToString(Body).Replace("-", "").ToLower()); + } + } #endregion } diff --git a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs index 185d78c..9dd39d7 100644 --- a/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs +++ b/NFC/NXP MIFARE DESFire/MIFARE_DESFire.cs @@ -412,40 +412,54 @@ namespace NFC.Mifare_DESFire #region DESFire Commands /// - /// Format PICC - /// Works after PICC Authentication + /// Select Application by ApplicationID (AID) /// - public void Format() + /// 3 Byte AID + public void SelectApplication(UInt32 aid) { - _Log.Debug("Start Format"); + if(aid > 0xFFFFFF) + { + throw new ArgumentOutOfRangeException("AID is too large"); + } - APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short) + byte[] id_byte = BitConverter.GetBytes(aid); + _Log.InfoFormat("Select Application: {0}", HexConverter.ConvertToHexString(id_byte.ToArray())); + + APDUCommand cmd_SelectApplication = new APDUCommand(IsoCase.Case4Short) { CLA = 0x90, - INS = 0xFC, + INS = (byte)APDUInstructions.SELECT_APPLICATION, + Data = new byte[] + { + id_byte[0], + id_byte[1], + id_byte[2] + } }; - _Log.DebugFormat("APDU_CMD(cmd_format): {0}", HexConverter.ConvertToHexString(cmd_format.ToArray())); - - APDUResponse response = _Card.Transmit(cmd_format); - _Log.DebugFormat("APDU_RES(cmd_format): {0}", HexConverter.ConvertToHexString(response.ToArray())); + _Log.Debug(cmd_SelectApplication.ToString()); + HexConverter.ConvertToHexString(cmd_SelectApplication.ToArray()); + APDUResponse response = _Card.Transmit(cmd_SelectApplication); + _Log.DebugFormat(response.ToString()); CheckAPDUResponse(response); - - _Log.Debug("End Format"); } /// - /// Authenticate to PICC, with ISO Authenticate + /// Authenticate to PICC, with ISO Authenticate for DES Key /// /// 0x01 - 0x0D - /// + /// Array of 8/16 Bytes /// !!! WARNING For Testing only !!! - /// Retry after short Time public void AuthenticateISO_DES(byte key_id, byte[] key, byte[] rndA = null) { - _Log.Debug("Start AuthenticateISO_DES"); + if(key_id >= 0x0E) + { + throw new ArgumentOutOfRangeException("KeyID is invalid"); + } - // Sepearte InitialisationVector for Authentication + _Log.InfoFormat("Authenticate with DES Key No: 0x{0:x}", key_id); + + // Sepearte Initialisation Vector for Authentication Process byte[] iv = new byte[8]; APDUCommand cmd_challange_request = new APDUCommand(IsoCase.Case4Short) @@ -457,10 +471,10 @@ namespace NFC.Mifare_DESFire key_id } }; - _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", HexConverter.ConvertToHexString(cmd_challange_request.ToArray())); + _Log.Debug(cmd_challange_request.ToString()); APDUResponse response = _Card.Transmit(cmd_challange_request); - _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", HexConverter.ConvertToHexString(response.ToArray())); + _Log.Debug(response.ToString()); CheckAPDUResponse(response); @@ -476,7 +490,7 @@ namespace NFC.Mifare_DESFire byte[] rndB_rl = RotateLeft(rndB); _Log.DebugFormat("rndB_enc: {0}", HexConverter.ConvertToHexString(rndB_rl)); - if(rndA == null) + if (rndA == null) { Random rnd = new Random(); rndA = new byte[8]; @@ -488,7 +502,7 @@ namespace NFC.Mifare_DESFire _Log.DebugFormat("rndAB: {0}", HexConverter.ConvertToHexString(rndAB)); byte[] rndAB_enc = des.Encrypt(rndAB, key, rndB_enc); - _Log.DebugFormat("rndA_rndB_enc: {0}", HexConverter.ConvertToHexString(rndAB_enc)); + _Log.DebugFormat("rndAB_enc: {0}", HexConverter.ConvertToHexString(rndAB_enc)); iv = ExtractLastBlock(rndAB_enc, 8); APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) @@ -497,10 +511,10 @@ namespace NFC.Mifare_DESFire INS = 0xAF, Data = rndAB_enc }; - _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray())); + _Log.Debug(cmd_challange_response.ToString()); response = _Card.Transmit(cmd_challange_response); - _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray())); + _Log.Debug(response.ToString()); CheckAPDUResponse(response); @@ -515,28 +529,52 @@ namespace NFC.Mifare_DESFire if (!rndA.SequenceEqual(rndAFromCard)) { - throw new Exception("Authentication failed, PICC Challenge is not corret"); + throw new Exception("Authentication failed, PICC Challenge is invalid."); } + _Log.Info("Authenticated"); + _SessionKey = GenerateSesionKey_DES(rndA, rndB); - _Log.DebugFormat("_SessionKey: {0}", HexConverter.ConvertToHexString(_SessionKey)); + _Log.DebugFormat("SessionKey: {0}", HexConverter.ConvertToHexString(_SessionKey)); _IV = GenerateEmptyArray(8); - _Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV)); - - _Log.Debug("End AuthenticateISO_DES"); + _Log.DebugFormat("IV: {0}", HexConverter.ConvertToHexString(_IV)); } /// - /// Create Application for ID + /// Format PICC + /// Need Authentication for PICC / Application 0x000000 + /// + public void Format() + { + _Log.Info("Format PICC"); + + APDUCommand cmd_format = new APDUCommand(IsoCase.Case2Short) + { + CLA = 0x90, + INS = 0xFC, + }; + _Log.Debug(cmd_format.ToString()); + + APDUResponse response = _Card.Transmit(cmd_format); + _Log.Debug(response.ToString()); + + CheckAPDUResponse(response); + } + + /// + /// Create Application for ApplicationID /// /// 3 Byte ID public void CreateApplication(UInt32 aid, byte keysetting1, byte keysetting2) { - _Log.Debug("Start CreateApplication"); + if (aid > 0xFFFFFF) + { + throw new ArgumentOutOfRangeException("AID is too large"); + } byte[] id_byte = BitConverter.GetBytes(aid); - _Log.DebugFormat("AID: {0}", HexConverter.ConvertToHexString(id_byte.ToArray())); + _Log.InfoFormat("Create Application: {0}", HexConverter.ConvertToHexString(id_byte.ToArray())); APDUCommand cmd_CreateApplication = new APDUCommand(IsoCase.Case4Short) { @@ -551,58 +589,28 @@ namespace NFC.Mifare_DESFire keysetting2 } }; - _Log.DebugFormat("APDU_CMD(cmd_CreateApplication): {0}", HexConverter.ConvertToHexString(cmd_CreateApplication.ToArray())); + _Log.Debug(cmd_CreateApplication.ToString()); APDUResponse response = _Card.Transmit(cmd_CreateApplication); - _Log.DebugFormat("APDU_RES(cmd_CreateApplication): {0}", HexConverter.ConvertToHexString(response.ToArray())); + _Log.Debug(response.ToString()); CheckAPDUResponse(response); - - _Log.Debug("End CreateApplication"); - } - - /// - /// Select Application by AID - /// - /// 3 Byte AID - public void SelectApplication(UInt32 aid) - { - _Log.Debug("Start SelectApplication"); - - byte[] id_byte = BitConverter.GetBytes(aid); - _Log.DebugFormat("AID: {0}", HexConverter.ConvertToHexString(id_byte.ToArray())); - - APDUCommand cmd_SelectApplication = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = (byte)APDUInstructions.SELECT_APPLICATION, - Data = new byte[] - { - id_byte[0], - id_byte[1], - id_byte[2] - } - }; - _Log.DebugFormat("APDU_CMD(cmd_SelectApplication): {0}", HexConverter.ConvertToHexString(cmd_SelectApplication.ToArray())); - - APDUResponse response = _Card.Transmit(cmd_SelectApplication); - _Log.DebugFormat("APDU_RES(cmd_SelectApplication): {0}", HexConverter.ConvertToHexString(response.ToArray())); - - CheckAPDUResponse(response); - - _Log.Debug("End SelectApplication"); } /// /// Authenticate to PICC, with ISO Authenticate /// /// 0x01 - 0x0D - /// + /// Array of 16 Bytes /// !!! WARNING For Testing only !!! - /// Retry after short Time public void AuthenticateISO_AES(byte key_id, byte[] key, byte[] rndA = null) { - _Log.Debug("Start AuthenticateISO_AES"); + if (key_id >= 0x0E) + { + throw new ArgumentOutOfRangeException("KeyID is invalid"); + } + + _Log.InfoFormat("Authenticate with AES Key No: 0x{0:x}", key_id); // Sepearte InitialisationVector for Authentication byte[] iv = new byte[16]; @@ -616,10 +624,10 @@ namespace NFC.Mifare_DESFire key_id } }; - _Log.DebugFormat("APDU_CMD(cmd_challange_request): {0}", HexConverter.ConvertToHexString(cmd_challange_request.ToArray())); + _Log.Debug(cmd_challange_request.ToString()); APDUResponse response = _Card.Transmit(cmd_challange_request); - _Log.DebugFormat("APDU_RES(cmd_challange_request): {0}", HexConverter.ConvertToHexString(response.ToArray())); + _Log.Debug(response.ToString()); CheckAPDUResponse(response); @@ -647,7 +655,7 @@ namespace NFC.Mifare_DESFire _Log.DebugFormat("rndAB: {0}", HexConverter.ConvertToHexString(rndAB)); byte[] rndAB_enc = aes.Encrypt(rndAB, key, rndB_enc); - _Log.DebugFormat("rndA_rndB_enc: {0}", HexConverter.ConvertToHexString(rndAB_enc)); + _Log.DebugFormat("rndAB_enc: {0}", HexConverter.ConvertToHexString(rndAB_enc)); iv = ExtractLastBlock(rndAB_enc, 16); APDUCommand cmd_challange_response = new APDUCommand(IsoCase.Case4Short) @@ -656,10 +664,10 @@ namespace NFC.Mifare_DESFire INS = 0xAF, Data = rndAB_enc }; - _Log.DebugFormat("APDU_CMD(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray())); + _Log.Debug(cmd_challange_response.ToString()); response = _Card.Transmit(cmd_challange_response); - _Log.DebugFormat("APDU_RES(cmd_challange_response): {0}", HexConverter.ConvertToHexString(cmd_challange_response.ToArray())); + _Log.Debug(response.ToString()); CheckAPDUResponse(response); @@ -674,83 +682,30 @@ namespace NFC.Mifare_DESFire if (!rndA.SequenceEqual(rndAFromCard)) { - throw new Exception("Authentication failed, PICC Challenge is not corret"); + throw new Exception("Authentication failed, PICC Challenge is invalid."); } _SessionKey = GenerateSesionKey_AES(rndA, rndB); - _Log.DebugFormat("_SessionKey: {0}", HexConverter.ConvertToHexString(_SessionKey)); + _Log.DebugFormat("SessionKey: {0}", HexConverter.ConvertToHexString(_SessionKey)); _IV = GenerateEmptyArray(16); - _Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV)); - - _Log.Debug("End AuthenticateISO_DES"); + _Log.DebugFormat("IV: {0}", HexConverter.ConvertToHexString(_IV)); } /// - /// Change Same DES key as Authenticated + /// Change AES key, the same as Authenticated /// - /// - /// - /// - 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}", HexConverter.ConvertToHexString(header)); - - byte[] key_and_version = new_key; - byte[] command = Concatenate(header, key_and_version); - _Log.DebugFormat("command: {0}", HexConverter.ConvertToHexString(command)); - - CRC32 crc32 = new CRC32(); - byte[] crc = crc32.Calculate(command); - _Log.DebugFormat("crc: {0}", HexConverter.ConvertToHexString(crc)); - - byte[] cryptogram = Concatenate(key_and_version, crc); - _Log.DebugFormat("cryptogram: {0}", HexConverter.ConvertToHexString(cryptogram)); - - byte[] cryptogram_block = ExpandToBlockSize(cryptogram, 16); - _Log.DebugFormat("cryptogram_block: {0}", HexConverter.ConvertToHexString(cryptogram_block)); - - TDES des = new TDES(); - byte[] cryptogram_enc = des.Encrypt(cryptogram_block, _SessionKey, _IV); - _Log.DebugFormat("cryptogram_enc: {0}", HexConverter.ConvertToHexString(cryptogram_enc)); - - _IV = ExtractLastBlock(cryptogram_enc, 8); - _Log.DebugFormat("_IV: {0}", HexConverter.ConvertToHexString(_IV)); - - byte[] data = Concatenate(new byte[] { key_id }, cryptogram_enc); - _Log.DebugFormat("data: {0}", HexConverter.ConvertToHexString(data)); - - APDUCommand cmd_ChangeKey = new APDUCommand(IsoCase.Case4Short) - { - CLA = 0x90, - INS = 0xC4, - Data = data - }; - _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(cmd_ChangeKey.ToArray())); - - APDUResponse response = _Card.Transmit(cmd_ChangeKey); - _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(response.ToArray())); - - CheckAPDUResponse(response); - - _Log.Debug("End ChangeKey_AES"); - } - - /// - /// Change Same AES key as Authenticated - /// - /// - /// - /// + /// 0x01 - 0x0D + /// Array of 16 Bytes + /// Version of Key(min. 0x10) public void ChangeKey_AES(byte key_id, byte[] new_key, byte key_version) { - _Log.Debug("Start ChangeKey_AES"); + if (key_id >= 0x0E) + { + throw new ArgumentOutOfRangeException("KeyID is invalid"); + } + + _Log.InfoFormat("Change AES Key No: 0x{0:x}", key_id); byte[] header = new byte[] { @@ -789,25 +744,28 @@ namespace NFC.Mifare_DESFire INS = 0xC4, Data = data }; - _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(cmd_ChangeKey.ToArray())); + _Log.Debug(cmd_ChangeKey.ToString()); APDUResponse response = _Card.Transmit(cmd_ChangeKey); - _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(response.ToArray())); + _Log.Debug(response.ToString()); CheckAPDUResponse(response); - - _Log.Debug("End ChangeKey_AES"); } /// - /// Change other AES key as Authenticated + /// Change AES key, other than Authenticated /// - /// - /// - /// + /// 0x01 - 0x0D + /// Array of 16 Bytes + /// Version of Key(min. 0x10) public void ChangeOtherKey_AES(byte key_id, byte[] new_key, byte[] old_key, byte key_version) { - _Log.Debug("Start ChangeOtherKey_AES"); + if (key_id >= 0x0E) + { + throw new ArgumentOutOfRangeException("KeyID is invalid"); + } + + _Log.InfoFormat("Change AES Key No: 0x{0:x}", key_id); byte[] header = new byte[] { @@ -851,28 +809,28 @@ namespace NFC.Mifare_DESFire INS = 0xC4, Data = data }; - _Log.DebugFormat("APDU_CMD(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(cmd_ChangeKey.ToArray())); + _Log.Debug(cmd_ChangeKey.ToString()); APDUResponse response = _Card.Transmit(cmd_ChangeKey); - _Log.DebugFormat("APDU_RES(cmd_ChangeKey): {0}", HexConverter.ConvertToHexString(response.ToArray())); + _Log.Debug(response.ToString()); CheckAPDUResponse(response); - - _Log.Debug("End ChangeOtherKey_AES"); } /// /// Create Standard Data File /// - /// ID of File (0x01 - 0x10) + /// ID of File (0x00 - 0x20) /// Type of File Communicaton /// Access Rights for File /// Size of File in Bytes public void CreateFile_Standard(byte file_id, FileCommunication communication, UInt16 accessRights, UInt32 size) { - _Log.Debug("Start CreateFile_Standard"); - - _Log.DebugFormat("FID: {0}", file_id); + if (file_id >= 0x20) + { + throw new ArgumentOutOfRangeException("FileID is to large"); + } + _Log.DebugFormat("Create STD File: {0}", file_id); byte[] accessRights_byte = BitConverter.GetBytes(accessRights); byte[] size_byte_tolong = BitConverter.GetBytes(size); @@ -896,97 +854,27 @@ namespace NFC.Mifare_DESFire INS = (byte)APDUInstructions.CREATE_STDDATAFILE, Data = Concatenate(data, accessRights_byte, size_byte) }; - _Log.DebugFormat("APDU_CMD(cmd_CreateFile_Standard): {0}", HexConverter.ConvertToHexString(cmd_CreateFile_Standard.ToArray())); + _Log.Debug(cmd_CreateFile_Standard.ToString()); APDUResponse response = _Card.Transmit(cmd_CreateFile_Standard); - _Log.DebugFormat("APDU_RES(cmd_CreateFile_Standard): {0}", HexConverter.ConvertToHexString(response.ToArray())); + _Log.DebugFormat(response.ToString()); CheckAPDUResponse(response); - - _Log.Debug("End CreateFile_Standard"); - } - - /// - /// Read Data from File - /// - /// ID of File (0x01 - 0x10) - /// Offset for File - /// Lenght of Data - public byte[] ReadData(byte file_id, UInt32 offset, UInt32 length) - { - _Log.Debug("Start ReadData"); - - int max_read_bytes_pre_transaction = 47; - long bytes_readed = 0; - - List read_data = new List(); - - 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], - }; - - long bytes_toread = 0; - - if (length - bytes_readed < max_read_bytes_pre_transaction) - { - bytes_toread = length - bytes_readed; - } - else - { - bytes_toread = max_read_bytes_pre_transaction; - } - - 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}", HexConverter.ConvertToHexString(cmd_ReadData.ToArray())); - - APDUResponse response = _Card.Transmit(cmd_ReadData); - _Log.DebugFormat("APDU_RES(cmd_ReadData): {0}", HexConverter.ConvertToHexString(response.ToArray())); - - CheckAPDUResponse(response); - read_data.AddRange(response.Body); - } - _Log.Debug("End ReadData"); - - return read_data.ToArray(); } /// /// Write Data to File /// - /// ID of File (0x01 - 0x10) + /// ID of File (0x00 - 0x20) /// Offset for File /// Data to write public void WriteData(byte file_id, UInt32 offset, byte[] data) { - _Log.Debug("Start WriteData"); + if (file_id >= 0x20) + { + throw new ArgumentOutOfRangeException("FileID is to large"); + } + _Log.DebugFormat("Write Data to File: {0}", file_id); int max_write_bytes_pre_transaction = 47; byte[] write_buffer; @@ -1040,15 +928,91 @@ namespace NFC.Mifare_DESFire INS = (byte)APDUInstructions.WRITE_DATA, Data = Concatenate(file_id_array, offset_byte, length_byte, write_buffer) }; - _Log.DebugFormat("APDU_CMD(cmd_WriteData): {0}", HexConverter.ConvertToHexString(cmd_WriteData.ToArray())); + _Log.Debug(cmd_WriteData.ToString()); APDUResponse response = _Card.Transmit(cmd_WriteData); - _Log.DebugFormat("APDU_RES(cmd_WriteData): {0}", HexConverter.ConvertToHexString(response.ToArray())); + _Log.Debug(response.ToString()); CheckAPDUResponse(response); } + } - _Log.Debug("End WriteData"); + /// + /// Read Data from File + /// + /// ID of File (0x00 - 0x20) + /// Offset for File + /// Lenght of Data + public byte[] ReadData(byte file_id, UInt32 offset, UInt32 length) + { + if (file_id >= 0x20) + { + throw new ArgumentOutOfRangeException("FileID is to large"); + } + _Log.DebugFormat("Read Data from File: {0}", file_id); + + int max_read_bytes_pre_transaction = 47; + long bytes_readed = 0; + byte[] readbuffer = new byte[47]; + + List read_data = new List(); + + 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], + }; + + long bytes_toread = 0; + + if (length - bytes_readed < max_read_bytes_pre_transaction) + { + bytes_toread = length - bytes_readed; + } + else + { + bytes_toread = max_read_bytes_pre_transaction; + } + + 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.Debug(cmd_ReadData.ToString()); + + APDUResponse response = _Card.Transmit(cmd_ReadData); + _Log.Debug(response.ToString()); + + CheckAPDUResponse(response); + + // Remove CMAC from Body + read_data.AddRange(GetSubArray(response.Body, 0, bytes_toread)); + } + + return read_data.ToArray(); } /// diff --git a/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs b/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs index 22de52a..f39d986 100644 --- a/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs +++ b/NFC_Test/NXP MIFARE DESFire/MIFARE_DESFire_Test.cs @@ -6,6 +6,7 @@ using NFC.NXP_MIFARE_DESFire.Exceptions; using NSubstitute; using NUnit.Framework; using System; +using System.Text; namespace NFC_Unit_Test.NXP_MIFARE_DESFire { @@ -697,6 +698,38 @@ namespace NFC_Unit_Test.NXP_MIFARE_DESFire #endregion #region DESFire Commands + [Test] + public void SelectApplication() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00 + }; + + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "905a00000333221100")).Returns(response); + + desfire.SelectApplication(0x112233); + } + + [Test] + public void SelectApplication_InvalidAID() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + desfire.SelectApplication(0xFF000000); + }); + } + [Test] public void AuthenticateISO_DES() { @@ -708,31 +741,93 @@ namespace NFC_Unit_Test.NXP_MIFARE_DESFire { SW1 = 0x91, SW2 = 0xAF, - Body = HexConverter.ConvertFromHexString("5D994CE085F24089") + Body = HexConverter.ConvertFromHexString("2bf9a938ecca02e2") }; APDUResponse response_challenge_response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, - Body = HexConverter.ConvertFromHexString("913C6DED84221C41") + Body = HexConverter.ConvertFromHexString("07d825607a552e2e") }; - byte[] rndA = HexConverter.ConvertFromHexString("849B36C5F8BF4A09"); + byte[] rndA = HexConverter.ConvertFromHexString("5f7d1dd12d979173"); byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); - card.Transmit(Arg.Is(x => x.INS == 0x1A)).Returns(response_challenge_request); - card.Transmit(Arg.Is(x => x.INS == 0xAF)).Returns(response_challenge_response); + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "901a0000010000")).Returns(response_challenge_request); + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90af000010f8cdb2eaa42a3167dfcb53852ce267fd00")).Returns(response_challenge_response); desfire.AuthenticateISO_DES(0x00, key, rndA); - byte[] expected_sessionkey = HexConverter.ConvertFromHexString("849B36C54FD1B759849B36C54FD1B759"); + byte[] expected_sessionkey = HexConverter.ConvertFromHexString("5f7d1dd1f449db5c5f7d1dd1f449db5c"); byte[] expected_iv = HexConverter.ConvertFromHexString("0000000000000000"); Assert.AreEqual(expected_sessionkey, desfire._SessionKey); Assert.AreEqual(expected_iv, desfire._IV); } + [Test] + public void AuthenticateISO_DES_InvalidKeyNo() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + desfire.AuthenticateISO_DES(0x0F, null); + }); + } + + [Test] + public void Format() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00 + }; + + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90fc000000")).Returns(response); + + desfire.Format(); + } + + [Test] + public void CreateApplication() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00 + }; + + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90ca000005eeffaa0b8200")).Returns(response); + + desfire.CreateApplication(0xAAFFEE, 0x0b, 0x82); + } + + [Test] + public void CreateApplication_InvalidAID() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + desfire.CreateApplication(0xFF000000, 0x00, 0x00); + }); + } + [Test] public void AuthenticateISO_AES() { @@ -744,31 +839,43 @@ namespace NFC_Unit_Test.NXP_MIFARE_DESFire { SW1 = 0x91, SW2 = 0xAF, - Body = HexConverter.ConvertFromHexString("43a28e28c653df83cd85039714bccb51") + Body = HexConverter.ConvertFromHexString("a33856932308775cf464610c2b17a558") }; APDUResponse response_challenge_response = new APDUResponse() { SW1 = 0x91, SW2 = 0x00, - Body = HexConverter.ConvertFromHexString("d8f70a0f9a43f522f775a56f5688592f") + Body = HexConverter.ConvertFromHexString("8fdc476f6bac44fe9150e285abd68d48") }; - byte[] rndA = HexConverter.ConvertFromHexString("8a8b3c15e576ae3a21c2b18e6aead1f1"); + byte[] rndA = HexConverter.ConvertFromHexString("2176770e7a6eb4bef00d5e4b201d1e57"); byte[] key = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); - card.Transmit(Arg.Is(x => x.INS == 0xAA)).Returns(response_challenge_request); - card.Transmit(Arg.Is(x => x.INS == 0xAF)).Returns(response_challenge_response); + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90aa0000010000")).Returns(response_challenge_request); + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90af000020cbe9726faf54bc76b2055d0b9700e7dc97ecad5627f1d1702a16e8408d2a0ada00")).Returns(response_challenge_response); desfire.AuthenticateISO_AES(0x00, key, rndA); - byte[] expected_sessionkey = HexConverter.ConvertFromHexString("8a8b3c15c71d0cf46aead1f148f27703"); + byte[] expected_sessionkey = HexConverter.ConvertFromHexString("2176770e11c512ca201d1e57fde6e15a"); byte[] expected_iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); Assert.AreEqual(expected_sessionkey, desfire._SessionKey); Assert.AreEqual(expected_iv, desfire._IV); } + [Test] + public void AuthenticateISO_AES_InvalidKeyNo() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + desfire.AuthenticateISO_AES(0x0F, null); + }); + } + [Test] public void ChangeKey_AES() { @@ -782,19 +889,31 @@ namespace NFC_Unit_Test.NXP_MIFARE_DESFire SW2 = 0x00 }; - byte[] new_key = HexConverter.ConvertFromHexString("45eeb8338ae8f49a032e85bb11143530"); + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90c400002100c2b54a718d0251845653199909bb32e8e38bd6719e8dc21799c29c922a0984fc00")).Returns(response); - byte[] sessionkey = HexConverter.ConvertFromHexString("2f96515262e1beb0129de2df3e97feb3"); + byte[] new_key = HexConverter.ConvertFromHexString("25432a462d4a614e645267556b587032"); + + byte[] sessionkey = HexConverter.ConvertFromHexString("a8514dd0350f3dfbc86e80744bcc9b57"); byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); desfire._SessionKey = sessionkey; desfire._IV = iv; - card.Transmit(null).ReturnsForAnyArgs(response); - desfire.ChangeKey_AES(0x00, new_key, 0x10); } + [Test] + public void ChangeKey_AES_InvalidKeyNo() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + desfire.ChangeKey_AES(0x0F, null, 0x10); + }); + } + [Test] public void ChangeOtherKey_AES() { @@ -808,19 +927,209 @@ namespace NFC_Unit_Test.NXP_MIFARE_DESFire SW2 = 0x00 }; - byte[] new_key = HexConverter.ConvertFromHexString("8db1f942f2d7cc82f6fa1486a30f8c12"); + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90c400002101a8c5a61a06f56f38dc91266fed2e87dc00a5ad72a634ff0e62c8d6d80707dd6000")).Returns(response); + + byte[] new_key = HexConverter.ConvertFromHexString("25432a462d4a614e645267556b587032"); byte[] old_key = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); - byte[] sessionkey = HexConverter.ConvertFromHexString("e7aff3361c3e85347993c3219a87d24b"); + byte[] sessionkey = HexConverter.ConvertFromHexString("1677623e1e158a62dc3d128db55f947d"); byte[] iv = HexConverter.ConvertFromHexString("00000000000000000000000000000000"); desfire._SessionKey = sessionkey; desfire._IV = iv; - card.Transmit(null).ReturnsForAnyArgs(response); - desfire.ChangeOtherKey_AES(0x01, new_key, old_key, 0x10); } + + [Test] + public void ChangeOtherKey_AES_InvalidKeyNo() + { + MIFARE_DESFire desfire = new MIFARE_DESFire(null); + + Assert.Throws( + delegate + { + desfire.ChangeKey_AES(0x0F, null, 0x10); + }); + } + + [Test] + public void CreateFile_Standard() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00 + }; + + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90cd000007010000e0f0000000")).Returns(response); + + UInt16 accesRights = desfire.GenerateFileAccessRights((byte)FileAccessRights.FREE, 0x00, 0x00, 0x00); + desfire.CreateFile_Standard(0x01, FileCommunication.PLAIN, accesRights, 0xF0); + } + + [Test] + public void CreateFile_Standard_InvalidFID() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + Assert.Throws( + delegate + { + desfire.CreateFile_Standard(0x21, FileCommunication.PLAIN, 0x0000, 0xF0); + }); + } + + [Test] + public void WriteData() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00 + }; + + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "903d00000f01000000080000546573743132333400")).Returns(response); + + desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes("Test1234")); + } + + [Test] + public void WriteData_Long() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00 + }; + + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "903d000036010000002f0000546573743132333454657374313233345465737431323334546573743132333454657374313233345465737431323300")).Returns(response); + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "903d000036012f00002f0000345465737431323334546573743132333454657374313233345465737431323334546573743132333454657374313200")).Returns(response); + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "903d000019015e000012000033345465737431323334546573743132333400")).Returns(response); + + desfire.WriteData(0x01, 0, Encoding.ASCII.GetBytes("Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234Test1234")); + } + + [Test] + public void WriteData_InvalidFileID() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + Assert.Throws( + delegate + { + desfire.WriteData(0x21, 0x00, Encoding.ASCII.GetBytes("Test1234")); + }); + } + + [Test] + public void ReadData() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00, + Body = HexConverter.ConvertFromHexString("54657374313233340000000000000000000000000000000000000000000000009100") + }; + + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90bd0000070100000020000000")).Returns(response); + + byte[] data = desfire.ReadData(0x01, 0x00, 0x20); + + Assert.AreEqual("Test1234", Encoding.ASCII.GetString(data).Replace("\u0000", "")); + } + + [Test] + public void ReadData_CMAC() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + APDUResponse response = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00, + Body = HexConverter.ConvertFromHexString("5465737431323334000000000000000000000000000000000000000000000000809a9bedbc559a5b9100") + }; + + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90bd0000070100000020000000")).Returns(response); + + byte[] data = desfire.ReadData(0x01, 0x00, 0x20); + + Assert.AreEqual("Test1234", Encoding.ASCII.GetString(data).Replace("\u0000", "")); + } + + [Test] + public void ReadData_Long() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + APDUResponse response_1 = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00, + Body = HexConverter.ConvertFromHexString("54657374313233340000000000000000000000000000000000000000000000000000000000000000000000000000009100") + }; + + APDUResponse response_2 = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00, + Body = HexConverter.ConvertFromHexString("00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009100") + }; + + APDUResponse response_3 = new APDUResponse() + { + SW1 = 0x91, + SW2 = 0x00, + Body = HexConverter.ConvertFromHexString("00009100") + }; + + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90bd000007010000002f000000")).Returns(response_1); + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90bd000007012f00002f000000")).Returns(response_2); + card.Transmit(Arg.Is(x => HexConverter.ConvertToHexString(x.ToArray()) == "90bd000007015e000002000000")).Returns(response_3); + + byte[] data = desfire.ReadData(0x01, 0x00, 0x60); + + Assert.AreEqual("Test1234", Encoding.ASCII.GetString(data).Replace("\u0000", "")); + } + + [Test] + public void ReadData_InvalidFileID() + { + ICard card = Substitute.For(); + + MIFARE_DESFire desfire = new MIFARE_DESFire(card); + + Assert.Throws( + delegate + { + desfire.ReadData(0x21, 0x00, 0x20); + }); + } #endregion } } diff --git a/NFC_Test/REAL_DESFireCommands.cs b/NFC_Test/REAL_DESFireCommands.cs index 36bd22f..5808d54 100644 --- a/NFC_Test/REAL_DESFireCommands.cs +++ b/NFC_Test/REAL_DESFireCommands.cs @@ -251,7 +251,7 @@ namespace NFC_Real_Test desfire.AuthenticateISO_AES(0x00, key_aes._Key); CipherKey key_aes_new = new CipherKey(ApplicationMasterKey, CipherType.AES, 0x10); - desfire.ChangeKey_AES(0x00, key._Key, key._KeyVersion); + desfire.ChangeKey_AES(0x00, key_aes_new._Key, key_aes_new._KeyVersion); test_successfully = true; diff --git a/NFC_Test/REAL_FabAccess_OTA.cs b/NFC_Test/REAL_FabAccess_OTA.cs index 7edc1ab..a17c0dc 100644 --- a/NFC_Test/REAL_FabAccess_OTA.cs +++ b/NFC_Test/REAL_FabAccess_OTA.cs @@ -17,7 +17,9 @@ namespace NFC_Real_Test private byte _FabAccess_FID = 0x01; private UInt32 _FabAccess_FSize = 0xF0; - private CipherKey _FabAccess_Card_MasterKey = new CipherKey("294A404E635266556A576E5A72347537", CipherType.AES, 0x10); + // Change of PICC Key is not implementet yet + // private CipherKey _FabAccess_Card_MasterKey = new CipherKey("294A404E635266556A576E5A72347537", CipherType.AES, 0x10); + private CipherKey _FabAccess_Application_MasterKey = new CipherKey("50645367566B59703273357638792F42", CipherType.AES, 0x10); private CipherKey _FabAccess_Application_AuthKey = new CipherKey("6D5A7134743677397A24432646294A40", CipherType.AES, 0x10); From 8a2ca3e280c76bdfa506e9494e45c46d52ee80c4 Mon Sep 17 00:00:00 2001 From: Jannis Rieger Date: Mon, 9 Nov 2020 18:42:44 +0100 Subject: [PATCH 20/21] downgraded Xamarin.Forms --- .../Borepin.Android/Borepin.Android.csproj | 2 +- .../Resources/Resource.designer.cs | 543 +++++++++--------- Borepin/Borepin.GTK/Borepin.GTK.csproj | 31 +- Borepin/Borepin.GTK/packages.config | 4 +- Borepin/Borepin.GTK/webkit-sharp.dll.config | 10 +- Borepin/Borepin.iOS/Borepin.iOS.csproj | 4 +- Borepin/Borepin.macOS/Borepin.macOS.csproj | 29 +- Borepin/Borepin.macOS/packages.config | 2 +- Borepin/Borepin/Borepin.csproj | 2 +- 9 files changed, 296 insertions(+), 331 deletions(-) diff --git a/Borepin/Borepin.Android/Borepin.Android.csproj b/Borepin/Borepin.Android/Borepin.Android.csproj index 70d8c2f..afcad44 100644 --- a/Borepin/Borepin.Android/Borepin.Android.csproj +++ b/Borepin/Borepin.Android/Borepin.Android.csproj @@ -53,7 +53,7 @@ - + diff --git a/Borepin/Borepin.Android/Resources/Resource.designer.cs b/Borepin/Borepin.Android/Resources/Resource.designer.cs index 9ef43e5..1bc81a8 100644 --- a/Borepin/Borepin.Android/Resources/Resource.designer.cs +++ b/Borepin/Borepin.Android/Resources/Resource.designer.cs @@ -575,7 +575,6 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimAnimationDuration = global::Borepin.Droid.Resource.Attribute.scrimAnimationDuration; global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimBackground = global::Borepin.Droid.Resource.Attribute.scrimBackground; global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrimVisibleHeightTrigger = global::Borepin.Droid.Resource.Attribute.scrimVisibleHeightTrigger; - global::Xamarin.Forms.Platform.Android.Resource.Attribute.scrollViewStyle = global::Borepin.Droid.Resource.Attribute.scrollViewStyle; global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchHintIcon = global::Borepin.Droid.Resource.Attribute.searchHintIcon; global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchIcon = global::Borepin.Droid.Resource.Attribute.searchIcon; global::Xamarin.Forms.Platform.Android.Resource.Attribute.searchViewStyle = global::Borepin.Droid.Resource.Attribute.searchViewStyle; @@ -1718,6 +1717,7 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Android.Resource.Style.CardView = global::Borepin.Droid.Resource.Style.CardView; global::Xamarin.Forms.Platform.Android.Resource.Style.CardView_Dark = global::Borepin.Droid.Resource.Style.CardView_Dark; global::Xamarin.Forms.Platform.Android.Resource.Style.CardView_Light = global::Borepin.Droid.Resource.Style.CardView_Light; + global::Xamarin.Forms.Platform.Android.Resource.Style.collectionViewScrollBars = global::Borepin.Droid.Resource.Style.collectionViewScrollBars; global::Xamarin.Forms.Platform.Android.Resource.Style.collectionViewTheme = global::Borepin.Droid.Resource.Style.collectionViewTheme; global::Xamarin.Forms.Platform.Android.Resource.Style.MainTheme = global::Borepin.Droid.Resource.Style.MainTheme; global::Xamarin.Forms.Platform.Android.Resource.Style.MainTheme_Base = global::Borepin.Droid.Resource.Style.MainTheme_Base; @@ -1752,8 +1752,6 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Android.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text = global::Borepin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text; global::Xamarin.Forms.Platform.Android.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton = global::Borepin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton; global::Xamarin.Forms.Platform.Android.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = global::Borepin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow; - global::Xamarin.Forms.Platform.Android.Resource.Style.scrollViewScrollBars = global::Borepin.Droid.Resource.Style.scrollViewScrollBars; - global::Xamarin.Forms.Platform.Android.Resource.Style.scrollViewTheme = global::Borepin.Droid.Resource.Style.scrollViewTheme; global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat; global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Body1 = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat_Body1; global::Xamarin.Forms.Platform.Android.Resource.Style.TextAppearance_AppCompat_Body2 = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat_Body2; @@ -2603,8 +2601,6 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground = global::Borepin.Droid.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground; global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollingViewBehavior_Layout = global::Borepin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout; global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop = global::Borepin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollViewRendererTheme = global::Borepin.Droid.Resource.Styleable.ScrollViewRendererTheme; - global::Xamarin.Forms.Platform.Android.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle = global::Borepin.Droid.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle; global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView = global::Borepin.Droid.Resource.Styleable.SearchView; global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_focusable = global::Borepin.Droid.Resource.Styleable.SearchView_android_focusable; global::Xamarin.Forms.Platform.Android.Resource.Styleable.SearchView_android_imeOptions = global::Borepin.Droid.Resource.Styleable.SearchView_android_imeOptions; @@ -3149,7 +3145,6 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Resource.Attribute.scrimAnimationDuration = global::Borepin.Droid.Resource.Attribute.scrimAnimationDuration; global::Xamarin.Forms.Platform.Resource.Attribute.scrimBackground = global::Borepin.Droid.Resource.Attribute.scrimBackground; global::Xamarin.Forms.Platform.Resource.Attribute.scrimVisibleHeightTrigger = global::Borepin.Droid.Resource.Attribute.scrimVisibleHeightTrigger; - global::Xamarin.Forms.Platform.Resource.Attribute.scrollViewStyle = global::Borepin.Droid.Resource.Attribute.scrollViewStyle; global::Xamarin.Forms.Platform.Resource.Attribute.searchHintIcon = global::Borepin.Droid.Resource.Attribute.searchHintIcon; global::Xamarin.Forms.Platform.Resource.Attribute.searchIcon = global::Borepin.Droid.Resource.Attribute.searchIcon; global::Xamarin.Forms.Platform.Resource.Attribute.searchViewStyle = global::Borepin.Droid.Resource.Attribute.searchViewStyle; @@ -4292,6 +4287,7 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Resource.Style.CardView = global::Borepin.Droid.Resource.Style.CardView; global::Xamarin.Forms.Platform.Resource.Style.CardView_Dark = global::Borepin.Droid.Resource.Style.CardView_Dark; global::Xamarin.Forms.Platform.Resource.Style.CardView_Light = global::Borepin.Droid.Resource.Style.CardView_Light; + global::Xamarin.Forms.Platform.Resource.Style.collectionViewScrollBars = global::Borepin.Droid.Resource.Style.collectionViewScrollBars; global::Xamarin.Forms.Platform.Resource.Style.collectionViewTheme = global::Borepin.Droid.Resource.Style.collectionViewTheme; global::Xamarin.Forms.Platform.Resource.Style.MainTheme = global::Borepin.Droid.Resource.Style.MainTheme; global::Xamarin.Forms.Platform.Resource.Style.MainTheme_Base = global::Borepin.Droid.Resource.Style.MainTheme_Base; @@ -4326,8 +4322,6 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text = global::Borepin.Droid.Resource.Style.RtlOverlay_Widget_AppCompat_Search_DropDown_Text; global::Xamarin.Forms.Platform.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton = global::Borepin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton; global::Xamarin.Forms.Platform.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = global::Borepin.Droid.Resource.Style.RtlUnderlay_Widget_AppCompat_ActionButton_Overflow; - global::Xamarin.Forms.Platform.Resource.Style.scrollViewScrollBars = global::Borepin.Droid.Resource.Style.scrollViewScrollBars; - global::Xamarin.Forms.Platform.Resource.Style.scrollViewTheme = global::Borepin.Droid.Resource.Style.scrollViewTheme; global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat; global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Body1 = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat_Body1; global::Xamarin.Forms.Platform.Resource.Style.TextAppearance_AppCompat_Body2 = global::Borepin.Droid.Resource.Style.TextAppearance_AppCompat_Body2; @@ -5177,8 +5171,6 @@ namespace Borepin.Droid global::Xamarin.Forms.Platform.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground = global::Borepin.Droid.Resource.Styleable.ScrimInsetsFrameLayout_insetForeground; global::Xamarin.Forms.Platform.Resource.Styleable.ScrollingViewBehavior_Layout = global::Borepin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout; global::Xamarin.Forms.Platform.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop = global::Borepin.Droid.Resource.Styleable.ScrollingViewBehavior_Layout_behavior_overlapTop; - global::Xamarin.Forms.Platform.Resource.Styleable.ScrollViewRendererTheme = global::Borepin.Droid.Resource.Styleable.ScrollViewRendererTheme; - global::Xamarin.Forms.Platform.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle = global::Borepin.Droid.Resource.Styleable.ScrollViewRendererTheme_scrollViewStyle; global::Xamarin.Forms.Platform.Resource.Styleable.SearchView = global::Borepin.Droid.Resource.Styleable.SearchView; global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_focusable = global::Borepin.Droid.Resource.Styleable.SearchView_android_focusable; global::Xamarin.Forms.Platform.Resource.Styleable.SearchView_android_imeOptions = global::Borepin.Droid.Resource.Styleable.SearchView_android_imeOptions; @@ -6491,427 +6483,424 @@ namespace Borepin.Droid public const int scrimVisibleHeightTrigger = 2130903377; // aapt resource value: 0x7F030152 - public const int scrollViewStyle = 2130903378; + public const int searchHintIcon = 2130903378; // aapt resource value: 0x7F030153 - public const int searchHintIcon = 2130903379; + public const int searchIcon = 2130903379; // aapt resource value: 0x7F030154 - public const int searchIcon = 2130903380; + public const int searchViewStyle = 2130903380; // aapt resource value: 0x7F030155 - public const int searchViewStyle = 2130903381; + public const int seekBarStyle = 2130903381; // aapt resource value: 0x7F030156 - public const int seekBarStyle = 2130903382; + public const int selectableItemBackground = 2130903382; // aapt resource value: 0x7F030157 - public const int selectableItemBackground = 2130903383; + public const int selectableItemBackgroundBorderless = 2130903383; // aapt resource value: 0x7F030158 - public const int selectableItemBackgroundBorderless = 2130903384; + public const int showAsAction = 2130903384; // aapt resource value: 0x7F030159 - public const int showAsAction = 2130903385; + public const int showDividers = 2130903385; // aapt resource value: 0x7F03015A - public const int showDividers = 2130903386; + public const int showMotionSpec = 2130903386; // aapt resource value: 0x7F03015B - public const int showMotionSpec = 2130903387; + public const int showText = 2130903387; // aapt resource value: 0x7F03015C - public const int showText = 2130903388; + public const int showTitle = 2130903388; // aapt resource value: 0x7F03015D - public const int showTitle = 2130903389; + public const int singleChoiceItemLayout = 2130903389; // aapt resource value: 0x7F03015E - public const int singleChoiceItemLayout = 2130903390; + public const int singleLine = 2130903390; // aapt resource value: 0x7F03015F - public const int singleLine = 2130903391; + public const int singleSelection = 2130903391; // aapt resource value: 0x7F030160 - public const int singleSelection = 2130903392; + public const int snackbarButtonStyle = 2130903392; // aapt resource value: 0x7F030161 - public const int snackbarButtonStyle = 2130903393; + public const int snackbarStyle = 2130903393; // aapt resource value: 0x7F030162 - public const int snackbarStyle = 2130903394; + public const int spanCount = 2130903394; // aapt resource value: 0x7F030163 - public const int spanCount = 2130903395; + public const int spinBars = 2130903395; // aapt resource value: 0x7F030164 - public const int spinBars = 2130903396; + public const int spinnerDropDownItemStyle = 2130903396; // aapt resource value: 0x7F030165 - public const int spinnerDropDownItemStyle = 2130903397; + public const int spinnerStyle = 2130903397; // aapt resource value: 0x7F030166 - public const int spinnerStyle = 2130903398; + public const int splitTrack = 2130903398; // aapt resource value: 0x7F030167 - public const int splitTrack = 2130903399; + public const int srcCompat = 2130903399; // aapt resource value: 0x7F030168 - public const int srcCompat = 2130903400; + public const int stackFromEnd = 2130903400; // aapt resource value: 0x7F030169 - public const int stackFromEnd = 2130903401; + public const int state_above_anchor = 2130903401; // aapt resource value: 0x7F03016A - public const int state_above_anchor = 2130903402; + public const int state_collapsed = 2130903402; // aapt resource value: 0x7F03016B - public const int state_collapsed = 2130903403; + public const int state_collapsible = 2130903403; // aapt resource value: 0x7F03016C - public const int state_collapsible = 2130903404; + public const int state_liftable = 2130903404; // aapt resource value: 0x7F03016D - public const int state_liftable = 2130903405; + public const int state_lifted = 2130903405; // aapt resource value: 0x7F03016E - public const int state_lifted = 2130903406; + public const int statusBarBackground = 2130903406; // aapt resource value: 0x7F03016F - public const int statusBarBackground = 2130903407; + public const int statusBarScrim = 2130903407; // aapt resource value: 0x7F030170 - public const int statusBarScrim = 2130903408; + public const int strokeColor = 2130903408; // aapt resource value: 0x7F030171 - public const int strokeColor = 2130903409; + public const int strokeWidth = 2130903409; // aapt resource value: 0x7F030172 - public const int strokeWidth = 2130903410; + public const int subMenuArrow = 2130903410; // aapt resource value: 0x7F030173 - public const int subMenuArrow = 2130903411; + public const int submitBackground = 2130903411; // aapt resource value: 0x7F030174 - public const int submitBackground = 2130903412; + public const int subtitle = 2130903412; // aapt resource value: 0x7F030175 - public const int subtitle = 2130903413; + public const int subtitleTextAppearance = 2130903413; // aapt resource value: 0x7F030176 - public const int subtitleTextAppearance = 2130903414; + public const int subtitleTextColor = 2130903414; // aapt resource value: 0x7F030177 - public const int subtitleTextColor = 2130903415; + public const int subtitleTextStyle = 2130903415; // aapt resource value: 0x7F030178 - public const int subtitleTextStyle = 2130903416; + public const int suggestionRowLayout = 2130903416; // aapt resource value: 0x7F030179 - public const int suggestionRowLayout = 2130903417; + public const int switchMinWidth = 2130903417; // aapt resource value: 0x7F03017A - public const int switchMinWidth = 2130903418; + public const int switchPadding = 2130903418; // aapt resource value: 0x7F03017B - public const int switchPadding = 2130903419; + public const int switchStyle = 2130903419; // aapt resource value: 0x7F03017C - public const int switchStyle = 2130903420; + public const int switchTextAppearance = 2130903420; // aapt resource value: 0x7F03017D - public const int switchTextAppearance = 2130903421; + public const int tabBackground = 2130903421; // aapt resource value: 0x7F03017E - public const int tabBackground = 2130903422; + public const int tabContentStart = 2130903422; // aapt resource value: 0x7F03017F - public const int tabContentStart = 2130903423; + public const int tabGravity = 2130903423; // aapt resource value: 0x7F030180 - public const int tabGravity = 2130903424; + public const int tabIconTint = 2130903424; // aapt resource value: 0x7F030181 - public const int tabIconTint = 2130903425; + public const int tabIconTintMode = 2130903425; // aapt resource value: 0x7F030182 - public const int tabIconTintMode = 2130903426; + public const int tabIndicator = 2130903426; // aapt resource value: 0x7F030183 - public const int tabIndicator = 2130903427; + public const int tabIndicatorAnimationDuration = 2130903427; // aapt resource value: 0x7F030184 - public const int tabIndicatorAnimationDuration = 2130903428; + public const int tabIndicatorColor = 2130903428; // aapt resource value: 0x7F030185 - public const int tabIndicatorColor = 2130903429; + public const int tabIndicatorFullWidth = 2130903429; // aapt resource value: 0x7F030186 - public const int tabIndicatorFullWidth = 2130903430; + public const int tabIndicatorGravity = 2130903430; // aapt resource value: 0x7F030187 - public const int tabIndicatorGravity = 2130903431; + public const int tabIndicatorHeight = 2130903431; // aapt resource value: 0x7F030188 - public const int tabIndicatorHeight = 2130903432; + public const int tabInlineLabel = 2130903432; // aapt resource value: 0x7F030189 - public const int tabInlineLabel = 2130903433; + public const int tabMaxWidth = 2130903433; // aapt resource value: 0x7F03018A - public const int tabMaxWidth = 2130903434; + public const int tabMinWidth = 2130903434; // aapt resource value: 0x7F03018B - public const int tabMinWidth = 2130903435; + public const int tabMode = 2130903435; // aapt resource value: 0x7F03018C - public const int tabMode = 2130903436; + public const int tabPadding = 2130903436; // aapt resource value: 0x7F03018D - public const int tabPadding = 2130903437; + public const int tabPaddingBottom = 2130903437; // aapt resource value: 0x7F03018E - public const int tabPaddingBottom = 2130903438; + public const int tabPaddingEnd = 2130903438; // aapt resource value: 0x7F03018F - public const int tabPaddingEnd = 2130903439; + public const int tabPaddingStart = 2130903439; // aapt resource value: 0x7F030190 - public const int tabPaddingStart = 2130903440; + public const int tabPaddingTop = 2130903440; // aapt resource value: 0x7F030191 - public const int tabPaddingTop = 2130903441; + public const int tabRippleColor = 2130903441; // aapt resource value: 0x7F030192 - public const int tabRippleColor = 2130903442; + public const int tabSelectedTextColor = 2130903442; // aapt resource value: 0x7F030193 - public const int tabSelectedTextColor = 2130903443; + public const int tabStyle = 2130903443; // aapt resource value: 0x7F030194 - public const int tabStyle = 2130903444; + public const int tabTextAppearance = 2130903444; // aapt resource value: 0x7F030195 - public const int tabTextAppearance = 2130903445; + public const int tabTextColor = 2130903445; // aapt resource value: 0x7F030196 - public const int tabTextColor = 2130903446; + public const int tabUnboundedRipple = 2130903446; // aapt resource value: 0x7F030197 - public const int tabUnboundedRipple = 2130903447; + public const int textAllCaps = 2130903447; // aapt resource value: 0x7F030198 - public const int textAllCaps = 2130903448; + public const int textAppearanceBody1 = 2130903448; // aapt resource value: 0x7F030199 - public const int textAppearanceBody1 = 2130903449; + public const int textAppearanceBody2 = 2130903449; // aapt resource value: 0x7F03019A - public const int textAppearanceBody2 = 2130903450; + public const int textAppearanceButton = 2130903450; // aapt resource value: 0x7F03019B - public const int textAppearanceButton = 2130903451; + public const int textAppearanceCaption = 2130903451; // aapt resource value: 0x7F03019C - public const int textAppearanceCaption = 2130903452; + public const int textAppearanceHeadline1 = 2130903452; // aapt resource value: 0x7F03019D - public const int textAppearanceHeadline1 = 2130903453; + public const int textAppearanceHeadline2 = 2130903453; // aapt resource value: 0x7F03019E - public const int textAppearanceHeadline2 = 2130903454; + public const int textAppearanceHeadline3 = 2130903454; // aapt resource value: 0x7F03019F - public const int textAppearanceHeadline3 = 2130903455; + public const int textAppearanceHeadline4 = 2130903455; // aapt resource value: 0x7F0301A0 - public const int textAppearanceHeadline4 = 2130903456; + public const int textAppearanceHeadline5 = 2130903456; // aapt resource value: 0x7F0301A1 - public const int textAppearanceHeadline5 = 2130903457; + public const int textAppearanceHeadline6 = 2130903457; // aapt resource value: 0x7F0301A2 - public const int textAppearanceHeadline6 = 2130903458; + public const int textAppearanceLargePopupMenu = 2130903458; // aapt resource value: 0x7F0301A3 - public const int textAppearanceLargePopupMenu = 2130903459; + public const int textAppearanceListItem = 2130903459; // aapt resource value: 0x7F0301A4 - public const int textAppearanceListItem = 2130903460; + public const int textAppearanceListItemSecondary = 2130903460; // aapt resource value: 0x7F0301A5 - public const int textAppearanceListItemSecondary = 2130903461; + public const int textAppearanceListItemSmall = 2130903461; // aapt resource value: 0x7F0301A6 - public const int textAppearanceListItemSmall = 2130903462; + public const int textAppearanceOverline = 2130903462; // aapt resource value: 0x7F0301A7 - public const int textAppearanceOverline = 2130903463; + public const int textAppearancePopupMenuHeader = 2130903463; // aapt resource value: 0x7F0301A8 - public const int textAppearancePopupMenuHeader = 2130903464; + public const int textAppearanceSearchResultSubtitle = 2130903464; // aapt resource value: 0x7F0301A9 - public const int textAppearanceSearchResultSubtitle = 2130903465; + public const int textAppearanceSearchResultTitle = 2130903465; // aapt resource value: 0x7F0301AA - public const int textAppearanceSearchResultTitle = 2130903466; + public const int textAppearanceSmallPopupMenu = 2130903466; // aapt resource value: 0x7F0301AB - public const int textAppearanceSmallPopupMenu = 2130903467; + public const int textAppearanceSubtitle1 = 2130903467; // aapt resource value: 0x7F0301AC - public const int textAppearanceSubtitle1 = 2130903468; + public const int textAppearanceSubtitle2 = 2130903468; // aapt resource value: 0x7F0301AD - public const int textAppearanceSubtitle2 = 2130903469; + public const int textColorAlertDialogListItem = 2130903469; // aapt resource value: 0x7F0301AE - public const int textColorAlertDialogListItem = 2130903470; + public const int textColorSearchUrl = 2130903470; // aapt resource value: 0x7F0301AF - public const int textColorSearchUrl = 2130903471; + public const int textEndPadding = 2130903471; // aapt resource value: 0x7F0301B0 - public const int textEndPadding = 2130903472; + public const int textInputStyle = 2130903472; // aapt resource value: 0x7F0301B1 - public const int textInputStyle = 2130903473; + public const int textStartPadding = 2130903473; // aapt resource value: 0x7F0301B2 - public const int textStartPadding = 2130903474; + public const int theme = 2130903474; // aapt resource value: 0x7F0301B3 - public const int theme = 2130903475; + public const int thickness = 2130903475; // aapt resource value: 0x7F0301B4 - public const int thickness = 2130903476; + public const int thumbTextPadding = 2130903476; // aapt resource value: 0x7F0301B5 - public const int thumbTextPadding = 2130903477; + public const int thumbTint = 2130903477; // aapt resource value: 0x7F0301B6 - public const int thumbTint = 2130903478; + public const int thumbTintMode = 2130903478; // aapt resource value: 0x7F0301B7 - public const int thumbTintMode = 2130903479; + public const int tickMark = 2130903479; // aapt resource value: 0x7F0301B8 - public const int tickMark = 2130903480; + public const int tickMarkTint = 2130903480; // aapt resource value: 0x7F0301B9 - public const int tickMarkTint = 2130903481; + public const int tickMarkTintMode = 2130903481; // aapt resource value: 0x7F0301BA - public const int tickMarkTintMode = 2130903482; + public const int tint = 2130903482; // aapt resource value: 0x7F0301BB - public const int tint = 2130903483; + public const int tintMode = 2130903483; // aapt resource value: 0x7F0301BC - public const int tintMode = 2130903484; + public const int title = 2130903484; // aapt resource value: 0x7F0301BD - public const int title = 2130903485; + public const int titleEnabled = 2130903485; // aapt resource value: 0x7F0301BE - public const int titleEnabled = 2130903486; + public const int titleMargin = 2130903486; // aapt resource value: 0x7F0301BF - public const int titleMargin = 2130903487; + public const int titleMarginBottom = 2130903487; // aapt resource value: 0x7F0301C0 - public const int titleMarginBottom = 2130903488; - - // aapt resource value: 0x7F0301C1 - public const int titleMarginEnd = 2130903489; - - // aapt resource value: 0x7F0301C4 - public const int titleMargins = 2130903492; - - // aapt resource value: 0x7F0301C2 - public const int titleMarginStart = 2130903490; + public const int titleMarginEnd = 2130903488; // aapt resource value: 0x7F0301C3 - public const int titleMarginTop = 2130903491; + public const int titleMargins = 2130903491; + + // aapt resource value: 0x7F0301C1 + public const int titleMarginStart = 2130903489; + + // aapt resource value: 0x7F0301C2 + public const int titleMarginTop = 2130903490; + + // aapt resource value: 0x7F0301C4 + public const int titleTextAppearance = 2130903492; // aapt resource value: 0x7F0301C5 - public const int titleTextAppearance = 2130903493; + public const int titleTextColor = 2130903493; // aapt resource value: 0x7F0301C6 - public const int titleTextColor = 2130903494; + public const int titleTextStyle = 2130903494; // aapt resource value: 0x7F0301C7 - public const int titleTextStyle = 2130903495; + public const int toolbarId = 2130903495; // aapt resource value: 0x7F0301C8 - public const int toolbarId = 2130903496; + public const int toolbarNavigationButtonStyle = 2130903496; // aapt resource value: 0x7F0301C9 - public const int toolbarNavigationButtonStyle = 2130903497; + public const int toolbarStyle = 2130903497; // aapt resource value: 0x7F0301CA - public const int toolbarStyle = 2130903498; + public const int tooltipForegroundColor = 2130903498; // aapt resource value: 0x7F0301CB - public const int tooltipForegroundColor = 2130903499; + public const int tooltipFrameBackground = 2130903499; // aapt resource value: 0x7F0301CC - public const int tooltipFrameBackground = 2130903500; + public const int tooltipText = 2130903500; // aapt resource value: 0x7F0301CD - public const int tooltipText = 2130903501; + public const int track = 2130903501; // aapt resource value: 0x7F0301CE - public const int track = 2130903502; + public const int trackTint = 2130903502; // aapt resource value: 0x7F0301CF - public const int trackTint = 2130903503; + public const int trackTintMode = 2130903503; // aapt resource value: 0x7F0301D0 - public const int trackTintMode = 2130903504; + public const int ttcIndex = 2130903504; // aapt resource value: 0x7F0301D1 - public const int ttcIndex = 2130903505; + public const int useCompatPadding = 2130903505; // aapt resource value: 0x7F0301D2 - public const int useCompatPadding = 2130903506; + public const int viewInflaterClass = 2130903506; // aapt resource value: 0x7F0301D3 - public const int viewInflaterClass = 2130903507; + public const int voiceIcon = 2130903507; // aapt resource value: 0x7F0301D4 - public const int voiceIcon = 2130903508; + public const int windowActionBar = 2130903508; // aapt resource value: 0x7F0301D5 - public const int windowActionBar = 2130903509; + public const int windowActionBarOverlay = 2130903509; // aapt resource value: 0x7F0301D6 - public const int windowActionBarOverlay = 2130903510; + public const int windowActionModeOverlay = 2130903510; // aapt resource value: 0x7F0301D7 - public const int windowActionModeOverlay = 2130903511; + public const int windowFixedHeightMajor = 2130903511; // aapt resource value: 0x7F0301D8 - public const int windowFixedHeightMajor = 2130903512; + public const int windowFixedHeightMinor = 2130903512; // aapt resource value: 0x7F0301D9 - public const int windowFixedHeightMinor = 2130903513; + public const int windowFixedWidthMajor = 2130903513; // aapt resource value: 0x7F0301DA - public const int windowFixedWidthMajor = 2130903514; + public const int windowFixedWidthMinor = 2130903514; // aapt resource value: 0x7F0301DB - public const int windowFixedWidthMinor = 2130903515; + public const int windowMinWidthMajor = 2130903515; // aapt resource value: 0x7F0301DC - public const int windowMinWidthMajor = 2130903516; + public const int windowMinWidthMinor = 2130903516; // aapt resource value: 0x7F0301DD - public const int windowMinWidthMinor = 2130903517; - - // aapt resource value: 0x7F0301DE - public const int windowNoTitle = 2130903518; + public const int windowNoTitle = 2130903517; static Attribute() { @@ -10135,7 +10124,10 @@ namespace Borepin.Droid public const int CardView_Light = 2131624133; // aapt resource value: 0x7F0E01F7 - public const int collectionViewTheme = 2131624439; + public const int collectionViewScrollBars = 2131624439; + + // aapt resource value: 0x7F0E01F8 + public const int collectionViewTheme = 2131624440; // aapt resource value: 0x7F0E00C6 public const int MainTheme = 2131624134; @@ -10236,12 +10228,6 @@ namespace Borepin.Droid // aapt resource value: 0x7F0E00E6 public const int RtlUnderlay_Widget_AppCompat_ActionButton_Overflow = 2131624166; - // aapt resource value: 0x7F0E01F8 - public const int scrollViewScrollBars = 2131624440; - - // aapt resource value: 0x7F0E01F9 - public const int scrollViewTheme = 2131624441; - // aapt resource value: 0x7F0E00E7 public const int TextAppearance_AppCompat = 2131624167; @@ -11071,7 +11057,7 @@ namespace Borepin.Droid public partial class Styleable { - // aapt resource value: { 0x7F030031,0x7F030032,0x7F030033,0x7F030092,0x7F030093,0x7F030094,0x7F030095,0x7F030096,0x7F030097,0x7F0300A5,0x7F0300AA,0x7F0300AB,0x7F0300B6,0x7F0300E0,0x7F0300E5,0x7F0300EA,0x7F0300EB,0x7F0300ED,0x7F0300F7,0x7F030101,0x7F030124,0x7F030130,0x7F030141,0x7F030145,0x7F030146,0x7F030175,0x7F030178,0x7F0301BD,0x7F0301C7 } + // aapt resource value: { 0x7F030031,0x7F030032,0x7F030033,0x7F030092,0x7F030093,0x7F030094,0x7F030095,0x7F030096,0x7F030097,0x7F0300A5,0x7F0300AA,0x7F0300AB,0x7F0300B6,0x7F0300E0,0x7F0300E5,0x7F0300EA,0x7F0300EB,0x7F0300ED,0x7F0300F7,0x7F030101,0x7F030124,0x7F030130,0x7F030141,0x7F030145,0x7F030146,0x7F030174,0x7F030177,0x7F0301BC,0x7F0301C6 } public static int[] ActionBar = new int[] { 2130903089, 2130903090, @@ -11098,10 +11084,10 @@ namespace Borepin.Droid 2130903361, 2130903365, 2130903366, - 2130903413, - 2130903416, - 2130903485, - 2130903495}; + 2130903412, + 2130903415, + 2130903484, + 2130903494}; // aapt resource value: { 0x10100B3 } public static int[] ActionBarLayout = new int[] { @@ -11208,14 +11194,14 @@ namespace Borepin.Droid public static int[] ActionMenuView = new int[] { -1}; - // aapt resource value: { 0x7F030031,0x7F030032,0x7F03007E,0x7F0300E0,0x7F030178,0x7F0301C7 } + // aapt resource value: { 0x7F030031,0x7F030032,0x7F03007E,0x7F0300E0,0x7F030177,0x7F0301C6 } public static int[] ActionMode = new int[] { 2130903089, 2130903090, 2130903166, 2130903264, - 2130903416, - 2130903495}; + 2130903415, + 2130903494}; // aapt resource value: 0 public const int ActionMode_background = 0; @@ -11246,7 +11232,7 @@ namespace Borepin.Droid // aapt resource value: 1 public const int ActivityChooserView_initialActivityCount = 1; - // aapt resource value: { 0x10100F2,0x7F030052,0x7F030053,0x7F03011B,0x7F03011C,0x7F03012D,0x7F03015D,0x7F03015E } + // aapt resource value: { 0x10100F2,0x7F030052,0x7F030053,0x7F03011B,0x7F03011C,0x7F03012D,0x7F03015C,0x7F03015D } public static int[] AlertDialog = new int[] { 16842994, 2130903122, @@ -11254,8 +11240,8 @@ namespace Borepin.Droid 2130903323, 2130903324, 2130903341, - 2130903389, - 2130903390}; + 2130903388, + 2130903389}; // aapt resource value: 0 public const int AlertDialog_android_layout = 0; @@ -11347,12 +11333,12 @@ namespace Borepin.Droid 2130903228, 2130903318}; - // aapt resource value: { 0x7F03016B,0x7F03016C,0x7F03016D,0x7F03016E } + // aapt resource value: { 0x7F03016A,0x7F03016B,0x7F03016C,0x7F03016D } public static int[] AppBarLayoutStates = new int[] { + 2130903402, 2130903403, 2130903404, - 2130903405, - 2130903406}; + 2130903405}; // aapt resource value: 0 public const int AppBarLayoutStates_state_collapsed = 0; @@ -11395,12 +11381,12 @@ namespace Borepin.Droid // aapt resource value: 5 public const int AppBarLayout_liftOnScroll = 5; - // aapt resource value: { 0x1010119,0x7F030168,0x7F0301BB,0x7F0301BC } + // aapt resource value: { 0x1010119,0x7F030167,0x7F0301BA,0x7F0301BB } public static int[] AppCompatImageView = new int[] { 16843033, - 2130903400, - 2130903483, - 2130903484}; + 2130903399, + 2130903482, + 2130903483}; // aapt resource value: 0 public const int AppCompatImageView_android_src = 0; @@ -11414,12 +11400,12 @@ namespace Borepin.Droid // aapt resource value: 3 public const int AppCompatImageView_tintMode = 3; - // aapt resource value: { 0x1010142,0x7F0301B8,0x7F0301B9,0x7F0301BA } + // aapt resource value: { 0x1010142,0x7F0301B7,0x7F0301B8,0x7F0301B9 } public static int[] AppCompatSeekBar = new int[] { 16843074, + 2130903479, 2130903480, - 2130903481, - 2130903482}; + 2130903481}; // aapt resource value: 0 public const int AppCompatSeekBar_android_thumb = 0; @@ -11464,7 +11450,7 @@ namespace Borepin.Droid // aapt resource value: 0 public const int AppCompatTextHelper_android_textAppearance = 0; - // aapt resource value: { 0x1010034,0x7F03002C,0x7F03002D,0x7F03002E,0x7F03002F,0x7F030030,0x7F0300CF,0x7F0300D2,0x7F030109,0x7F030117,0x7F030198 } + // aapt resource value: { 0x1010034,0x7F03002C,0x7F03002D,0x7F03002E,0x7F03002F,0x7F030030,0x7F0300CF,0x7F0300D2,0x7F030109,0x7F030117,0x7F030197 } public static int[] AppCompatTextView = new int[] { 16842804, 2130903084, @@ -11476,7 +11462,7 @@ namespace Borepin.Droid 2130903250, 2130903305, 2130903319, - 2130903448}; + 2130903447}; // aapt resource value: 0 public const int AppCompatTextView_android_textAppearance = 0; @@ -11511,7 +11497,7 @@ namespace Borepin.Droid // aapt resource value: 10 public const int AppCompatTextView_textAllCaps = 10; - // aapt resource value: { 0x1010057,0x10100AE,0x7F030000,0x7F030001,0x7F030002,0x7F030003,0x7F030004,0x7F030005,0x7F030006,0x7F030007,0x7F030008,0x7F030009,0x7F03000A,0x7F03000B,0x7F03000C,0x7F03000E,0x7F03000F,0x7F030010,0x7F030011,0x7F030012,0x7F030013,0x7F030014,0x7F030015,0x7F030016,0x7F030017,0x7F030018,0x7F030019,0x7F03001A,0x7F03001B,0x7F03001C,0x7F03001D,0x7F03001E,0x7F030021,0x7F030022,0x7F030023,0x7F030024,0x7F030025,0x7F03002B,0x7F03003E,0x7F03004C,0x7F03004D,0x7F03004E,0x7F03004F,0x7F030050,0x7F030054,0x7F030055,0x7F03005F,0x7F030064,0x7F030085,0x7F030086,0x7F030087,0x7F030088,0x7F030089,0x7F03008A,0x7F03008B,0x7F03008C,0x7F03008D,0x7F03008F,0x7F03009E,0x7F0300A7,0x7F0300A8,0x7F0300A9,0x7F0300AC,0x7F0300AE,0x7F0300B1,0x7F0300B2,0x7F0300B3,0x7F0300B4,0x7F0300B5,0x7F0300EA,0x7F0300F6,0x7F030119,0x7F03011A,0x7F03011D,0x7F03011E,0x7F03011F,0x7F030120,0x7F030121,0x7F030122,0x7F030123,0x7F030138,0x7F030139,0x7F03013A,0x7F030140,0x7F030142,0x7F030149,0x7F03014A,0x7F03014B,0x7F03014C,0x7F030155,0x7F030156,0x7F030157,0x7F030158,0x7F030165,0x7F030166,0x7F03017C,0x7F0301A3,0x7F0301A4,0x7F0301A5,0x7F0301A6,0x7F0301A8,0x7F0301A9,0x7F0301AA,0x7F0301AB,0x7F0301AE,0x7F0301AF,0x7F0301C9,0x7F0301CA,0x7F0301CB,0x7F0301CC,0x7F0301D3,0x7F0301D5,0x7F0301D6,0x7F0301D7,0x7F0301D8,0x7F0301D9,0x7F0301DA,0x7F0301DB,0x7F0301DC,0x7F0301DD,0x7F0301DE } + // aapt resource value: { 0x1010057,0x10100AE,0x7F030000,0x7F030001,0x7F030002,0x7F030003,0x7F030004,0x7F030005,0x7F030006,0x7F030007,0x7F030008,0x7F030009,0x7F03000A,0x7F03000B,0x7F03000C,0x7F03000E,0x7F03000F,0x7F030010,0x7F030011,0x7F030012,0x7F030013,0x7F030014,0x7F030015,0x7F030016,0x7F030017,0x7F030018,0x7F030019,0x7F03001A,0x7F03001B,0x7F03001C,0x7F03001D,0x7F03001E,0x7F030021,0x7F030022,0x7F030023,0x7F030024,0x7F030025,0x7F03002B,0x7F03003E,0x7F03004C,0x7F03004D,0x7F03004E,0x7F03004F,0x7F030050,0x7F030054,0x7F030055,0x7F03005F,0x7F030064,0x7F030085,0x7F030086,0x7F030087,0x7F030088,0x7F030089,0x7F03008A,0x7F03008B,0x7F03008C,0x7F03008D,0x7F03008F,0x7F03009E,0x7F0300A7,0x7F0300A8,0x7F0300A9,0x7F0300AC,0x7F0300AE,0x7F0300B1,0x7F0300B2,0x7F0300B3,0x7F0300B4,0x7F0300B5,0x7F0300EA,0x7F0300F6,0x7F030119,0x7F03011A,0x7F03011D,0x7F03011E,0x7F03011F,0x7F030120,0x7F030121,0x7F030122,0x7F030123,0x7F030138,0x7F030139,0x7F03013A,0x7F030140,0x7F030142,0x7F030149,0x7F03014A,0x7F03014B,0x7F03014C,0x7F030154,0x7F030155,0x7F030156,0x7F030157,0x7F030164,0x7F030165,0x7F03017B,0x7F0301A2,0x7F0301A3,0x7F0301A4,0x7F0301A5,0x7F0301A7,0x7F0301A8,0x7F0301A9,0x7F0301AA,0x7F0301AD,0x7F0301AE,0x7F0301C8,0x7F0301C9,0x7F0301CA,0x7F0301CB,0x7F0301D2,0x7F0301D4,0x7F0301D5,0x7F0301D6,0x7F0301D7,0x7F0301D8,0x7F0301D9,0x7F0301DA,0x7F0301DB,0x7F0301DC,0x7F0301DD } public static int[] AppCompatTheme = new int[] { 16842839, 16842926, @@ -11602,28 +11588,29 @@ namespace Borepin.Droid 2130903370, 2130903371, 2130903372, + 2130903380, 2130903381, 2130903382, 2130903383, - 2130903384, + 2130903396, 2130903397, - 2130903398, - 2130903420, + 2130903419, + 2130903458, 2130903459, 2130903460, 2130903461, - 2130903462, + 2130903463, 2130903464, 2130903465, 2130903466, - 2130903467, + 2130903469, 2130903470, - 2130903471, + 2130903496, 2130903497, 2130903498, 2130903499, - 2130903500, - 2130903507, + 2130903506, + 2130903508, 2130903509, 2130903510, 2130903511, @@ -11632,8 +11619,7 @@ namespace Borepin.Droid 2130903514, 2130903515, 2130903516, - 2130903517, - 2130903518}; + 2130903517}; // aapt resource value: 2 public const int AppCompatTheme_actionBarDivider = 2; @@ -12149,7 +12135,7 @@ namespace Borepin.Droid // aapt resource value: 12 public const int CardView_contentPaddingTop = 12; - // aapt resource value: { 0x1010034,0x10100AB,0x101011F,0x101014F,0x10101E5,0x7F030061,0x7F030062,0x7F030063,0x7F030065,0x7F030066,0x7F030067,0x7F030069,0x7F03006A,0x7F03006B,0x7F03006C,0x7F03006D,0x7F03006E,0x7F030073,0x7F030074,0x7F030075,0x7F030077,0x7F030078,0x7F030079,0x7F03007A,0x7F03007B,0x7F03007C,0x7F03007D,0x7F0300E4,0x7F0300EE,0x7F0300F2,0x7F03014E,0x7F03015B,0x7F0301B0,0x7F0301B2 } + // aapt resource value: { 0x1010034,0x10100AB,0x101011F,0x101014F,0x10101E5,0x7F030061,0x7F030062,0x7F030063,0x7F030065,0x7F030066,0x7F030067,0x7F030069,0x7F03006A,0x7F03006B,0x7F03006C,0x7F03006D,0x7F03006E,0x7F030073,0x7F030074,0x7F030075,0x7F030077,0x7F030078,0x7F030079,0x7F03007A,0x7F03007B,0x7F03007C,0x7F03007D,0x7F0300E4,0x7F0300EE,0x7F0300F2,0x7F03014E,0x7F03015A,0x7F0301AF,0x7F0301B1 } public static int[] Chip = new int[] { 16842804, 16842923, @@ -12182,18 +12168,18 @@ namespace Borepin.Droid 2130903278, 2130903282, 2130903374, - 2130903387, - 2130903472, - 2130903474}; + 2130903386, + 2130903471, + 2130903473}; - // aapt resource value: { 0x7F030060,0x7F03006F,0x7F030070,0x7F030071,0x7F03015F,0x7F030160 } + // aapt resource value: { 0x7F030060,0x7F03006F,0x7F030070,0x7F030071,0x7F03015E,0x7F03015F } public static int[] ChipGroup = new int[] { 2130903136, 2130903151, 2130903152, 2130903153, - 2130903391, - 2130903392}; + 2130903390, + 2130903391}; // aapt resource value: 0 public const int ChipGroup_checkedChip = 0; @@ -12315,7 +12301,7 @@ namespace Borepin.Droid // aapt resource value: 33 public const int Chip_textStartPadding = 33; - // aapt resource value: { 0x7F030081,0x7F030082,0x7F03009D,0x7F0300BD,0x7F0300BE,0x7F0300BF,0x7F0300C0,0x7F0300C1,0x7F0300C2,0x7F0300C3,0x7F03014F,0x7F030151,0x7F030170,0x7F0301BD,0x7F0301BE,0x7F0301C8 } + // aapt resource value: { 0x7F030081,0x7F030082,0x7F03009D,0x7F0300BD,0x7F0300BE,0x7F0300BF,0x7F0300C0,0x7F0300C1,0x7F0300C2,0x7F0300C3,0x7F03014F,0x7F030151,0x7F03016F,0x7F0301BC,0x7F0301BD,0x7F0301C7 } public static int[] CollapsingToolbarLayout = new int[] { 2130903169, 2130903170, @@ -12329,10 +12315,10 @@ namespace Borepin.Droid 2130903235, 2130903375, 2130903377, - 2130903408, + 2130903407, + 2130903484, 2130903485, - 2130903486, - 2130903496}; + 2130903495}; // aapt resource value: 0 public const int CollapsingToolbarLayout_collapsedTitleGravity = 0; @@ -12423,10 +12409,10 @@ namespace Borepin.Droid // aapt resource value: 2 public const int CompoundButton_buttonTintMode = 2; - // aapt resource value: { 0x7F030107,0x7F03016F } + // aapt resource value: { 0x7F030107,0x7F03016E } public static int[] CoordinatorLayout = new int[] { 2130903303, - 2130903407}; + 2130903406}; // aapt resource value: 0 public const int CoordinatorLayout_keylines = 0; @@ -12476,7 +12462,7 @@ namespace Borepin.Droid // aapt resource value: 1 public const int DesignTheme_bottomSheetStyle = 1; - // aapt resource value: { 0x7F030029,0x7F03002A,0x7F030036,0x7F030084,0x7F0300AF,0x7F0300DD,0x7F030164,0x7F0301B4 } + // aapt resource value: { 0x7F030029,0x7F03002A,0x7F030036,0x7F030084,0x7F0300AF,0x7F0300DD,0x7F030163,0x7F0301B3 } public static int[] DrawerArrowToggle = new int[] { 2130903081, 2130903082, @@ -12484,8 +12470,8 @@ namespace Borepin.Droid 2130903172, 2130903215, 2130903261, - 2130903396, - 2130903476}; + 2130903395, + 2130903475}; // aapt resource value: 0 public const int DrawerArrowToggle_arrowHeadLength = 0; @@ -12511,7 +12497,7 @@ namespace Borepin.Droid // aapt resource value: 7 public const int DrawerArrowToggle_thickness = 7; - // aapt resource value: { 0x7F030034,0x7F030035,0x7F03003D,0x7F0300B6,0x7F0300C8,0x7F0300C9,0x7F0300E4,0x7F0300EC,0x7F03012A,0x7F030144,0x7F03014E,0x7F03015B,0x7F0301D2 } + // aapt resource value: { 0x7F030034,0x7F030035,0x7F03003D,0x7F0300B6,0x7F0300C8,0x7F0300C9,0x7F0300E4,0x7F0300EC,0x7F03012A,0x7F030144,0x7F03014E,0x7F03015A,0x7F0301D1 } public static int[] FloatingActionButton = new int[] { 2130903092, 2130903093, @@ -12524,8 +12510,8 @@ namespace Borepin.Droid 2130903338, 2130903364, 2130903374, - 2130903387, - 2130903506}; + 2130903386, + 2130903505}; // aapt resource value: 0 public const int FloatingActionButton_backgroundTint = 0; @@ -12593,7 +12579,7 @@ namespace Borepin.Droid 2130903255, 2130903256}; - // aapt resource value: { 0x1010532,0x1010533,0x101053F,0x101056F,0x1010570,0x7F0300D1,0x7F0300D9,0x7F0300DA,0x7F0300DB,0x7F0301D1 } + // aapt resource value: { 0x1010532,0x1010533,0x101053F,0x101056F,0x1010570,0x7F0300D1,0x7F0300D9,0x7F0300DA,0x7F0300DB,0x7F0301D0 } public static int[] FontFamilyFont = new int[] { 16844082, 16844083, @@ -12604,7 +12590,7 @@ namespace Borepin.Droid 2130903257, 2130903258, 2130903259, - 2130903505}; + 2130903504}; // aapt resource value: 0 public const int FontFamilyFont_android_font = 0; @@ -12738,7 +12724,7 @@ namespace Borepin.Droid // aapt resource value: 0 public const int ItemsViewRendererTheme_collectionViewStyle = 0; - // aapt resource value: { 0x10100AF,0x10100C4,0x1010126,0x1010127,0x1010128,0x7F0300AB,0x7F0300AD,0x7F03012B,0x7F03015A } + // aapt resource value: { 0x10100AF,0x10100C4,0x1010126,0x1010127,0x1010128,0x7F0300AB,0x7F0300AD,0x7F03012B,0x7F030159 } public static int[] LinearLayoutCompat = new int[] { 16842927, 16842948, @@ -12748,7 +12734,7 @@ namespace Borepin.Droid 2130903211, 2130903213, 2130903339, - 2130903386}; + 2130903385}; // aapt resource value: 2 public const int LinearLayoutCompat_android_baselineAligned = 2; @@ -12807,7 +12793,7 @@ namespace Borepin.Droid // aapt resource value: 1 public const int ListPopupWindow_android_dropDownVerticalOffset = 1; - // aapt resource value: { 0x10101B7,0x10101B8,0x10101B9,0x10101BA,0x7F030034,0x7F030035,0x7F0300A0,0x7F0300ED,0x7F0300EF,0x7F0300F0,0x7F0300F1,0x7F0300F3,0x7F0300F4,0x7F03014E,0x7F030171,0x7F030172 } + // aapt resource value: { 0x10101B7,0x10101B8,0x10101B9,0x10101BA,0x7F030034,0x7F030035,0x7F0300A0,0x7F0300ED,0x7F0300EF,0x7F0300F0,0x7F0300F1,0x7F0300F3,0x7F0300F4,0x7F03014E,0x7F030170,0x7F030171 } public static int[] MaterialButton = new int[] { 16843191, 16843192, @@ -12823,8 +12809,8 @@ namespace Borepin.Droid 2130903283, 2130903284, 2130903374, - 2130903409, - 2130903410}; + 2130903408, + 2130903409}; // aapt resource value: 3 public const int MaterialButton_android_insetBottom = 3; @@ -12874,10 +12860,10 @@ namespace Borepin.Droid // aapt resource value: 15 public const int MaterialButton_strokeWidth = 15; - // aapt resource value: { 0x7F030171,0x7F030172 } + // aapt resource value: { 0x7F030170,0x7F030171 } public static int[] MaterialCardView = new int[] { - 2130903409, - 2130903410}; + 2130903408, + 2130903409}; // aapt resource value: 0 public const int MaterialCardView_strokeColor = 0; @@ -12885,7 +12871,7 @@ namespace Borepin.Droid // aapt resource value: 1 public const int MaterialCardView_strokeWidth = 1; - // aapt resource value: { 0x7F030041,0x7F030042,0x7F030068,0x7F030072,0x7F030076,0x7F030085,0x7F030086,0x7F03008C,0x7F03008D,0x7F03008E,0x7F0300B5,0x7F0300D0,0x7F030126,0x7F030127,0x7F030131,0x7F030150,0x7F030161,0x7F030194,0x7F030199,0x7F03019A,0x7F03019B,0x7F03019C,0x7F03019D,0x7F03019E,0x7F03019F,0x7F0301A0,0x7F0301A1,0x7F0301A2,0x7F0301A7,0x7F0301AC,0x7F0301AD,0x7F0301B1 } + // aapt resource value: { 0x7F030041,0x7F030042,0x7F030068,0x7F030072,0x7F030076,0x7F030085,0x7F030086,0x7F03008C,0x7F03008D,0x7F03008E,0x7F0300B5,0x7F0300D0,0x7F030126,0x7F030127,0x7F030131,0x7F030150,0x7F030160,0x7F030193,0x7F030198,0x7F030199,0x7F03019A,0x7F03019B,0x7F03019C,0x7F03019D,0x7F03019E,0x7F03019F,0x7F0301A0,0x7F0301A1,0x7F0301A6,0x7F0301AB,0x7F0301AC,0x7F0301B0 } public static int[] MaterialComponentsTheme = new int[] { 2130903105, 2130903106, @@ -12903,8 +12889,9 @@ namespace Borepin.Droid 2130903335, 2130903345, 2130903376, - 2130903393, - 2130903444, + 2130903392, + 2130903443, + 2130903448, 2130903449, 2130903450, 2130903451, @@ -12914,11 +12901,10 @@ namespace Borepin.Droid 2130903455, 2130903456, 2130903457, - 2130903458, - 2130903463, + 2130903462, + 2130903467, 2130903468, - 2130903469, - 2130903473}; + 2130903472}; // aapt resource value: 0 public const int MaterialComponentsTheme_bottomSheetDialogTheme = 0; @@ -13043,7 +13029,7 @@ namespace Borepin.Droid // aapt resource value: 2 public const int MenuGroup_android_visible = 2; - // aapt resource value: { 0x1010002,0x101000E,0x10100D0,0x1010106,0x1010194,0x10101DE,0x10101DF,0x10101E1,0x10101E2,0x10101E3,0x10101E4,0x10101E5,0x101026F,0x7F03000D,0x7F03001F,0x7F030020,0x7F030028,0x7F030091,0x7F0300F3,0x7F0300F4,0x7F030132,0x7F030159,0x7F0301CD } + // aapt resource value: { 0x1010002,0x101000E,0x10100D0,0x1010106,0x1010194,0x10101DE,0x10101DF,0x10101E1,0x10101E2,0x10101E3,0x10101E4,0x10101E5,0x101026F,0x7F03000D,0x7F03001F,0x7F030020,0x7F030028,0x7F030091,0x7F0300F3,0x7F0300F4,0x7F030132,0x7F030158,0x7F0301CC } public static int[] MenuItem = new int[] { 16842754, 16842766, @@ -13066,8 +13052,8 @@ namespace Borepin.Droid 2130903283, 2130903284, 2130903346, - 2130903385, - 2130903501}; + 2130903384, + 2130903500}; // aapt resource value: 13 public const int MenuItem_actionLayout = 13; @@ -13138,7 +13124,7 @@ namespace Borepin.Droid // aapt resource value: 22 public const int MenuItem_tooltipText = 22; - // aapt resource value: { 0x10100AE,0x101012C,0x101012D,0x101012E,0x101012F,0x1010130,0x1010131,0x7F030143,0x7F030173 } + // aapt resource value: { 0x10100AE,0x101012C,0x101012D,0x101012E,0x101012F,0x1010130,0x1010131,0x7F030143,0x7F030172 } public static int[] MenuView = new int[] { 16842926, 16843052, @@ -13148,7 +13134,7 @@ namespace Borepin.Droid 16843056, 16843057, 2130903363, - 2130903411}; + 2130903410}; // aapt resource value: 4 public const int MenuView_android_headerBackground = 4; @@ -13234,9 +13220,9 @@ namespace Borepin.Droid 16843465, 2130903347}; - // aapt resource value: { 0x7F03016A } + // aapt resource value: { 0x7F030169 } public static int[] PopupWindowBackgroundState = new int[] { - 2130903402}; + 2130903401}; // aapt resource value: 0 public const int PopupWindowBackgroundState_state_above_anchor = 0; @@ -13261,7 +13247,7 @@ namespace Borepin.Droid // aapt resource value: 1 public const int RecycleListView_paddingTopNoTitle = 1; - // aapt resource value: { 0x10100C4,0x10100F1,0x7F0300CA,0x7F0300CB,0x7F0300CC,0x7F0300CD,0x7F0300CE,0x7F03010B,0x7F03014D,0x7F030163,0x7F030169 } + // aapt resource value: { 0x10100C4,0x10100F1,0x7F0300CA,0x7F0300CB,0x7F0300CC,0x7F0300CD,0x7F0300CE,0x7F03010B,0x7F03014D,0x7F030162,0x7F030168 } public static int[] RecyclerView = new int[] { 16842948, 16842993, @@ -13272,8 +13258,8 @@ namespace Borepin.Droid 2130903246, 2130903307, 2130903373, - 2130903395, - 2130903401}; + 2130903394, + 2130903400}; // aapt resource value: 1 public const int RecyclerView_android_descendantFocusability = 1; @@ -13322,14 +13308,7 @@ namespace Borepin.Droid // aapt resource value: 0 public const int ScrollingViewBehavior_Layout_behavior_overlapTop = 0; - // aapt resource value: { 0x7F030152 } - public static int[] ScrollViewRendererTheme = new int[] { - 2130903378}; - - // aapt resource value: 0 - public const int ScrollViewRendererTheme_scrollViewStyle = 0; - - // aapt resource value: { 0x10100DA,0x101011F,0x1010220,0x1010264,0x7F030077,0x7F030090,0x7F0300A6,0x7F0300DE,0x7F0300F5,0x7F03010A,0x7F030147,0x7F030148,0x7F030153,0x7F030154,0x7F030174,0x7F030179,0x7F0301D4 } + // aapt resource value: { 0x10100DA,0x101011F,0x1010220,0x1010264,0x7F030077,0x7F030090,0x7F0300A6,0x7F0300DE,0x7F0300F5,0x7F03010A,0x7F030147,0x7F030148,0x7F030152,0x7F030153,0x7F030173,0x7F030178,0x7F0301D3 } public static int[] SearchView = new int[] { 16842970, 16843039, @@ -13343,11 +13322,11 @@ namespace Borepin.Droid 2130903306, 2130903367, 2130903368, + 2130903378, 2130903379, - 2130903380, - 2130903412, - 2130903417, - 2130903508}; + 2130903411, + 2130903416, + 2130903507}; // aapt resource value: 0 public const int SearchView_android_focusable = 0; @@ -13400,10 +13379,10 @@ namespace Borepin.Droid // aapt resource value: 16 public const int SearchView_voiceIcon = 16; - // aapt resource value: { 0x7F030161,0x7F030162 } + // aapt resource value: { 0x7F030160,0x7F030161 } public static int[] Snackbar = new int[] { - 2130903393, - 2130903394}; + 2130903392, + 2130903393}; // aapt resource value: { 0x101011F,0x7F0300B6,0x7F030128 } public static int[] SnackbarLayout = new int[] { @@ -13483,22 +13462,22 @@ namespace Borepin.Droid // aapt resource value: 1 public const int StateListDrawable_android_visible = 1; - // aapt resource value: { 0x1010124,0x1010125,0x1010142,0x7F03015C,0x7F030167,0x7F03017A,0x7F03017B,0x7F03017D,0x7F0301B5,0x7F0301B6,0x7F0301B7,0x7F0301CE,0x7F0301CF,0x7F0301D0 } + // aapt resource value: { 0x1010124,0x1010125,0x1010142,0x7F03015B,0x7F030166,0x7F030179,0x7F03017A,0x7F03017C,0x7F0301B4,0x7F0301B5,0x7F0301B6,0x7F0301CD,0x7F0301CE,0x7F0301CF } public static int[] SwitchCompat = new int[] { 16843044, 16843045, 16843074, - 2130903388, - 2130903399, + 2130903387, + 2130903398, + 2130903417, 2130903418, - 2130903419, - 2130903421, + 2130903420, + 2130903476, 2130903477, 2130903478, - 2130903479, + 2130903501, 2130903502, - 2130903503, - 2130903504}; + 2130903503}; // aapt resource value: 1 public const int SwitchCompat_android_textOff = 1; @@ -13557,8 +13536,9 @@ namespace Borepin.Droid // aapt resource value: 2 public const int TabItem_android_text = 2; - // aapt resource value: { 0x7F03017E,0x7F03017F,0x7F030180,0x7F030181,0x7F030182,0x7F030183,0x7F030184,0x7F030185,0x7F030186,0x7F030187,0x7F030188,0x7F030189,0x7F03018A,0x7F03018B,0x7F03018C,0x7F03018D,0x7F03018E,0x7F03018F,0x7F030190,0x7F030191,0x7F030192,0x7F030193,0x7F030195,0x7F030196,0x7F030197 } + // aapt resource value: { 0x7F03017D,0x7F03017E,0x7F03017F,0x7F030180,0x7F030181,0x7F030182,0x7F030183,0x7F030184,0x7F030185,0x7F030186,0x7F030187,0x7F030188,0x7F030189,0x7F03018A,0x7F03018B,0x7F03018C,0x7F03018D,0x7F03018E,0x7F03018F,0x7F030190,0x7F030191,0x7F030192,0x7F030194,0x7F030195,0x7F030196 } public static int[] TabLayout = new int[] { + 2130903421, 2130903422, 2130903423, 2130903424, @@ -13580,10 +13560,9 @@ namespace Borepin.Droid 2130903440, 2130903441, 2130903442, - 2130903443, + 2130903444, 2130903445, - 2130903446, - 2130903447}; + 2130903446}; // aapt resource value: 0 public const int TabLayout_tabBackground = 0; @@ -13660,7 +13639,7 @@ namespace Borepin.Droid // aapt resource value: 24 public const int TabLayout_tabUnboundedRipple = 24; - // aapt resource value: { 0x1010095,0x1010096,0x1010097,0x1010098,0x101009A,0x101009B,0x1010161,0x1010162,0x1010163,0x1010164,0x10103AC,0x7F0300D2,0x7F030198 } + // aapt resource value: { 0x1010095,0x1010096,0x1010097,0x1010098,0x101009A,0x101009B,0x1010161,0x1010162,0x1010163,0x1010164,0x10103AC,0x7F0300D2,0x7F030197 } public static int[] TextAppearance = new int[] { 16842901, 16842902, @@ -13674,7 +13653,7 @@ namespace Borepin.Droid 16843108, 16843692, 2130903250, - 2130903448}; + 2130903447}; // aapt resource value: 10 public const int TextAppearance_android_fontFamily = 10; @@ -13845,7 +13824,7 @@ namespace Borepin.Droid // aapt resource value: 2 public const int ThemeEnforcement_enforceTextAppearance = 2; - // aapt resource value: { 0x10100AF,0x1010140,0x7F030051,0x7F03007F,0x7F030080,0x7F030092,0x7F030093,0x7F030094,0x7F030095,0x7F030096,0x7F030097,0x7F030124,0x7F030125,0x7F030129,0x7F03012E,0x7F03012F,0x7F030141,0x7F030175,0x7F030176,0x7F030177,0x7F0301BD,0x7F0301BF,0x7F0301C0,0x7F0301C1,0x7F0301C2,0x7F0301C3,0x7F0301C4,0x7F0301C5,0x7F0301C6 } + // aapt resource value: { 0x10100AF,0x1010140,0x7F030051,0x7F03007F,0x7F030080,0x7F030092,0x7F030093,0x7F030094,0x7F030095,0x7F030096,0x7F030097,0x7F030124,0x7F030125,0x7F030129,0x7F03012E,0x7F03012F,0x7F030141,0x7F030174,0x7F030175,0x7F030176,0x7F0301BC,0x7F0301BE,0x7F0301BF,0x7F0301C0,0x7F0301C1,0x7F0301C2,0x7F0301C3,0x7F0301C4,0x7F0301C5 } public static int[] Toolbar = new int[] { 16842927, 16843072, @@ -13864,18 +13843,18 @@ namespace Borepin.Droid 2130903342, 2130903343, 2130903361, + 2130903412, 2130903413, 2130903414, - 2130903415, - 2130903485, + 2130903484, + 2130903486, 2130903487, 2130903488, 2130903489, 2130903490, 2130903491, 2130903492, - 2130903493, - 2130903494}; + 2130903493}; // aapt resource value: 0 public const int Toolbar_android_gravity = 0; @@ -13964,13 +13943,13 @@ namespace Borepin.Droid // aapt resource value: 28 public const int Toolbar_titleTextColor = 28; - // aapt resource value: { 0x1010000,0x10100DA,0x7F030135,0x7F030136,0x7F0301B3 } + // aapt resource value: { 0x1010000,0x10100DA,0x7F030135,0x7F030136,0x7F0301B2 } public static int[] View = new int[] { 16842752, 16842970, 2130903349, 2130903350, - 2130903475}; + 2130903474}; // aapt resource value: { 0x10100D4,0x7F030034,0x7F030035 } public static int[] ViewBackgroundHelper = new int[] { diff --git a/Borepin/Borepin.GTK/Borepin.GTK.csproj b/Borepin/Borepin.GTK/Borepin.GTK.csproj index 3e4d45f..c2e3526 100644 --- a/Borepin/Borepin.GTK/Borepin.GTK.csproj +++ b/Borepin/Borepin.GTK/Borepin.GTK.csproj @@ -1,6 +1,6 @@  - + Debug @@ -77,20 +77,20 @@ - - ..\..\packages\Xamarin.Forms.Platform.GTK.4.8.0.1560\lib\net45\webkit-sharp.dll + + ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\netstandard2.0\Xamarin.Forms.Core.dll - - ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\netstandard2.0\Xamarin.Forms.Core.dll + + ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\netstandard2.0\Xamarin.Forms.Platform.dll - - ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\netstandard2.0\Xamarin.Forms.Platform.dll + + ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\netstandard2.0\Xamarin.Forms.Xaml.dll - - ..\..\packages\Xamarin.Forms.Platform.GTK.4.8.0.1560\lib\net45\Xamarin.Forms.Platform.GTK.dll + + ..\..\packages\Xamarin.Forms.Platform.GTK.4.8.0.1364\lib\net45\webkit-sharp.dll - - ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\netstandard2.0\Xamarin.Forms.Xaml.dll + + ..\..\packages\Xamarin.Forms.Platform.GTK.4.8.0.1364\lib\net45\Xamarin.Forms.Platform.GTK.dll @@ -110,12 +110,5 @@ - - - Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". - - - - - + \ No newline at end of file diff --git a/Borepin/Borepin.GTK/packages.config b/Borepin/Borepin.GTK/packages.config index 90bea8d..3ec538e 100644 --- a/Borepin/Borepin.GTK/packages.config +++ b/Borepin/Borepin.GTK/packages.config @@ -1,6 +1,6 @@  - - + + \ No newline at end of file diff --git a/Borepin/Borepin.GTK/webkit-sharp.dll.config b/Borepin/Borepin.GTK/webkit-sharp.dll.config index 4384801..2c002a5 100644 --- a/Borepin/Borepin.GTK/webkit-sharp.dll.config +++ b/Borepin/Borepin.GTK/webkit-sharp.dll.config @@ -1,5 +1,5 @@ - - - - - + + + + + diff --git a/Borepin/Borepin.iOS/Borepin.iOS.csproj b/Borepin/Borepin.iOS/Borepin.iOS.csproj index f99ed15..e966ce7 100644 --- a/Borepin/Borepin.iOS/Borepin.iOS.csproj +++ b/Borepin/Borepin.iOS/Borepin.iOS.csproj @@ -26,7 +26,7 @@ prompt 4 x86_64 - None + Full true iPhone Developer @@ -116,7 +116,7 @@ - + diff --git a/Borepin/Borepin.macOS/Borepin.macOS.csproj b/Borepin/Borepin.macOS/Borepin.macOS.csproj index 7bc19f0..144ef00 100644 --- a/Borepin/Borepin.macOS/Borepin.macOS.csproj +++ b/Borepin/Borepin.macOS/Borepin.macOS.csproj @@ -1,6 +1,6 @@  - + Debug AnyCPU @@ -61,16 +61,16 @@ - - ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\Xamarin.Mac\Xamarin.Forms.Core.dll - - - ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\Xamarin.Mac\Xamarin.Forms.Platform.dll - - - ..\..\packages\Xamarin.Forms.4.8.0.1560\lib\Xamarin.Mac\Xamarin.Forms.Xaml.dll - + + ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\Xamarin.Mac\Xamarin.Forms.Core.dll + + + ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\Xamarin.Mac\Xamarin.Forms.Platform.dll + + + ..\..\packages\Xamarin.Forms.4.8.0.1364\lib\Xamarin.Mac\Xamarin.Forms.Xaml.dll + @@ -112,12 +112,5 @@ - - - Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}". - - - - - + \ No newline at end of file diff --git a/Borepin/Borepin.macOS/packages.config b/Borepin/Borepin.macOS/packages.config index 85b5327..f09afaf 100644 --- a/Borepin/Borepin.macOS/packages.config +++ b/Borepin/Borepin.macOS/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file diff --git a/Borepin/Borepin/Borepin.csproj b/Borepin/Borepin/Borepin.csproj index 16bdb1b..7c81734 100644 --- a/Borepin/Borepin/Borepin.csproj +++ b/Borepin/Borepin/Borepin.csproj @@ -20,7 +20,7 @@ - + From 47ae630c0f6e72191e44926afcc66cb428f2bc89 Mon Sep 17 00:00:00 2001 From: Jannis Rieger Date: Mon, 9 Nov 2020 18:43:02 +0100 Subject: [PATCH 21/21] enabled iOS NFC Entitlement --- Borepin/Borepin.iOS/Entitlements.plist | 8 ++++++-- Borepin/Borepin.iOS/Info.plist | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Borepin/Borepin.iOS/Entitlements.plist b/Borepin/Borepin.iOS/Entitlements.plist index e9a3005..91c9872 100644 --- a/Borepin/Borepin.iOS/Entitlements.plist +++ b/Borepin/Borepin.iOS/Entitlements.plist @@ -1,7 +1,11 @@ - + + com.apple.developer.nfc.readersession.formats + + NDEF + TAG + - diff --git a/Borepin/Borepin.iOS/Info.plist b/Borepin/Borepin.iOS/Info.plist index 9fcb7e2..b464cc1 100644 --- a/Borepin/Borepin.iOS/Info.plist +++ b/Borepin/Borepin.iOS/Info.plist @@ -38,5 +38,7 @@ 0.2 ITSAppUsesNonExemptEncryption + NFCReaderUsageDescription + FabAccess needs to be able to read your card for authentication with the server.