SmartCard I2C-Protokoll. Tauschen Sie APDU-Befehle über die I2C-Schnittstelle aus

Einführung


Vor einiger Zeit war ich an der Entwicklung eines Geräts beteiligt, bei dem die russische Kryptographie implementiert werden musste. Da diese Entscheidung künftig bescheinigt werden sollte, wurden bestimmte Anforderungen an die Implementierung der Kryptographie gestellt. Als eine der Optionen zur Vereinfachung der Implementierung dieser Anforderungen haben wir die Möglichkeit in Betracht gezogen, einen Smartcard-Leser in das Gerät zu integrieren oder einen Smartcard-Chip zu installieren, in dem bereits viele notwendige Szenarien für die Arbeit mit Schlüsselinformationen implementiert wurden.

Leider passte eine solche Lösung aus irgendeinem Grund nicht, obwohl die Verwendung der bereits vorbereiteten russischen Hardware-Kryptographie die Entwicklung und anschließende Zertifizierung des Endprodukts erheblich beschleunigen würde. Die Gründe für die Unmöglichkeit, USB-Token oder Smartcards zu verwenden, waren weit verbreitet: Das Gerät sollte recht kompakt sein (ein kleines Modul für M2M- oder IoT-Geräte), hauptsächlich im wartungsfreien Modus betrieben werden und in einem weiten Temperaturbereich arbeiten.

In diesem Artikel möchte ich über eine mögliche Lösung für einen solchen Fall unter Verwendung des A7001-Chips sprechen, der über die I2C-Schnittstelle mit dem System verbunden ist.



Probleme bei der Implementierung der Kryptographie im PAC


Ich möchte nicht auf die Probleme der Kryptografie-Zertifizierung eingehen. Wer damit arbeitet, ist sich dessen sowieso bewusst, aber der Rest scheint es nicht zu brauchen. Zu einigen wichtigen Punkten lohnt es sich jedoch noch zu sagen.

Theoretisch sollte es keine besonderen Probleme mit der Kryptographie geben. Schließlich reicht es aus, eine der kryptografischen Bibliotheken, zum Beispiel OpenSSL, oder eine andere von vielen vorhandenen zu verwenden.

Probleme beginnen, wenn diese Lösung zertifiziert werden muss. Und die reine Software-Implementierung der Kryptografie in der Firmware macht das Gerät zu einem vollwertigen Gerät zum Schutz kryptografischer Informationen, das in einem Testlabor genau untersucht werden muss. Schließlich müssen Sie bei der Entwicklung einer Lösung mit Kryptografie früher oder später über Dinge wie ein Schlüsselschema nachdenken, Schlüssel speichern, Zufallszahlen generieren und andere subtile Dinge.

Für einige Lösungen gibt es eine elegante Methode zur Implementierung zertifizierter russischer kryptografischer Algorithmen, mit der wir den Prozess der Erstellung von Endgeräten leicht vereinfachen und die Zeit für deren Entwicklung und anschließende Zertifizierung verkürzen können. Es reicht aus, eine Smartcard oder einen Smartcard-Chip in das Gerät einzubetten und diese als eine Art „Vertrauenswurzel“ zu verwenden, um so eine erhebliche Anzahl schmerzhafter Probleme zu lösen, die langwierige Forschung und Bestätigung in Testlabors erfordern.



Smartcard-Mikrocontroller mit I2C-Schnittstelle


Um diesen Artikel zu schreiben, habe ich den A7001-Chip verwendet, der über den I2C-Bus, der in fast jedem Gerät verfügbar ist, mit dem Endgerät verbunden ist. Der Chip wurde von Aladdin RD bereitgestellt, auf dem bereits eine Firmware installiert ist, die die russische Kryptographie unterstützt.

Der Mikrocontroller A7001AG (Secure Authentication Microcontroller) wird von NXP hergestellt. Laut Datenblatt auf dem Chip ist der A7001AG ein Mikrocontroller, der auf der klassischen 80C51-Architektur mit einem kryptografischen Coprozessor vor unbefugtem Zugriff geschützt ist.

Im Energiesparmodus verbraucht der Mikrocontroller 50 μA. Es unterstützt Versorgungsspannungen im Bereich von 1,62 V bis 5,5 V und kann bei Temperaturen von –25 ° C bis + 85 ° C betrieben werden.

Für die Interaktion mit externen Geräten wird die I2C-Slave-Schnittstelle mit einer Geschwindigkeit von bis zu 100 kbit / s verwendet.

Der Mikrocontroller ist in verschiedenen Gehäuseoptionen erhältlich. Ich bin im HVQFN32-Format gelandet. Dies ist ein Kunststoffgehäuse von 5 x 5 x 0,85 mm mit 32 Kontakten und einem Abstand von 0,5 mm.

Aussehen des Falles:



Seine Pinbelegung:



Hostsystem zum Anschließen des A7001-Chips


Die ESP32 WiFi Kit 32-Karte von Heltec wurde als Layout des Host-Systems mit der I2C-Schnittstelle verwendet. Es kostet weniger als 1000 Rubel, verfügt über alle erforderlichen kabelgebundenen und kabellosen Schnittstellen, einen Anschluss zum Anschließen einer Lithiumbatterie an eine Ladeschaltung sowie ein 0,96-Zoll-OLED-Display.



Ein nahezu perfektes System für das Prototyping verschiedener IoT- und M2M-Geräte, mit denen ich schon lange spielen wollte.

Das Board kann sowohl in der nativen Entwicklungsumgebung als auch in der Arduino IDE programmiert werden. Es gibt viele Beispiele für die Arbeit damit. Der Einfachheit halber habe ich mich für die Standard-Arduino-IDE entschieden.

Schaltplan


Das Schaltbild zum Anschließen des A7001-Chips ist in der Abbildung dargestellt. Es unterscheidet sich geringfügig vom empfohlenen Datenblatt. Gemäß der Beschreibung des Herstellers sollte Klemme 22 (Rücksetzsignal RST_N) ein hohes Potential haben, aber die Schaltung startete nicht gemäß diesem Schema. Infolge des „wissenschaftlichen Stoßes“ wurde die Bedienbarkeit durch Anschließen eines Pull-up-Widerstands R4 an den negativen Leistungsleiter erreicht.

UPDATE: Wie in den Kommentaren vorgeschlagen, entspricht das Schema dem Datenblatt, während mich die Ausgabebeschreibung verwirrte
RST_N - Eingang zurücksetzen, aktiv LOW




Die Schaltung ist auf einem kleinen Steckbrett montiert. Strom- und I2C-Signale werden über vier Verbindungskabel verbunden, und das ESP32-Modul selbst wird über USB mit dem Computer verbunden, um den gesamten Stromkreis mit Strom zu versorgen und die Firmware zu füllen.



Smart Card I2C-Protokoll


Als ich zum ersten Mal von der Verbindung von Smartcard-Mikrocontrollern über den I2C-Bus hörte, erklärten sie mir, dass die physische Schicht der Smartcard-Schnittstelle (GOST R ISO / IEC 7816-3-2013) durch I2C (SMBus) ersetzt wurde und alles andere wie gewohnt funktionierte Smartcards gemäß GOST R ISO / IEC 7816-4-2013 mit APDU-Befehlen.

