|
@@ -0,0 +1,239 @@
|
|
|
|
|
+/**
|
|
|
|
|
+ * Typical pin layout used:
|
|
|
|
|
+ * -----------------------------------------------------------------------------------------
|
|
|
|
|
+ * MFRC522 Arduino Arduino Arduino Arduino Arduino
|
|
|
|
|
+ * Reader/PCD Uno/101 Mega Nano v3 Leonardo/Micro Pro Micro
|
|
|
|
|
+ * Signal Pin Pin Pin Pin Pin Pin
|
|
|
|
|
+ * -----------------------------------------------------------------------------------------
|
|
|
|
|
+ * RST/Reset RST 9 5 D9 RESET/ICSP-5 RST
|
|
|
|
|
+ * SPI SS SDA(SS) 10 53 D10 10 10
|
|
|
|
|
+ * SPI MOSI MOSI 11 / ICSP-4 51 D11 ICSP-4 16
|
|
|
|
|
+ * SPI MISO MISO 12 / ICSP-1 50 D12 ICSP-1 14
|
|
|
|
|
+ * SPI SCK SCK 13 / ICSP-3 52 D13 ICSP-3 15
|
|
|
|
|
+ *
|
|
|
|
|
+ * For arduino uno
|
|
|
|
|
+ */
|
|
|
|
|
+
|
|
|
|
|
+#include <SPI.h>
|
|
|
|
|
+#include <MFRC522.h>
|
|
|
|
|
+
|
|
|
|
|
+#define RST_PIN 9
|
|
|
|
|
+#define SS_PIN 10
|
|
|
|
|
+
|
|
|
|
|
+MFRC522 mfrc522(SS_PIN, RST_PIN); // Create MFRC522 instance.
|
|
|
|
|
+
|
|
|
|
|
+MFRC522::MIFARE_Key keyB;
|
|
|
|
|
+MFRC522::MIFARE_Key keyA;
|
|
|
|
|
+
|
|
|
|
|
+byte LazoAKeys[64][6] = {
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x4E, 0x30, 0x3D, 0x40, 0x2F, 0x20 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x21, 0x6F, 0x5B, 0x21, 0x2A, 0x7A },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x51, 0x48, 0x75, 0x5C, 0x34, 0x27 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x5C, 0x7A, 0x37, 0x5C, 0x29, 0x5A },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x52, 0x46, 0x61, 0x2E, 0x7C, 0x4B },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x35, 0x4B, 0x39, 0x45, 0x48, 0x61 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x45, 0x5D, 0x73, 0x2C, 0x38, 0x5F },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
|
|
|
|
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
|
|
|
|
|
+};
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Initialize.
|
|
|
|
|
+ */
|
|
|
|
|
+void setup() {
|
|
|
|
|
+ Serial.begin(9600); // Initialize serial communications with the PC
|
|
|
|
|
+ while (!Serial)
|
|
|
|
|
+ ; // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
|
|
|
|
|
+ SPI.begin(); // Init SPI bus
|
|
|
|
|
+ mfrc522.PCD_Init(); // Init MFRC522 card
|
|
|
|
|
+
|
|
|
|
|
+ // Prepare the key (used both as key A and as key B)
|
|
|
|
|
+ // using FFFFFFFFFFFFh which is the default at chip delivery from the factory
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ Serial.println(F("Scan a MIFARE Classic PICC to demonstrate read and write."));
|
|
|
|
|
+ Serial.print(F("Using key (for A and B):"));
|
|
|
|
|
+ dump_byte_array(keyB.keyByte, MFRC522::MF_KEY_SIZE);
|
|
|
|
|
+ Serial.println();
|
|
|
|
|
+
|
|
|
|
|
+ Serial.println(F("BEWARE: Data will be written to the PICC, in sector #1"));
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Main loop.
|
|
|
|
|
+ */
|
|
|
|
|
+void loop() {
|
|
|
|
|
+ // Look for new cards
|
|
|
|
|
+ if (!mfrc522.PICC_IsNewCardPresent())
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ // Select one of the cards
|
|
|
|
|
+ if (!mfrc522.PICC_ReadCardSerial())
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ // Show some details of the PICC (that is: the tag/card)
|
|
|
|
|
+ Serial.print(F("Card UID:"));
|
|
|
|
|
+ dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
|
|
|
|
|
+ Serial.println();
|
|
|
|
|
+ Serial.print(F("PICC type: "));
|
|
|
|
|
+ MFRC522::PICC_Type piccType = mfrc522.PICC_GetType(mfrc522.uid.sak);
|
|
|
|
|
+ Serial.println(mfrc522.PICC_GetTypeName(piccType));
|
|
|
|
|
+
|
|
|
|
|
+ // Check for compatibility
|
|
|
|
|
+ if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI
|
|
|
|
|
+ && piccType != MFRC522::PICC_TYPE_MIFARE_1K
|
|
|
|
|
+ && piccType != MFRC522::PICC_TYPE_MIFARE_4K) {
|
|
|
|
|
+ Serial.println(F("This sample only works with MIFARE Classic cards."));
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (piccType == MFRC522::PICC_TYPE_MIFARE_1K) {
|
|
|
|
|
+ Serial.println(F("Type: mifare classic 1K"));
|
|
|
|
|
+ keyA.keyByte[0] = 0x04;
|
|
|
|
|
+ keyA.keyByte[1] = 0x00;
|
|
|
|
|
+ keyA.keyByte[2] = 0x0C;
|
|
|
|
|
+ keyA.keyByte[3] = 0x0F;
|
|
|
|
|
+ keyA.keyByte[4] = 0x09;
|
|
|
|
|
+ keyA.keyByte[5] = 0x03;
|
|
|
|
|
+
|
|
|
|
|
+ keyB.keyByte[0] = 0x04;
|
|
|
|
|
+ keyB.keyByte[1] = 0x00;
|
|
|
|
|
+ keyB.keyByte[2] = 0x0C;
|
|
|
|
|
+ keyB.keyByte[3] = 0x0F;
|
|
|
|
|
+ keyB.keyByte[4] = 0x09;
|
|
|
|
|
+ keyB.keyByte[5] = 0x03;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (piccType == MFRC522::PICC_TYPE_MIFARE_4K) {
|
|
|
|
|
+ Serial.println(F("Type: mifare classic 4K"));
|
|
|
|
|
+
|
|
|
|
|
+ //keyA.keyByte[0] = 0x4E;
|
|
|
|
|
+ //keyA.keyByte[1] = 0x30;
|
|
|
|
|
+ //keyA.keyByte[2] = 0x3D;
|
|
|
|
|
+ //keyA.keyByte[3] = 0x40;
|
|
|
|
|
+ //keyA.keyByte[4] = 0x2F;
|
|
|
|
|
+ //keyA.keyByte[5] = 0x20;
|
|
|
|
|
+
|
|
|
|
|
+ keyB.keyByte[0] = 0x24;
|
|
|
|
|
+ keyB.keyByte[1] = 0x33;
|
|
|
|
|
+ keyB.keyByte[2] = 0x72;
|
|
|
|
|
+ keyB.keyByte[3] = 0x40;
|
|
|
|
|
+ keyB.keyByte[4] = 0x7C;
|
|
|
|
|
+ keyB.keyByte[5] = 0x2E;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // In this sample we use the second sector,
|
|
|
|
|
+ // that is: sector #1, covering block #4 up to and including block #7
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+ MFRC522::StatusCode status;
|
|
|
|
|
+ byte buffer[18];
|
|
|
|
|
+ byte size = sizeof(buffer);
|
|
|
|
|
+
|
|
|
|
|
+ // Authenticate using key A
|
|
|
|
|
+ //Serial.println(F("Authenticating using key B..."));
|
|
|
|
|
+ //status = (MFRC522::StatusCode)mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_B, trailerBlock, &keyB, &(mfrc522.uid));
|
|
|
|
|
+ //if (status != MFRC522::STATUS_OK) {
|
|
|
|
|
+ // Serial.print(F("PCD_Authenticate() failed en auth B: "));
|
|
|
|
|
+ // Serial.println(mfrc522.GetStatusCodeName(status));
|
|
|
|
|
+ //}
|
|
|
|
|
+ //Serial.println(F("Autenticado con clave B "));
|
|
|
|
|
+ for (int sector = 15; sector >= 0; sector--) {
|
|
|
|
|
+ if (sector == 11 || sector == 12 || sector == 13 || sector == 14 || sector == 15 ) {
|
|
|
|
|
+
|
|
|
|
|
+ Serial.print(F("Unable to read:"));
|
|
|
|
|
+ Serial.println(sector);
|
|
|
|
|
+ } else {
|
|
|
|
|
+
|
|
|
|
|
+ for (byte i = 0; i < 6; i++) {
|
|
|
|
|
+ keyA.keyByte[i] = LazoAKeys[sector][i];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ int trailerBlock = sector * 4 - 1;
|
|
|
|
|
+ if (sector == 0){
|
|
|
|
|
+ trailerBlock = 3;
|
|
|
|
|
+ }
|
|
|
|
|
+ status = (MFRC522::StatusCode)mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &keyA, &(mfrc522.uid));
|
|
|
|
|
+ if (status != MFRC522::STATUS_OK) {
|
|
|
|
|
+ Serial.print(F("PCD_Authenticate() failed in blcks: "));
|
|
|
|
|
+ Serial.println(mfrc522.GetStatusCodeName(status));
|
|
|
|
|
+ return;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (status == MFRC522::STATUS_OK) {
|
|
|
|
|
+ // Show the whole sector as it currently is
|
|
|
|
|
+ mfrc522.PICC_DumpMifareClassicSectorToSerial(&(mfrc522.uid), &keyA, sector);
|
|
|
|
|
+ Serial.println();
|
|
|
|
|
+ // Halt PICC
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ mfrc522.PICC_HaltA();
|
|
|
|
|
+ // Stop encryption on PCD
|
|
|
|
|
+ mfrc522.PCD_StopCrypto1();
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * Helper routine to dump a byte array as hex values to Serial.
|
|
|
|
|
+ */
|
|
|
|
|
+void dump_byte_array(byte *buffer, byte bufferSize) {
|
|
|
|
|
+ for (byte i = 0; i < bufferSize; i++) {
|
|
|
|
|
+ Serial.print(buffer[i] < 0x10 ? " 0" : " ");
|
|
|
|
|
+ Serial.print(buffer[i], HEX);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|