From 180220f19bc951f9cd6b2c4280321e2ede52a661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergiusz=20=27q3k=27=20Baza=C5=84ski?= Date: Thu, 5 Mar 2015 00:44:42 +0100 Subject: Add MAC'd PC comms --- arduino/src/.pc.cpp.swp | Bin 0 -> 16384 bytes arduino/src/config.h | 7 ++- arduino/src/doorman.ino | 5 +- arduino/src/emem.cpp | 8 +-- arduino/src/pc.cpp | 158 ++++++++++++++++++++++++++++++++---------------- 5 files changed, 119 insertions(+), 59 deletions(-) create mode 100644 arduino/src/.pc.cpp.swp diff --git a/arduino/src/.pc.cpp.swp b/arduino/src/.pc.cpp.swp new file mode 100644 index 0000000..2c4fdeb Binary files /dev/null and b/arduino/src/.pc.cpp.swp differ 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 #include +#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: + * $,,,,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>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 -- cgit v1.2.3