Es stellte sich heraus, dass dies nicht ganz oder gar nicht stimmt. Die Interaktion mit dem Mikrocontroller auf hoher Ebene erfolgt zwar mit herkömmlichen APDU-Befehlen, es gab jedoch auch einige „Aber“.

  1. Die I2C-Schnittstelle (SMBus) ru.wikipedia.org/wiki/I%C2%B2C ist ein Bus mit Slave-Adressierung, der sich grundlegend von der seriellen UART-Schnittstelle unterscheidet, die für die Kommunikation von zwei Geräten auf Punkt-zu-Punkt-Basis und ohne Adressierung ausgelegt ist . Dies bedeutet, dass alle übertragenen Daten (APDU-Befehle) in das I2C-Bus-Datenformat „gepackt“ werden müssen.
  2. Die Arbeit mit einer Smartcard beginnt mit dem Zurücksetzen, normalerweise durch Ausschalten der Stromversorgung, z. B. durch physisches Entfernen der Karte aus dem Kartenleser. Nach dem Zurücksetzen sendet die Smartcard zuerst den ATR-Datenblock (Answer To Reset), der die Konfigurationsinformationen enthält, die zum Konfigurieren der Interaktion mit der Smartcard erforderlich sind.
    Und der Chip auf dem I2C-Bus ist keine Ausnahme, aber in dem Fall, in dem der Mikrocontroller auf die Leiterplatte gelötet werden sollte, verfügt er möglicherweise nicht über eine Stromversorgungsschaltung der Mikroschaltung oder eine Softwaresteuerung des Rücksetzausgangs. Daher wird das Zurücksetzen des Chips implementiert, einschließlich auf der Ebene der I2C-Protokollbefehle.

Diese und andere Probleme werden durch das Smart Card I2C-Protokoll behoben , dessen Beschreibung auf der NXP-Website unter www.nxp.com/docs/en/supporting-information/AN12207.pdf zu finden ist .

Software-Teil


Eine Bibliothekssuche mit der Implementierung des Smart Card I2C-Protokollprotokolls ergab keine Ergebnisse. Daher musste ich die Spezifikationen verstehen und die Grundfunktionen des vorliegenden Objekts umsetzen.

