Commit graph

74 commits

Author SHA1 Message Date
eddy
68b15ce7f1 Fix CDC line coding parity byte
Change parity from 0x08 (SPACE) to 0x00 (NONE) to match 115200 8N1
specification. ESP32-S3 ignores this setting but the value was
technically incorrect.

Reviewed in codereview.md (recommendation #4).
2026-07-26 16:23:55 +02:00
eddy
ea0718218c Merge branch 'fix/remove-usb-key-receiver-duplication': remove dead code 2026-07-26 16:21:59 +02:00
eddy
3616f7162f Remove dead UsbKeyReceiver code
UsbKeyReceiver was never registered in AndroidManifest or dynamically,
making it 318 lines of dead code duplicating SettingsActivity key-exchange
logic and UsbUtils USB helpers.

Reviewed in codereview.md (recommendation #3).
2026-07-26 16:19:14 +02:00
eddy
3b5831364d Merge branch 'fix/encrypted-shared-preferences': encrypt HMAC key at rest 2026-07-26 16:09:12 +02:00
eddy
b5d42d53ba Use EncryptedSharedPreferences for HMAC key storage
Replace plain-text SharedPreferences with AES256-GCM encrypted prefs
via androidx.security:security-crypto. Adds PrefsHelper utility to
centralize encrypted prefs access across MainActivity, SettingsActivity
and UsbKeyReceiver.

Reviewed in codereview.md (recommendation #2).
2026-07-26 16:09:10 +02:00
eddy
4a70f94a51 Merge branch 'fix/remove-key-logging': remove HMAC key logging from logcat 2026-07-26 16:04:24 +02:00
eddy
eb337d2157 Remove HMAC key logging from logcat
Replace full key values in Log.d() calls with length-only metadata
to prevent key material leakage via logcat access.

Reviewed in codereview.md (recommendation #1).
2026-07-26 16:03:06 +02:00
eddy
81abf2d824 Replace BLE encryption with HMAC-only auth, add buildnr, fix post-flash flow
BLE bonding/encryption removed — HMAC-SHA256 on application level provides
authentication + replay protection. Eliminates bonding state bugs, write
queue issues, and GATT_INSUFFICIENT_AUTHENTICATION complexity.

Firmware:
- Remove BLESecurity, setRespEncryptionKey, ESP_GATT_PERM_WRITE_ENCRYPTED
- Characteristic permission: ESP_GATT_PERM_WRITE (no encryption required)
- Characteristic property: PROPERTY_WRITE_NR (Write Without Response)
  Enables direct ON/OFF sequences without ACK wait time

Android:
- Remove bondReceiver, createBond, bonding state handling
- Remove write queue / pendingRelayState / writeInProgress
- Use WRITE_TYPE_NO_RESPONSE for minimal latency
- Post-flash dialog auto-dismisses on USB detach (currentAction = NONE)
- Separate progressDialog (flash progress) from dialog (post-flash info)
- Detach during active action now calls cleanupAction()

Build number:
- BuildConfig.BUILD_NUMBER in build.gradle as yyyyMMddHHmmss timestamp
- buildFeatures.buildConfig enabled
- Displayed in SettingsActivity bottom (12sp, secondary color)

Gradle:
- Wrapper upgraded 8.5 → 8.14
- minSdk 24 → 26 (Android 8+)

README updated to reflect HMAC-only security model.
2026-07-26 15:46:28 +02:00
eddy
0ff2c59b6d Add esp32-flash-lib dependency to build.gradle (was missing from git) 2026-07-26 14:21:45 +02:00
eddy
06a99793a2 Revert UsbSerialTransport.read() to return 0 on timeout (library expects this) v2.0 2026-07-26 13:33:17 +02:00
eddy
8ef971c051 Add code review fixes implementation plan 2026-07-26 12:54:11 +02:00
eddy
21aa62c2d7 Disable allowBackup, fix download-modus instruction text 2026-07-26 12:53:49 +02:00
eddy
4954c91d77 Fix MainActivity: receiver flag, handler cleanup, onPause, boolean state 2026-07-26 12:53:18 +02:00
eddy
475d4d9162 Fix SettingsActivity: use UsbUtils, add lifecycle guard 2026-07-26 12:52:01 +02:00
eddy
2a86fa5d39 Fix EspFlasher: connection leak (try/finally), progress mapping, use UsbUtils 2026-07-26 12:51:02 +02:00
eddy
2e08f9a340 Fix UsbSerialTransport.read() to throw IOException on error 2026-07-26 12:50:22 +02:00
eddy
5fbe0712e8 Add UsbUtils utility object for shared USB functions 2026-07-26 12:49:37 +02:00
eddy
ff419d9f36 Update README for USB key provisioning architecture
- Unified toast message to 'Beveiligingssleutel gelezen' throughout
- Updated key management section with bidirectional provisioning flow
- Added provisioning flow diagram (ASCII sequence)
- Updated security analysis: key no longer in APK, extracted from
  SharedPreferences requiring root; added USB key extraction risk
  and NVS wiping notes
- Added serial monitor example for unprovisioned ESP (no-key case)
- Added factory reset instructions (pio run -t erase)
- Added setup scenarios: existing ESP + new phone, new ESP + existing phone
- Updated projectstructuur: removed stale usb-serial-for-android references
- Updated technische notities: raw USB API justification, CDC control
  interface setup, retry behavior
2026-07-26 09:40:38 +02:00
eddy
8e53abe8b4 Unify provisioning toast message
Both provisioning paths (reading existing key and generating new key)
now show the same neutral toast: 'Beveiligingssleutel gelezen'
2026-07-26 09:38:19 +02:00
eddy
9a84b05b8a 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
2026-07-26 09:30:21 +02:00
eddy
c707c21d7f Rewrite USB key reader: raw USB API + retry logic
- Replaced usb-serial-for-android library with raw Android USB API
  (UsbDeviceConnection.bulkTransfer) — the library's testConnection()
  sent a get_status CDC request that the ESP32-S3 USB-JTAG/serial
  controller does not support, causing read failures
- Added CDC control interface setup (line coding + DTR/RTS) to enable
  data flow before sending KEY? command
- Added retry logic: 5 attempts, 1s delay between retries, to handle
  other apps grabbing the USB device first (JTAG/serial debug unit
  triggers multiple system dialogs before our app gets permission)
- Re-lookup ESP device on each retry to handle device path changes
- Removed usb-serial-for-android dependency and JitPack repository
2026-07-26 09:02:41 +02:00
eddy
4518aec34e Add USB auto-read key transfer + UI redesign
USB auto-read:
- ESP responds to 'KEY?\n' over USB serial with 'HMAC_KEY:<hex>'
- Android UsbKeyReceiver (manifest BroadcastReceiver) catches USB_DEVICE_ATTACHED
- Filters on Espressif vendor 0x303a, requests USB permission
- Opens CDC-ACM serial (115200), sends KEY?, parses response, saves to SharedPreferences
- Works even when app not in foreground
- usb-serial-for-android v3.7.3 via JitPack

UI redesign:
- activity_main.xml: FrameLayout with settings icon top-right, relay button center, status bottom-left (14sp)
- Scan & Connect button moved to SettingsActivity
- SettingsActivity: hint text 'Voer de HMAC sleutel in of sluit de relaismodule aan op de telefoon'
- SettingsActivity: scan button saves key + returns RESULT_OK to trigger scanning
- MainActivity: removed scanButton, auto-scan on onResume when key is set
- Back button removed from settings (ActionBar up navigation only)

README updated with USB protocol docs, new UI description, and updated setup guide
2026-07-26 08:39:28 +02:00
eddy
7f68e9ad70 Add BLE security: Just Works pairing + HMAC-SHA256 authentication
Two-layer security for the BLE relay:

1. BLE Just Works pairing (link-layer encryption)
   - ESP32 requires bonding before accepting writes
   - Characteristic permissions set to ESP_GATT_PERM_WRITE_ENCRYPTED
   - IO capability NO_INPUT_NO_OUTPUT (no passkey needed)
   - LE Secure Connections with bonding (ESP_LE_AUTH_REQ_SC_BOND)

2. HMAC-SHA256 authentication (application-level)
   - 32-byte shared secret in src/hmac_key.h (generated, gitignored)
   - Each command signed: HMAC-SHA256(key, command || sequence)
   - 37-byte packet format: [cmd:1][seq:4][hmac:32]
   - Sequence counter prevents replay (strictly increasing, starts at 1)
   - mbedtls on ESP, javax.crypto.Mac on Android

Key management:
- tools/generate_hmac_key.py generates random key + writes src/hmac_key.h
- ESP prints hex key to serial 5 seconds after boot
- Android app: SettingsActivity with eye-toggle password field
- Key stored in SharedPreferences, supports multiple ESP modules

Other changes:
- Android app: bonding flow (createBond -> BOND_BONDED -> discover)
- Android app: MTU negotiation (request 256)
- Android app: settings button (gear icon) in main screen
- Fix: sequence counter starts at 1 to prevent first-packet rejection
- Updated README with full security documentation
2026-07-26 08:18:52 +02:00
eddy
7c9dde172a Initial commit: BLE relay controller for Atom VoiceS3R 2026-07-26 01:17:31 +02:00