#include <SPI.h>

#include <MFRC522.h>
#include <EEPROM.h> // Libreria di gestione EEPROM
MFRC522 mfrc522(10, 9);
MFRC522::MIFARE_Key key;
boolean prog_flg = true;
/*
* Initialize.
*/
// Define variables
#define LED_ON LOW
#define LED_OFF HIGH
constexpr uint8_t Tx_pin = 8; // Pin di trasmissione
constexpr uint8_t Supply_pin = 7; // Pin di alimentazione del trasmettirote (attivo HIGH)
constexpr uint8_t UNO = LOW; // Segnale di uno logico
constexpr uint8_t ZERO = HIGH; // Segnale di zero logico
/*
**************
Mappa EEPROM
**************

00-03 Contatore di chiave
04 Flag di inizializzazione
05-FF non usati

*/

constexpr uint8_t Led_Rosso = 4;
constexpr uint8_t Led_Verde = 3;
/*
* PASSWORD GENERATRICE
*
1CA97A224432B78088A91048A5C739C54BAB2C8400372600B8A37C0F825A5386F65F62368CDBF3A69492DB949DE0D7D069C35640632C7811A6C03C7651A1D070
414A8E117B18F5FF9C971568F491AF16D7C752584B8130DC5B37C37A540E9EC2945289FA2E424411FDFEA903918119483687A82D7C40A0C8B2D3ACC3DF6E7A15
41885C9090E2FE1652CF87FF35A9CD87456D13944398DD26192672AF8D588D9AD03431173C581C114F3BA5B849211A7AC13009833B9AA277EC95A54C943303F2
0E77972C8F631E0E5565B05D853D7BCD2AF969D3C38E10906FCE03BD6A3E4EA2176A9A887582F1CC81901D907C8ACC36CEC8124EE2BB8146C83F2FB2E0C2E621
AF57E4EAE8DE641BA14027631FDB1C4E20C5E9FFC8DA14A73229122122B7D5F519E2DA9D9DC8CCF394AFC8FFF34ADA97DC4E70958E11DBB1424AAA55B0738ABD
C478E46212A00FC7617599265EF717B621CCBD2125F780945DDEA454AF2EA2D74A34262770C21A8A862EC61E0022D09D00ADFA815F33BB32866E6713DB85639E
8EBB8B3E129D3FA312F7B90876F495DFC9CC0BB7ED630FCDFD128D67FFA78059D7AAC3965A0A0C49D25C2C09D136779049E4C14555745CF53352B3C69ECF6389
8B6A75991CAEC19270ECBF7E1095D2E1E745F7DFA42B53CE987B6B0881CE0A802C3018EDA109A8FACFCBEA5B9FDC8C18DB0E131E27DF124B2B2C5E101E5D162D
968193F815A2A09B5D692D8C450D81D8
*
*/
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 s[33];
byte a[8], b[8];
byte icnt[8] = {0, 0, 0, 1, 0,0,0,0};

byte trailerBlock, blockAddr;
byte sector = 1;
byte blockoff = 0;
byte sectdata[4][16];
byte blockdata[16];
byte LockN[7]; // codice dispositivo