Skizzieren Sie Quellen für Arduino IDE
#include <Wire.h> #include <vector> // I2C address on chip A7001 #define ADDR_A7001 static_cast<uint16_t>(0x48) using namespace std; typedef std::vector<uint8_t> vect; //-------------------------------------------------------------------------- // Output dump data by serial port void vect_dump(const char * prefix, const vect & v, const size_t start = 0, const size_t count = 0) { if(prefix) { Serial.print(prefix); } if(v.size() < start) { Serial.println("Empty"); return; } for(size_t i=0; i < (v.size()-start) && (count == 0 || i < count); i++) { uint8_t b = v[start + i]; // Format output HEX data if(i) Serial.print(" "); if(b < 0x0F) Serial.print("0"); Serial.print(b, HEX); } Serial.println(""); } //-------------------------------------------------------------------------- // Send array bytes by I2C to address A7001 and read response result_size bytes vect sci2c_exchange(const vect data, const uint8_t result_size) { Wire.beginTransmission(ADDR_A7001); Wire.write(data.data(), data.size()); Wire.endTransmission(false); Wire.requestFrom(ADDR_A7001, result_size, true); //delay(1); vect result(result_size, 0); if(result_size >= 2) { result[0] = Wire.read(); // Data size CDB result[1] = Wire.read(); // PCB for(size_t i=2; i<result.size()-2 && Wire.available(); i++) { result[i+2] = Wire.read(); } } return result; } //-------------------------------------------------------------------------- // Read Status Code uint8_t sci2c_status(const char * msg = nullptr) { vect v = sci2c_exchange({0b0111}, 2); uint8_t status = v[1] >> 4; if(msg) { Serial.print(msg); // Prefix switch(status) { case 0b0000: Serial.println("OK (Ready)"); break; case 0b0001: Serial.println("OK (Busy)"); break; case 0b1000: Serial.println("ERROR (Exception raised)"); break; case 0b1001: Serial.println("ERROR (Over clocking)"); break; case 0b1010: Serial.println("ERROR (Unexpected Sequence)"); break; case 0b1011: Serial.println("ERROR (Invalid Data Length)"); break; case 0b1100: Serial.println("ERROR (Unexpected Command)"); break; case 0b1101: Serial.println("ERROR (Invalid EDC)"); break; default: Serial.print("ERROR (Other Exception "); Serial.print(status, BIN); Serial.println("b)"); break; } } return status; } static uint8_t apdu_master_sequence_counter = 0; // Sequence Counter Master, Master to Slave //-------------------------------------------------------------------------- // Send APDU void sci2c_apdu_send(const vect apdu) { vect_dump("C-APDU => ", apdu); vect data(2, 0); // 0x00 - Master to Slave Data Transmission command + reserve to length data.insert(data.end(), std::begin(apdu), std::end(apdu)); data[0] |= (apdu_master_sequence_counter << 4); if(++apdu_master_sequence_counter > 0b111) { apdu_master_sequence_counter = 0; } data[1] = data.size() - 2; sci2c_exchange(data, 2); delay(10); sci2c_status(""); } //-------------------------------------------------------------------------- // Receive APDU vect sci2c_apdu_recv(uint8_t result_size) { Wire.beginTransmission(ADDR_A7001); Wire.write(0b0010); // 0010b - Slave to Master Data Transmission command Wire.endTransmission(false); Wire.requestFrom(ADDR_A7001, result_size, true); vect result(result_size, 0); for(size_t i=0; i<result.size() && Wire.available(); i++) { result[i] = Wire.read(); } vect_dump("R-APDU <= ", result); return result; } //-------------------------------------------------------------------------- void setup(){ Wire.begin(); Serial.begin(9600); while (!Serial); Serial.println(""); Serial.println("Smart Card I2C Protocol Arduino demo on A7001"); Serial.println(""); sci2c_exchange({0b00001111}, 2); //The bits b0 to b5 set to 001111b indicate the Wakeup command. sci2c_status("Status Wakeup: "); sci2c_exchange({0b00001111}, 2); //The bits b0 to b5 set to 001111b indicate the Wakeup command. sci2c_status("Status Wakeup: "); // Soft Reset sci2c_exchange({0b00011111}, 2); //The bits b0 to b5 set to 011111b indicate the Soft Reset command. delay(5); // Wait at least tRSTG (time, ReSeT Guard) sci2c_status("Status SoftReset: "); // Read ATR vect ATR = sci2c_exchange({0b101111}, 29+2); //The bits b0 to b5 set to 101111b indicate the Read Answer to Reset command. sci2c_status("Status ATR: "); vect_dump("ATR: ", ATR, 2); // Parameter Exchange // The bits b0 to b5 set to 111111b of the PCB send by the master device indicate the Parameter Exchange command. // The bits b6 and b7 of the PCB send by the master device code the CDBIsm,max(Command Data Bytes Integer, Slave to Master, MAXimum) vect CDB = sci2c_exchange({0b11111111}, 2); sci2c_status("Status CDB: "); vect_dump("CDB: ", CDB, 1); // Further examples of the exchange of APDU // Exchanges APDU from exmaple chapter sci2c_apdu_send({0x00, 0xA4, 0x04, 0x04, 0x04, 0x54, 0x65, 0x73, 0x74, 0x00}); sci2c_status("Status Test send: "); sci2c_apdu_recv(3+1); // R-APDU size + 1 byte PBC sci2c_status("Status Test recv: "); // Read Card Production Life Cycle sci2c_apdu_send({0x80, 0xCA, 0x9F, 0x7F, 0x00}); sci2c_status("Status card LC send: "); sci2c_apdu_recv(0x30+1); // R-APDU size + 1 byte PBC sci2c_status("Status card LC recv: "); // Read Card Info sci2c_apdu_send({0x80, 0xCA, 0x00, 0x66, 0x00}); sci2c_status("Status card info send: "); sci2c_apdu_recv(0x51+1); // R-APDU size + 1 byte PBC sci2c_status("Status card info recv: "); // Read Key Info sci2c_apdu_send({0x80, 0xCA, 0x00, 0xE0, 0x00}); sci2c_status("Status key send: "); sci2c_apdu_recv(0x17+1); // R-APDU size + 1 byte PBC sci2c_status("Status key recv: "); // Again exchanges APDU from exmaple chapter sci2c_apdu_send({0x00, 0xA4, 0x04, 0x04, 0x04, 0x54, 0x65, 0x73, 0x74, 0x00}); sci2c_status("Status Test send: "); sci2c_apdu_recv(3+1); // R-APDU size + 1 byte PBC sci2c_status("Status Test recv: "); Serial.println("Done!\n"); } //-------------------------------------------------------------------------- void loop() { delay(100); } 


