Files
n_signer/firmware/cyd_esp32_2432s028/README.md

176 lines
8.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# n_signer CYD Firmware (ESP32-2432S028)
The **Cheap Yellow Display** (ESP32-2432S028) is a $15 ESP32-WROOM-32 board with
a 2.8" 320×240 ILI9341 resistive-touch display, CH340 USB-UART bridge, and a
Micro SD card slot. This firmware turns it into a hardware n_signer that speaks
the same algorithm-based API as the host ([`README.md`](../../README.md) §4).
**Firmware version:** 0.0.2 (algorithm-based API)
## Hardware summary
| Concern | Value |
|---|---|
| MCU | ESP32-WROOM-32 (classic, dual-core Xtensa, 512 KB SRAM, no PSRAM) |
| USB-UART | CH340 (`1a86:7523`) → `/dev/ttyUSB0` |
| Flash | 4 MB |
| Display | 2.8" 320×240 ILI9341 (HSPI: DC=IO2, CS=IO15, SCK=IO14, MOSI=IO13, MISO=IO12, BL=IO21) |
| Touch | XPT2046 resistive (bit-banged SPI: CLK=IO25, MOSI=IO32, CS=IO33, MISO=IO39, IRQ=IO36) |
| SD card | Micro SD, VSPI (CS=IO5, SCK=IO18, MISO=IO19, MOSI=IO23) |
| RGB LED | R=IO4, G=IO16, B=IO17 (active LOW) |
| LDR | IO34 |
| Speaker | IO26 (DAC) |
| BOOT button | IO0 |
| GUI | LVGL 8.3 |
For the full pin map, connectors (P1/P3/CN1), and add-ons, see the upstream
hardware docs copied to [`docs/`](docs/) — especially
[`docs/PINS.md`](docs/PINS.md) and [`docs/SETUP.md`](docs/SETUP.md).
## SD card — size limits and OTP pad storage
The CYD's Micro SD slot is wired to VSPI (IO5/18/19/23). ESP-IDF drives it via
the SDSPI host + FATFS filesystem. The proven bring-up example is
`07_sd_card` in the `esp32_playground/cyb-esp32-2432s028/` workspace.
**Size limits:**
- **SDSC (≤ 2 GB):** supported.
- **SDHC (2 GB 32 GB):** supported — this is the recommended range. The
Makerfabs CYD ships with a 16 GB card, which works.
- **SDXC (> 32 GB):** **not supported** out of the box. SDXC cards ship
formatted as exFAT, and ESP-IDF's FATFS does not include exFAT. An SDXC card
reformatted to FAT32 will work up to 32 GB; beyond that, FAT32's 32 GB limit
applies. For OTP pad storage, 32 GB is vastly more than enough (see below).
**Recommendation:** use any **SDHC card from 432 GB** formatted **FAT32**.
### Using the SD card for the OTP pad
The current v0.0.2 firmware derives the OTP pad from the mnemonic seed via
HKDF-SHA256 into a 1024-byte in-RAM pad (no SD card required). This keeps the
wire contract identical to the host's `encrypt`/`decrypt` (algorithm:"otp")
verbs but limits the pad to 1024 bytes per session.
To hold a **large OTP pad** (the original n_signer host design binds a pad file
from `--otp-pad-dir`), the SD card is the right storage. The plan:
1. Format the SD card as FAT32.
2. Place a pad file (e.g. `nsigner.pad`) on it — any size up to the card's free
space. A 1 GB pad gives ~1 billion one-time-pad bytes before exhaustion.
3. The firmware mounts the SD card at boot via `esp_vfs_fat_sdmmc_mount()` on
the SDSPI host, opens the pad file, and reads pad bytes on demand into a
small ring buffer, advancing a persistent offset (stored in a small
`nsigner.offset` file on the SD so the offset survives power cycles).
4. The `encrypt`/`decrypt` verbs XOR against the SD-backed pad instead of the
HKDF-derived in-RAM pad.
This is a planned enhancement (see [`plans/cyd_algorithm_api_upgrade.md`](../../plans/cyd_algorithm_api_upgrade.md)
§13 — the current implementation uses the mnemonic-derived pad as the embedded
fallback). The SD card slot is confirmed working and the pin map is in
[`docs/PINS.md`](docs/PINS.md).
**Note on simultaneous display + touch + SD:** The CYD's display (HSPI), touch
(bit-banged), and SD (VSPI) use three different SPI buses. All three can run at
the same time — the touch is bit-banged precisely so it doesn't contend with
the other two hardware SPI buses (see [`docs/TROUBLESHOOTING.md`](docs/TROUBLESHOOTING.md)).
## Building and flashing
Requires ESP-IDF v5.x (tested with v5.4.2). The classic ESP32 target uses the
`xtensa-esp-elf` unified toolchain.
```bash
source /home/user/esp/esp-idf/export.sh
cd firmware/cyd_esp32_2432s028
idf.py build
idf.py -p /dev/ttyUSB0 flash
```
If flashing fails with `Wrong boot mode detected (0x13)`, see the serial-reset
hardware note below.
## Validation — Web Serial
The CYD has no native USB; the CH340 bridge exposes a serial port. The browser
transport is **Web Serial** (`navigator.serial`), Chromium-only. A full test
page covering every algorithm and verb lives at
[`examples/cyd_webserial_demo.html`](../../examples/cyd_webserial_demo.html):
1. Open [`examples/cyd_webserial_demo.html`](../../examples/cyd_webserial_demo.html) in Chrome/Edge.
2. Click **Connect Web Serial**, select the CH340 port (`1a86:7523`).
3. On the CYD touchscreen, enter or generate a mnemonic to reach the "ready" state.
4. Exercise each card: `get_public_key` (all 6 algorithms), `sign`/`verify`,
`encapsulate`/`decapsulate`, `derive_shared_secret`, `derive`,
`nostr_get_public_key`, `nostr_sign_event`, `nostr_mine_event`,
`nostr_nip04`/`nostr_nip44` encrypt+decrypt, and `encrypt`/`decrypt` (otp).
## API
The CYD firmware speaks the same algorithm-based API as the host n_signer
([`README.md`](../../README.md) §4). Supported verbs:
| Verb | Algorithms |
|---|---|
| `get_public_key` | secp256k1, ed25519, x25519, ml-dsa-65, slh-dsa-128s, ml-kem-768 |
| `sign` / `verify` | secp256k1 (schnorr/ecdsa), ed25519, ml-dsa-65, slh-dsa-128s |
| `encapsulate` / `decapsulate` | ml-kem-768 |
| `derive_shared_secret` | x25519 |
| `derive` | secp256k1 (HMAC-SHA256) |
| `encrypt` / `decrypt` | otp |
| `nostr_get_public_key` | secp256k1 (NIP-06) |
| `nostr_sign_event` | secp256k1 (NIP-06) |
| `nostr_mine_event` | secp256k1 (NIP-06, single-threaded PoW) |
| `nostr_nip04_encrypt` / `decrypt` | secp256k1 (NIP-06) |
| `nostr_nip44_encrypt` / `decrypt` | secp256k1 (NIP-06) |
All requests require an auth envelope (kind 27235). The `key_id` in every
structured result is the first 16 hex characters of the public key, matching
the host. Invalid `(verb, algorithm)` pairs return error `1010`.
### Embedded-specific notes
- **OTP pad:** derived from the mnemonic seed (HKDF-SHA256, 1024 bytes) in
v0.0.2. The offset advances monotonically and is reported in every
`encrypt`/`decrypt` response. SD-card-backed pad is a planned enhancement
(see above).
- **`nostr_mine_event`:** single-threaded, hard 30 s default timeout, shows a
"mining…" screen. Keep difficulty low (≤ 8) on ESP32.
- **SLH-DSA-128s:** keygen and signing take 530 s. The UI shows a "deriving
key…" / "signing…" indicator. ML-DSA-65 is much faster (~100 ms) and is the
recommended PQ signature algorithm for interactive use.
## Crypto backend
- **SHA-256 / SHA-512:** mbedtls (ESP32 hardware accelerated).
- **SHA3 / SHAKE-128 / SHAKE-256:** vendored Keccak-f[1600] (FIPS 202) in
[`resources/pqclean/common/crypto_backend_mbedtls.c`](../../resources/pqclean/common/crypto_backend_mbedtls.c).
No `CONFIG_MBEDTLS_SHA3_C` or SHAKE menuconfig dependency.
- **ed25519 / x25519:** PSA Crypto API (`psa_import_key`, `psa_sign_message`,
`psa_raw_key_agreement`, etc.) — ESP-IDF v5.x mbedtls removed the
`mbedtls_ed25519_*` functions. Requires `CONFIG_MBEDTLS_PSA_CRYPTO_C=y`
(set in [`sdkconfig.defaults`](sdkconfig.defaults)).
- **secp256k1:** the vendored secp256k1 component (schnorr + ECDSA).
- **PQ (ML-DSA-65, SLH-DSA-128s, ML-KEM-768):** PQClean via the
[`components/pqclean/`](components/pqclean/) component.
## Serial-reset hardware note (CH340 auto-reset)
Opening `/dev/ttyUSB0` can reset the ESP32 because the CH340's DTR/RTS lines
are wired into the ESP32 auto-reset circuit. Symptoms: the device returns to
the startup menu when a host app opens the serial port.
**Mitigation:** add a **10 µF capacitor between EN and GND** on the CYD board
(negative leg to GND). Typical working range is 4.722 µF. This also fixes the
`Wrong boot mode detected (0x13)` flashing error. See
[`docs/TROUBLESHOOTING.md`](docs/TROUBLESHOOTING.md) and the
[`firmware/README.md`](../README.md) CYD section for details.
## Reference documentation
- [`docs/`](docs/) — upstream CYD hardware docs (PINS, SETUP, TROUBLESHOOTING, ADDONS, etc.)
- [`plans/cyd_signer_port.md`](../../plans/cyd_signer_port.md) — original port plan (hardware comparison, architecture, UI flow)
- [`plans/cyd_algorithm_api_upgrade.md`](../../plans/cyd_algorithm_api_upgrade.md) — v0.0.2 API upgrade plan
- [`firmware/README.md`](../README.md) — shared firmware README (PQ crypto, mbedtls backend, feather target)
- [`README.md`](../../README.md) §4 — the authoritative n_signer API reference