808bits

OpenSC

read from source · 0.27.1 plus main · LGPL-2.1 · read at 4fab8b5, 2026-09-10

OpenSC is two things to a PKCS#11 user. Its module is the library behind most smart cards and USB tokens on Linux and macOS, and its pkcs11-tool is the command everyone runs first against any module, HSM vendors’ included. The module’s return values are not chosen where the failure happens. They are chosen in one translation function that maps the card library’s errors onto the specification’s, and the map has a default.

The translation function

Every card operation inside the module returns one of libopensc’s own error codes, of which errors.h defines 84. Before a code reaches the caller it passes through sc_to_cryptoki_error_common, a switch with about twenty-five cases. Wrong PIN becomes CKR_PIN_INCORRECT, a blocked PIN becomes CKR_PIN_LOCKED, a missing card CKR_TOKEN_NOT_PRESENT, a card pulled mid-operation CKR_DEVICE_REMOVED. The card’s “security status not satisfied” status word, which the ISO 7816 layer produces from 0x6982, becomes CKR_USER_NOT_LOGGED_IN. Everything the switch does not name falls through to line 122, which returns CKR_GENERAL_ERROR. That default is the finding. On OpenSC the general error does not mean the library is unusable. It means the card said something the translation table has no word for, which is around sixty of the 84 codes. The card’s own reason is in the debug log one line earlier, as a libopensc name and number. The PKCS#11 caller sees only the general error.

Three exceptions by function name

A small table in front of the switch (lines 37 to 42) overrides the mapping when the calling function is known. A PIN length problem during C_GenerateKeyPair is reported as the general error rather than the PIN code. A card refusing C_Sign or C_Decrypt with “not allowed” comes back as CKR_FUNCTION_FAILED, one of only five places in the module that returns that code at all. So the recoverable failure, on OpenSC, most often means the key on the card is not permitted to do what was asked of it. One line in the switch carries a comment. A detached reader maps to CKR_TOKEN_NOT_PRESENT with /* Maybe CKR_DEVICE_REMOVED ? */ beside it (line 114). The two codes have different pages on this site, and the person who wrote the mapping was not sure either.

What pkcs11-tool prints

The string that ends up in the search box comes from p11_fatal, which finalises the library and prints PKCS11 function C_Login failed: rv = CKR_PIN_INCORRECT (0xa0). The name is looked up in CKR2Str, a switch over 85 return values. A value it does not know, which is every vendor-defined one, prints as unknown PKCS11 error with the hex beside it. That hex is what the decoder on this site is for. pkcs11-tool --list-mechanisms is also the only widely installed tool I know of that prints the per-mechanism key sizes and operation flags from C_GetMechanismInfo (list_mechs), which is the half of the mechanism story the vendor pages here had to be probed for.

