Secrets, PKI & CertificatesXV · KMS, HSM and Key ProtectionKeyProtection
Hardware security modules and what non-exportable really means
What you'll learn
- Separate the sensitivity attribute from the extractability attribute and state what each one blocks
- Select the attributes an auditor should read to learn a key's history rather than its current state
- Identify the wrapping defaults that allow a protected key to be exported or re-imported weakened
- State the scope and the expiry of a FIPS 140-3 validation in terms a risk owner can act on
Prerequisites
Verified against OpenSSL 3.5.x teaching target; 3.0+ minimum · OpenSSH 10.x teaching target; 8.2+ minimum for certificate workflows · OpenBao 2.6.x · Smallstep step-ca 0.30.x · Certbot / Pebble Certbot current release; Pebble 2.10.x ACME test server · Kubernetes (cross-course target) 1.36.x · PostgreSQL 17.x · 2026-08-26
A non-exportable key is one the module will not emit in plaintext under any command you are able to issue. That is a narrower claim than most architecture documents assume, and the gap between the narrow claim and the assumed one is where real incidents live. The standard interface that expresses the claim is PKCS #11, and reading how it does so is the fastest route to understanding what your hardware actually guarantees.
The two attributes that make a key non-exportable
PKCS #11 defines the C programming interface called Cryptoki, an object-based view of a device that holds keys and performs operations on them. Keys are objects; objects have attributes; two of those attributes decide exportability, and they are independent of each other.
CKA_SENSITIVE CK_TRUE certain attributes of the key cannot be
revealed in plaintext outside the token
CKA_EXTRACTABLE CK_FALSE the key cannot be wrapped out of the token
at all
Either condition on its own suppresses plaintext readout of the
key value. Only CKA_EXTRACTABLE = CK_FALSE also blocks wrapping.
The specification is explicit that if the sensitivity attribute is true, or the extractability attribute is false, certain attributes of the key cannot be revealed in plaintext outside the token. Both attributes are also one-way. Sensitivity cannot be changed once it has been set true, and extractability cannot be changed once it has been set false; each becomes a read-only attribute at that point. There is no supported command that walks either of them back, which is exactly the property you want and exactly the property that makes the creation-time template the only chance you get.
flowchart TD
A["Key object inside the token"] --> B{"CKA_EXTRACTABLE"}
B -- "CK_FALSE" --> C["Cannot be wrapped out\noperations only"]
B -- "CK_TRUE" --> D{"CKA_SENSITIVE"}
D -- "CK_TRUE" --> E["No plaintext readout\nbut wrapping is permitted"]
D -- "CK_FALSE" --> F["Value readable\nnot a protected key"]
The middle branch is the one that surprises people. A key that is sensitive but still extractable cannot be read out in clear, yet it can be wrapped under another key and carried away as ciphertext. That is a perfectly legitimate design when you intend to move keys between modules, and a serious finding when you believed the key could never leave. Attempting to wrap a key that is genuinely non-extractable returns a distinct refusal saying so, which is different from the refusal a module returns when it merely cannot perform the requested wrap.
What still works, and what an auditor should read
Non-exportability removes one thing only: getting the key value out. Everything the module can do internally remains available.
- Encrypt and decrypt, with the key never leaving the module.
- Sign and verify, which is how a certificate authority key or a code-signing key normally lives.
- Wrap and unwrap other keys, which is how a non-exportable key becomes the wrapping key in the previous lesson’s pattern.
- Derive new keys from an existing key plus public inputs.
- Encapsulate and decapsulate, the key-establishment functions added in version 3.2 alongside its post-quantum mechanisms.
An auditor who reads the current values of the two attributes learns what is true now. That is not the question they came to ask. The history is carried by a different pair: one attribute is true only if the key has always been sensitive, and another is true only if the key has never been extractable. A key that was created extractable, wrapped out to a laptop during a migration in 2023, and then hardened afterwards presents exactly the same current attributes as a key that was born inside the module and never left. Only the historical attributes tell them apart, and only they belong in a control that claims a key has never existed outside the boundary.
The defaults that undo the protection
Two specific defaults in the standard are worth checking on every token you operate, because both fail open.
The first governs which keys may be used to wrap a protected key. An attribute exists to require that wrapping is only performed with a wrapping key that the security officer has explicitly marked trusted, and its default is false. Left at the default, a sensitive-but-extractable key can be wrapped under any key present on the token, including one an attacker with the right role just created. Turning the requirement on, and reserving the trusted marking for keys the security officer sets, is what makes the constraint meaningful.
The second governs what happens on the way back in. An unwrap creates a new key object, and unless the wrapping key carries a template dictating the attributes of anything unwrapped with it, the attacker chooses those attributes. That is how a key wrapped out under strong controls returns as an ordinary extractable object that can then simply be read. The unwrap template is the control that closes it.
What a FIPS 140-3 validation actually says
FIPS 140-3 states that there are four increasing, qualitative security levels. It does not contain the level-by-level requirements. The standard aligns with ISO/IEC 19790:2012 and directs testing to ISO/IEC 24759:2017, and those documents are sold rather than published. Any slide that quotes “FIPS 140-3 Level 3 requires…” is really paraphrasing a paywalled ISO clause, and the honest thing is to say so and cite the ISO reference rather than invent wording.
The requirements are grouped into eleven areas: module specification, module interfaces, roles and services and authentication, software and firmware security, operating environment, physical security, non-invasive security, sensitive security parameter management, self-tests, life-cycle assurance, and mitigation of other attacks. A certificate records a level for each area as well as a separate overall level, so “Level 3” without qualification is an incomplete statement about a module.
One level-differentiated requirement is reproduced in free CMVP material and is worth knowing, because it is the one that touches key ceremonies directly.
Entry and output of plaintext security parameters
Levels 1 and 2 may use physical ports and logical interfaces
shared with other ports and interfaces
Level 3 must be entered or output either encrypted or
over a trusted channel
Level 4 adds multi-factor, separate, identity-based
operator authentication for each key component
Note the vocabulary while you are here. FIPS 140-3 speaks of sensitive security parameters, which comprise critical security parameters and public security parameters. The older habit of saying “CSP” for everything belongs to 140-2 and no longer covers the full set.
What a validation does not say
The standard is unusually direct about its own limits. Its qualifications section states that conformance to the standard is not sufficient to ensure that a particular module is secure, and that the operator is responsible for deciding whether the security provided is acceptable and for accepting the residual risk. Four practical consequences follow.
- A validation binds a version, not a product line. It covers a specific module version in a specific tested configuration. Your firmware revision is either that one or it is not.
- Validated is not the same as enabled. Validated modules ship an approved mode and a non-approved mode. The module’s security policy document enumerates what is permitted in the approved mode, and nothing in the certificate proves you turned it on.
- Validations expire. They carry a sunset date, standard five years, two for an interim validation, and a follow-up submission is required to extend one.
- Validations can be withdrawn. A revoked validation may no longer be referenced to demonstrate compliance, with triggers including discovery of a security flaw or of false information in the submission. Moving to the historical list is softer: agencies may make their own risk determination about continued use.
That last mechanism is about to matter to a great many inventories. FIPS 140-2 validated modules are accepted through 21 September 2026, and on 22 September 2026 all FIPS 140-2 certificates move to the historical list. If your compliance evidence names a 140-2 certificate, that evidence has a date on it that has now nearly arrived.
Production discipline
- Set the attributes in the creation template. Both are one-way, so the object you create is the object you keep. There is no remediation pass afterwards.
- Audit on history, not on state. A control that reads only the current sensitivity and extractability attributes cannot distinguish a key that never left from one that was hardened after a migration.
- Turn on the trusted-wrapping requirement and set an unwrap template. Both default to the permissive setting, and both are single configuration decisions that close an entire class of extraction.
- Record the certificate number, the module version and the sunset date together. A certificate number alone cannot be checked against your running firmware, and cannot warn you about its own expiry.
- Ask the vendor for the mechanism list, not the badge. A Cryptoki library need not implement every function, and an unsupported one is allowed to exist purely as a stub, so “supports PKCS #11” tells you almost nothing about which algorithms are actually present.
Cross-course references
- Linux for Production Sysadmins - Part XXIX (Hardening) covers the host-level controls that still apply to the machine driving the module, which remains an ordinary attack surface.
- Kubernetes for Production Sysadmins - Part LXIV (SupplyChain) covers signing keys whose value comes from being impossible to copy, the canonical use for a non-extractable key.
- Git, CI/CD & GitOps for Infrastructure Engineers - Part LXIX (ArtifactSigning) covers release signing, where per-use authorisation turns a stolen pipeline credential into a single refused request.
Quiz
Knowledge check · 4 questions
Q1. A review finds a signing key on an HSM whose sensitivity attribute is true and whose extractability attribute is also true. The team says the key is protected because it cannot be read out. What is the accurate assessment?
Q2. A FIPS 140-3 certificate applies to a specific module version in a specific tested configuration, carries a sunset date, and can be revoked, so it is not a durable statement that a deployment is secure.
Q3. Which attributes should an auditor read to establish that a key has never existed outside the module, and why are the current sensitivity and extractability values insufficient?
Q4. Determine whether the control has actually failed, what you would collect to decide, and what change closes the gap.
A payments platform states in its control documentation that the transaction signing key on its HSM has never left the module. During a control test on 14 May, the reviewer reads the key object and finds sensitivity true and extractability false, but also finds that the attribute recording whether the key has always been sensitive is false. The HSM was replaced in 2024 and the platform team recalls a migration weekend.
Passing score: 75%. Answers are checked in this browser.