Implement an extra layer of encryption, but it's untested.

This commit is contained in:
Starbeamrainbowlabs 2019-07-15 13:49:44 +01:00
parent 0604062966
commit 723941bdf8
7 changed files with 45 additions and 6 deletions

View file

@ -20,8 +20,14 @@ Run `bash ./build setup` from the command line at the root of this repository.
### IoT Device ### IoT Device
- Copy `settings.custom.cpp.example` to `settings.custom.cpp` and fill in the fields there - Copy `settings.custom.cpp.example` to `settings.custom.cpp` and fill in the fields there
- This Bash one-liner can be used to generate a new encryption key in the right formats: `head -c16 /dev/urandom | od -tx1 | awk '{ gsub(/^0+\s+/, "", $0); toml=$0; gsub(/\s+/, "", toml); print("settings.toml format: " toml); arduino=toupper($0); gsub(/\s+/, ", 0x", arduino); print("settings.custom.cpp format: 0x" arduino); exit }'`
- Review `settings.h` to make sure it matches your setup - Review `settings.h` to make sure it matches your setup
- Copy the folders in `iot/libraries` to your Arduino IDE libraries folder - Copy the folders in `iot/libraries` to your Arduino IDE libraries folder
### Server
- The `bash ./build setup` should have already installed the necessary dependencies.
- Create `settings.toml` in the root of the repository if it doesn't exist already.
- Review `server/settings.default.toml` and adjust `settings.toml` to fill in the values for the required fields, not forgetting the encryption key generated when setting up the IoT device.
## Useful Links ## Useful Links
- Entropy extraction from the watchdog timer vs the internal clock: https://github.com/taoyuan/Entropy - Entropy extraction from the watchdog timer vs the internal clock: https://github.com/taoyuan/Entropy

View file

@ -8,19 +8,24 @@
// LoRaWAN NwkSKey, network session key // LoRaWAN NwkSKey, network session key
// This is the default Semtech key, which is used by the early prototype TTN // This is the default Semtech key, which is used by the early prototype TTN
// network. // network.
static const PROGMEM u1_t NWKSKEY[16] = { .... }; const PROGMEM u1_t NWKSKEY[16] = { .... };
// LoRaWAN AppSKey, application session key // LoRaWAN AppSKey, application session key
// This is the default Semtech key, which is used by the early prototype TTN // This is the default Semtech key, which is used by the early prototype TTN
// network. // network.
static const u1_t PROGMEM APPSKEY[16] = { ..... }; const u1_t PROGMEM APPSKEY[16] = { ..... };
// LoRaWAN end-device address (DevAddr) // LoRaWAN end-device address (DevAddr)
static const u4_t DEVADDR = 0x....; // <-- Change this address for every node! const u4_t DEVADDR = 0x....; // <-- Change this address for every node!
// The RFM95 pin mapping
const lmic_pinmap lmic_pins = { const lmic_pinmap lmic_pins = {
.nss = PIN_SPI_CS_RFM95, .nss = PIN_SPI_CS_RFM95,
.rxtx = LMIC_UNUSED_PIN, .rxtx = LMIC_UNUSED_PIN,
.rst = 9, .rst = 9,
.dio = {2, 6, 7}, .dio = {2, 6, 7},
}; };
// The AES-ECB 128-bit key to encrypt the data with.
// See the README for a Bash oneliner that generates a new key in the right format.
uint8_t encrypt_key[16] = { ..... };

View file

@ -7,8 +7,15 @@
* it settings.cpp, and edit that instead. * it settings.cpp, and edit that instead.
*/ */
// The network session key. From The Things Network console
extern const PROGMEM u1_t NWKSKEY[16]; extern const PROGMEM u1_t NWKSKEY[16];
// The application session key from The Things Network console
extern const u1_t PROGMEM APPSKEY[16]; extern const u1_t PROGMEM APPSKEY[16];
// The device address
extern const u4_t DEVADDR; extern const u4_t DEVADDR;
// The pin mapping for the RFM95
extern const lmic_pinmap lmic_pins; extern const lmic_pinmap lmic_pins;
// The key to encrypt the data with
extern uint8_t encrypt_key[16];

