808bits

CKR_PIN_LOCKED

PKCS#11 return value · 0x000000A4 · decimal 164
hex 0x000000A4 decimal 164 name CKR_PIN_LOCKED

Every other authentication error in this specification is recoverable by typing the right thing. This one is not. The token has counted consecutive failures up to its limit and stopped accepting the credential entirely, and what happens next is decided by the device's policy rather than by anything the caller does. On a production HSM that policy is sometimes destructive, which makes this the code most worth designing against rather than handling.

What the token is reporting

The token’s failed-attempt counter for this role has reached its limit. The credential is no longer accepted even if it is correct, and clearing that state needs an administrator, a different role, or in the worst case a reinitialization that destroys the keys.

Likely causes

Ordered by how often they turn out to be the answer. That ordering is a judgement from experience, not a measured frequency.

A retry loop with a stale credential

The most common way a token gets locked is not a person mistyping. It is an application that reads a PIN from configuration, gets an authentication failure, and retries, three or four times, in a second. A rotated secret that nobody updated in one deployment will lock a token faster than any human could.

Check it: Look at whether the failures arrived faster than a person could type. If they did, the loop is the cause, and the credential source is where the wrong value came from.

Fix: Never retry an authentication failure automatically. Treat an incorrect credential as fatal to that process and let something else raise the alarm.

Several processes sharing one credential, one of them stale

The counter is on the token and counts every failure from everywhere. One misconfigured instance among a dozen healthy ones will lock the token for all of them, and the instance that caused it is not the one that reports the problem.

Check it: Check every client of that token, not the one that noticed. The failing one is usually the one nobody thought was still running.

Someone is trying credentials against it

The counter exists for this reason, and a lockout is the control working rather than failing. It is the least likely explanation and the one with the largest consequence if it is true.

Check it: Read the token’s audit log for the failures, and check where they came from before unlocking anything.

Which calls return it

C_Login, C_SetPIN

What it is not

It is not a timeout, and it does not usually clear itself. Waiting is the wrong response. On tokens where a counter does reset after a period, that period is measured against the device’s own clock and not the calling application’s.

Often confused with

  • CKR_PIN_INCORRECT: The recoverable one, and the state immediately before this one. Code that treats them alike is code that will eventually turn a typo into a lockout.
  • CKR_PIN_EXPIRED: The credential is right and too old. That needs a new PIN rather than an administrator.

See also

By library

Thales ProtectServer

Worth stating plainly, because it shapes how this page was written. Reaching this state on a real token means deliberately failing authentication until the counter trips, and that is a persistent change to the device. None of the examples here were produced that way. The mechanism and constant data on this site comes from read-only calls that cannot alter token state.

SoftHSMv2

SoftHSMv2 never returns this. There is no retry counter. [Token::logi nUser](https://github.com/softhsm/SoftHSMv2/blob/884cb38f3d2012a0447b d5f50dbd29c429987c41/src/lib/slot_mgr/Token.cpp#L150-L184) sets the count-low flag on a wrong PIN and accepts the right one on the next attempt however many misses came before, which I confirmed with five wrong PINs in a row on a fresh token. A test suite that retries PINs will pass on SoftHSM and lock a real token.

OpenSC

On a card this is what libopensc’s SC_ERROR_AUTH_METHOD_BLOCKED becomes in the translation switch ([misc.c](https://github.com/OpenSC/ OpenSC/blob/4fab8b57301f035432191d582922d95d7d426802/src/pkcs11/misc.c #L70-L123)). The card counted the failures itself and OpenSC only relays the state. Unblocking is a card operation with the PUK, through pkcs11-tool --unlock-pin or the card’s own tooling, and nothing the PKCS#11 session does can undo it.

Sources

Every description, cause and check on this page is written from scratch. The specification is cited for the constant's name and its number, which are facts, and for nothing else.