Kleidos#
Hardware BLE password manager for the M5Stack / LilyGo ESP32 device family.
Kleidos stores your credentials encrypted on-device and types them over Bluetooth to any paired computer or phone — no software installation required on the host. The device stays in deep sleep until you press a button, unlocks with a shoulder-surf-resistant PIN, and goes back to sleep after use.
Features#
- BLE HID keyboard — types credentials directly into any login field
- AES-256-CBC + HMAC-SHA256 — encrypt-then-MAC; PBKDF2-SHA256 key derivation (175,000 iterations on ESP32-S3 boards, 40,000 on classic-ESP32 boards); hardware RNG
- TOTP authenticator — RFC 6238, displayed on screen and typed via BLE
- Timing Arc PIN entry — hold button to select digits, resistant to observation
- Multi-host pairing — up to 4 bonded hosts; BLE LE Secure Connections with Numeric Comparison (MITM + re-pair confirmation)
- 7 keyboard layouts — US, ES, UK, FR, DE, PT, IT
- WiFi admin portal — mobile-friendly web UI (WPA3-SAE, no WPA2 fallback) for credential management
- On-device settings — Display, Security, Power, Device, About sections; no WiFi required
- Unified popup system — toast / spinner / confirm / alert with hysteresis-aware status events
- OTA updates — browser-based firmware updates with rollback detection; RSA-3072 signature verification on
_securebuilds (Secure Boot v2) - ESP Web Tools — one-click initial flash from a web page (Chrome/Edge)
- Password generator — cryptographically random, configurable charset
- Shake-to-lock — IMU-based instant lock via device shake
- Deep sleep — < 20 µA, months of standby on 250 mAh battery
Supported Hardware#
| Variant | Board | MCU | Flash |
|---|---|---|---|
sticks3 |
M5StickC Plus S3 (StickS3) | ESP32-S3 | 8 MB — primary target |
cardputer |
M5Cardputer | ESP32-S3 | 8 MB |
tdeck |
LilyGo T-Deck | ESP32-S3 | 16 MB |
cores3_se |
M5Stack CoreS3 SE | ESP32-S3 | 8 MB |
m5stickc_plus2 |
M5StickC Plus2 | ESP32 | 8 MB |
m5stack_gray |
M5Stack Gray | ESP32 | 16 MB |
core2_v13 |
M5Stack Core2 v1.3 | ESP32 | 16 MB |
m5stickc_plus1 |
M5StickC Plus1 | ESP32 | 4 MB (no OTA) |
m5core_ink |
M5Stack CoreInk | ESP32 | 4 MB (no OTA) |
See docs/variants.md for the full hardware matrix and build target reference.
Quick Start#
1. Flash (no development tools needed)#
Visit the Kleidos Web Installer in Chrome or Edge. Connect the device via USB and click "Install". This uses ESP Web Tools — no drivers needed on Linux, macOS, or Windows.
2. First Use#
- Press BtnA to wake from deep sleep
- Set your 4-digit PIN (first boot only)
- Hold BtnA to select each digit using the timing arc
- After PIN is set, enter admin mode (hold BtnB 2 s) to add credentials
- Connect to the Kleidos-XXXX WiFi network shown on screen
- Open
192.168.4.1in your browser to manage passwords
3. Daily Use#
- Press BtnA → enter PIN → select credential → press A to type via BLE
- Device auto-locks and enters deep sleep after typing
Documentation#
See docs/README.md for the full documentation index and navigation map.
| Document | Description |
|---|---|
| User Guide | End-user manual: setup, daily use, troubleshooting |
| Developer Guide | Build from source, testing, contributing |
| Architecture | FSM design, module structure, state flow |
| Platform Abstraction | RTOS/logging/platform facade rules and future abstraction candidates |
| Security Model | User and auditor security docs: threat model, crypto, BLE, WiFi, OTA |
| Hardware Reference | Per-device specs, pin mapping, PMIC, peripherals |
| REST API Reference | Admin portal API endpoints |
| Building & Flashing | PlatformIO setup, environments, CI/CD |
| OTA Updates | Firmware update procedure, rollback, ESP Web Tools |
| Testing | Hardware QA runbooks, including BLE HID automated tests |
| Brand Logos | Embedded service-logo atlas pipeline, source policy, and verification |
Project Structure#
src/
├── main.cpp FSM dispatcher (~240 lines)
├── platform/ RTOS/logging/platform facades
├── states/ State handlers (one per FSM state)
│ ├── app_context.h Shared state struct
│ ├── app_state_handler.h Abstract handler interface
│ ├── pin_state.cpp PIN entry logic
│ ├── home_state.cpp Vault menu + TOTP display
│ ├── ble_state.cpp BLE HID typing
│ ├── admin_state.cpp WiFi admin mode
│ └── hw_test_state.cpp Hardware test screens
├── ble/ BLE HID keyboard + layouts
├── crypto/ AES-256, PBKDF2, password generator
├── hal/ Hardware abstraction (power, IMU, audio)
├── totp/ TOTP generator (RFC 6238)
├── ui/ PIN entry UI, button abstractions
├── vault/ Encrypted storage, brute-force guard, audit log
└── web/ WiFi admin portal + gzip HTML
test/ Native unit tests (run on PC, no hardware)
scripts/ Build, flash, test automation scripts
docs/ Documentation
web/ ESP Web Tools installer page
Security Highlights#
- Vault encrypted with AES-256-CBC + HMAC-SHA256 (encrypt-then-MAC, verify-before-decrypt)
- Key derivation via PBKDF2-SHA256: 175,000 iterations on ESP32-S3, 40,000 on classic ESP32
- PIN and MAC-tag comparisons are constant-time (
psa_mac_verify/mbedtls_ct_memcmp) - Brute-force protection: progressive lockout from 4 failures, vault wipe after 10
- All key material wiped with
mbedtls_platform_zeroize()/psa_destroy_key()after use - BLE LE Secure Connections — Numeric Comparison, sc-only, MITM required, re-pair confirmation
- Device-bound key on
_securebuilds (HKDF over eFuse-HMAC/NVS pepper): offline PIN brute-force infeasible - Flash encryption + Secure Boot v2 (RSA-3072) on
_securebuilds - NVS encryption for stored key material
- Credentials never appear in logs, BLE advertisements, or HTTP responses without auth
- See Security Overview for the full threat model and audit docs
Power Budget#
| State | Current | Battery Life (250 mAh) |
|---|---|---|
| Deep sleep | < 20 µA | > 1 year |
| PIN entry | < 20 mA | ~12 hours |
| BLE HID typing | < 50 mA | ~5 hours |
| WiFi admin/OTA | < 130 mA | ~2 hours |
Build#
# Install PlatformIO CLI
pip install platformio
# Build for StickS3
pio run -e sticks3
# Build for M5StickC Plus2
pio run -e m5stickc_plus2
# Run unit tests (no hardware needed)
pio test -e native
# Upload to device
pio run -e sticks3 -t upload
License#
See LICENSE for details.
Changelog#
See CHANGELOG.md for release history.