/*
Mappa EEPROM
00-02 Progressivo
03-05 Lotto
06-0D Passepartout Card Corrente
0E-10 Counter
*/
#include <EEPROM.h> // Libreria di gestione EEPROM
#include <SPI.h>
#include <MFRC522.h>
#define LED_ON LOW
#define LED_OFF HIGH
constexpr uint8_t Led_pin = 5; // Pin del LED, attivo LOW
constexpr uint8_t RST_PIN = 9;
constexpr uint8_t SS_PIN = 10;
MFRC522 mfrc522(SS_PIN, RST_PIN);
MFRC522::MIFARE_Key key;
/*
Inizializzazione
*/
byte blockAddr, trailerBlock;
byte sectdata[4][16];
/*
* PASSWORD GENERATRICE DI ESEMPIO
*
1CA97A224432B78088A91048A5C739C54BAB2C8400372600B8A37C0F825A5386F65F62368CDBF3A69492
DB949DE0D7D069C35640632C7811A6C03C7651A1D070414A8E117B18F5FF9C971568F491AF16D7C75258
4B8130DC5B37C37A540E9EC2945289FA2E424411FDFEA903918119483687A82D7C40A0C8B2D3ACC3DF6E
7A1541885C9090E2FE1652CF87FF35A9CD87456D13944398DD26192672AF8D588D9AD03431173C581C11
4F3BA5B849211A7AC13009833B9AA277EC95A54C943303F20E77972C8F631E0E5565B05D853D7BCD2AF9
69D3C38E10906FCE03BD6A3E4EA2176A9A887582F1CC81901D907C8ACC36CEC8124EE2BB8146C83F2FB2
E0C2E621AF57E4EAE8DE641BA14027631FDB1C4E20C5E9FFC8DA14A73229122122B7D5F519E2DA9D9DC8
CCF394AFC8FFF34ADA97DC4E70958E11DBB1424AAA55B0738ABDC478E46212A00FC7617599265EF717B6
21CCBD2125F780945DDEA454AF2EA2D74A34262770C21A8A862EC61E0022D09D00ADFA815F33BB32866E
6713DB85639E8EBB8B3E129D3FA312F7B90876F495DFC9CC0BB7ED630FCDFD128D67FFA78059D7AAC396
5A0A0C49D25C2C09D136779049E4C14555745CF53352B3C69ECF63898B6A75991CAEC19270ECBF7E1095
D2E1E745F7DFA42B53CE987B6B0881CE0A802C3018EDA109A8FACFCBEA5B9FDC8C18DB0E131E27DF124B
2B2C5E101E5D162D968193F815A2A09B5D692D8C450D81D8
*
*/
byte Key [][8] = {
{203, 129, 150, 202, 104, 213, 42, 252},
{6, 240, 136, 110, 195, 193, 237, 109},
{218, 208, 198, 117, 74, 137, 219, 76},
{191, 35, 77, 220, 136, 155, 119, 134},
{183, 26, 29, 164, 170, 66, 214, 180},
{223, 11, 22, 186, 122, 42, 126, 133},
{126, 224, 172, 32, 242, 55, 61, 51},
{43, 231, 27, 38, 72, 142, 1, 149},
{52, 6, 93, 0, 117, 239, 26, 26},
{151, 113, 214, 179, 155, 13, 191, 107},
{58, 65, 180, 66, 136, 249, 149, 70},
{176, 20, 66, 20, 58, 248, 67, 150},
{157, 97, 233, 185, 77, 217, 246, 175},
{194, 101, 44, 253, 61, 206, 47, 210},
{199, 20, 201, 193, 206, 164, 24, 48},
{198, 134, 153, 159, 238, 115, 12, 83},
{26, 240, 158, 222, 163, 239, 29, 247},
{201, 83, 138, 247, 42, 56, 116, 21},
{210, 217, 66, 196, 186, 130, 160, 188},
{155, 122, 155, 152, 199, 61, 72, 107},
{7, 220, 21, 14, 155, 109, 135, 75},
{100, 245, 160, 203, 63, 16, 94, 76},
{73, 213, 140, 117, 4, 214, 145, 199},
{131, 65, 111, 158, 17, 6, 7, 32},
{72, 107, 212, 38, 94, 152, 79, 201},
{236, 147, 71, 143, 183, 114, 58, 130},
{101, 196, 214, 23, 35, 6, 85, 129},
{227, 97, 34, 16, 118, 197, 168, 124},
{219, 169, 131, 61, 114, 79, 39, 201},
{85, 150, 166, 90, 233, 238, 254, 26},
{112, 74, 236, 48, 17, 144, 71, 23},
{92, 122, 206, 207, 164, 179, 109, 39},
{183, 80, 89, 133, 74, 245, 39, 227},
{135, 43, 38, 36, 63, 45, 83, 15},
{131, 28, 200, 125, 101, 241, 71, 58},
{51, 89, 255, 81, 106, 83, 79, 131},
{194, 254, 197, 43, 26, 73, 223, 11},
{163, 76, 219, 137, 119, 121, 151, 16},
{96, 125, 131, 86, 83, 180, 152, 251},
{100, 85, 125, 109, 238, 104, 184, 227},
{182, 170, 106, 226, 32, 238, 245, 238},
{83, 32, 127, 45, 85, 121, 170, 157},
{189, 234, 171, 40, 174, 89, 122, 102},
{13, 47, 3, 83, 81, 239, 181, 12},
{197, 79, 183, 173, 25, 219, 88, 50},
{247, 45, 142, 72, 244, 191, 204, 100},
{171, 62, 153, 255, 245, 205, 17, 133},
{41, 155, 189, 246, 48, 223, 236, 42},
{239, 179, 233, 71, 155, 165, 116, 147},
{48, 160, 13, 155, 122, 158, 62, 51},
{140, 177, 253, 6, 41, 40, 151, 159},
{135, 30, 159, 192, 173, 42, 191, 187},
{195, 229, 201, 146, 221, 213, 224, 213},
{236, 204, 248, 34, 53, 218, 65, 3},
{47, 38, 136, 61, 35, 129, 123, 211},
{71, 22, 107, 217, 15, 1, 216, 185},
{186, 185, 241, 184, 158, 69, 115, 206},
{218, 109, 153, 244, 64, 224, 53, 129},
{37, 148, 168, 19, 167, 134, 170, 20},
{41, 172, 153, 72, 176, 134, 164, 152},
{126, 196, 216, 186, 192, 191, 164, 106},
{33, 99, 126, 224, 137, 161, 62, 98},
{4, 176, 112, 177, 169, 247, 203, 103},
{82, 73, 45, 227, 206, 165, 156, 37},
{168, 201, 113, 232, 82, 20, 174, 53},
{208, 181, 253, 161, 239, 174, 203, 112}
};
char buf[20];
char ch[2];
char s[33];
byte a[8], b[8], dataBlock[16], ii, kk;
byte CardN[8]; // codice card: diventa a in programmazione
byte LockN[8]; // codice serratura: diventa b in programmazione
void setup() {
pinMode(Led_pin, OUTPUT);
digitalWrite(Led_pin, LED_OFF);
//Configurazione del microcontrollore
Serial.begin(9600); // Inizializza la comunicazione seriale con il PC
delay(1000);
SPI.begin(); // Inizializza l'interfaccia SPI
mfrc522.PCD_Init(); // Inizializza il lettore MFRC522
// usa FFFFFFFFFFFFh che sono le chiavi di cifratura di default della Card
for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xff;
}
ch[0] = 0;
Serial.print("Lotto:");
EEPROMPrint(a, 3, 3);
for (byte i = 0; i < 3; i++) {
LockN[i+4] = a[i];
}
Serial.print(" Progressivo:");
EEPROMPrint(a, 3, 0);
Serial.println();
Serial.print("Passepartout Card corrente:");
EEPROMPrint(a, 7, 6);
Serial.println();
Serial.print("Contatore di programmazione:");
EEPROMPrint(a, 3, 14);
Serial.println();
}
/**
* Main loop.
*/
void loop() {
// Acquisizione comando
if (Serial.available()){
ch[0] = Serial.read();
delay(5);
/* Comando L: CAMBIO DEL NUMERO DI LOTTO
Struttura del comando: LXXXXXX: XXXXXX codice esadecimale del lotto
Il comando azzera anche il contatore progressivo
*/
if(ch[0] == 'L') {
for (byte i=0; i<6; i++){
buf[i] = Serial.read();
delay(5);
}
ii= 0;
for (byte i=0; i<6; i=i+2) {
LockN[ii+4] = HextoDec(buf[i], buf[i+1]);
EEPROM.write(ii+3, LockN[ii+4]);
ii = ii + 1;
}
Serial.print("Lotto:");
EEPROMPrint(a, 3, 3);
EEPROMReset(a, 3, 0);
Serial.print(" Progressivo:");
EEPROMPrint(a, 3, 0);
Serial.println();
ch[0] = 0;
}
/* Comando N: CAMBIO DEL NUMERO PROGRESSIVO DI LOTTO
Struttura del comando: NXXXXXX: XXXXXX codice esadecimale del progressivo
Il comando non altera il numero di lotto
*/
else if(ch[0] == 'N') {
for (byte i=0; i<6; i++){
buf[i] = Serial.read();
delay(5);
}
ii= 0;
for (byte i=0; i<6; i=i+2) {
a[ii] = HextoDec(buf[i], buf[i+1]);
EEPROM.write(ii, a[ii]);
ii = ii + 1;
}
Serial.print("Lotto:");
EEPROMPrint(a, 3, 3);
Serial.print(" Progressivo:");
EEPROMPrint(a, 3, 0);
Serial.println();
ch[0] = 0;
}
/* Comando A: AZZERAMENTO DEL NUMERO PROGRESSIVO DI LOTTO
Struttura del comando: A
Il comando non altera il numero di lotto
*/
else if(ch[0] == 'A') {
for (byte i=0; i<3; i++){
a[i]= 0;
}
EEPROMWrite(a, 3, 0);
Serial.print("Lotto:");
EEPROMPrint(a, 3, 3);
Serial.print(" Progressivo:");
EEPROMPrint(a, 3, 0);
Serial.println();
ch[0] = 0;
}
/* Comando B: AZZERAMENTO DEL CONTATORE
Struttura del comando: B
Il comando non altera il numero di lotto
*/
else if(ch[0] == 'B') {
for (byte i=0; i<3; i++){
a[i]= 0;
}
EEPROMWrite(a, 3, 14);
Serial.print("Contatore:");
EEPROMPrint(a, 3, 14);
Serial.println();
ch[0] = 0;
}
/* Comando I: INFO SU NUMERO DI LOTTO E PROGRESSIVO
Struttura del comando: I
*/
else if(ch[0] == 'I') {
Serial.print("Lotto:");
EEPROMPrint(a, 3, 3);
Serial.print(" Progressivo:");
EEPROMPrint(a, 3, 0);
Serial.println();
Serial.print("Passepartout Card corrente:");
EEPROMPrint(a, 7, 6);
Serial.println();
Serial.print("Contatore di programmazione:");
EEPROMPrint(a, 3, 14);
Serial.println();
ch[0] = 0;
}
/* Comando V: VERIFICA IL CONTENUTO DECIFRATO DELLA CARD
Struttura del comando: V
Il comando attende di leggere la card da verificare
*/
else if (ch[0] == 'V') {
Serial.println("Verifica card: in attesa di una card da verificare...");
}
/* Comando ?: RESTITUISCE IL CODICE UNIVOCO DI CARD E IL TIPO
Struttura del comando: ?
Il comando attende di leggere la card da identificare
*/
else if (ch[0] == '?') {
Serial.println("Tipo card: in attesa di una card da leggere...");
}
/* Comando E: Cancellazione card
Struttura del comando: E
Il comando attende di leggere la card da cancellare
*/
else if (ch[0] == 'E') {
Serial.println("Cancellazione Card: in attesa della card da cancellare...");
}
/* Comando R: RESTITUISCE IL CONTENUTO COMPLETO DELLA CARD NON DECIFRATO
Struttura del comando: R
Il comando attende di leggere la card da leggere
*/
else if (ch[0] == 'R') {
Serial.println("Legge card: in attesa di una card da leggere...");
}
/* Comando A: Annulla il comando in corso
Struttura del comando: A
*/
else if (ch[0] == 'C') {
Serial.println("Comando annullato");
ch[0] = 0;
}
/* Comando P: COMANDO DI PROGRAMMAZIONE CARD PASSEPARTOUT
Struttura del comando: P
Il comando attende di leggere la card passepartout da programmare
La card sarà programmata con il suo codice univoco, il numero di lotto corrente ed il progressivo corrente
Alla fine del comando il progressivo sarà incrementato
*/
else if (ch[0] == 'P') {
Serial.print("Lotto:");
EEPROMPrint(a, 3, 3);
Serial.print(" Progressivo:");
EEPROMPrint(a, 3, 0);
Serial.println();
Serial.println("Legge card: in attesa di una card da programmare...");
}
/* Comando K: INSERIMENTO DI PASSEPARTOUT CARD CORRENTE
Struttura del comando: K
Il comando attende di leggere la passepartout card corrente
*/
else if (ch[0] == 'K') {
Serial.println("Passepartout card: in attesa della card da acquisire...");
}
/* Comando U: COMANDO DI PROGRAMMAZIONE USER CARD
Struttura del comando: U
Il comando attende di leggere la user card da programmare
La card sarà programmata con il suo codice univoco, il numero di serratura fornito dalla Passepartout Card
*/
else if (ch[0] == 'U') {
EEPROMRead(LockN, 8, 6);
if(LockN[7] == 0) {
Serial.print("Passepartout Card:");
VectorPrint(LockN, 0, 7);
Serial.println();
Serial.println("User Card: in attesa di una card da programmare...");
}
else {
Serial.println("Inserire prima una Passepartout Card valida");
ch[0] = 0;
}
}
/* Comando Q: COMANDO DI PROGRAMMAZIONE QUESTION CARD
Struttura del comando: Q
Il comando attende di leggere la question card da programmare
La card sarà programmata con il suo codice univoco, il numero di serratura fornito dalla Passepartout Card
*/
else if (ch[0] == 'Q') {
EEPROMRead(LockN, 8, 6);
if(LockN[7] == 0) {
Serial.print("Passepartout Card:");
VectorPrint(LockN, 0, 7);
Serial.println();
Serial.println("Question Card: in attesa di una card da programmare...");
}
else {
Serial.println("Inserire prima una Passepartout Card valida");
ch[0] = 0;
}
}
}
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) return;
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) return;
else digitalWrite(Led_pin, LED_ON); // Led acceso
for ( uint8_t i = 0; i < 4; i++) {
CardN[4+i] = mfrc522.uid.uidByte[i]; // Salva il codice chiave in CardN
}
if(ch[0] == 0) ch[0] = '?';
if (ch[0] == 'V') { // Verifica contenuto card
boolean flg, blk_err = false ;
for (byte sector = 0; sector < 16 ; sector++) {
Serial.print("Settore ");
Serial.println(sector);
mfrc522.PICC_DumpMifareClassicSectorToSave(&(mfrc522.uid), &key, sector, sectdata);
for ( uint8_t j=0; j<3; j++) {
for ( uint8_t i = 0; i < 8; i++) {
a[i] = sectdata[j][i];
}
for ( uint8_t i = 0; i < 8; i++) {
b[i] = sectdata[j][i+8];
}
blockAddr = sector*4+j;
if(blockAddr > 0) DeKrypto(a,b, 31);
if(blockAddr == 1) CopyVector(b, LockN, 8);
if(blockAddr<10) Serial.print(0);
Serial.print(blockAddr);
Serial.print(" ");
VectorPrint(a, 0, 8);
VectorPrint(b, 0, 8);
Serial.print(" Blocco ");
if(blockAddr > 0) {
flg = CompareVector(a, CardN, 4, 4, 4);
if(flg && a[3] == blockAddr) Serial.print("Ok");
else {
Serial.print("Er");
blk_err = true;
}
flg = CompareVector(b, LockN, 0, 0, 8);
if(flg) Serial.print(" Ok");
else {
Serial.print("Er");
blk_err = true;
}
}
else {
Serial.print("Ok Ok");
}
Serial.println();
}
}
Serial.print("Card ");
VectorPrint(mfrc522.uid.uidByte, 0, 4);
if(blk_err) Serial.println(" Codice non valido");
else {
if(LockN[7] == 0) Serial.println(" User");
else if(LockN[7] == 170) Serial.println(" Question");
else if(LockN[7] == 255) Serial.println(" Passepartout");
else Serial.println(" Card non valida");
}
ch[0] = 0;
// Halt PICC
mfrc522.PICC_HaltA();
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
else if (ch[0] == '?') { // Verifica tipo card
mfrc522.PICC_DumpMifareClassicSectorToSave(&(mfrc522.uid), &key, 1, sectdata);
for ( uint8_t i = 0; i < 8; i++) {
a[i] = sectdata[1][i];
}
for ( uint8_t i = 0; i < 8; i++) {
b[i] = sectdata[1][i+8];
}
DeKrypto(a,b, 31);
if(a[3] != 5) Serial.print ("Codice non valido");
else {
if(b[7] == 0) {
Serial.print("User di");
VectorPrint(b, 0, 7);
}
else if(b[7] == 170) {
Serial.print("Question di");
VectorPrint(b, 0, 7);
}
else if(b[7] == 255) {
if(CompareVector(a, b, 4, 0, 4)){
Serial.print("Passepartout Card:");
VectorPrint(a, 4, 4);
Serial.print(" Lotto:");
VectorPrint(b, 4, 3);
Serial.print(" Progressivo:");
VectorPrint(a, 0, 3);
}
else {
Serial.print ("Codice non valido");
}
}
else {
Serial.print("Card non valida");
}
}
Serial.println();
ch[0] = 0;
// Halt PICC
mfrc522.PICC_HaltA();
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
else if(ch[0] == 'R') { // Legge il contenuto della card
ch[0] = 0;
Serial.println(F("Contenuto cifrato"));
// Dump debug info about the card; PICC_HaltA() is automatically called
mfrc522.PICC_DumpToSerial(&(mfrc522.uid));
Serial.println(F("Fine scanning"));
}
else if (ch[0] == 'K') { // Acquisizione Passpartout Card corrente
mfrc522.PICC_DumpMifareClassicSectorToSave(&(mfrc522.uid), &key, 1, sectdata);
for ( uint8_t i = 0; i < 8; i++) {
a[i] = sectdata[1][i];
}
for ( uint8_t i = 0; i < 8; i++) {
b[i] = sectdata[1][i+8];
}
DeKrypto(a,b, 31);
if(a[3] != 5) Serial.print ("Codice non valido");
else {
if(b[7] == 0) {
Serial.print("User Card");
}
if(b[7] == 170) {
Serial.print("Question Card");
}
else if(b[7] == 255) {
if(CompareVector(a, b, 4, 0, 4)){
Serial.print("Passepartout Card:");
VectorPrint(b, 0, 7);
b[7] = 0; // Predispone alla memorizzaione di User Card
EEPROMWrite(b, 8, 6); // Salva il codice serratura
}
else {
Serial.print (" Codice non valido");
}
}
else {
Serial.print(" Card non valida");
}
}
Serial.println();
ch[0] = 0;
// Halt PICC
mfrc522.PICC_HaltA();
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
else if(ch[0] == 'P'){ // Programma la Passepartout Card
boolean valid_flag = true;
EEPROMRead(CardN, 3, 0); // inizializza CardN al progressivo di lotto
Serial.print(F("Card UID:"));
VectorPrint(mfrc522.uid.uidByte, 0, mfrc522.uid.size);
EEPROMRead(a, 3, 3); // legge il numero di Lotto
a[3] = 255;
for ( uint8_t i = 0; i < 4; i++) {
LockN[i] = mfrc522.uid.uidByte[i];
LockN[i+4] = a[i];
CardN[i+4] = LockN[i]; // Salva il codice chiave in CardN
}
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;
}
MFRC522::StatusCode status;
for (byte sector = 0; sector < 16 ; sector++) {
trailerBlock = sector * 4 + 3;
status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
for (int bk = 0; bk<3; bk++) {
blockAddr = sector * 4 + bk;
if(blockAddr > 0) {
for ( uint8_t i = 0; i < 8; i++) {
a[i] = CardN[i]; // Salva il codice chiave in a
}
for ( uint8_t i = 0; i < 8; i++) {
b[i] = LockN[i]; // Salva il codice serratura in b
}
a[3] = blockAddr;
Serial.print("Blocco: ");
Serial.print(blockAddr);
Krypto(a,b,32);
for ( uint8_t i = 0; i < 8; i++) {
dataBlock[i] = a[i]; // salva kra in dataBlock
}
for ( uint8_t i = 0; i < 8; i++) {
dataBlock[i+8] = b[i]; // salva krb in dataBlock
}
status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16);
if(status != 0) {
valid_flag = false;
Serial.println(" Err");
}
else {
Serial.println(" Ok");
}
}
}
}
ch[0] = 0;
if(valid_flag) {
EEPROMIncrement(3, 0);
EEPROMWrite(LockN, 7, 6); // Salva il nuovo codice serratura come corrente
Serial.println(F("Programmazione completata"));
}
else {
Serial.println(F("Errore"));
// Halt PICC
mfrc522.PICC_HaltA();
}
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
else if(ch[0] == 'U'){ // Programma la User Card
boolean valid_flag = true;
EEPROMRead(CardN, 3, 14); // inizializza CardN con il Contatore di programmatore corrente
EEPROMRead(LockN, 8, 6); // inizializza LockN con il codice di Passepartout Card corrente
Serial.print(F("Card UID:"));
VectorPrint(mfrc522.uid.uidByte, 0, mfrc522.uid.size);
for ( uint8_t i = 0; i < 4; i++) {
CardN[i+4] = mfrc522.uid.uidByte[i];; // Salva il codice chiave in CardN
}
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;
}
MFRC522::StatusCode status;
for (byte sector = 0; sector < 16 ; sector++) {
trailerBlock = sector * 4 + 3;
status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
for (int bk = 0; bk<3; bk++) {
blockAddr = sector * 4 + bk;
if(blockAddr > 0) {
for ( uint8_t i = 0; i < 8; i++) {
a[i] = CardN[i]; // Salva il codice chiave in a
}
for ( uint8_t i = 0; i < 8; i++) {
b[i] = LockN[i]; // Salva il codice serratura in b
}
a[3] = blockAddr;
Krypto(a,b,32);
for ( uint8_t i = 0; i < 8; i++) {
dataBlock[i] = a[i]; // salva kra in dataBlock
}
for ( uint8_t i = 0; i < 8; i++) {
dataBlock[i+8] = b[i]; // salva krb in dataBlock
}
status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16);
if(status != 0) {
valid_flag = false;
}
}
}
}
ch[0] = 0;
if(valid_flag) {
Serial.println(F("Programmazione completata"));
EEPROMIncrement(3, 14); // Incrementa il Contatore di programmazione
}
else {
Serial.println(F("Errore"));
// Halt PICC
mfrc522.PICC_HaltA();
}
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
else if(ch[0] == 'Q'){ // Programma la Question Card
boolean valid_flag = true;
EEPROMRead(CardN, 3, 14); // inizializza CardN con il Contatore di programmatore corrente
EEPROMRead(LockN, 8, 6); // inizializza LockN con il codice di Passepartout Card corrente
Serial.print(F("Card UID:"));
VectorPrint(mfrc522.uid.uidByte, 0, mfrc522.uid.size);
for ( uint8_t i = 0; i < 4; i++) {
CardN[i+4] = mfrc522.uid.uidByte[i];; // Salva il codice chiave in CardN
}
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;
}
MFRC522::StatusCode status;
for (byte sector = 0; sector < 16 ; sector++) {
trailerBlock = sector * 4 + 3;
status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
for (int bk = 0; bk<3; bk++) {
blockAddr = sector * 4 + bk;
if(blockAddr > 0) {
for ( uint8_t i = 0; i < 8; i++) {
a[i] = CardN[i]; // Salva il codice chiave in a
}
for ( uint8_t i = 0; i < 7; i++) {
b[i] = LockN[i]; // Salva il codice serratura in b
}
b[7] = 170; // inserisce il codice AA di question card
a[3] = blockAddr;
Krypto(a,b,32);
for ( uint8_t i = 0; i < 8; i++) {
dataBlock[i] = a[i]; // salva kra in dataBlock
}
for ( uint8_t i = 0; i < 8; i++) {
dataBlock[i+8] = b[i]; // salva krb in dataBlock
}
status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16);
if(status != 0) {
valid_flag = false;
}
}
}
}
ch[0] = 0;
if(valid_flag) {
Serial.println(F("Programmazione completata"));
EEPROMIncrement(3, 14); // Incrementa il Contatore di programmazione
}
else {
Serial.println(F("Errore"));
// Halt PICC
mfrc522.PICC_HaltA();
}
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
else if(ch[0] == 'E'){ // Cancella la Card
boolean valid_flag = true;
Serial.print(F("Card UID:"));
VectorPrint(mfrc522.uid.uidByte, 0, mfrc522.uid.size);
for ( uint8_t i = 0; i < 4; i++) {
CardN[i+4] = mfrc522.uid.uidByte[i];; // Salva il codice chiave in CardN
}
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;
}
MFRC522::StatusCode status;
for (byte sector = 0; sector < 16 ; sector++) {
trailerBlock = sector * 4 + 3;
status = (MFRC522::StatusCode) mfrc522.PCD_Authenticate(MFRC522::PICC_CMD_MF_AUTH_KEY_A, trailerBlock, &key, &(mfrc522.uid));
for (int bk = 0; bk<3; bk++) {
blockAddr = sector * 4 + bk;
if(blockAddr > 0) {
for ( uint8_t i = 0; i < 8; i++) {
a[i] = 0; // azzera a
b[i] = 0; // azzera b
}
for ( uint8_t i = 0; i < 8; i++) {
dataBlock[i] = a[i]; // salva kra in dataBlock
}
for ( uint8_t i = 0; i < 8; i++) {
dataBlock[i+8] = b[i]; // salva krb in dataBlock
}
status = (MFRC522::StatusCode) mfrc522.MIFARE_Write(blockAddr, dataBlock, 16);
if(status != 0) {
valid_flag = false;
}
}
}
}
ch[0] = 0;
if(valid_flag) {
Serial.println(F("Cancellazione completata"));
}
else {
Serial.println(F("Errore"));
// Halt PICC
mfrc522.PICC_HaltA();
}
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
delay(500);
digitalWrite(Led_pin, LED_OFF); // Led spento
}
/*
Visualizza vettore in formato esadecimale
*/
void VectorPrint(byte *x, byte ix, byte dv) {
Serial.print(" <");
for (byte i = 0; i < dv; i++) {
Serial.print(x[ix+i] < 0x10 ? " 0" : " ");
Serial.print(x[ix+i], HEX);
}
Serial.print(" >");
}
/////////////////////////////////////// Gestione EEPROM //////////////////////////////
void EEPROMRead(byte *x, int dv, int adr){
for ( int i = 0; i < dv; i++) { // Legge il vettore dalla EEPROM
x[i] = EEPROM.read(adr+i); // Salva il byte nel vettore
}
}
void EEPROMWrite(byte *x, int dv, int adr){
for ( int i = 0; i < dv; i++) { // Scrive il vettore nella EEPROM
EEPROM.write(adr+i, x[i]);
}
}
void EEPROMReset(byte *x, int dv, int adr){
for ( int i = 0; i < dv; i++) { // Reset della porzione di EEPROM
x[i] = 0;
EEPROM.write(adr+i, 0);
}
}
void EEPROMPrint(byte *x, int dv, int adr){
EEPROMRead(x, dv, adr);
VectorPrint(x, 0, dv);
}
void EEPROMIncrement(int dv, int adr){
byte rep = 1;
EEPROMRead(a, dv, adr);
for (int i = dv-1; i >= 0; i=i-1) {
if(rep == 1 && a[i] == 255){
a[i] = 0;
}
else {
a[i] = a[i] + rep;
rep = 0;
}
}
EEPROMWrite(a, dv, adr);
}
/*-----( Funzioni di Conversione )-----*/
byte HextoDec(char x, char y) {
byte h, l, r;
h = 0;
l = 0;
if(x>64) h = x - 55;
else h = x - 48;
if(y>64) l = y - 55;
else l = y - 48;
r = h*16 + l;
return r;
}
void DectoHex(byte z, char ch[2]) {
byte nb;
nb = z / 16;
if (nb>9){nb = nb + 55;}
else {nb = nb + 48;}
ch[0] = char(nb);
nb = z % 16;
if (nb>9){nb = nb + 55;}
else {nb = nb + 48;}
ch[1] = char(nb);
}
/*-----( Funzioni di Cifratura )-----*/
byte Krypto(byte a[8], byte b[8], byte nit) {
byte i, j, rck, rtb;
byte rs[8];
Sum(a, Key[0], a);
Sum(b, Key[1], b);
for (i = 1; i Xor(a, b, rs);
rck = b[7] & 1;
if(rck > 0){
Swap(rs, rs);
}
rck = b[7] & 63;
rtb = b[7] & 64;
if(rtb > 0) LeftRot(rs, rck, rs);
else RightRot(rs, rck, rs);
Sum(rs, Key[2*i], a);
Xor(b, a, rs);
rck = a[7] & 1;
if(rck > 0){
Swap(rs, rs);
}
rck = a[7] & 63;
rtb = a[7] & 64;
if(rtb > 0) LeftRot(rs, rck, rs);
else RightRot(rs, rck, rs);
Sum(rs, Key[2*i+1], b);
}
return ZeroNB(a, b);
}
byte DeKrypto(byte a[8], byte b[8], byte nit) {
byte i, j, k, rck, rtb;
byte rs[8];
for (k = 0; k i = nit - k;
Subt (b, Key[2*i+1], rs);
rck = a[7] & 63;
rtb = a[7] & 64;
if(rtb > 0) {
RightRot(rs, rck, rs);
}
else {
LeftRot(rs, rck, rs);
}
rck = a[7] & 1;
if(rck > 0){
Swap(rs, rs);
}
Xor(rs, a, b);
Subt (a, Key[2*i], rs);
rck = b[7] & 63;
rtb = b[7] & 64;
if(rtb > 0){
RightRot(rs, rck, rs);
}
else {
LeftRot(rs, rck, rs);
}
rck = b[7] & 1;
if(rck > 0){
Swap(rs, rs);
}
Xor(rs, b, a);
}
Subt(b, Key[1], b);
Subt(a, Key[0], a);
return ZeroNB(a, b);
}
void Sum(byte x[8], byte y[8], byte z[8]) {
byte rp = 0, i, j;
int rs;
for (j = 0; j<8; j++) {
i = 7 - j;
rs = x[i] + y[i] + rp;
if(rs > 255) {
rs = rs - 256;
rp = 1;
}
else rp = 0;
z[i] = byte(rs);
}
}
void Subt(byte x[8], byte y[8], byte z[8]) {
byte rp = 0, i, j;
int rs;
for (j = 0; j<8; j++) {
i = 7 - j;
rs = x[i] - y[i] - rp;
if(rs < 0) {
rs = rs + 256;
rp = 1;
}
else rp = 0;
z[i] = byte(rs);
}
}
void LeftRot(byte x[8], byte rotn, byte z[8]) {
byte rp;
int rs;
byte i;
byte j;
byte k;
for (k = 0; k rp = 0;
for (j = 0; j<8; j++) {
i = 7 - j;
rs = x[i] << 1;
rs = rs | int(rp);
if(rs > 255) {
rs = rs - 256;
rp = 1;
}
else rp = 0;
z[i] = byte(rs);
}
z[7] = z[7] | rp;
}
}
void RightRot(byte x[8], byte rotn, byte z[8]) {
byte rp;
byte rs;
byte j;
byte k;
for (k = 0; k rp = 0;
for (j = 0; j<8; j++) {
rs = rp;
if((x[j] & 1) > 0) rp = 128;
else rp = 0;
z[j] = (x[j] >> 1) | rs;
}
z[0] = z[0] | rp;
}
}
void Xor(byte x[8], byte y[8], byte z[8]) {
byte j;
for (j = 0; j<8; j++) {
z[j] = x[j]^y[j];
}
}
byte ZeroNB(byte x[8], byte y[8]) {
byte i;
byte j;
byte msk;
byte z;
z = 0;
for (i = 0; i<8; i++) {
msk = 1;
for (j = 0; j<8; j++) {
if((x[i]&msk) == 0) z = z + 1;
if((y[i]&msk) == 0) z = z + 1;
msk = msk << 1;
}
}
return z;
}
void Swap(byte x[8], byte z[8]) {
byte j;
for (j = 0; j<8; j++) {
z[j] = (x[j] << 4) | (x[j] >> 4);
}
}
boolean CompareVector(byte *x, byte *z, byte ix, byte iz, byte dv) {
byte j;
boolean flg = true;
for (j = 0; j if(x[j+ix] != z[j+iz]) flg = false;
}
return flg;
}
void CopyVector(byte *x, byte *z, byte dv) {
byte j;
for (j = 0; j z[j] = x[j];
}
}