Replace compile-time HMAC key with USB provisioning
ESP firmware: - Store HMAC key in NVS via Preferences library instead of compile-time hmac_key.h - KEY? responds with HMAC_KEY:<hex> (if provisioned) or NO_KEY - New SET_KEY:<64-hex> command stores key in NVS and responds OK - Boot messages updated to reflect provisioning state Android app: - UsbKeyReceiver detects NO_KEY response and auto-provisions: generates random 32-byte key via SecureRandom, sends SET_KEY, waits for OK, saves key to SharedPreferences - Read loop now breaks on both HMAC_KEY: and NO_KEY responses Cleanup: - Removed tools/generate_hmac_key.py and src/hmac_key.h - Removed hmac_key.h from .gitignore - README updated for new provisioning flow
This commit is contained in:
parent
c707c21d7f
commit
9a84b05b8a
5 changed files with 155 additions and 116 deletions
78
src/main.cpp
78
src/main.cpp
|
|
@ -5,7 +5,7 @@
|
|||
#include <BLE2902.h>
|
||||
#include <BLESecurity.h>
|
||||
#include <mbedtls/md.h>
|
||||
#include "hmac_key.h"
|
||||
#include <Preferences.h>
|
||||
|
||||
#define SENSOR_PIN 38
|
||||
#define RELAY_PIN 1
|
||||
|
|
@ -15,6 +15,9 @@
|
|||
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361f26d8"
|
||||
|
||||
#define HMAC_PKT_SIZE 37 // 1 cmd + 4 seq + 32 hmac
|
||||
#define HMAC_KEY_LEN 32
|
||||
#define NVS_NAMESPACE "hmac"
|
||||
#define NVS_KEY_NAME "key"
|
||||
|
||||
BLECharacteristic *pCharacteristic;
|
||||
bool deviceConnected = false;
|
||||
|
|
@ -22,6 +25,10 @@ bool bleCommand = false;
|
|||
bool relayState = false;
|
||||
uint32_t lastSeq = 0;
|
||||
|
||||
uint8_t hmacKey[HMAC_KEY_LEN];
|
||||
bool keyProvisioned = false;
|
||||
Preferences preferences;
|
||||
|
||||
class MyServerCallbacks : public BLEServerCallbacks {
|
||||
void onConnect(BLEServer *pServer) override {
|
||||
deviceConnected = true;
|
||||
|
|
@ -58,7 +65,7 @@ static bool verifyHmac(const uint8_t *packet) {
|
|||
|
||||
uint8_t computed[32];
|
||||
const mbedtls_md_info_t *mdInfo = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
|
||||
mbedtls_md_hmac(mdInfo, HMAC_KEY, 32, hmacData, 5, computed);
|
||||
mbedtls_md_hmac(mdInfo, hmacKey, HMAC_KEY_LEN, hmacData, 5, computed);
|
||||
|
||||
if (memcmp(computed, packet + 5, 32) != 0) {
|
||||
Serial.println("BLE: HMAC mismatch");
|
||||
|
|
@ -69,6 +76,20 @@ static bool verifyHmac(const uint8_t *packet) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool isHexKey(const String &hex) {
|
||||
for (int i = 0; i < hex.length(); i++) {
|
||||
char c = hex.charAt(i);
|
||||
if (!((c >= '0' && c <= '9') || (c >= 'A' && c <= 'F'))) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void parseHexKey(const String &hex, uint8_t *out) {
|
||||
for (int i = 0; i < HMAC_KEY_LEN; i++) {
|
||||
out[i] = (uint8_t)strtoul(hex.substring(i * 2, i * 2 + 2).c_str(), nullptr, 16);
|
||||
}
|
||||
}
|
||||
|
||||
class MyCharacteristicCallbacks : public BLECharacteristicCallbacks {
|
||||
void onWrite(BLECharacteristic *pChar) override {
|
||||
std::string value = pChar->getValue();
|
||||
|
|
@ -103,6 +124,18 @@ void setup() {
|
|||
delay(500);
|
||||
Serial.println("=== Atom VoiceS3R BLE Relay ===");
|
||||
|
||||
preferences.begin(NVS_NAMESPACE, true);
|
||||
size_t len = preferences.getBytes(NVS_KEY_NAME, hmacKey, HMAC_KEY_LEN);
|
||||
preferences.end();
|
||||
|
||||
if (len == HMAC_KEY_LEN) {
|
||||
keyProvisioned = true;
|
||||
Serial.println("HMAC key loaded from NVS");
|
||||
} else {
|
||||
keyProvisioned = false;
|
||||
Serial.println("No HMAC key provisioned — connect USB and run SET_KEY");
|
||||
}
|
||||
|
||||
pinMode(SENSOR_PIN, INPUT_PULLUP);
|
||||
pinMode(RELAY_PIN, OUTPUT);
|
||||
pinMode(LED_PIN, OUTPUT);
|
||||
|
|
@ -145,14 +178,15 @@ void setup() {
|
|||
|
||||
Serial.println("BLE: advertising started as 'AtomS3R-Relay'");
|
||||
|
||||
Serial.println("Printing HMAC key in 5 seconds...");
|
||||
delay(5000);
|
||||
Serial.print("HMAC Key: ");
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.printf("%02X", HMAC_KEY[i]);
|
||||
if (keyProvisioned) {
|
||||
Serial.print("HMAC Key: ");
|
||||
for (int i = 0; i < HMAC_KEY_LEN; i++) {
|
||||
Serial.printf("%02X", hmacKey[i]);
|
||||
}
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.println("No HMAC key — use USB SET_KEY to provision");
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println("Enter this key in the Android app > Settings.");
|
||||
|
||||
Serial.println("Setup done.");
|
||||
}
|
||||
|
|
@ -165,11 +199,29 @@ void loop() {
|
|||
if (c == '\n') {
|
||||
serialBuf.trim();
|
||||
if (serialBuf == "KEY?") {
|
||||
Serial.print("HMAC_KEY:");
|
||||
for (int i = 0; i < 32; i++) {
|
||||
Serial.printf("%02X", HMAC_KEY[i]);
|
||||
if (keyProvisioned) {
|
||||
Serial.print("HMAC_KEY:");
|
||||
for (int i = 0; i < HMAC_KEY_LEN; i++) {
|
||||
Serial.printf("%02X", hmacKey[i]);
|
||||
}
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.println("NO_KEY");
|
||||
}
|
||||
} else if (serialBuf.startsWith("SET_KEY:")) {
|
||||
String hex = serialBuf.substring(8);
|
||||
hex.toUpperCase();
|
||||
if (hex.length() == 64 && isHexKey(hex)) {
|
||||
parseHexKey(hex, hmacKey);
|
||||
preferences.begin(NVS_NAMESPACE, false);
|
||||
preferences.putBytes(NVS_KEY_NAME, hmacKey, HMAC_KEY_LEN);
|
||||
preferences.end();
|
||||
keyProvisioned = true;
|
||||
Serial.println("OK");
|
||||
Serial.println("HMAC key stored in NVS");
|
||||
} else {
|
||||
Serial.println("ERROR: invalid key format");
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
serialBuf = "";
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue