Access Bits

Wie auf einer vorhergehenden Seite angemerkt, möchte ich hier eine kurze Erläuterung zu den Access Bits geben.

Achtung: Ohne Kenntnisse über die Funktionalität der Access Bits sollten diese nicht verändert werden. Eine unsachgemäße Änderung der Access Bits eines Sektors kann zur irreversiblen Blockade des gesamten Sektors führen!

Mit den Access Bits des jeweiligen Sektors werden die Zugriffsbedingungen für den Sektor Trailer und für die Datenblöcke bestimmt. Die Access Bits sind im jeweiligen Sector Trailer Byte 6 bis 8 (Byte 9 wird nicht verwendet) gespeichert. In Abbildung 5-1 ist die Anordnung der Access Bits in den Bytes 6 bis 8 ersichtlich. Jedes Zugriffsbit ist dabei sowohl invertiert, als auch nicht invertiert gespeichert.

Abbildung 5-1: Zuordnung der Access Bits zu Bytes 6 bis 9 im Sector Trailer


Zu jedem Block sind 3 Access Bits (C1 bis C3) zugehörig. Abbildung 5-2 zeigt die Zuordnung der Access Bits zu den einzelnen Blöcken eines Sektors.

Abbildung 5-2: Zuordnung der Access Bits zu den Blöcken am Beispiel des Sektor 0


Beim Sector Trailer können in Abhängigkeit der gesetzten Access Bits C1 bis C3 (mit Index 3, siehe Abbildung 5-2) die Schlüssel KeyA und KeyB und die Access Bits selbst nur gelesen und/oder geschrieben werden oder der Zugriff ist nicht möglich. In nachfolgender Abbildung 5-3 sind die Zugriffsbedingungen für Sector Trailer in Abhängigkeit der Access Bits ersichtlich.

1) Für diese Zugriffsbedingung ist der KeyB lesbar und kann für Daten verwendet werden

Abbildung 5-3: Zugriffsbedingungen für Sector Trailer


Die Datenblöcke können in Abhängigkeit der Access Bits C1 bis C3 (mit Index 0 bis 2, siehe Abbildung 5-2) gelesen, geschrieben und, sofern ein Block als Value Block definiert ist, auch inkrementiert (increment), dekrementiert (decrement), in einen volatilen Speicher gelegt (restore) und vom volatilen Speicher in einen Block übertragen (transfer) werden. Nachfolgende Abbildung 5-4 zeigt die Zugriffsbedingungen bei den Datenblöcken in Abhängigkeit der Access Bits.


1) Wenn KeyB in dem entsprechenden Sektor Trailer gelesen werden kann, kann er nicht zur Authentifizierung dienen (siehe Abbildung 5-3 Anmerkung). Als Konsequenz verweigert nach der Authentifizierung die Karte alle nachfolgenden Speicherzugriffe.

Abbildung 5-4: Zugriffsbedingungen für Datenblöcke


Programmbeispiel 4: Ausgabe des Speicherinhalts und der Access Bits

Funktionsbeschreibung:

Nach Erkennen eines RFID-Tags wird der Speicherinhalt und die Access Bits ausgegeben (siehe Abbildung 5-4). Dazu wird die Library-Funktion "PICC_DumpToSerial()" verwendet, die auch die UID- und SAK-Nummer, sowie den Tag-Typ ausgibt.


Im Beispiel 4 finden folgende Funktionen der MFRC522-Library Verwendung:

(Es werden nur die neuen Funktionen gegenüber den Beispielen 1 bis 3 vorgestellt)

void MIFARE_SetAccessBits(byte*, byte, byte, byte);

void PICC_DumpToSerial(Uid*);

void PICC_DumpMifareClassicSectorToSerial(Uid*, MIFARE*, byte sector)


Beschreibung der neuen Funktion:

Setzen der Access Bits:

Die MFRC522-Library bietet dafür eine Funktion, mit der die ausgewählten Bit-Kombinationen entsprechend den Aufstellungen - wie in den Abbildungen 5-3 und 5-4 ersichtlich - für einen Sector Trailer und für die 3 dazugehörigen Datenblöcke richtig (nicht invertiert und invertiert) in einen anzugebenden Zwischenspeicher geschrieben werden:


void MIFARE_SetAccessBits(byte* accessBitBuffer, byte g0, byte g1, byte g2, byte g3);

Funktion: Setzen der Inhalte der Access Bytes aus den vorgegebenen Access Bits und zwischenspeichern in einem Array

