PINs & lockout
The badge has two independent PIN systems with different lockout behaviour. Confusing them is the most common source of “did I just brick my badge?” worries, so this page keeps them strictly apart.
- The badge PIN unlocks the device UI and the serial console. Its lockout is a temporary rate limit that recovers automatically.
- The OpenPGP card PINs (PW1 / PW3) follow smartcard semantics: their retry counters are persistent and reaching zero is terminal until reset.
All PINs are managed by PinManager and stored, signed, in secure-element
R-Memory slot 0 (see Secure element & key generation).
Badge PIN
Section titled “Badge PIN”| Property | Value | Source |
|---|---|---|
| Length | 4-8 digits, digits only | PinManager.h BADGE_PIN_MIN/MAX; PinManager.cpp |
| Default | 123456 | PinManager.h DEFAULT_BADGE_PIN |
| Stored as | LEFT(SHA256(PIN), 16) | PinManager.cpp computeBadgeHash |
| Max attempts | 3 (MAX_RETRIES) | PinManager.h |
| Comparison | constant-time-style | PinManager.cpp compareHash |
How the badge PIN lockout actually works
Section titled “How the badge PIN lockout actually works”The badge PIN does not use a persistent attempt counter on the chip. Only a binary “locked” flag is stored in R-Memory; the retry count lives in RAM. The behaviour is a self-recovering rate limit:
- On boot the firmware grants one attempt (or zero if the locked flag was set) and starts a recovery timer.
- A correct PIN restores the counter to 3 and clears any lock.
- A wrong PIN decrements the counter. When it hits zero, the locked flag is set and the recovery timer (re)starts.
- After the 60-second recovery window expires, the counter is restored to 3 and the locked flag is cleared automatically.
The serial console reuses the same badge PIN and the same lockout state: an
exhausted badge PIN blocks AUTH over serial for the recovery window, and the
console reports the remaining seconds.
Changing the badge PIN
Section titled “Changing the badge PIN”Set or change it from the badge’s PIN settings. A new badge PIN must satisfy the 4-8 digit rule and, if a duress PIN is armed, must differ from it.
OpenPGP card PINs (PW1 / PW3)
Section titled “OpenPGP card PINs (PW1 / PW3)”When the badge is used as an OpenPGP smartcard over USB CCID, it presents the two standard OpenPGP PINs. These are separate from the badge PIN, with their own values and their own counters.
| PIN | Role | Min length | Max length | Default | Max attempts |
|---|---|---|---|---|---|
| PW1 | User PIN (sign/decrypt/authenticate) | 6 | 16 | 123456 | 3 |
| PW3 | Admin PIN (card management) | 8 | 16 | 12345678 | 3 |
Both are hashed with OpenPGP iterated + salted S2K over SHA-256 (default 100000 iterations) with a per-PIN random salt, as required by the OpenPGP card KDF-DO (see ADR-0004).
Terminal lockout
Section titled “Terminal lockout”PW1 and PW3 use smartcard semantics: the retry counter is decremented and persisted synchronously before the comparison, so a power-cycle in the middle of a verify cannot resurrect an attempt. When a counter reaches zero, that PIN is blocked.
- A blocked PW1 can be unblocked by the admin (PW3) via the OpenPGP RESET RETRY COUNTER command, or by the Resetting Code path.
- A blocked PW3 is terminal: there is no host command that resets the admin PIN’s counter on the card. Recovering an admin-locked card means wiping the device and re-initialising.
The OpenPGP card protocol itself (CCID transport, APDUs, status words) is covered in the developer protocol docs.
At a glance
Section titled “At a glance”| Badge PIN | OpenPGP PW1 | OpenPGP PW3 | |
|---|---|---|---|
| Scope | device UI + serial | OpenPGP card user | OpenPGP card admin |
| Length | 4-8 | 6-16 | 8-16 |
| Counter | RAM, self-recovering | persistent, terminal | persistent, terminal |
| After max attempts | 60 s recovery, then restored | blocked until PW3/RC reset | blocked, wipe to recover |