feat(adapters/pkcs11): HSM-backed MAC (vault.Macer) verified against SoftHSM2#11
Closed
canaan5 wants to merge 6 commits into
Closed
feat(adapters/pkcs11): HSM-backed MAC (vault.Macer) verified against SoftHSM2#11canaan5 wants to merge 6 commits into
canaan5 wants to merge 6 commits into
Conversation
Foundation for a PKCS#11/HSM-backed vault.Vault, in a separate cgo module so the stdlib-only core is untouched. NOT production-ready. Implemented and build-verified (cgo, miekg/pkcs11): - Config + Open/Close: module load, token selection, session, C_Login. - Key lookup by CKA_LABEL (keyRef -> object handle). - Compile-time vault.Vault conformance; no-HSM tests for stubs + config. Deliberately stubbed (return ErrNotImplemented), with documented intended PKCS#11 mappings: - GenerateMAC/VerifyMAC: ISO 9797-1 -> mechanism mapping is HSM-specific; must be verified against SoftHSM and security-reviewed. - EncryptPINBlock: EncodePINBlock + CKM_DES3_ECB (forms clear PIN block in host). - TranslatePIN: BLOCKED. A secure HSM translate is an atomic operation where the clear PIN never leaves the token; stock PKCS#11 has no such mechanism, and the decrypt-reencrypt emulation of the current vault.Vault contract would expose the clear PIN block in host memory (PCI PIN Security violation). This surfaces a v1 vault-API decision (see README + ROADMAP B1): the production HSM path likely needs HSM-oriented operations over encrypted PIN blocks, rather than the software-model clear-PIN interface. No working/secure crypto is shipped here on purpose.
Make the key-management façade HSM-adapter-ready by splitting it into small capability interfaces, so an adapter implements exactly what its device supports. - Add PINEncryptor, PINTranslator, and Macer. Vault is now their composition, so it keeps the same method set — source-compatible; SoftVault and SealedVault still satisfy Vault unchanged. - PINTranslator documents the PCI PIN Security contract: a conforming hardware implementation must re-encipher the PIN block atomically inside the device so the clear PIN never leaves it; an adapter that cannot (e.g. stock PKCS#11) must not implement the interface, since callers rely on its presence to mean the operation is PIN-secure. - A general-purpose PKCS#11 HSM provides Macer (and possibly PINEncryptor); a payment HSM (Thales payShield, Futurex) additionally provides PINTranslator. Callers type-assert for the narrowest capability they need. Adds capability-detection tests. gofmt/vet clean; ./... builds, vault/flow/gateway pass under -race.
…aces # Conflicts: # CHANGELOG.md
Turn the PKCS#11 foundation into a working, capability-correct MAC adapter. What it does: - Implements vault.Macer (GenerateMAC/VerifyMAC) for ISO 9797-1 algorithm 1 (single-DES CBC-MAC) and algorithm 3 (ANSI X9.19 retail MAC). - Composes the MAC from the token's 3DES primitives (CKM_DES3_CBC/CKM_DES3_ECB), since modern tokens disable single-DES and expose no retail-MAC mechanism: a single-DES E_K is obtained by presenting K as a triple-length key K||K||K. The key never leaves the token; only the public padding/message are host-side. - Output is byte-for-byte identical to vault.GenerateMAC, cross-checked against a real token under SoftHSM2 (new CI job; verified locally on SoftHSM 2.7.0). Capability surface (the security property): - The type now advertises exactly vault.Macer. The PIN methods are REMOVED, not stubbed, so the type does not structurally satisfy vault.PINTranslator — callers rely on that interface's presence to mean the op is PIN-secure, and a stock PKCS#11 HSM has no PCI-compliant atomic translate. EncryptPINBlock is a clear-PIN issuer-context op and likewise omitted. A test asserts the type is not a PINTranslator/PINEncryptor/Vault. Tests: - No-HSM: capability surface, ISO 9797-1 padding vectors, config validation. - SoftHSM2 (env-gated, skips without a token): provisions its own keys and cross-checks adapter MAC == vault.GenerateMAC across both algorithms, both paddings, empty/partial/multi-block messages, plus verify match/truncate/tamper. CI: new adapters/pkcs11 job installs softhsm2, provisions a token, runs the race suite. README rewritten for the MAC-only capability and key provisioning.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Turns the PKCS#11 foundation into a working, capability-correct MAC adapter for a general-purpose HSM.
What it does
Implements
vault.Macer(GenerateMAC/VerifyMAC) for ISO 9797-1 algorithm 1 (single-DES CBC-MAC) and algorithm 3 (ANSI X9.19 retail MAC), composed from the token's 3DES primitives (CKM_DES3_CBC/CKM_DES3_ECB). Modern tokens disable single-DES and expose no retail-MAC mechanism, so a single-DESE_Kis obtained by presentingKas a triple-length keyK‖K‖K. The key never leaves the token; only the public padding/message are host-side.Output is byte-for-byte identical to
vault.GenerateMAC— cross-checked against a real token under SoftHSM2 (new CI job; also verified locally on SoftHSM 2.7.0): both algorithms, both paddings, empty/partial/multi-block messages, plus verify match / 4-byte-truncated / tamper.Capability surface (the security property)
The type now advertises exactly
vault.Macer. The PIN methods are removed, not stubbed, so the type does not structurally satisfyvault.PINTranslator— callers rely on that interface's presence to mean the op is PIN-secure, and a stock PKCS#11 HSM has no PCI-compliant atomic translate. A test asserts the type is not aPINTranslator/PINEncryptor/Vault. PIN translation lives in the payment-HSM adapter (#13, payShield).Tests
vault.GenerateMAC, verify/tamper.Note on stacking
Built on #12 (
vaultcapability interfaces), required forMacer. Until #12 merges, this diff includes #12's commits; it cleans up once #12 lands. Separate cgo module; the core stays stdlib-only.