Um mit dem I2C-Port zu arbeiten, habe ich die Standard-Wire-Bibliothek verwendet. Ich muss sofort sagen, dass diese Bibliothek nicht für die vollständige Implementierung des Smart Card I2C-Protokolls geeignet ist, weil Es ist nicht möglich, ACK und NACK beim Senden und Lesen einzelner Bytes zu steuern, was erforderlich ist, um den korrekten Empfang von Daten variabler Länge von einer Smartcard zu implementieren.

Ja, und die üblichen Beispiele für den Wire-Code funktionierten nicht beim ersten Mal, aber nach einigem Tanzen mit einer Tamburin- Tastatur, mehreren Litern Kaffee, Googeln in Yandex und Yandex in Google wurde eine Lösung gefunden.

 Wire.write ( ); Wire.endTransmission (false); Wire.requestFrom (ADDR_A7001, 2, true); 

Gemessen an der Bibliotheksdokumentation gibt dieses Design den I2C-Bus nach dem Aufruf von endTransmission nicht frei . Es stellte sich jedoch heraus, dass für das von mir verwendete ESP32-basierte Modul die Datenübertragung nicht physisch während des Aufrufs von endTransmission (false) erfolgt , wie in der Dokumentation für die Wire-Bibliothek beschrieben, sondern während des Aufrufs von requestFrom (true) , während die Daten nur davor in die Warteschlange gestellt werden zu übertragen.

Angesichts dieser Einschränkungen musste ich einige „Krücken“ herstellen, aber ich wollte unbedingt den A7001-Chip starten, ohne die Standardbibliotheken neu zu schreiben. Aus diesem Grund wurde die Behandlung von Protokollfehlern nicht implementiert, und es war auch nicht möglich, Daten variabler Länge zu empfangen (d. H. Es ist immer erforderlich, die genaue Anzahl der zu lesenden Bytes anzugeben).

Solche Einschränkungen sind in einem realen System nicht zulässig, aber nicht unbedingt erforderlich, um die Verwendung von APDU-Befehlen bei der Arbeit am I2C-Bus zu demonstrieren. Wenn daher beim Austausch von Daten über den I2C-Port ein Fehler im Austauschprotokoll auftritt, gehört der Kippschalter uns.
Mit anderen Worten, wenn während der Wiederholung dieser Experimente alles funktioniert hat und plötzlich angehalten hat, bevor nach einem Fehler im Code gesucht wurde, schalten Sie das Gerät aus und wieder ein. Mit hoher Wahrscheinlichkeit kann dies das Problem beheben.

Codebeispiele für die Arbeit mit dem A7001-Chip


In den Beispielen verwende ich mehrere Hilfsfunktionen:

vect_dump - Ausgabe von Dump-Daten im HEX-Format an den Debug-Port;
sci2c_exchange - sendet ein Datenarray über I2C und liest die angegebene Anzahl von Antwortbytes;
sci2c_status - liest den Antwortstatus des Mikroschaltkreises und zeigt gegebenenfalls seinen Status im Debug-Port an;
sci2c_apdu_send - sendet einen APDU-Befehl;
sci2c_apdu_recv - Liest die Antwort auf den APDU-Befehl.

Mikrochip-Initialisierung


Gemäß der Beschreibung des Smart Card I2C-Protokolls sollten vor Beginn der Arbeit mit dem Chip drei Befehle nacheinander ausgeführt werden: Neustart (Cold oder Soft Reset), Read ATR (Read Answer to Reset) und Setup-Austauschparameter (Master Device Exchange Parameters). Und erst danach ist der Chip bereit, APDU-Befehle anzunehmen.

Soft Reset


Hier ist alles einfach, wir senden einen Neustartbefehl und warten auf die eingestellte Zeit:

 sci2c_exchange ({0b00011111}, 2); delay(5); //      (tRSTG, time, ReSeT Guard) 

Antwort zum Zurücksetzen lesen


