Crypto: - Replace broken ChaCha20 (static nonce) with ChaCha20-Poly1305 AEAD - HKDF-SHA256 key derivation from per-device factory NVS master keys - Random 12-byte nonce per message (ESP32 hardware RNG) - crypto_init/encrypt/decrypt API with mbedtls legacy (ESP-IDF v5.3.2) - Custom partition table with factory NVS (fctry at 0x10000) Firmware: - crypto.c full rewrite, messages.c device_id prefix + AEAD encrypt - crypto_init() at boot with esp_restart() on failure - Fix command_t initializations across all modules (sub/help fields) - Clean CMakeLists dependencies for ESP-IDF v5.3.2 C3PO (C2): - Rename tools/c2 + tools/c3po -> tools/C3PO - Per-device CryptoContext with HKDF key derivation - KeyStore (keys.json) for master key management - Transport parses device_id:base64(...) wire format Tools: - New tools/provisioning/provision.py for factory NVS key generation - Updated flasher with mbedtls config for v5.3.2 Docs: - Update all READMEs for new crypto, C3PO paths, provisioning - Update roadmap, architecture diagrams, security sections - Update CONTRIBUTING.md project structure |
||
|---|---|---|
| .. | ||
| flash.py | ||
| README.md | ||
Espilon Multi-Device Flasher
Automated tool for building and flashing multiple ESP32 devices with custom configurations for the Espilon project.
Features
- Build firmware with custom configurations per device
- Support for WiFi and GPRS modes
- Configurable modules (Network, Recon, FakeAP)
- Multi-device batch processing
- Individual device manual configuration
- Automatic hostname generation
- Build-only and flash-only modes
Prerequisites
- Python 3.8+
- ESP-IDF v5.3.2 (properly configured with
export.sh) - esptool.py (usually included with ESP-IDF)
- ESP32 development boards connected via USB
Installation
No installation required. The script is standalone.
cd tools/flasher
chmod +x flash.py
Configuration File
Structure
The devices.json file contains:
- project: Path to the
espilon_botdirectory - devices: Array of device configurations
Example: devices.json
{
"project": "/home/user/epsilon/espilon_bot",
"devices": [
## WiFi AGENT ##
{
"device_id": "ce4f626b",
"port": "/dev/ttyUSB0",
"srv_ip": "192.168.1.13",
"srv_port": 2626,
"network_mode": "wifi",
"wifi_ssid": "MyWiFi",
"wifi_pass": "MyPassword123",
"hostname": "pixel-8-pro",
"module_network": true,
"module_recon": false,
"module_fakeap": false,
"recon_camera": false,
"recon_ble_trilat": false,
"crypto_key": "testde32chars00000000000000000000",
"crypto_nonce": "noncenonceno"
},
## GPRS AGENT ##
{
"device_id": "a91dd021",
"port": "/dev/ttyUSB1",
"srv_ip": "203.0.113.10",
"srv_port": 2626,
"network_mode": "gprs",
"gprs_apn": "sl2sfr",
"hostname": "galaxy-s24-ultra",
"module_network": true,
"module_recon": false,
"module_fakeap": false
}
]
}
Device Configuration Fields
| Field | Required | Default | Description |
|---|---|---|---|
device_id |
Yes | - | Unique device identifier (8 hex chars) |
port |
Yes | - | Serial port (e.g., /dev/ttyUSB0, COM3) |
srv_ip |
Yes | - | C2 server IP address |
srv_port |
No | 2626 | C2 server port |
network_mode |
No | "wifi" | Network mode: "wifi" or "gprs" |
wifi_ssid |
WiFi only | - | WiFi network SSID |
wifi_pass |
WiFi only | - | WiFi network password |
gprs_apn |
GPRS only | "sl2sfr" | GPRS APN |
hostname |
No | Random | Device hostname for network identification |
module_network |
No | true | Enable network commands module |
module_recon |
No | false | Enable reconnaissance module |
module_fakeap |
No | false | Enable fake AP module |
recon_camera |
No | false | Enable camera reconnaissance (ESP32-CAM) |
recon_ble_trilat |
No | false | Enable BLE trilateration |
crypto_key |
No | Test key | ChaCha20 encryption key (32 chars) |
crypto_nonce |
No | Test nonce | ChaCha20 nonce (12 chars) |
Usage
1. Flash All Devices from Config
python3 flash.py --config devices.json
This will:
- Read device configurations from
devices.json - Build firmware for each device
- Flash each device sequentially
- Display summary report
2. Manual Single Device (WiFi)
python3 flash.py --manual \
--project /home/user/epsilon/espilon_bot \
--device-id abc12345 \
--port /dev/ttyUSB0 \
--srv-ip 192.168.1.100 \
--wifi-ssid MyWiFi \
--wifi-pass MyPassword123
3. Manual Single Device (GPRS)
python3 flash.py --manual \
--project /home/user/epsilon/espilon_bot \
--device-id def67890 \
--port /dev/ttyUSB1 \
--srv-ip 203.0.113.10 \
--network-mode gprs \
--gprs-apn sl2sfr
4. Build Only (No Flash)
Useful for generating firmware files without flashing:
python3 flash.py --config devices.json --build-only
Firmware files are saved to: espilon_bot/firmware/<device_id>.bin
5. Flash Only (Skip Build)
Flash pre-built firmware:
python3 flash.py --config devices.json --flash-only
Requires firmware files in espilon_bot/firmware/ directory.
6. Enable Modules
python3 flash.py --manual \
--project /home/user/epsilon/espilon_bot \
--device-id xyz98765 \
--port /dev/ttyUSB0 \
--srv-ip 192.168.1.100 \
--wifi-ssid MyWiFi \
--wifi-pass MyPassword123 \
--enable-recon \
--enable-fakeap \
--enable-ble-trilat
7. Custom Encryption Keys
python3 flash.py --manual \
--project /home/user/epsilon/espilon_bot \
--device-id secure01 \
--port /dev/ttyUSB0 \
--srv-ip 192.168.1.100 \
--wifi-ssid MyWiFi \
--wifi-pass MyPassword123 \
--crypto-key "your32charencryptionkeyhere!!" \
--crypto-nonce "yournonce12b"
Advanced Features
Hostname Generation
If hostname is not specified, the script generates a realistic device name:
- iPhone models (iPhone-15-pro-max, etc.)
- Android devices (galaxy-s24-ultra, pixel-8-pro, etc.)
- Windows PCs (DESKTOP-XXXXXXX)
This helps devices blend in on networks during authorized testing.
Configuration Backup
Before building, the script automatically backs up the existing sdkconfig.defaults to sdkconfig.defaults.bak.
Firmware Storage
Built firmware is saved in:
espilon_bot/firmware/<device_id>.bin
This allows:
- Reuse without rebuilding (--flash-only)
- Firmware version archival
- Quick reflashing of multiple devices
Workflow Examples
Scenario 1: Initial Setup (3 devices)
-
Edit
devices.json:{ "project": "/home/user/epsilon/espilon_bot", "devices": [ {"device_id": "dev00001", "port": "/dev/ttyUSB0", ...}, {"device_id": "dev00002", "port": "/dev/ttyUSB1", ...}, {"device_id": "dev00003", "port": "/dev/ttyUSB2", ...} ] } -
Flash all:
python3 flash.py --config devices.json -
Devices are ready for deployment
Scenario 2: Update Single Device
- Modify configuration in
devices.json - Flash only that device:
# Remove other devices from JSON or use manual mode python3 flash.py --manual --device-id dev00002 --port /dev/ttyUSB1 ...
Scenario 3: Quick Reflash
# Build once
python3 flash.py --config devices.json --build-only
# Flash multiple times (testing, replacement devices)
python3 flash.py --config devices.json --flash-only
Scenario 4: WiFi + GPRS Mixed Fleet
{
"project": "/home/user/epsilon/espilon_bot",
"devices": [
{
"device_id": "wifi001",
"network_mode": "wifi",
"wifi_ssid": "HomeNetwork",
"wifi_pass": "password123",
...
},
{
"device_id": "gprs001",
"network_mode": "gprs",
"gprs_apn": "sl2sfr",
...
}
]
}
Troubleshooting
Error: "Port not found"
❌ Flash failed: Serial port /dev/ttyUSB0 not found
Solution: Check device connection and port:
ls /dev/ttyUSB* /dev/ttyACM*
Add user to dialout group:
sudo usermod -a -G dialout $USER
# Log out and log back in
Error: "Build failed"
❌ Build failed for device_id
Solutions:
-
Verify ESP-IDF is sourced:
. $HOME/esp-idf/export.sh -
Check project path in
devices.json -
Manually test build:
cd espilon_bot idf.py build
Error: "Permission denied"
❌ Permission denied: /dev/ttyUSB0
Solution:
sudo chmod 666 /dev/ttyUSB0
# Or add user to dialout group (permanent)
sudo usermod -a -G dialout $USER
Error: "Binary not found"
❌ Binary not found: epsilon_bot.bin
Solution: Check build output for compilation errors. The binary name should match the project configuration.
WiFi Mode Missing Credentials
ValueError: WiFi mode requires wifi_ssid and wifi_pass
Solution: Ensure wifi_ssid and wifi_pass are set for devices with network_mode: "wifi".
Output Example
============================================================
# Device 1/3: ce4f626b
############################################################
============================================================
🔧 Building firmware for: ce4f626b (WIFI) on /dev/ttyUSB0
============================================================
✅ Generated sdkconfig.defaults for ce4f626b
🗑️ Removed old sdkconfig
⚙️ Running idf.py build...
✅ Firmware saved: espilon_bot/firmware/ce4f626b.bin
============================================================
🚀 Flashing: ce4f626b (WIFI) on /dev/ttyUSB0
============================================================
📁 Bootloader: espilon_bot/build/bootloader/bootloader.bin
📁 Partitions: espilon_bot/build/partition_table/partition-table.bin
📁 Application: espilon_bot/firmware/ce4f626b.bin
🔌 Port: /dev/ttyUSB0
✅ Successfully flashed ce4f626b
============================================================
📊 SUMMARY
============================================================
✅ Success: 3/3
❌ Failed: 0/3
============================================================
Security Considerations
Encryption Keys
WARNING: The default crypto keys are for TESTING ONLY:
crypto_key: "testde32chars00000000000000000000"crypto_nonce: "noncenonceno"
For production use:
-
Generate secure keys:
# 32-byte key openssl rand -hex 32 # 12-byte nonce openssl rand -hex 12 -
Update in
devices.jsonor use--crypto-keyand--crypto-nonce -
Never commit real keys to version control
Device IDs
Generate random device IDs:
openssl rand -hex 4 # Generates 8-character hex ID
Files Generated
During operation, the script creates:
espilon_bot/
├── sdkconfig # Generated during build (auto-deleted)
├── sdkconfig.defaults # Overwritten per device
├── sdkconfig.defaults.bak # Backup of previous config
├── build/ # ESP-IDF build artifacts
│ ├── bootloader/
│ ├── partition_table/
│ └── epsilon_bot.bin
└── firmware/ # Saved firmware binaries
├── ce4f626b.bin
├── a91dd021.bin
└── f34592e0.bin
Tips
-
Batch Processing: Connect multiple ESP32s to different USB ports, configure all in
devices.json, and flash them all at once. -
Parallel Builds: For faster processing with many devices, consider building in parallel (future enhancement).
-
Configuration Templates: Keep multiple
devices.jsonfiles for different deployment scenarios:devices-wifi.jsondevices-gprs.jsondevices-production.jsondevices-testing.json
-
Firmware Archive: Save firmware binaries with version tags:
mkdir -p firmware-archive/v1.0 cp espilon_bot/firmware/*.bin firmware-archive/v1.0/ -
Serial Port Mapping: Create udev rules for consistent port naming (Linux):
# /etc/udev/rules.d/99-esp32.rules SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="esp32-dev1" SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", SYMLINK+="esp32-dev2"
Help
python3 flash.py --help
Displays full usage information with examples.
Related Documentation
- Installation Guide - Full Espilon setup
- Hardware Guide - Supported boards and wiring
- Module API - Available commands and modules
- Security - Security best practices
License
Part of the Espilon project. See LICENSE for details.