/********************************************************************************** * Autor: Fco. Javier Rodriguez Navarro www.pinguytaz.net * Version 2.0 Abril 2.017 * * Volcado total de la tarjeta con la clave A de una tarjeta MIFARE Classic 1 K * debemos dejarla puesta ya que para cada sector se vuelve a autentificar. * *----------------------------------- *MFRC522 Arduino Arduino *Reader/PCD Uno Nano v3 * ---------------------------------- * RST 9 D9 * SDA(SS) 10 D10 * MOSI 11 / ICSP-4 D11 * MISO 12 / ICSP-1 D12 * SCK 13 / ICSP-3 D13 * * * Reconocimientos: * Libreria de Miguel Balboa. * * DATOS ALMACENAMIENTO: * Programa: 10.692 bytes * Variables Globales 759 bytes *********************************************************************************/ #include #include #define RST_PIN 9 // Pin 9 para el reset del RC522 #define SS_PIN 10 // Pin 10 para el SS (SDA) del RC522 MFRC522 rfid(SS_PIN, RST_PIN); // Crear instancia del MFRC522 /***************************+ SETUP solo al inicio ************/ void setup() { Serial.begin(9600); SPI.begin(); //Función que inicializa SPI rfid.PCD_Init(); //Función que inicializa RFID rfid.PCD_DumpVersionToSerial(); // Traduce PCD_ReadRegister(rfid.VersionReg) Serial.println("Volcado de Tarjeta MIFARE CLassic (Fco. Javier Rodriguez Navarro)"); Serial.println("A la espera de leer una tarjeta"); } // Finaliza setup /***************** LOOP que se ejecuta siempre ****************/ void loop() { MFRC522::PICC_Type piccTipo; int bloque=4 ; // Tenemos 4 bloques que van del 0 al 3. Se inicializan para probocar pregunta int sector=16; // Tenemos 16 sectores que van del 0-15. Se inicializan para probocar pregunta byte dBloque[18]; // Los datos leidos en un bloque son 16 bytes más 2 CRC. byte dBloque3[18]; // Tendra los datos del bloque 3 de un sector para no leerlo 2 veces. if (! rfid.PICC_IsNewCardPresent()) return; // Si no detecta tarjeta otro Bucle. if (! rfid.PICC_ReadCardSerial()) return; // Lee los datos de la tarjeta, si error sale del bucle piccTipo = rfid.PICC_GetType(rfid.uid.sak); // Recoge el tipo de tarjeta PIC. Serial.println("Tipo PICC: "+ String(rfid.PICC_GetTypeName(piccTipo))); Serial.print("NUID("+ String(rfid.uid.size)+")"); printHex(rfid.uid.uidByte,rfid.uid.size); Serial.println(" SAK: "+ String(rfid.uid.sak)); if (piccTipo = MFRC522::PICC_TYPE_MIFARE_1K) // Este programa solo interpreta tarjetas MIFARE 1K 4bytes UID(NUID) { Serial.println("Dir.\tSector\tBloque\t 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 [Acceso]"); // Cabecera for(sector = 0; sector < 16 ; sector ++) // Recorrido por los sectores { Lectura_Sector(sector, 3, dBloque3); // Leemos el bloque 3 del sector for (bloque = 0; bloque < 4 ; bloque ++) // Recorrido por los bloques { if (bloque!=3) Lectura_Sector(sector,bloque, dBloque); // Bloque 3 ya se leyo. Serial.print(String(sector*4+bloque)+"\t"+String(sector)+"\t"+String(bloque)+"\t"); if (bloque==3) Volcado_Trailer(dBloque3); else if(sector==0 && bloque == 0) Volcado_Fabrica(dBloque,dBloque3); else Volcado_Datos(dBloque,dBloque3,bloque); } // Fin for de Bloques Serial.println("-----------------------"); } // Fin For de sectores Serial.println(" ********************************************************"); } // Fin OK MIFARE 1K . else { Serial.println("No es una tarjeta MIFARE Classic 1K"); } // Fin desconozco tarjeta rfid.PICC_HaltA(); rfid.PCD_StopCrypto1(); delay(250); } // Finaliza Loop /******************************************************************* * Lectura_Sector(int, int, *buffer * * Realiza la lectura de un sector con su autentificación * * @param Sector que se desea leer * @param Bloque a leer * @param array donde se almacenaran los datos * @return true si fue correcta o false erronea *****************************************************************/ boolean Lectura_Sector(int sector,int bloque, byte *buffer) { MFRC522::MIFARE_Key clave; byte dirBloque, Bloque0; MFRC522::StatusCode estado; // Tendra los retornos de envios de comandos. MFRC522:.STATUS_???? // byte buffer[18]; byte numByte = 18; for(byte i =0 ; i< 6 ; i++) clave.keyByte[i] = 0xFF; // Clave por defecto 0xFFFFFFFFFFFF que llega de fabrica. Bloque0 = sector*4; // Calculamos direccion bloque 0 del sector. dirBloque = Bloque0 + bloque; // Direccion del bloque a leer. //Realizamos autentificación que siempre es necesaria en cada lectura de sector en MIFARE 1K estado = rfid.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, Bloque0, &clave, &rfid.uid); if (estado != MFRC522::STATUS_OK) { Serial.println("Fallo en la autentificación "+String(sector)+"/"+String(bloque)); return false; } // Realizamos la lectura. estado = rfid.MIFARE_Read(dirBloque, buffer, &numByte); if(estado != MFRC522::STATUS_OK) { Serial.print(rfid.GetStatusCodeName(estado)); // Existio un error Serial.println(" "+String(sector)+"/"+String(bloque)); return false; } //buffer2 = buffer; return true; } /******************************************************************* * Volcado_Trailer(byte *) * * Realiza un voldado de los datos de un sector Trailer * El Bloque 0 de cualquier sector se llama Sector Trailes * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 * [ KEY A ] [ A.Bits ] [ KEY B ] * * @param Datos a imprimir * @return ninguno *****************************************************************/ void Volcado_Trailer(byte *buffer) { printHex(buffer,16); // Datos en Hexadecimal. Serial.print(" ["+String(bitRead(buffer[7],7))+String(bitRead(buffer[8],3))+String(bitRead(buffer[8],7))+"]"); Serial.print(" KEY A:("); printCar(buffer,6,0); //Serial.println(" "); Serial.print(") KEY B:("); printCar(buffer,6,10); //Serial.println(""); //Serial.print("\t\t\t\t\t\t\t\t\t Bits Acceso: "); //Serial.print("B3:"+String(bitRead(buffer[7],7))+String(bitRead(buffer[8],3))+String(bitRead(buffer[8],7))+" "); // Serial.print("B2:"+String(bitRead(buffer[7],6))+String(bitRead(buffer[8],2))+String(bitRead(buffer[8],6))+" "); // Serial.print("B1:"+String(bitRead(buffer[7],5))+String(bitRead(buffer[8],1))+String(bitRead(buffer[8],5))+" "); // Serial.println("B0:"+String(bitRead(buffer[7],4))+String(bitRead(buffer[8],0))+String(bitRead(buffer[8],4))); Serial.print(") Usu:("); printCar(buffer,1,9); Serial.println(")"); } /******************************************************************* * Volcado_Fabrica(byte *) * * Realiza un voldado de los datos de fabrica de una MIFARE * El sector0 Bloque0 es de Fabricante. * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 * [ NUID ] [CRC][SAK=8][ATQA_0=4][ATQA_1=0][ Datos fabricante ] * * @param Datos a imprimir * @param Los datos del bloqye3. * @return ninguno *****************************************************************/ void Volcado_Fabrica(byte *buffer, byte *buffer3) { printHex(buffer,16); // Datos en Hexadecimal. Serial.print(" ["+String(bitRead(buffer3[7],4))+String(bitRead(buffer3[8],0))+String(bitRead(buffer3[8],4))+"]"); Serial.println(" NUID: "+String(buffer[0],HEX)+String(buffer[1],HEX)+String(buffer[2],HEX)+String(buffer[3],HEX)); Serial.println("\t\t\t\t\t\t\t\t\t\t CRC:"+String(buffer[4],HEX)); Serial.println("\t\t\t\t\t\t\t\t\t\t SAK:"+String(buffer[5],HEX)); Serial.println("\t\t\t\t\t\t\t\t\t\t ATQA:"+String(buffer[5],HEX)+String(buffer[7],HEX)); Serial.print("\t\t\t\t\t\t\t\t\t\t Fabricante: "); printCar(buffer,8,8); Serial.println(""); } /******************************************************************* * Volcado_Datos(byte *, int, int) * * Realiza un voldado de los datos de un bloque datos * * Los bloques pueden ser simplemente datos o Bloque Valor * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 * [ VAL ] [VAL_INV ] [ VAL ] [A] [aI] [A] [aI] * * @param Datos a imprimir * @param Bloque para la seguridad * @return ninguno *****************************************************************/ void Volcado_Datos(byte *buffer, byte *buffer3, int bloque) { printHex(buffer,16); // Datos en Hexadecimal. Serial.print(" ["+String(bitRead(buffer3[7],4+bloque))+String(bitRead(buffer3[8],bloque))+String(bitRead(buffer3[8],4+bloque))+"] "); printCar(buffer,16); Serial.println(""); } /******************************************************************* * printHex((byte *buffer, byte bufferSize) * * Vuelca un array de bytes en Hexadeciaml. * * @param array de bytes a imprimir * @param Numero de bytes a volcar. * @return Ninguno. *****************************************************************/ void printHex(byte *buffer, byte bufferSize) { for (byte i = 0; i < bufferSize; i++) { Serial.print(buffer[i] < 0x10 ? " 0" : " "); Serial.print(buffer[i], HEX); } } /******************************************************************* * printDec((byte *buffer, byte bufferSize) * * Vuelca un array de bytes en Decimal. * * @param array de bytes a imprimir * @param Numero de bytes a volcar. * @return Ninguno. *******************************************************************/ void printDec(byte *buffer, byte bufferSize) { for (byte i = 0; i < bufferSize; i++) { Serial.print(buffer[i] < 0x10 ? " 0" : " "); Serial.print(buffer[i], DEC); } } /******************************************************************* * printCar((byte *buffer, byte bufferSize) * * Vuelca un array de bytes en caracteres imprimible (ASCII 32-127) * * @param array de bytes a imprimir * @param Numero de bytes a volcar. * @param Inicio del array. * @return Ninguno. *******************************************************************/ void printCar(byte *buffer, byte bufferSize) {printCar(buffer,bufferSize,0);} void printCar(byte *buffer, byte bufferSize, int inicio) { for (byte i = inicio; i < bufferSize+inicio; i++) { Serial.print(""); if(buffer[i]>32 && buffer[i]< 127) Serial.print(String((char) buffer[i])+" "); else { Serial.print(" 0x"); Serial.print(buffer[i], HEX); Serial.print(" "); } } }