Das Lesen von ATR ist etwas komplizierter Sie müssen nicht nur einen Befehl senden, sondern auch die Antwortdaten lesen. Gemäß der Protokollbeschreibung kann die maximale Größe der zurückgegebenen Daten CDBATS, MAX (Befehlsdatenbytes, Antwort zum Zurücksetzen, MAXimum) 29 Bytes betragen.

 vect ATR = sci2c_exchange({0b101111}, 29+2); // 29  + 1  PCB + 1  —   vect_dump("ATR: ", ATR); 

ATR-Daten lesen: 1E 00 00 00 B8 03 11 01 05 B9 02 01 01 BA 01 01 BB 0D 41 37 30 30 31 43 47 20 32 34 32 52 31

Dabei ist 1E die Größe der zurückgegebenen Daten (29 Bytes + 1 Byte der Leiterplatte) und 00 die Leiterplatte (Protocol Control Byte), die gleich 0 sein sollte, und anscheinend wurden in diesem Beispiel die Daten nicht korrekt gelesen (es sollte ein Byte der Leiterplatte vorhanden sein). und es gibt drei von ihnen).

Die folgenden Daten sind im TLV-Format codiert:

B8h - Datenobjekt auf niedriger Ebene , Größe 3 Byte ( 11h 01h 05h );
B9h - Protokollbindungsdatenobjekt , 2 Bytes groß ( 01h 01h );
BAh - Datenobjekt höherer Ebene , 1 Byte ( 01h ) groß;
BBh - Betriebssystemdatenobjekt , 13 Byte ( 41 37 30 30 31 43 47 20 32 34 32 52 31 ).

Entschlüsselung der Lesekonfiguration des Chips
Low-Level-Datenobjekt : 11h - Haupt- und Nebenversionen des unterstützten Protokolls.

Fehlererkennungscodes : 01h - Unterstützung für die Fehlererkennung und Integritätskontrolle übertragener Daten mithilfe von LRC (Longitudinal Redundancy Code).

Frame Waiting Integer (FWI) : 05h - maximale Verzögerung zwischen zwei Befehlen. Der Wertebereich kann zwischen 10 ms und 5120 ms liegen, der Standardwert ist 5120 ms. Der Wert wird nach der Formel T = 10ms x 2 ^ FWI berechnet. Dies ergibt in diesem Fall eine Verzögerung von 320 ms (10 ms x 2 ^ 5).

Protokollbindungsdatenobjekt - besteht aus zwei Werten, 01h 01h , die das unterstützte Protokoll und das Standardprotokoll codieren. Diese Werte bedeuten Unterstützung für das APDU-Protokoll [GOST R ISO / IEC 7816-3-2013], und wie Sie sich vorstellen können, wird standardmäßig dasselbe Protokoll installiert.

Datenobjekt mit höherer Schicht - Die Nummer 01h bedeutet Unterstützung für das kurze und erweiterte APDU-Format.

Das Betriebssystemdatenobjekt ist eine Kennung mit einer Größe von bis zu 15 Byte, wie in der Norm [GOST R ISO / IEC 7816-4-2013] definiert. In unserem Fall ist dies die Zeichenfolge " A7001CG 242R1 ".

Master-Gerät tauscht Parameter aus


Der letzte Befehl zum Initialisieren der Austauscheinstellungen:

 vect CDB = sci2c_exchange({0b11111111}, 2); sci2c_status("Status CDB: "); vect_dump("CDB: ", CDB, 1); 

Rückgabewert: CCh - (11001100b) Gemäß Datenblatt müssen 4 und 5 Bits eine bitweise Negation der Bits 2 und 3 sein (NNb codiert das bitweise negierte CDBIMS, MAX), und gemäß dem codierten Wert unterstützt der Chip die maximal mögliche Befehlsgröße von 252 Byte CDBIMS , MAX-Wert (Command Data Bytes Integer, Master to Slave, MAXimum).

