#[repr(u8)]pub enum CommandOpcode {
Show 24 variants
Info = 1,
GetPubkey = 2,
Sign = 3,
GenKey = 4,
ReadConfigZone = 5,
ReadConfigSlot = 6,
VerifyPin = 7,
SetPin = 8,
UnblockPin = 9,
GetPinStatus = 10,
SetPuk = 11,
CloseSession = 12,
EmergencyReset = 13,
ReadSlotBlock = 14,
ReadSlotWord = 15,
WriteConfigZone = 16,
ProvisionSlot = 17,
ProvisionInitialPin = 18,
ProvisionInitialPuk = 19,
ProvisionIoKey = 20,
ReadCounter = 21,
LockConfigZone = 240,
LockDataZone = 241,
LockSlot = 242,
}Expand description
Opcode byte for each command.
Variants§
Info = 1
0x01 - Info: read firmware version, chip serial, provisioning state.
Payload: empty.
GetPubkey = 2
0x02 - GetPubkey(slot): read a slot’s public key (64 bytes).
Payload: [slot: u8].
Sign = 3
0x03 - Sign(slot, digest): produce an ECDSA P-256 signature.
Requires an active PIN session and a touch.
Payload: [slot: u8, digest: [u8; 32]].
GenKey = 4
0x04 - GenKey(slot): regenerate a P-256 key pair.
Requires an active PIN session.
Payload: [slot: u8].
ReadConfigZone = 5
0x05 - Read the 128 bytes of the chip’s config zone.
Payload: [block: u8] where block is in 0..=3. The 128-byte
config zone is returned one 32-byte block at a time so the response
fits in a single report. The host issues this command four times,
once per block, to assemble the full image.
ReadConfigSlot = 6
0x06 - Read the 4-byte SlotConfig + KeyConfig for one slot.
Payload: [slot: u8].
VerifyPin = 7
0x07 - VerifyPin(pin): open a PIN session (30 s window).
Payload: [pin: [u8; 4]] (each byte holds an ASCII digit '0'..'9').
SetPin = 8
0x08 - SetPin(old, new): change PIN within an active session.
Payload: [old: [u8; 4], new: [u8; 4]].
UnblockPin = 9
0x09 - UnblockPin(puk, new_pin): reset PIN counter via PUK.
Payload: [puk: [u8; 8], new_pin: [u8; 4]].
GetPinStatus = 10
0x0A - Read current PIN / PUK retry counters.
Payload: empty.
SetPuk = 11
0x0B - SetPuk(old_puk, new_puk, io_key): change the PUK.
Requires an active PIN session (proves the caller knows the
current PIN). Rewrites slot 6 via the encrypted-write protocol.
Payload: [old_puk: [u8; 8], new_puk: [u8; 8], io_key: [u8; 32]].
CloseSession = 12
0x0C - CloseSession: terminate the current PIN session
immediately, without waiting for the 30 s inactivity timeout.
Idempotent: closing an already-closed session is a no-op and
still returns Ok. No payload from the host. No payload in the
response.
EmergencyReset = 13
0x0D - EmergencyReset(magic, io_key): last-chance reset.
Requires that both PIN and PUK batches are exhausted. The
firmware refuses to run otherwise with the
EmergencyResetNotPermitted status (which carries the actual
tries-remaining figures in its payload).
Regenerates the ECC private keys in slots 0..=4 and 7 (the
user’s secrets are lost), resets PIN to "0000", generates and
stores a fresh random PUK (returned in the response payload).
The user is granted one fresh batch of PIN attempts and one
fresh batch of PUK attempts.
Protected against accidental invocation by a magic word
(0xBADC0FFE, little-endian on the wire). The CLI also
requires an interactive double-confirm before sending.
Payload: [magic: [u8; 4], io_key: [u8; 32]] (36 bytes).
Response payload on success: [new_puk: [u8; 8]].
ReadSlotBlock = 14
0x0E - ReadSlotBlock(slot, block): read one 32-byte block from
a data slot. Useful for bring-up diagnostics (verify what
ProvisionSlot wrote) and for inspecting the IO key in slot 8
before locking the data zone.
The chip applies the slot’s IsSecret / EncryptRead policy and
rejects reads of private ECC keys. No host-side filter is added
here: the chip is the authority.
Payload: [slot: u8, block: u8]. Response: [data: [u8; 32]].
ReadSlotWord = 15
0x0F - ReadSlotWord(slot, block, offset_words): read one 4-byte
word from a data slot. Same policy as Self::ReadSlotBlock.
Payload: [slot: u8, block: u8, offset_words: u8].
Response: [data: [u8; 4]].
WriteConfigZone = 16
0x10 - WriteConfigZone(blob): replace the writable part of the
config zone. Payload: [block: u8, blob: [u8; 32]]. The host issues
this command four times, once per block index 0..=3.
Two blocks of the config zone have a special wire-level shape
because the chip’s Write command refuses some words inside them:
- Block 0 : words 0..=3 (chip-side bytes 0..16) are the
read-only factory area. The firmware writes only words 4..=7
(bytes 16..32) as four 4-byte transfers. Payload bytes 0..16 are
ignored; callers may set them to any placeholder value (the
canonical
config-generatoremits zeros). - Block 2 : word 5 (chip-side bytes 84..88) covers
UserExtra,Selector,LockValue, andLockConfig. Those are modified only via the dedicatedUpdateExtraandLockcommands; theWritecommand rejects a 32-byte transfer that includes them. The firmware writes block 2 as seven 4-byte transfers at word offsets 0..=4 and 6..=7. Payload bytes 20..24 are ignored.
Blocks 1 and 3 are written wholesale as a single 32-byte transfer.
This mirrors the strategy of CryptoAuthLib’s
calib_write_bytes_zone (lib/calib/calib_basic.c).
ProvisionSlot = 17
0x11 - ProvisionSlot(slot, value): write a 32-byte cleartext
value into one of the data slots. Only accepted by the firmware
for the three policy-allowed slots (5, 6, 8). Used at
provisioning to install the initial PIN hash, PUK hash, and IO
key, before LockDataZone. Returns InvalidSlot for other
slots and chip-error after data lock.
Payload: [slot: u8, value: [u8; 32]].
ProvisionInitialPin = 18
0x12 - ProvisionInitialPin: write SHA256("0000" || pin_salt)
into slot 5 in cleartext, where pin_salt is derived from the
chip’s serial. No payload. Used at provisioning instead of
ProvisionSlot --slot 5 so that the host does not need to
reimplement the PIN-hash derivation. Returns Ok (empty
payload) on success.
ProvisionInitialPuk = 19
0x13 - ProvisionInitialPuk: generate a fresh random 8-digit
PUK from the chip’s RNG, compute its hash with the per-chip
salt, write the hash into slot 6 in cleartext, and return the
PUK in the response payload so the operator can record it.
This is the only opportunity to learn the PUK. No payload
from the host. Response: [puk: [u8; 8]].
ProvisionIoKey = 20
0x14 - ProvisionIoKey: generate a fresh random 32-byte I/O
Protection Key from the chip’s RNG, write it into slot 8 in
cleartext, and return it in the response payload so the host
can store it for later encrypted writes. This is the only
opportunity to learn the IO key. No payload from the host.
Response: [io_key: [u8; 32]].
ReadCounter = 21
0x15 - ReadCounter(counter_id): read the raw value of an
ATECC608B monotonic counter without modifying it. Diagnostic
tool used for bring-up and debugging. Payload: [counter_id: u8]
where counter_id is 0 (Counter0, backs PIN slot) or 1
(Counter1, backs PUK slot). Response: [value: [u8; 4]] in
little-endian (the same u32 the chip returns from
Counter(mode=Read)).
Unlike GetPinStatus which converts the
raw count into “tries remaining” via the service’s batch logic,
this command returns the chip’s binary count unmodified. Useful
to verify the batch-arithmetic against the actual hardware
state during development.
LockConfigZone = 240
0xF0 - Lock the config zone permanently.
Payload: [magic: [u8; 4], crc: [u8; 2]]. The CRC is computed
by the host CLI over the full 128 bytes of the current
configuration zone and is verified one last time by the chip
before commit.
LockDataZone = 241
0xF1 - Lock the data zone permanently.
Payload: [magic: [u8; 4]]. No CRC: secret-bearing slots cannot
be read back to compute one.
LockSlot = 242
0xF2 - Lock a single slot permanently.
Payload: [magic: [u8; 4], slot: u8].
Implementations§
Source§impl CommandOpcode
impl CommandOpcode
Sourcepub(crate) const fn from_byte(byte: u8) -> Option<Self>
pub(crate) const fn from_byte(byte: u8) -> Option<Self>
Map a raw byte to a CommandOpcode, if it is a recognized value.
Returns None for any opcode the firmware does not implement,
including reserved-for-future-use values.
Trait Implementations§
Source§impl Clone for CommandOpcode
impl Clone for CommandOpcode
Source§fn clone(&self) -> CommandOpcode
fn clone(&self) -> CommandOpcode
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more