enigmastick
Documentation menu
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

OffsetSizeField
04 bytesASCII KMGR (4B 4D 47 52)
41 byteProtocol version, currently 1
51 byteCommand or response ID
62 bytesPayload 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.

Hex / status request
4B 4D 47 52  01 02  00 00
└─ KMGR ─┘  │  │   └─ no payload
             │  └─ status command
             └─ protocol version 1

Payload 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

IDOperationSuccessful response
0x01PingOK
0x02StatusToken u32, session u32
0x10InitializeOK
0x11AuthenticateOK
0x12LockOK
0x20Generate keyKey ID u32
0x21 / 0x22Encrypt / decryptLength-prefixed bytes
0x23Sign / MACLength-prefixed signature / MAC
0x24Verify HMACVerified flag u8
0x25ECDH + HKDFKey ID, length-prefixed salt, info string
0x30Export public keyEncoding u32, length-prefixed DER bytes
0x40List keysCount and key metadata entries
0x41Destroy keyOK

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

Error payload / response ID 0xFF
code:u8 || message_length:u32 || message_bytes

An 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.

CodeMeaning
0x01Authentication required
0x02Authentication failed
0x03Invalid input
0x04Unsupported operation
0x05Missing key
0x06Policy rejected
0x07Storage failure
0x08Bad command
0x09Serialization error
0x0AInitialization failed
0x0BInvalid state
0xFFGeneric 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.