How It Works
How the DuoKey PKCS#11 library behaves — the proxy model, sessions, login, sensitive attributes, configuration precedence and known quirks.
These notes complement the Overview and the Function Coverage. They describe how the provider behaves so integrators can reason about errors, sessions and configuration.
The proxy model
The library performs no cryptography locally and holds no keys. Each Cryptoki call is turned into a single HTTPS request to the DuoKey Cockpit, which executes the operation against the tenant vault or backing HSM and returns the result. The library only encodes payloads and forwards them; key material never crosses the PKCS#11 boundary onto the application host.
- Serial sessions only. All library state is serialized behind a single global lock, and only serial sessions are supported —
C_OpenSessionrejects any request lackingCKF_SERIAL_SESSIONwithCKR_SESSION_PARALLEL_NOT_SUPPORTED. The slow network round-trip is performed without holding the lock, so a slow backend does not block unrelated calls. - Object handles. PKCS#11 integer handles map to server-side object identifiers. Interning de-duplicates by server id, so re-discovering the same object returns the same handle.
C_DestroyObjectdeletes the object at the Cockpit, then forgets the local handle.
Login & authentication
C_Login sends no PIN — the pPin / ulPinLen arguments are ignored. Backend authentication is carried per request by the bearer access token from the configuration. C_Login only accepts CKU_USER and CKU_CONTEXT_SPECIFIC (the SO role returns CKR_USER_TYPE_INVALID) and simply moves the session to the user state so the application proceeds. C_GenerateKey and C_GenerateKeyPair require the logged-in state.
Attributes & sensitive material
C_GetAttributeValue answers from a cached descriptor and follows the standard two-call Cryptoki buffer protocol (a null value pointer returns the required length; a too-small buffer returns CKR_BUFFER_TOO_SMALL).
CKA_VALUEalways returnsCKR_ATTRIBUTE_SENSITIVE— raw key material lives only in the backend.- Keys report sensible defaults:
CKA_TOKEN = true,CKA_SENSITIVE = true,CKA_EXTRACTABLE = false,CKA_NEVER_EXTRACTABLE = true,CKA_MODIFIABLE = false. - An unrecognized attribute type returns
CKR_ATTRIBUTE_TYPE_INVALID. Unrecognized attributes in find filters and key-generation templates are silently dropped.
AES-GCM handling
For AES-GCM the authentication tag is concatenated onto the ciphertext (ciphertext || tag) and split back on decrypt, so callers see a single opaque blob.
Wire protocol
Every Cryptoki operation is a single HTTPS request to the one configured server_url, authenticated with the bearer access token. Cryptographic failures are returned in a way that lets the library map the exact Cryptoki return value rather than a generic transport error.
Configuration precedence
The library reads a TOML file from DKE_PKCS11_CONF; environment variables override the file. Precedence is environment variable (non-empty) > TOML file > built-in default. If no file is set, the config is built entirely from environment variables (at least DKE_PKCS11_SERVER_URL is required).
verify_tls = falsedisables TLS certificate validation — testing only.- Logging is initialized on
C_Initializefromlogging_level/logging_folder.
See the Overview → Configuration for the full pkcs11.toml schema and the variable list.
Known quirks & caveats
CKM_SHA_1is advertised byC_GetMechanismList, but a SHA-1 digest is rejected by the backend (CKR_MECHANISM_INVALID) — only SHA-256/384/512 are computed.- Encrypt and decrypt use the same vault primitive, so the Cryptoki mechanism is advisory — round-trip integrity is guaranteed for the opaque blobs the consumer stores.
C_CreateObject, C_CopyObject and C_SetAttributeValue are not supported (CKR_FUNCTION_NOT_SUPPORTED). Objects are created through the key-generation operations (C_GenerateKey / C_GenerateKeyPair) or discovered with C_FindObjects, never assembled attribute-by-attribute on the client.
Because this is a general Cryptoki provider, the advertised mechanisms (AES / RSA / EC / SHA / HMAC) are used per consumer. Oracle TDE uses AES only — its master key is AES256 — see Oracle TDE → Cockpit v2.