void setup() {
Serial.begin(9600);
pinMode(Led_Rosso, OUTPUT);
pinMode(Led_Verde, OUTPUT);
pinMode(Supply_pin, OUTPUT);
digitalWrite(Supply_pin, LOW); // trasmissione disabilitata
pinMode(Tx_pin, OUTPUT);
digitalWrite(Tx_pin, ZERO); // segnale di trasmissione basso

for (byte i = 0; i < 6; i++) {
key.keyByte[i] = 0xff;
}
digitalWrite(Led_Rosso, LOW);
digitalWrite(Led_Verde, LOW);
delay(1000);
digitalWrite(Led_Rosso, HIGH);
digitalWrite(Led_Verde, HIGH);
}
void loop() {
SPI.begin();
delay(500);
mfrc522.PCD_Init();
delay(500);
blockoff = blockoff + 1;
if(blockoff > 2) {
blockoff = 0;
sector = sector + 1;
if(sector > 15) sector = 1;
}
blockAddr = sector*4 + blockoff;
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent()) return;
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial()) return;
trailerBlock = sector * 4 + 3;
mfrc522.PICC_DumpMifareClassicBlockToRead(&(mfrc522.uid), &key, sector, blockAddr, blockdata);
for ( uint8_t i = 0; i < 8; i++) {
a[i] = blockdata[i];
}
for ( uint8_t i = 0; i < 8; i++) {
b[i] = blockdata[i+8];
}
DeKrypto(a,b, 31);
// Test di coerenza di a
boolean valid_flg = true;
// Test sul blocco
if(a[3] != blockAddr){
valid_flg = false;
}
// Confronta a con l'UID
for ( uint8_t i = 0; i < 4; i++) {
if(mfrc522.uid.uidByte[i] != a[i+4]) valid_flg = false;
}
if(valid_flg) {
// Verifica la tipologia di card
if(b[7] == 255){
// Passepartout Card:
if(prog_flg){
//Appena dopo il reset imposta il codice serratura
EEPROMWrite(b, 7, 8);
EEPROMRead(LockN, 7, 8); // salva il nuovo valore della serratura in LockN[
}
EEPROMCounterReset(); // Azzera il contatore nella EEPROM
RFTransmit(); // Comunque trasmette il codice
}
else if(b[7] == 0){
// User Card: verifica la coerenza di codice di serratura
if(CompareVector(b, LockN, 0, 7)){
for(byte i=0;i<4;++i){
a[i+4] = LockN[i];
}
RFTransmit();
}
}
prog_flg = false;
}
else {
digitalWrite(Led_Rosso, LOW);
delay(1000);
digitalWrite(Led_Rosso, HIGH);
}
// Halt PICC
mfrc522.PICC_HaltA();
// Stop encryption on PCD
mfrc522.PCD_StopCrypto1();
}
boolean CompareVector(byte *x, byte *z, byte inz, byte dv) {
byte j;
boolean flg = true;
for (j = inz; j if(x[j] != z[j]) flg = false;
}
return flg;
}
void VectorValue(char* code, byte *x) {
byte j=0;
for(byte i=0; i<8; i=i+2) {
x[j] = HextoDec(code[i], code[i+1]);
j=j+1;
}
}
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;
}

/*-----( Funzioni di Cifratura )-----*/

void 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);
}
}

void 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);
}

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 UnoNB(byte x[8], byte y[8]) {
byte u = 0;
for (byte i = 0; i<8; i++) {
for (byte j = 0; j < 8; j++) {
if(bitRead(x[i], j) == 1) u = u + 1;
if(bitRead(y[i], j) == 1) u = u + 1;
}
}
return u;
}

void Swap(byte x[8], byte z[8]) {
byte j;
for (j = 0; j<8; j++) {
z[j] = (x[j] << 4) | (x[j] >> 4);
}
}

void RFTransmit() {
digitalWrite(Led_Verde, LOW);
byte unocnt;
EEPROMRead(a, 4, 0);
Sum(a, icnt, a); // Incremento
EEPROMWrite(a, 4, 0);
VectorPrint(a, 8);
VectorPrint(b, 8);
Serial.println();
Krypto(a, b, 33);
unocnt = UnoNB(a, b);
digitalWrite(Supply_pin, HIGH); // Abilitazione trasmissione
for (byte k = 0; k < 10; k++) {
digitalWrite(Tx_pin, UNO); // Start bit
delayMicroseconds(1200);
for (byte i = 0; i < 8; i++) {
ByteTx(a[i]);
}
for (byte i = 0; i < 8; i++) {
ByteTx(b[i]);
}
ByteTx(unocnt); // Invio di un byte di controllo (numero di uno)
}
digitalWrite(Supply_pin, LOW); // Disabilitazione trasmissione
delay(1000);
digitalWrite(Led_Verde, HIGH);
}

void ByteTx(byte xc){
for (byte i = 0; i < 8; i++) {
digitalWrite(Tx_pin, ZERO); // ith bit
if(bitRead(xc, 7-i) == 1){
delayMicroseconds(600); // bit a 1
}
else {
delayMicroseconds(300); // bit a 0
}
digitalWrite(Tx_pin, UNO); // end bit
delayMicroseconds(300); // durata end bit
}
}

void CopyVector(byte *src, byte *dst, byte inz, byte dv) {
for (byte j = inz; j dst[j] = src[j];
}
}

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);
}
void VectorPrint(byte *x, byte dv) {
char ch[2];
for (byte i = 0; i < dv; i++) {
DectoHex(x[i], ch);
Serial.print(ch[0]);
Serial.print(ch[1]);
}
}

/////////////////////////////////////// Gestione Contatore su EEPROM 00-03 //////////////////////////////

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 EEPROMCounterReset(){
for ( int i = 0; i < 4; i++) { // Azzera il contatore nella EEPROM
EEPROM.write(i, 0);
}
}