An open-source PKCS#11 v3.2 cryptographic module under Simorgh Labs
fhsm-token — provisioning a tokenInitialises a token, sets its user PIN, and reports what state a slot is in. This is the first command an operator runs; everything else in this project assumes a provisioned token.
It should have existed from the start. FHSM_CSR.md told anyone hitting
CKR_TOKEN_NOT_PRESENT to “initialise it first (C_InitToken, or the
module’s own provisioning tool)” — and there was no such tool. Every
documented path into this project’s own tooling began with a step that could
not be taken.
It went unnoticed because the test suite calls C_InitToken directly from C,
so nothing that ran regularly ever needed the missing piece. It surfaced the
first time someone followed the manual instead.
fhsm-token init [--label TEXT] [--slot N] [--module PATH] [--force]
fhsm-token info [--slot N] [--module PATH]
Both PINs come from the environment:
| Variable | Meaning |
|---|---|
FHSM_SO_PIN |
Security Officer PIN — initialises the token, can reset the user PIN |
FHSM_PIN |
user PIN — what applications log in with |
Neither can be passed as an argument, and passing one is refused rather than
ignored: an argument is visible in ps to every user on the machine. That rule
matters more here than in the other tools, because init is the only command
that handles the SO PIN.
export FHSM_SO_PIN='…'
export FHSM_PIN='…'
fhsm-token info # is this slot blank?
fhsm-token init --label "prod-ca"
fhsm-token info # initialised: yes, user PIN: set
fhsm-csr keygen --label root-ca # now the rest of the tooling works
init destroysC_InitToken erases every object on the token. That is what the operation
means in PKCS#11, not a quirk of this implementation.
So init refuses to run against an already-initialised token unless --force
is given, and says which token it found:
fhsm-token: slot 0 already holds an initialised token ("prod-ca").
Re-initialising DESTROYS every key on it. If that is what you
want, pass --force. If you meant to look, use `fhsm-token info`.
init and info differ by four characters, and one of them loses a CA key.
infoPrints the label, manufacturer, model, serial, PIN-length bounds, and three states worth knowing before anything else fails:
C_InitToken has ever runC_InitPIN has ever run--slot takes a CK_SLOT_ID as the module reports it through
C_GetSlotList, not a position in a list. Omitted, the tools enumerate:
fhsm-csr, fhsm-ca, fhsm-sign use the slot holding a token, and
refuse when several do, listing them with their labels. Signing with a
key the operator did not choose is invisible until someone reads the
certificate.fhsm-token init takes the lowest slot with no token. Where every slot
holds one it refuses, since any choice would destroy keys.fhsm-token info prints the slot it read.So on a module with one token, --slot is never needed; on one with several,
it is compulsory and the refusal tells you the values to choose from.
A blank slot reports initialised: no rather than an error. That is
deliberate on the module’s side too: applications call C_GetTokenInfo before
C_InitToken to discover whether a slot needs provisioning, so returning
CKR_TOKEN_NOT_PRESENT there would make bootstrap impossible.
| Code | Meaning |
|---|---|
0 |
Success |
1 |
Usage error, or a PIN missing from the environment |
2 |
Module could not be loaded, or a PKCS#11 call failed |
5 |
The token is already initialised and --force was not given |
FHSM_CSR.md — keys, requests and the CA’s own certificateFHSM_CA.md — issuing, revoking, revocation lists and OCSPFHSM_SIGN.md — detached signatures over arbitrary dataAGD_OPE.md — operational guidance, including what
FHSM_INTEGRITY_ALLOW_UNSIGNED is for and why it is forbidden in production