Parameter: accessBitBuffer: Zeiger auf ein Zwischenspeicher-Array

                 g0: Access Bits für Block 0 eines Sektors (z.B. für Block 4 im Sektor 1)

                 g1: Access Bits für Block 1 eines Sektors (z.B. für Block 5 im Sektor 1)

                 g2: Access Bits für Block 2 eines Sektors (z.B. für Block 6 im Sektor 1)

                 g3: Access Bits für den Trailer Sector eines Sektors (z.B. für Block 7 im Sektor 1)

Rückgabe: keine

Bemerkung: Die Funktion setzt nicht die Access Bits eines Sector Trailers selbst, sondern trägt diese nur in ein Zwischenspeicher-Array ein. Das Setzen der Access Bits eines Sector Trailers muss anschließend mit der MIFARE_Write-Funktion durchgeführt werden!

Beispiel:

byte trailerBlock = 7; //Beispiel Sector Trailer Block 7

//Sector Trailer-Buffer

byte trailerBuffer[] = { 0xFF,  0xFF, 0xFF, 0xFF, 0xFF, 0xFF,     //KeyA

                                  0x00, 0x00, 0x00,    //Access Bits

                                  0x00,                       //frei verfügbar

                                  0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };  //KeyB

//Festlegen der Access Bits eines Sektors

byte g0 = B000;

byte g1 = B110;

byte g2 = B110;

byte g3 = B011;

//Setzen der Access Bits im accessBitBuffer-Array

byte accessBitBuffer[3];

MFR.MIFARE_SetAccessBits(accessBitBuffer, g0, g1, g2, g3);

//Überschreiben der Access Bits im trailerBuffer-Array

for (byte i = 6; i < 9; i++) trailerBuffer[i] = accessBitBuffer[i - 6];

//Pruefe, ob die Access Bits im Trailer Sector bereits gesetzt sind
if (trailerBuffer[6] != accessBitBuffer[0] ||
    trailerBuffer[7] != accessBitBuffer[1] ||
    trailerBuffer[8] != accessBitBuffer[2])
{
   //Access Bits sind noch nicht gesetzt -> Schreiben des Sector Tailer

   MFR.MIFARE_Write(trailerBlock, trailerBuffer, 16);

}


Anzeige der Access Bits:

Um sich die Access Bits eines Sektors anzusehen, kann man natürlich den entsprechenden Sector Trailer auslesen und aus den Bytes 6 bis 8 die entsprechenden Bits extrahieren.

Schneller geht es mit Funktionen, die die MFRC522-Library zur Verfügung stellt:


void PICC_DumpToSerial(Uid* uid)

Funktion: Ausgabe von RFID-Tag-Infos, dem Speicherinhalt und den Access Bits

Parameter: uid: Pointer auf die Uid-Struktur in der Library

Rückgabe: keine

Bemerkung: Die Funktion setzt den werkseitig vorgegebenen Schlüssel 0xFFFFFFFFFFFF voraus.

Beispiel (siehe auch nachfolgendes Programmbeispiel 4):

MFR.PICC_DumpToSerial(&(MFR.uid));


void PICC_DumpMifareClassicSectorToSerial(Uid* uid, MIFARE *key, byte sector)

Funktion: Ausgabe des Speicherinhalts und der Access Bits eines Sektors

Parameter: uid: Pointer auf die Uid-Struktur in der Library

                 key: Pointer auf den Schlüssel (MIFARE_Key-Struktur in der Library)

                 sector: Sektor, der angezeigt werden soll

Rückgabe: keine

Beispiel:

MFR.PICC_DumpMifareClassicSectorToSerial(&(MFR.uid), &key, sector);


Hier nun das vollständige Programm:

//RFID Programm 4
//Ausgabe des Speicherinhalts und der Access Bits
//Code fuer Arduino
//Author Retian
//Version 1.0


#include <SPI.h>
#include <MFRC522.h>


#define rstPin 9
#define ssPin 10


MFRC522 MFR(ssPin, rstPin);

MFRC522::MIFARE_Key key;


byte myKey[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};


void setup() {
  Serial.begin(115200);
  SPI.begin();
  MFR.PCD_Init();
  for (byte i = 0; i < 6; i++) key.keyByte[i] = myKey[i];
}


void loop() {

  //Auf RFID-Tag warten
  Serial.println(F("Warte auf RFID-Tag ..."));
  while (!MFR.PICC_IsNewCardPresent() || !MFR.PICC_ReadCardSerial());

  //Wenn RFID-Tag erkannt, dann Ausgabe des Inhalts
  MFR.PICC_DumpToSerial(&(MFR.uid));
}

Ausgabe am Seriellen Monitor (Ausschnitt Sektor 15 bis 13):

Abbildung 5-5: Ausgabe am Seriellen Monitor des RFID Programm 4


Zurück zu Tag-Speicher schreiben

Weiter zu Value Blocks