summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSergiusz 'q3k' Bazański <q3k@q3k.org>2015-03-05 00:44:42 +0100
committerSergiusz 'q3k' Bazański <q3k@q3k.org>2015-03-05 00:44:42 +0100
commit180220f19bc951f9cd6b2c4280321e2ede52a661 (patch)
tree29cebafb1c145a9fc3c9bf7ec0139fac32c8b1a2
parentfbca8b027a3d2fe9440ae5ae6cf97a7a606e3afe (diff)
downloaddoorman-180220f19bc951f9cd6b2c4280321e2ede52a661.tar.gz
doorman-180220f19bc951f9cd6b2c4280321e2ede52a661.tar.bz2
doorman-180220f19bc951f9cd6b2c4280321e2ede52a661.zip
Add MAC'd PC comms
-rw-r--r--arduino/src/.pc.cpp.swpbin0 -> 16384 bytes
-rw-r--r--arduino/src/config.h7
-rw-r--r--arduino/src/doorman.ino5
-rw-r--r--arduino/src/emem.cpp8
-rw-r--r--arduino/src/pc.cpp158
5 files changed, 119 insertions, 59 deletions
diff --git a/arduino/src/.pc.cpp.swp b/arduino/src/.pc.cpp.swp
new file mode 100644
index 0000000..2c4fdeb
--- /dev/null
+++ b/arduino/src/.pc.cpp.swp
Binary files 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<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