diff options
author | Sergiusz 'q3k' Bazański <q3k@q3k.org> | 2015-03-05 00:44:42 +0100 |
---|---|---|
committer | Sergiusz 'q3k' Bazański <q3k@q3k.org> | 2015-03-05 00:44:42 +0100 |
commit | 180220f19bc951f9cd6b2c4280321e2ede52a661 (patch) | |
tree | 29cebafb1c145a9fc3c9bf7ec0139fac32c8b1a2 | |
parent | fbca8b027a3d2fe9440ae5ae6cf97a7a606e3afe (diff) | |
download | doorman-180220f19bc951f9cd6b2c4280321e2ede52a661.tar.gz doorman-180220f19bc951f9cd6b2c4280321e2ede52a661.tar.bz2 doorman-180220f19bc951f9cd6b2c4280321e2ede52a661.tar.xz doorman-180220f19bc951f9cd6b2c4280321e2ede52a661.zip |
Add MAC'd PC comms
-rw-r--r-- | arduino/src/.pc.cpp.swp | bin | 0 -> 16384 bytes | |||
-rw-r--r-- | arduino/src/config.h | 7 | ||||
-rw-r--r-- | arduino/src/doorman.ino | 5 | ||||
-rw-r--r-- | arduino/src/emem.cpp | 8 | ||||
-rw-r--r-- | arduino/src/pc.cpp | 158 |
5 files changed, 119 insertions, 59 deletions
diff --git a/arduino/src/.pc.cpp.swp b/arduino/src/.pc.cpp.swp Binary files differnew file mode 100644 index 0000000..2c4fdeb --- /dev/null +++ b/arduino/src/.pc.cpp.swp diff --git a/arduino/src/config.h b/arduino/src/config.h index 126e51f..83597cf 100644 --- a/arduino/src/config.h +++ b/arduino/src/config.h @@ -21,7 +21,12 @@ //#define DEBUG_KEYPAD_SIM 1 /** Max length of message from rfid reader. */ #define RF_MAX_BYTES (16) +/** Length of MAC **/ +#define PC_MAC_SIZE (32) /** Max length of message from or to PC. */ -#define PC_MAX_BYTES (2+1+4+1+EMEM_HASH_SIZE*2+1+8+1) +#define PC_MAX_BYTES (2+1+4+1+EMEM_HASH_SIZE*2+1+PC_MAC_SIZE*2+1) /** Period for quering rfid reader. */ #define RF_PERIOD_MS (500) + +/** PC Communications MAC secret **/ +#define PC_MAC_SECRET ("hackme") diff --git a/arduino/src/doorman.ino b/arduino/src/doorman.ino index 384e936..10fba30 100644 --- a/arduino/src/doorman.ino +++ b/arduino/src/doorman.ino @@ -21,8 +21,9 @@ #include "rf.h" #include "emem.h" -//Global var -unsigned char global_hash[EMEM_HASH_SIZE]; +// Global var +/** Used to pass current command hash **/ +unsigned char g_Hash[EMEM_HASH_SIZE]; /** Door control pin. */ #define DOOR_CTRN (4) diff --git a/arduino/src/emem.cpp b/arduino/src/emem.cpp index 50fa99d..ae9fc83 100644 --- a/arduino/src/emem.cpp +++ b/arduino/src/emem.cpp @@ -4,7 +4,7 @@ #include "config.h" // from doorman.ino -extern unsigned char global_hash[]; +extern unsigned char g_Hash[]; /** * Function reads record with given address from EEPROM. @@ -120,17 +120,17 @@ boolean emem_set_record(unsigned int adr,unsigned char * data) { void emem_print() { unsigned int id; for (int ii=0;ii<EMEM_HASH_SIZE;ii++){ - global_hash[ii] = 0; + g_Hash[ii] = 0; } for (int ii=ENEM_MIN_ADR;ii<=EMEM_MAX_ADR;ii++){ - if (emem_get_record(ii,&id,global_hash)){ + if (emem_get_record(ii,&id,g_Hash)){ Serial.print("REC,"); Serial.print(ii,HEX); Serial.print(','); Serial.print(id,HEX); for (int jj=0;jj<EMEM_HASH_SIZE;jj++){ Serial.print(','); - Serial.print(*(global_hash+jj),HEX); + Serial.print(*(g_Hash+jj),HEX); } Serial.println(); } else { diff --git a/arduino/src/pc.cpp b/arduino/src/pc.cpp index 5c5841c..fb340b4 100644 --- a/arduino/src/pc.cpp +++ b/arduino/src/pc.cpp @@ -1,17 +1,21 @@ #include <Arduino.h> #include <EEPROM.h> +#include "sha256.h" + #include "config.h" #include "pc.h" #include "emem.h" -/** Global vatiable that holds last message from PC. Lenght is plus one for zero termination. */ +/** Global variable that holds last message from PC. Length is plus one for zero termination. */ char pc_bytes[PC_MAX_BYTES+1]; /** Flag set when next scan should send mid. */ boolean pc_send_flag = false; +/** Global varuiable that holds last MAC from PC. Length is 32 bytes, no termination. */ +unsigned char pc_mac[PC_MAC_SIZE]; // from doorman.ino -extern unsigned char global_hash[]; +extern unsigned char g_Hash[]; /** * Function receives bytes from PC and parses them into message. @@ -25,7 +29,7 @@ boolean pc_parse(){ //read the incoming byte: in = Serial.read(); if (in=='$') { - //Start + //Start condition pc_idx=0; pc_bytes[pc_idx]=in; continue; @@ -35,7 +39,7 @@ boolean pc_parse(){ Serial.print("Got newline "); Serial.println(pc_idx); #endif //DEBUG - // what the fuck? + // Did we match the required length? if (pc_idx==PC_MAX_BYTES-2) {; pc_bytes[pc_idx+1]=in; pc_idx=0; @@ -88,41 +92,62 @@ void pc_print(char code,unsigned int id,unsigned char * data) { /** * Handles communication with PC. + * Message structure is: + * $<code>,<id>,<hash/data>,<token>,newline + * eg.: + * $a,0000,dfdd69691a7af8c141cef1ce69b5196b327f71f40b54da3c4e673283dcebd9b7,\ + * e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 + * where code is a command code, hash/data is a 32-byte piece of data in + * lowercase hexdigest, and token is a 32-byte MAC in lowecase hexdigest + * */ void pc_comm(){ if (pc_parse()){ #ifdef DEBUG Serial.print("I received: "); for (int ii=0;ii<PC_MAX_BYTES;ii++) { - Serial.print(pc_bytes[ii], HEX); + Serial.print(pc_bytes[ii]); } #endif //DEBUG pc_bytes[PC_MAX_BYTES]=0; - char code = 0; - unsigned int id = 0; - for (int ii=0;ii<EMEM_HASH_SIZE;ii++){ - global_hash[ii]=0; + // Zero global hash + for (int i = 0; i < EMEM_HASH_SIZE; i++) { + g_Hash[i] = 0; + } + // Zero given MAC + for (int i = 0; i < PC_MAC_SIZE; i++) { + pc_mac[i] = 0; } - unsigned long token = 0; - //$a,0000,dfdd69691a7af8c141cef1ce69b5196b327f71f40b54da3c4e673283dcebd9b7,386855c3 - code=pc_bytes[1]; - char ids[5]; - for (int ii=0;ii<4;ii++){ - ids[ii]=pc_bytes[ii+3]; + // Get code + char code = pc_bytes[1]; + // Get ID + char id_string[5]; + for (int i = 0; i < 4; i++) { + id_string[i] = pc_bytes[3 + i]; } - ids[4]='\0'; - sscanf(ids,"%d",&id); - for (int ii=0;ii<32;ii++){ + id_string[4] = '\0'; + unsigned short id; + sscanf(id_string, "%d", &id); + + // Get hash + for (int i = 0; i < EMEM_HASH_SIZE; i++) { char hex[3]; - hex[0]= pc_bytes[ii*2+8]; - hex[1]= pc_bytes[ii*2+8+1]; - hex[2]= 0; - sscanf(hex,"%02x",global_hash+ii); + hex[0] = pc_bytes[8+i*2]; + hex[1] = pc_bytes[8+i*2+1]; + hex[2] = 0; + sscanf(hex, "%02x", g_Hash + i); } - sscanf(pc_bytes+32*2+8+1,"%8lx",&token); + // Get MAC + for (int i = 0; i < PC_MAC_SIZE; i++) { + char hex[3]; + hex[0] = pc_bytes[73+i*2]; + hex[1] = pc_bytes[73+i*2+1]; + hex[2] = 0; + sscanf(hex, "%02x", pc_mac + i); + } #ifdef DEBUG Serial.print("CODE: "); @@ -130,63 +155,92 @@ void pc_comm(){ Serial.print(", ID: "); Serial.print(id, HEX); Serial.print(", HASH: "); - for (int ii=0; ii<EMEM_HASH_SIZE; ii++){ - Serial.print(global_hash[ii], HEX); + for (int i = 0; i < EMEM_HASH_SIZE; i++) { + Serial.print(g_Hash[i], HEX); Serial.print(','); } Serial.print(" TOKEN: "); - Serial.print(token>>24 & 0x0ff, HEX); - Serial.print(','); - Serial.print(token>>16 & 0x0ff, HEX); - Serial.print(','); - Serial.print(token>>8 & 0x0ff, HEX); - Serial.print(','); - Serial.print(token & 0x0ff, HEX); - Serial.println(); - + for (int i = 0; i < PC_MAC_SIZE; i++) { + Serial.print(pc_mac[i], HEX); + if (i == PC_MAC_SIZE - 1) + Serial.println(""); + else + Serial.print(','); + } + + // Check MAC + pc_bytes[1+1+1+4+1+EMEM_HASH_SIZE*2] = '\0'; +#ifdef DEBUG + Serial.print("MACing "); + Serial.println(pc_bytes); +#endif //DEBUG + Sha256.initHmac((const uint8_t *)PC_MAC_SECRET, strlen(PC_MAC_SECRET)); + Sha256.print(pc_bytes); + uint8_t *expected_mac = Sha256.resultHmac(); + // anti-timing attack - xor all MAC bytes together, or-fold, check if null + uint8_t mac_result = 0; + for (int i = 0; i < PC_MAC_SIZE; i++) { + mac_result |= (pc_mac[i] ^ expected_mac[i]); + } +#ifdef DEBUG + Serial.print("Expected MAC: "); + for (int i = 0; i < PC_MAC_SIZE; i++) { + Serial.print(expected_mac[i], HEX); + Serial.print(','); + } + Serial.println(""); +#endif #endif //DEBUG - if (0){ + if (mac_result != 0){ #ifdef DEBUG Serial.println("WRONG TOKEN"); #endif //DEBUG - pc_print('E', id, global_hash); - } else if (pc_bytes[1]=='A' || pc_bytes[1]=='a'){ + pc_print('E', id, g_Hash); + return; + } + + if (code == 'A' || code == 'a') { //Add - if (id == 0) - { + if (id == 0) { id = emem_find_free(); } - if (emem_find_data(global_hash)!=EMEM_INV_ADR){ + if (emem_find_data(g_Hash) != EMEM_INV_ADR) { //Already have this data #ifdef DEBUG Serial.println("ADD FAILED, USER EXISTS"); #endif - pc_print('E',id,global_hash); - } else if (emem_set_record(id,global_hash)){ + pc_print('E', id, g_Hash); + return; + } + if (emem_set_record(id, g_Hash)) { #ifdef DEBUG Serial.println("ADD DONE"); #endif //DEBUG - pc_print('C',id,global_hash); - } else { + pc_print('C', id, g_Hash); + return; + } + #ifdef DEBUG - Serial.println("ADD FAILED"); + Serial.println("ADD FAILED"); #endif //DEBUG - pc_print('E',id,global_hash); - } - } else if (pc_bytes[1]=='R' || pc_bytes[1]=='r'){ -// //Revoke - if (id==0) id=emem_find_data(global_hash); + pc_print('E', id, g_Hash); + return; + } + + if (pc_bytes[1]=='R' || pc_bytes[1]=='r') { + if (id == 0) + id=emem_find_data(g_Hash); if (emem_del_record(id)){ #ifdef DEBUG Serial.println("REVOKE DONE"); #endif //DEBUG - pc_print('K',id,global_hash); + pc_print('K',id,g_Hash); } else { #ifdef DEBUG Serial.println("REVOKE FAILED"); #endif //DEBUG - pc_print('E',id,global_hash); + pc_print('E',id,g_Hash); } } else if (pc_bytes[1]=='Z' || pc_bytes[1]=='z'){ //Zero eeprom |