From 0833327cea62366b31b7ce964583504c5cf9e64b Mon Sep 17 00:00:00 2001 From: eddy Date: Wed, 29 Jul 2026 23:51:16 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20code=20review=20fixes=20=E2=80=94=20Shar?= =?UTF-8?q?edPreferences=20docs,=20Log.e,=20dead=20notify=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 12 ++++++------ .../main/java/nl/eddydevink/sylda/BleRelayManager.kt | 9 +-------- .../java/nl/eddydevink/sylda/SettingsActivity.kt | 1 + src/main.cpp | 3 +-- 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 5ef0145..f9b485c 100644 --- a/README.md +++ b/README.md @@ -61,13 +61,13 @@ Offset Grootte Veld Beschrijving 5 32 bytes hmac HMAC-SHA256(key, command || sequence) ``` -De sequence counter reset naar 0 bij elke (re)connectie op de module. De app start bij 1 om te zorgen dat het eerste packet altijd geaccepteerd wordt (`1 > 0`). Replay van een eerder packet wordt geweerd omdat `seq <= lastSeq`. De sequence counter wordt gepersisteerd in EncryptedSharedPreferences en overleeft app-herstarts — bij een Activity-restart met actieve BLE-verbinding blijft de counter oplopen in plaats van terug te vallen naar 1. +De sequence counter reset naar 0 bij elke (re)connectie op de module. De app start bij 1 om te zorgen dat het eerste packet altijd geaccepteerd wordt (`1 > 0`). Replay van een eerder packet wordt geweerd omdat `seq <= lastSeq`. De sequence counter wordt gepersisteerd in SharedPreferences en overleeft app-herstarts — bij een Activity-restart met actieve BLE-verbinding blijft de counter oplopen in plaats van terug te vallen naar 1. #### Key management - De HMAC key wordt **niet meegecompileerd** — de module start zonder key en wordt geprovisioneerd via USB - De key wordt opgeslagen in **NVS** (Non-Volatile Storage) op de module via de Arduino `Preferences` library (namespace `hmac`, key `key`, partitie op 0x9000-0xDFFF) -- De app slaat de key op in **EncryptedSharedPreferences** (AES256-GCM versleuteld, overleeft app-herstarts) +- De app slaat de key op in **SharedPreferences** (overleeft app-herstarts) - **USB provisioning:** Open Instellingen → Firmware bijwerken. De app checkt eerst de firmware versie (`VERSION?`) en flasht indien nodig. Na het flashen (of als versie al actueel is) volgt automatisch de key exchange: - Als de module al een key heeft → module antwoordt `HMAC_KEY:` → app slaat op lokaal op - Als de module nog geen key heeft → module antwoordt `NO_KEY` → app genereert willekeurige 32-byte key via `SecureRandom` → stuurt `SET_KEY:\n` en `SET_ID:\n` → module slaat op in NVS → app slaat op lokaal op @@ -115,7 +115,7 @@ module → App: OK\n (bevestiging) | **Commando vervalsing** | HMAC dekt command byte + sequence — wijzigen maakt handtekening ongeldig | | **Brute-force key** | 32-byte key = 2^256 mogelijkheden — onhaalbaar | | **Sniffen** | Pakketten zijn onversleuteld; geen confidentiality. Alleen commando's (aan/uit) zijn zichtbaar, niet de key. | -| **Reverse engineering van key** | Sleutel staat niet in de APK — wordt pas bij USB provisioning gegenereerd en in EncryptedSharedPreferences (AES256-GCM) opgeslagen. Extractie vereist fysieke toegang tot de telefoon én root. | +| **Reverse engineering van key** | Sleutel staat niet in de APK — wordt pas bij USB provisioning gegenereerd en in SharedPreferences opgeslagen. Extractie vereist fysieke toegang tot de telefoon. | | **Key extractie via USB** | Fysieke USB-toegang tot de module geeft `KEY?\n` de huidige key terug. Bescherming: fysieke toegang tot het board beperken. | | **NVS wiping** | `pio run -t erase` wist alle flash waaronder NVS — module is daarna leeg en kan opnieuw geprovisioneerd worden. | @@ -149,7 +149,7 @@ De touch sensoren en BLE werken onafhankelijk. Als de sensor losgelaten wordt en | Relay Characteristic | `beb5483e-36e1-4688-b7f5-ea07361f26d8` | | UUID Characteristic | `beb5483e-36e1-4688-b7f5-ea07361f26d9` | -De relay characteristic ondersteunt `WRITE_NR` (Write Without Response) en `NOTIFY`. De UUID characteristic is read-only en bevat het unieke device-ID van de module. +De relay characteristic ondersteunt `WRITE_NR` (Write Without Response). De UUID characteristic is read-only en bevat het unieke device-ID van de module. ### Key provisioning @@ -251,7 +251,7 @@ De firmware binaries worden via `tools/copy_firmware.sh` naar de app assets geko 3. **Weergave:** Kies Systeem (volgt telefoon), Licht of Donker 4. **Relais labels:** Stel eigen namen in voor de twee relais knoppen -De key wordt opgeslagen in EncryptedSharedPreferences (AES256-GCM versleuteld) en overleeft app-herstarts. Bij geen key toont de hoofdapp "Geen sleutel — open Instellingen" en wordt er niet gescant. +De key wordt opgeslagen in SharedPreferences en overleeft app-herstarts. Bij geen key toont de hoofdapp "Geen sleutel — open Instellingen" en wordt er niet gescant. ### Hoofdscherm UI @@ -385,7 +385,7 @@ De app gebruikt `Theme.AppCompat.DayNight` in plaats van het eerder geforceerde - De app gebruikt raw Android USB API (`UsbDeviceConnection.bulkTransfer`) in plaats van een externe serial library. - `minSdk` is 26 (Android 8.0). - ProgressDialog is vervangen door eigen `AlertDialog` layouts (`dialog_waiting.xml`, `dialog_progress.xml`). -- De HMAC key in de app is opgeslagen via `EncryptedSharedPreferences` (AES256-GCM). +- De HMAC key in de app is opgeslagen via `SharedPreferences`. - De app gebruikt `Theme.AppCompat.DayNight` met Systeem/Licht/Donker thema-selector. - `compileSdk`/`targetSdk` blijft op 34 (Android 14) voor maximale compatibiliteit met de doelgroep. diff --git a/android/app/src/main/java/nl/eddydevink/sylda/BleRelayManager.kt b/android/app/src/main/java/nl/eddydevink/sylda/BleRelayManager.kt index 0f137f9..1cc0195 100644 --- a/android/app/src/main/java/nl/eddydevink/sylda/BleRelayManager.kt +++ b/android/app/src/main/java/nl/eddydevink/sylda/BleRelayManager.kt @@ -6,7 +6,6 @@ import android.annotation.SuppressLint import android.bluetooth.BluetoothAdapter import android.bluetooth.BluetoothGatt import android.bluetooth.BluetoothGattCharacteristic -import android.bluetooth.BluetoothGattDescriptor import android.bluetooth.BluetoothProfile import android.bluetooth.le.ScanCallback import android.bluetooth.le.ScanFilter @@ -34,7 +33,7 @@ class BleRelayManager( private val SERVICE_UUID: UUID = UUID.fromString("4fafc201-1fb5-459e-8fcc-c5c9c331914b") private val CHARACTERISTIC_UUID: UUID = UUID.fromString("beb5483e-36e1-4688-b7f5-ea07361f26d8") private val UUID_CHAR_UUID: UUID = UUID.fromString("beb5483e-36e1-4688-b7f5-ea07361f26d9") - private val CCCD_UUID: UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb") + private const val SCAN_TIMEOUT_MS = 30000L private const val RECONNECT_DELAY_MS = 2000L private const val MAX_SCAN_RETRIES = 3 @@ -251,12 +250,6 @@ class BleRelayManager( val storedUuid = deviceUuid if (storedUuid != null && value.contentEquals(storedUuid)) { Log.d(TAG, "UUID verified, setting up relay") - relayCharacteristic?.let { rc -> - gatt.setCharacteristicNotification(rc, true) - val descriptor = rc.getDescriptor(CCCD_UUID) - descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE - gatt.writeDescriptor(descriptor) - } handler.post { callbacks.onStatusChanged(BleStatus.Connected) } } else { Log.w(TAG, "UUID mismatch -- disconnecting") diff --git a/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt b/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt index a860c32..6037d5f 100644 --- a/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt +++ b/android/app/src/main/java/nl/eddydevink/sylda/SettingsActivity.kt @@ -376,6 +376,7 @@ class SettingsActivity : AppCompatActivity() { cleanupAction() throw e } catch (e: Exception) { + Log.e(TAG, "Flash inner error", e) progressDialog?.dismiss() progressDialog = null Toast.makeText(this@SettingsActivity, getString(R.string.flash_failed, e.message), Toast.LENGTH_LONG).show() diff --git a/src/main.cpp b/src/main.cpp index e674ecb..280da7b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -192,10 +192,9 @@ void setup() { NimBLEService *pService = pServer->createService(SERVICE_UUID); pCharacteristic = pService->createCharacteristic( CHARACTERISTIC_UUID, - NIMBLE_PROPERTY::WRITE_NR | NIMBLE_PROPERTY::NOTIFY + NIMBLE_PROPERTY::WRITE_NR ); pCharacteristic->setCallbacks(new MyCharacteristicCallbacks()); - pCharacteristic->setValue("0"); NimBLECharacteristic *pUuidChar = pService->createCharacteristic( UUID_CHAR_UUID,