Controllo accessi da remoto con protocollo di sicurezza

SOMMARIO

Come sviluppo del progetto Controllo accessi da remoto e quanto discusso nel post Protocollo di sicurezza per RFID Card, si propone di incrementare la sicurezza e la protezione da intrusioni del dispositivo di controllo accessi tramite RFID Card e/o telecomando.

PRINCIPALI MATERIALI UTILIZZATI

MFRC-522 RC522 RFID Modulo IC Card
ATMEGA328-PU MCU 8 bit, 20 MHz, 1kB
RFID Chip con 13,56 MHz Transponder MIFARE Classic (1kbytes)
RFID PVC Card 13,56 MHz Transponder MIFARE Classic (1kbytes)
H34A 433Mhz MINI RF Wireless Transmitter Module ASK 2.6-12V
H3V4F 3V 433Mhz mini ricevitore wireless Supereterodina ASK Remote
PIC16F684-I/P Microchip - MCU 8 Bit, Flash, 20 MHz, 3.5 KB, 256 EEPROM

DISCUSSIONE

Si assume che il Modulo RFID con trasmettitore RF sia quello di Figg.1, 3 e 4 del progetto Controllo accessi da remoto, a cui modificheremo il codice di programmazione. Il Ricevitore sarà invece esattamente quello di Fig.5   dello stesso progetto e, in questo caso, non sarà nemmeno necessario modificarne il codice di programmazione.

MODALITA' D'USO

Utilizzando la stessa password generatrice si programmeranno con il Programmatore, definito nel post Protocollo di sicurezza per RFID Card, una Passepartout Card e almeno una User Card relativa alla stessa Passepartout Card.
Vanno seguite le stessa modalità di programmazione del Ricevitore descritte nel progetto già citato.

PROGRAMMAZIONE

Qui si seguito è listato il codice da caricare nel Modulo RFID.

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