View file

@ -8,6 +8,9 @@
// Global static variable that's used to detect when LMIC has finished doing it's thing // Global static variable that's used to detect when LMIC has finished doing it's thing
bool is_sending_complete = false; bool is_sending_complete = false;
// Defined as part of LMIC, but LMIC is compiled and linked in separately
extern "C" void lmic_aes_encrypt(unsigned char *Data, unsigned char *Key);
void transmit_counter_save() { void transmit_counter_save() {
store_eeprom_uint32_save(0, LMIC.seqnoUp); store_eeprom_uint32_save(0, LMIC.seqnoUp);
@ -82,6 +85,9 @@ void transmit_init() {
* @param length The length of the given message. * @param length The length of the given message.
*/ */
bool transmit_send(uint8_t* data, int length) { bool transmit_send(uint8_t* data, int length) {
// Encrypt the data with the extra encryption key
lmic_aes_encrypt(data, encrypt_key);
// Check if there is not a current TX/RX job running // Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) { if (LMIC.opmode & OP_TXRXPEND) {
// Serial.println(F("OP_TXRXPEND: Job running, can't send")); // Serial.println(F("OP_TXRXPEND: Job running, can't send"));

View file

@ -40,6 +40,10 @@ app_id = "CHANGE_THIS"
# there. # there.
access_key = "CHANGE_THIS" access_key = "CHANGE_THIS"
# The additional encryption key, in hex, generated when setting up the IoT device.
# This is used as an exrtra layer of encryption to ensure that The Things Network does not have access to the decrypted data.
encryption_key = "CHANGE_THIS"
# A list of devices to monitor. # A list of devices to monitor.
# If a device isn't specified here, then we won't hear messages from it. # If a device isn't specified here, then we won't hear messages from it.
# FUTURE: Automatically fetch a list of devices from the TTN API # FUTURE: Automatically fetch a list of devices from the TTN API

View file

@ -1,11 +1,17 @@
"use strict"; "use strict";
import aes from 'aes-js';
const offset_id = 0; const offset_id = 0;
const offset_lat = 32 / 8; const offset_lat = 32 / 8;
const offset_lng = (32 / 8) + (32 / 8); const offset_lng = (32 / 8) + (32 / 8);
function decode_payload(payload_base64) { function decode_payload(payload_base64, key_hex) {
let payload_buffer = Buffer.from(payload_base64, "base64"); let payload_buffer_enc = Buffer.from(payload_base64, "base64");
let key_buffer = Buffer.from(key_hex, "hex");
let aes_ecb = new aes.ModeOfOperation.ecb(key_buffer);
let payload_buffer = aes_ecb.decrypt(payload_buffer_enc);
// console.debug(`Offsets: ${offset_id}, ${offset_lat}, ${offset_lng}`); // console.debug(`Offsets: ${offset_id}, ${offset_lat}, ${offset_lng}`);
// console.debug(`Message hex: ${payload_buffer.toString("hex")}`) // console.debug(`Message hex: ${payload_buffer.toString("hex")}`)

View file

@ -16,7 +16,12 @@ class MessageHandler {
async handle(message) { async handle(message) {
if(this.debug) console.log(message); if(this.debug) console.log(message);
let decoded_payload = decode_payload(message.payload_raw); if(this.settings.ttn.encryption_key == "CHANGE_THIS") {
this.log.error(`Error: No encryption key specified. Try filling in the required values in settings.toml. If they don't exist yet, try using server/settings.default.toml as a reference.`);
return false;
}
let decoded_payload = decode_payload(message.payload_raw, this.settings.ttn.encryption_key);
if(this.debug) console.log(decoded_payload); if(this.debug) console.log(decoded_payload);
let rssis = []; let rssis = [];