diff --git a/MySensors.h b/MySensors.h index cbeee90..8824e8d 100644 --- a/MySensors.h +++ b/MySensors.h @@ -131,6 +131,9 @@ #if defined(MY_SIGNING_ATSHA204) && defined(MY_SIGNING_SOFT) #error Only one signing engine can be activated #endif + #if defined(MY_SIGNING_ATSHA204) && defined(__linux__) + #error No support for ATSHA204 on this platform + #endif #if defined(MY_SIGNING_ATSHA204) #include "core/MySigningAtsha204.cpp" diff --git a/core/MyMainLinux.cpp b/core/MyMainLinux.cpp index 12687e8..50c5325 100644 --- a/core/MyMainLinux.cpp +++ b/core/MyMainLinux.cpp @@ -26,6 +26,7 @@ #include #include #include +#include #include "log.h" #include "MySensorsCore.h" @@ -101,20 +102,247 @@ void print_usage() { printf("Usage: mysGateway [options]\n\n" \ "Options:\n" \ - " -h Display a short summary of all program options.\n" \ - " -d Enable debug.\n" \ - " -b Become a daemon.\n"); + " -h, --help Display a short summary of all program options.\n" \ + " -d, --debug Enable debug.\n" \ + " -b, --background Run as a background process.\n" + " --gen-soft-hmac-key Generate and print a soft hmac key.\n" + " --gen-soft-serial-key Generate and print a soft serial key.\n" + " --gen-aes-key Generate and print an aes encryption key.\n" + " --print-soft-hmac-key Print the soft hmac key from the config file.\n" + " --print-soft-serial-key Print the soft serial key from the config file.\n" + " --print-aes-key Print the aes encryption key from the config file.\n" + " --set-soft-hmac-key Write a soft hmac key to the config file.\n" + " --set-soft-serial-key Write a soft serial key to the config file.\n" + " --set-aes-key Write an aes encryption key to the config file.\n"); +} + +void print_soft_sign_hmac_key() +{ + uint8_t key[32]; + + hwReadConfigBlock(&key, reinterpret_castEEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); + + printf("SOFT_HMAC_KEY | "); + for (int i = 0; i < 32; i++) { + printf("%02X", key[i]); + } + printf("\n"); + + printf("The next line is intended to be used in SecurityPersonalizer.ino:\n"); + printf("#define MY_SOFT_HMAC_KEY "); + for (int i=0; i<32; i++) { + printf("%#02X", key[i]); + if (i < 31) printf(","); + } + printf("\n"); +} + +void generate_soft_sign_hmac_key() +{ + uint8_t key[32]; + + for (int i = 0; i < 32; i++) { + key[i] = random(256) ^ micros(); + unsigned long enter = hwMillis(); + while (hwMillis() - enter < (unsigned long)2); + } + + printf("SOFT_HMAC_KEY | "); + for (int i = 0; i < 32; i++) { + printf("%02X", key[i]); + } + printf("\n"); +} + +void set_soft_sign_hmac_key(char *key_str) +{ + uint8_t key[32]; + int n; + + if (strlen(key_str) != 64) { + printf("invalid key!\n"); + } else { + for (int i = 0; i < 64; ++i) { + char c = key_str[i]; + if (c <= '9') + n = c - '0'; + else if (c >= 'a') + n = c - 'a' + 10; + else + n = c - 'A' + 10; + + if ((i & 0x1) == 0) { + key[i/2] = n * 16; + } else { + key[i/2] += n; + } + } + hwWriteConfigBlock(&key, reinterpret_castEEPROM_SIGNING_SOFT_HMAC_KEY_ADDRESS, 32); + print_soft_sign_hmac_key(); + } +} + +void print_soft_sign_serial_key() +{ + uint8_t key[9]; + + hwReadConfigBlock(&key, reinterpret_castEEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); + + printf("SOFT_SERIAL | "); + for (int i = 0; i < 9; i++) { + printf("%02X", key[i]); + } + printf("\n"); + + printf("The next line is intended to be used in SecurityPersonalizer.ino:\n"); + printf("#define MY_SOFT_SERIAL "); + for (int i=0; i<9; i++) { + printf("%#02X", key[i]); + if (i < 8) printf(","); + } + printf("\n"); +} + +void generate_soft_sign_serial_key() +{ + uint8_t key[9]; + + for (int i = 0; i < 9; i++) { + key[i] = random(256) ^ micros(); + unsigned long enter = hwMillis(); + while (hwMillis() - enter < (unsigned long)2); + } + + printf("SOFT_SERIAL | "); + for (int i = 0; i < 9; i++) { + printf("%02X", key[i]); + } + printf("\n"); +} + +void set_soft_sign_serial_key(char *key_str) +{ + uint8_t key[9]; + int n; + + if (strlen(key_str) != 18) { + printf("invalid key!\n"); + } else { + for (int i = 0; i < 18; ++i) { + char c = key_str[i]; + if (c <= '9') + n = c - '0'; + else if (c >= 'a') + n = c - 'a' + 10; + else + n = c - 'A' + 10; + + if ((i & 0x1) == 0) { + key[i/2] = n * 16; + } else { + key[i/2] += n; + } + } + hwWriteConfigBlock(&key, reinterpret_castEEPROM_SIGNING_SOFT_SERIAL_ADDRESS, 9); + print_soft_sign_serial_key(); + } +} + +void print_aes_key() +{ + uint8_t key[16]; + + hwReadConfigBlock(&key, reinterpret_castEEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); + + printf("AES_KEY | "); + for (int i = 0; i < 16; i++) { + printf("%02X", key[i]); + } + printf("\n"); + + printf("The next line is intended to be used in SecurityPersonalizer.ino:\n"); + printf("#define MY_AES_KEY "); + for (int i=0; i<16; i++) { + printf("%#02X", key[i]); + if (i < 15) printf(","); + } + printf("\n"); +} + +void generate_aes_key() +{ + uint8_t key[16]; + + for (int i = 0; i < 16; i++) { + key[i] = random(256) ^ micros(); + unsigned long enter = hwMillis(); + while (hwMillis() - enter < (unsigned long)2); + } + + printf("AES_KEY | "); + for (int i = 0; i < 16; i++) { + printf("%02X", key[i]); + } + printf("\n"); +} + +void set_aes_key(char *key_str) +{ + uint8_t key[16]; + int n; + + if (strlen(key_str) != 32) { + printf("invalid key!\n"); + } else { + for (int i = 0; i < 32; ++i) { + char c = key_str[i]; + if (c <= '9') + n = c - '0'; + else if (c >= 'a') + n = c - 'a' + 10; + else + n = c - 'A' + 10; + + if ((i & 0x1) == 0) { + key[i/2] = n * 16; + } else { + key[i/2] += n; + } + } + hwWriteConfigBlock(&key, reinterpret_castEEPROM_RF_ENCRYPTION_AES_KEY_ADDRESS, 16); + print_aes_key(); + } } int main(int argc, char *argv[]) { int opt, log_opts, debug = 0, foreground = 1; + char *key = NULL; /* register the signal handler */ signal(SIGINT, handle_sigint); signal(SIGTERM, handle_sigint); - while ((opt = getopt(argc, argv, "hdb")) != -1) { + hwRandomNumberInit(); + + static struct option long_options[] = { + {"help", no_argument, 0, 'h'}, + {"debug", no_argument, 0, 'd'}, + {"background", no_argument, 0, 'b'}, + {"gen-soft-hmac-key", no_argument, 0, 'A'}, + {"gen-soft-serial-key", no_argument, 0, 'B'}, + {"gen-aes-key", no_argument, 0, 'C'}, + {"print-soft-hmac-key", no_argument, 0, 'D'}, + {"print-soft-serial-key", no_argument, 0, 'E'}, + {"print-aes-key", no_argument, 0, 'F'}, + {"set-soft-hmac-key", required_argument, 0, 'G'}, + {"set-soft-serial-key", required_argument, 0, 'H'}, + {"set-aes-key", required_argument, 0, 'I'}, + {0, 0, 0, 0} + }; + + int long_index = 0; + while ((opt = getopt_long(argc, argv,"hdbABCDEFGHI", long_options, &long_index )) != -1) { switch (opt) { case 'h': print_usage(); @@ -125,6 +353,36 @@ int main(int argc, char *argv[]) case 'b': foreground = 0; break; + case 'A': + generate_soft_sign_hmac_key(); + exit(0); + case 'B': + generate_soft_sign_serial_key(); + exit(0); + case 'C': + generate_aes_key(); + exit(0); + case 'D': + print_soft_sign_hmac_key(); + exit(0); + case 'E': + print_soft_sign_serial_key(); + exit(0); + case 'F': + print_aes_key(); + exit(0); + case 'G': + key = strdup(optarg); + set_soft_sign_hmac_key(key); + exit(0); + case 'H': + key = strdup(optarg); + set_soft_sign_serial_key(key); + exit(0); + case 'I': + key = strdup(optarg); + set_aes_key(key); + exit(0); default: print_usage(); exit(0); diff --git a/core/MySensorsCore.cpp b/core/MySensorsCore.cpp index 11eadad..8586b2a 100644 --- a/core/MySensorsCore.cpp +++ b/core/MySensorsCore.cpp @@ -19,6 +19,11 @@ #include "MySensorsCore.h" +#if defined(__linux__) + #include + #include +#endif + ControllerConfig _cc; // Configuration coming from controller NodeConfig _nc; // Essential settings for node to work MyMessage _msg; // Buffer for incoming messages diff --git a/core/MySigningAtsha204Soft.cpp b/core/MySigningAtsha204Soft.cpp index 3c0b4b5..cec7ad6 100644 --- a/core/MySigningAtsha204Soft.cpp +++ b/core/MySigningAtsha204Soft.cpp @@ -64,6 +64,23 @@ static char i2h(uint8_t i) } } +#ifdef __linux__ +static void DEBUG_SIGNING_PRINTBUF(const char *str, uint8_t* buf, uint8_t sz) { + static char printBuffer[300]; + + for (int i=0; i> 4); + printBuffer[(i * 2) + 1] = i2h(buf[i]); + } + printBuffer[sz * 2] = '\0'; + debug(str); + if (sz > 0) + { + debug(printBuffer); + } +} +#else static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, uint8_t sz) { static char printBuffer[300]; #ifdef MY_GATEWAY_FEATURE @@ -88,6 +105,7 @@ static void DEBUG_SIGNING_PRINTBUF(const __FlashStringHelper* str, uint8_t* buf, } MY_SERIALDEVICE.println(""); } +#endif /* __linux__ */ #else #define DEBUG_SIGNING_PRINTBUF(str, buf, sz) #endif diff --git a/drivers/Linux/Arduino.h b/drivers/Linux/Arduino.h index cb0cb72..eaa4ed9 100644 --- a/drivers/Linux/Arduino.h +++ b/drivers/Linux/Arduino.h @@ -71,6 +71,7 @@ typedef string String; void yield(void); unsigned long millis(void); +unsigned long micros(void); void _delay_ms(unsigned int millis); void randomSeed(unsigned long seed); long randMax(long howbig); diff --git a/drivers/Linux/compatibility.cpp b/drivers/Linux/compatibility.cpp index b0ceee1..a19ce54 100644 --- a/drivers/Linux/compatibility.cpp +++ b/drivers/Linux/compatibility.cpp @@ -21,6 +21,19 @@ unsigned long millis(void) return ((curTime.tv_sec - millis_at_start) * 1000) + (curTime.tv_usec / 1000); } +unsigned long micros() +{ + timeval curTime; + + if (millis_at_start == 0) { + gettimeofday(&curTime, NULL); + millis_at_start = curTime.tv_sec; + } + + gettimeofday(&curTime, NULL); + return ((curTime.tv_sec - millis_at_start) * 1000000) + (curTime.tv_usec); +} + void _delay_ms(unsigned int millis) { struct timespec sleeper; diff --git a/examples_linux/mysGateway.cpp b/examples_linux/mysGateway.cpp index c0c69c2..c94d482 100644 --- a/examples_linux/mysGateway.cpp +++ b/examples_linux/mysGateway.cpp @@ -57,6 +57,16 @@ // Inverse the blinking feature //#define MY_WITH_LEDS_BLINKING_INVERSE +// Enable software signing +//#define MY_SIGNING_SOFT +// Enable signing related debug +//#define MY_DEBUG_VERBOSE_SIGNING +// Enable this to request signatures from nodes that in turn request signatures from gateway +//#define MY_SIGNING_REQUEST_SIGNATURES +// Enable this to have gateway require all nodes in the network to sign messages sent to it +// Note: MY_SIGNING_REQUEST_SIGNATURES must also be set +//#define MY_SIGNING_GW_REQUEST_SIGNATURES_FROM_ALL + #include void setup() {