Return values with a note for this library

  • CKR_HOST_MEMORY · The library could not allocate host memory. Rare as a real out-of-memory. More often a size computed from bad input, a leak, or a vendor error filed here.
  • CKR_GENERAL_ERROR · Not a failed call but a broken library. The specification says nothing further will work, so retrying it is wasted effort.
  • CKR_FUNCTION_FAILED · A recoverable failure. The library is still usable and the token unchanged, so this one is worth investigating rather than restarting.
  • CKR_ATTRIBUTE_READ_ONLY · The attribute cannot be changed on this object, or cannot be supplied at creation because the token sets it. Computed flags, identity, or a locked object.
  • CKR_ATTRIBUTE_SENSITIVE · The attribute exists and the token will not disclose it. Private key material behind CKA_SENSITIVE or a false CKA_EXTRACTABLE. Not a fault.
  • CKR_ATTRIBUTE_TYPE_INVALID · The object has no such attribute, or this library never stored it. Common when reading fields that only exist for another key type, and in object dumps.
  • CKR_DATA_INVALID · Right length, wrong content. A DigestInfo the token cannot parse, an EC point in the wrong encoding, or on a card, a status word with nowhere else to go.
  • CKR_DATA_LEN_RANGE · Input length the mechanism does not accept. A block cipher without padding, RSA input longer than the modulus, or a raw signing mechanism given a message.
  • CKR_DEVICE_ERROR · The PKCS#11 catch-all for a token that has gone wrong. Usually a stale handle after a reset, a dead client link, or a mechanism the firmware refuses.
  • CKR_DEVICE_REMOVED · The library noticed the token disappear between one call and the next. Usually a pulled card, a USB power event, or a network HSM whose link reset under you.
  • CKR_ENCRYPTED_DATA_INVALID · Ciphertext the token could not decrypt: bad padding, the wrong key, a failed tag. Some libraries use it for every decrypt failure, against padding oracles.
  • CKR_FUNCTION_NOT_SUPPORTED · The library exports the function and will not perform it. Usually a v3.0 message call, a dual-function update, or a wrap on a token that never wraps.
  • CKR_KEY_TYPE_INCONSISTENT · The key's type does not fit the mechanism. An EC key on an RSA mechanism, an Edwards key on ECDSA, or a find that returned the certificate instead.
  • CKR_OPERATION_ACTIVE · An Init was called while the session already holds an operation of that kind. A multi-part operation that was never finished, or two threads on one session.
  • CKR_OPERATION_NOT_INITIALIZED · Sign, Update or Final with no matching Init on this session. An Init whose failure was ignored, an operation the library reset, or a session shared by threads.
  • CKR_PIN_INCORRECT · The credential was wrong. The important part is what your code does next, because automatic retries are how tokens get locked.
  • CKR_PIN_LEN_RANGE · The PIN is too short or too long for this token. The limits are in the token info and are applied before the PIN is looked at, so the PIN may also be wrong.
  • CKR_PIN_LOCKED · The token has locked the PIN after too many failed attempts. On most HSMs this is not something you can wait out, and on some it destroys the partition.
  • CKR_TEMPLATE_INCOMPLETE · The template does not fully specify the object. A missing CKA_CLASS or CKA_KEY_TYPE on create, a missing CKA_VALUE_LEN on generate, or a vendor rule.
  • CKR_TOKEN_NOT_PRESENT · Better news than it looks: the slot identifier was right. On a network HSM this usually means the client cannot reach the partition rather than a missing card.
  • CKR_TOKEN_NOT_RECOGNIZED · The library saw a device in the slot and has no driver for it, or the card answered in a way it could not parse. A smart card code far more than an HSM one.
  • CKR_USER_ALREADY_LOGGED_IN · A login on a token that already has that user logged in through another session. Two components sharing a token, or a retry after a login that succeeded.
  • CKR_USER_NOT_LOGGED_IN · A private object needs an authenticated session. Often a login that happened on a different session, or one that a token event quietly ended.
  • CKR_DOMAIN_PARAMS_INVALID · The domain parameters are not ones this token accepts. An EC curve the token lacks or in the wrong encoding, or DH parameters given where the token makes them.
  • CKR_CRYPTOKI_ALREADY_INITIALIZED · C_Initialize on a library that is already initialized in this process. Usually two components sharing one module, or a fork the library did not notice.

How this page was made

Read from the source at the commit linked above, with every claim pinned to a line. Counts of return sites are from a search over the library's own code and are only as exact as a search can be. No mechanism table is shown, because there is no card on the machine this site is built from and the module lists no slots without one.

Scope. Read from the OpenSC repository at the commit named above, the main branch on the day this page was written and a few months after the 0.27.1 release. Counts of return sites are from searching the source under src/pkcs11 and are approximate. No mechanism table is shown, because there is no card on the machine this site is built from and the OpenSC module lists no slots without one.

Sources

  • OpenSC repository at 4fab8b5, OpenSC on GitHub. Read 2026-09-10. Used for the error translation, the pkcs11-tool output format and the return site counts.