On this page
Documentation / Reference
USB protocol.
A framed binary command interface between the host and the firmware.
Transport
The current host implementations use the ESP USB device with VID:PID 303a:1001, configuration 1, interface 1, alternate setting 0, and bulk endpoints 0x01 (OUT) / 0x81 (IN).
Those IDs are shared with other ESP development devices. Match the expected descriptors and avoid ambiguous device selection. USB read chunks are not frame boundaries; accumulate bytes until a complete frame is available.
Frame header
| Offset | Size | Field |
|---|---|---|
| 0 | 4 bytes | ASCII KMGR (4B 4D 47 52) |
| 4 | 1 byte | Protocol version, currently 1 |
| 5 | 1 byte | Command or response ID |
| 6 | 2 bytes | Payload byte length, big-endian |
An 8-byte header precedes the payload. The firmware accepts at most 1,024 incoming payload bytes. Development layouts have changed while retaining version 1, so matching that byte alone does not establish historical compatibility.
4B 4D 47 52 01 02 00 00
└─ KMGR ─┘ │ │ └─ no payload
│ └─ status command
└─ protocol version 1Payload encoding
Integers are explicitly big-endian. Strings contain a u32 byte length followed by bytes, without a trailing NUL. Byte buffers also use a u32 length followed by bytes. Native C struct layout and Rust enum layout are not wire formats.
Use the host library for normal integrations. A custom implementation must bound lengths, handle partial reads/writes, and keep transactions sequential because the protocol has no request IDs.
Commands
| ID | Operation | Successful response |
|---|---|---|
0x01 | Ping | OK |
0x02 | Status | Token u32, session u32 |
0x10 | Initialize | OK |
0x11 | Authenticate | OK |
0x12 | Lock | OK |
0x20 | Generate key | Key ID u32 |
0x21 / 0x22 | Encrypt / decrypt | Length-prefixed bytes |
0x23 | Sign / MAC | Length-prefixed signature / MAC |
0x24 | Verify HMAC | Verified flag u8 |
0x25 | ECDH + HKDF | Key ID, length-prefixed salt, info string |
0x30 | Export public key | Encoding u32, length-prefixed DER bytes |
0x40 | List keys | Count and key metadata entries |
0x41 | Destroy key | OK |
Successful data responses use the matching operation ID; empty success uses 0x00. Errors use 0xFF. Initialization exists in the firmware but is not exposed by the current public host interfaces.
Common request layouts
- Authenticate / initialize
pin:string- Generate key
type:u32 · usage:u32 · size:u16 · label:string · timestamp:u32- Encrypt / decrypt / sign
key_id:u32 · data:bytes- Verify HMAC
key_id:u32 · message:bytes · mac:bytes- ECDH + HKDF
key_id:u32 · encoding:u32 · peer_public:bytes · label:string · timestamp:u32- Export public key / destroy key
key_id:u32- List keys
flags:u32 · type:u32 · usage:u32 · label:string · key_id:u32
List filter flag bits are label 0, type 1, usage 2, and ID 3. A set ID filter overrides the others. The key type/usage values are listed in the C constants reference.
Device error response
code:u8 || message_length:u32 || message_bytesAn empty message is valid, so the smallest error payload is 5 bytes. Authentication-required is error code 0x01 inside a 0xFF response; it is not a separate response ID.
| Code | Meaning |
|---|---|
0x01 | Authentication required |
0x02 | Authentication failed |
0x03 | Invalid input |
0x04 | Unsupported operation |
0x05 | Missing key |
0x06 | Policy rejected |
0x07 | Storage failure |
0x08 | Bad command |
0x09 | Serialization error |
0x0A | Initialization failed |
0x0B | Invalid state |
0xFF | Generic failure |
Timeouts and retries
Keep incomplete input buffered, reject oversized frames, and preserve unexpected error codes in custom clients. A lost response can leave the command outcome ambiguous. Do not automatically replay initialization, key generation, derivation, or deletion after a timeout.