Gemäß der Protokollbeschreibung ist die Mikroschaltung nach dem Ausführen dieser drei Befehle und in dieser Reihenfolge bereit, die üblichen APDU-Befehle auszuführen (obwohl es zu funktionieren scheint, ohne Austauschparameter einzustellen, d. H. Es war ausreichend, einen Soft-Reset durchzuführen und ATR zu lesen).

Ausführen von APDU-Befehlen


Jeder Zyklus der Ausführung von APDU-Befehlen besteht aus den folgenden Schritten:

  1. APDU senden (Master to Slave-Datenübertragungsbefehl).
  2. Warten Sie auf die Schutzzeit für den Empfang und die Verarbeitung des Befehls.
  3. Warten Sie, bis die Verarbeitung des Befehls den Status gelesen hat (Statusbefehl).
  4. Antwortdaten lesen (Befehl Slave-to-Master-Datenübertragung).

Diese Logik ist in den Funktionen sci2c_apdu_send und sci2c_apdu_recv implementiert, und hier gibt es einen wichtigen Punkt: Im Format des Smart Card I2C-Protokollprotokolls gibt es Zähler der übertragenen APDU-Befehle. Diese Zähler müssen sowohl das Master- als auch das Slave-Gerät steuern und dienen zur Steuerung der Reihenfolge der übertragenen Daten, sodass im Falle eines Empfangsfehlers APDU-Daten erneut gesendet oder angefordert werden können.

Beispiele für die Implementierung dieser Funktionen finden Sie im Code. Nachfolgend sind nur APDU-Befehle und Antwortdaten aufgeführt.

Beispiel aus Datenblatt:


C-APDU => 00 A4 04 04 04 54 65 73 74 00 - Lesen Sie die Datei mit dem Namen "Test".
R-APDU <= 6A 86 - Laut Datenblatt sollte die Antwort 64 82 sein ( Datei oder Anwendung nicht gefunden ). In unserem Fall wird die Firmware jedoch in den Mikrokreis hochgeladen, und die Antwort unterscheidet sich von dem in der Dokumentation beschriebenen Beispiel.

Lebenszyklus der Lesekartenproduktion


C-APDU => 80 CA 9F 7F 00
R-APDU <= 9F 7F 2A 47 90 51 67 47 91 12 10 38 00 53 56 00 40 39 93 73 50 48 12 53 63 00 00 00 00 13 2C 19 30 34 30 33 39 00 00 00 00 00 00 90 00

Read Read Card Info



C-APDU => 80 CA 00 66 00
R-APDU <= 66 4C 73 4A 06 07 2A 86 48 86 FC 6B 01 60 0C 06 0A 2A 86 48 86 FC 6B 02 02 01 01 63 09 06 07 2A 86 48 86 FC 6B 03 64 0B 06 09 2A 86 48 86 FC 6B 04 02 55 65 0B 06 09 2B 85 10 86 48 64 02 01 03 66 0C 06 0A 2B 06 01 04 01 2A 02 6E 01 02 90 00

Read Read Key Info


C-APDU => 80 CA 00 E0 00
R-APDU <= E0 12 C0 04 01 FF 80 10 C0 04 02 FF 80 10 C0 04 03 FF 80 10 90 00

Abschließend


Diese Erfahrung bei der Implementierung des Austauschs von APDU-Teams über die I2C-Schnittstelle war sehr interessant. Ich habe sogar mehrmals gedacht, dass es mir Spaß macht, verschiedene Probleme aus dem Bereich der Schaltkreise und auch aus dem normalen Löten zu lösen, seit ich vor mehr als 5 Jahren das letzte Mal einen Lötkolben in die Hand nehmen musste.

Ich hoffe, dieser Artikel ist nützlich und hilft, die an diesem Thema Interessierten zu verstehen. Schreiben Sie, ob Sie das Material interessiert. Ich werde versuchen, alle Fragen zu diesem Artikel zu beantworten. Wenn das Thema der Verwendung des Smart Card I2C-Protokolls interessant ist, werde ich versuchen, es in den folgenden Veröffentlichungen ausführlicher zu veröffentlichen.

Referenzen:


Source: https://habr.com/ru/post/de439574/


All Articles