Attestation bundle verification
Verifying an attestation bundle requires a series of steps to, at a minimum, check the chain of trust between a key and its generating HSM. All verifications mentioned can be performed by any cryptographic provider as long as the required algorithms are supported. For a worked example for verification using Python and nShield libraries, see Bundle verification example.
Overview
Approaches
There are two possible approaches to verifying an attestation.
The first approach just verifies that the key was created in an nShield HSM. It says nothing about the policy controlling use of the key. If the reason for verification is to meet a formal requirement for keys generated in an HSM, and there is an appropriate level of trust between the key owner and the verifier, this approach is quite adequate.
The second approach does extensive checks on the policy controlling the use of the key, i.e. its Access Control List (ACL). This may be more appropriate if there is only limited trust between the key owner and the verifier. The nShield Key Attestation Verifier implements this second approach but may be unnecessary overhead for custom verifiers.
For the first approach the following verification steps are required:
-
WV1 (warrant verification)
-
MSCV1 (module state certificate verification)
-
MSCV2 (extracting KML from the verified module state certificate)
-
KGCV1 (key generation certificate verification)
-
KGCV2 (public key binding)
-
CSRL1 (CSR binding, if a CSR is in use)
The following steps are not required in the first approach:
-
MSCV3, MSCV4, MSCV5
-
WBCV1, WBCV2, WBCV3, WBCV4, WBCV5
-
ACLV1, ACLV3, ACLV4
-
WB1, WB2, WB3, WB5, WB6
-
RB1, RB2, RB3, RB5
-
KV1, KV2, KV3
For the second approach, all steps are required (except possibly CSRL1, KV1, KV2 and KV3, depending on the situation and the verifier’s requirements).
Key Hashes
All key hashes (denoted H(…) below) are nCore key hashes. At present they are always SHA-1 hashes but in the future wider hashes will be supported. For further information on the format, see nCore Key Hash.
Certificates
A number of certificates are used in the verification process.
-
a warrant (see nShield Warrants for details) provides the KLF2 and ESN (given trust in the root key)
-
a module state certificate provides the KML, the module’s HKNSO and list of installed module keys (given trust in KLF2)
-
CertKMaKMCbKNSO or CertKMaKMCaKFIPSbKNSO allow validation of KM and KMC (given trust in KNSO)
-
CertKREaKRAbKNSO allows validation of KRE and KRA (given trust in KNSO)
-
a key generation certificate gives the application key ACL, given trust in KML
Note that the material supplied for the world binding certificates (i.e. Cert*) is the signatures only. The certificate bodies are reconstructed during the verification process. These certificates don’t provide any key hashes directly, but they do allow validation of key hashes supplied by other fields from the attestation bundle.
Ciphersuites and recovery mechanisms
The following recovery mechanisms correspond to the given ciphersuites.
ciphersuite | recovery mechanism |
---|---|
CipherSuite_DLf1024s160mDES3 |
Mech_RSApPKCS1 |
CipherSuite_DLf1024s160mRijndael |
Mech_BlobCryptv2kRSAeRijndaelCBC0hSHA512mSHA512HMAC |
CipherSuite_DLf3072s256mRijndael |
Mech_BlobCryptv2kRSAeRijndaelCBC0hSHA512mSHA512HMAC |
CipherSuite_DLf3072s256mAEScSP800131Ar1 |
Mech_BlobCryptv3kRSAOAEPeAESCBC0dCTRCMACmSHA512HMAC |
Unpacking
The first step is to unpack the bundle from JSON. There is no signature checking here, the JSON bundle is just a container for certificates, key hashes, etc. If the implementation language has a distinction between 'safe' and 'unsafe' JSON decoders, the safe one should be used.
Warrant verification
Step WV1: Verify warrant under configured root key, yielding the KLF2 and ESN. If verification fails, exit with an error. Details on the structure and verification of a warrant can be found in Warrant format. It is essential to decide what root key will be trusted. Normally this would be KWARN-1 for nShield HSMs.
Module state certificate verification
The module state certificate is verified under KLF2. Having verified it following needs to be extracted:
-
the module’s ESN (the ESN attribute)
-
the module’s KML (the KML or KMLEx attributes)
If present the following can be retrieved:
-
the module’s HKNSO (the KNSO or KNSOEx attributes). This must be consistent with the knsopub field of the bundle if that is present.
-
the module’s module key list (the KMList or ModKeyInfoEx attributes). The hkm field must be among this list if it is present.
Step MSCV1: Verify modstatemsg and modstatesig under KLF2. If verification fails, exit with an error.
Step MSCV2: Extract ESN, KML and (optionally) HKNSO and module key list. If they are not present, exit with an error.
Step MSCV3: Check ESN from the module state certificate matches ESN from the warrant. If not, exit with an error.
Step MSCV4: Check H(knsopub) matches HKNSO, if knsopub present. If knsopub present but they don’t match, exit with an error.
Step MSCV5: Check hkm appears in module key list, if hkm present. If hkm is present but can’t be found, exit with an error.
Attestation bundles generated by standard nShield tooling will always include knsopub, so a verifier might make the simplifying assumption that it is always present. The only situation in which it would be appropriate to omit from an attestation bundle is if no part of the key’s ACL depends (even indirectly) on KNSO, which would rule out any blobbing actions.
World binding certificate verification
If any of the world binding certificates (fields Cert*) are present, they must be verified under KNSO.
It is expected that only one of CertKMaKMCbKNSO and CertKMaKMCaKFIPSbKNSO will be present. Verification is only possible if knsopub is present. To do this, it’s necessary to reconstruct the certificate subject.
Each certificate consists of a raw bytes representation of a header string and a series of key hashes. At the time of writing, these are be M_KeyHash representations. The header and keys depend on the certificate type and ciphersuite:
-
CertKMaKMCbKNSO:
-
ciphersuite DLf1024s160mDES3:
"Module keys\0" || H(KNSO) || H(KM) || H(KMC)
-
ciphersuite DLf1024s160mRijndael:
"Module keys: KM type Rijndael\0" || H(KNSO) || H(KM) || H(KMC)
-
other ciphersuites:
"Module keys: suite = <ciphersuite>\0" || H(KNSO) || H(KM) || H(KMC)
(e.g.
"Module keys: suite = DLf3072s256mRijndael\0" || H(KNSO) || H(KM) || H(KMC)
)
-
-
CertKMaKMCaKFIPSbKNSO:
-
ciphersuite DLf1024s160mDES3:
"Module setup, FIPS3\0" || H(KNSO) || H(KM) || H(KMC) | H(KFIPS)
-
ciphersuite DLf1024s160mRijndael:
"Module setup, FIPS3; KM type Rijndael\0" || H(KNSO) || H(KM) || H(KMC) | H(KFIPS)
-
other ciphersuites:
"Module setup, FIPS3; suite = <ciphersuite>\0" || H(KNSO) || H(KM) || H(KMC) | H(KFIPS)
(e.g.
"Module setup, FIPS3; suite = DLf3072s256mRijndael\0" || H(KNSO) || H(KM) || H(KMC) | H(KFIPS)
)
-
-
CertKREaKRAbKNSO:
"Card Recovery\0" || H(KNSO) || H(KRE) || H(KRA)
Step WBCV1: Verify CertKMaKMCbKNSO under knsopub if it the certificate is present. If any dependency (including knsopub) is absent or verification fails, exit with an error.
Step WBCV2: Verify CertKMaKMCaKFIPSbKNSO under knsopub if it the certificate is present. If any dependency (including knsopub) is absent or verification fails, exit with an error.
Step WBCV3: Verify CertKREaKRAbKNSO under knsopub if it the certificate is present. If any dependency (including knsopub) is absent or verification fails, exit with an error.
At this point some of the key hashes are trusted:
-
From steps MSCV1/2 the KML must have come from the HSM identified by ESN
-
From steps MSCV1/2 the given module was configured to trust HKSNO
-
From step MSCV4 the known knsopub corresponds to that HKNSO
-
From step MSCV5 the known hkm was installed as a module key in this module
Step WBCV4: If CertKREaKRAbKNSO is present (and verified) then the hkre field can be trusted. Otherwise, delete the hkre field.
Step WBCV5: If CertKMaKMCaKFIPSbKNSO or CertKMaKMCbKNSO are present (and verified) then the hkm field can be trusted. Otherwise, delete the hkm field.
The further known facts at this stage:
-
hkm must be the KM of the same security world as KNSO
-
The module was properly configured (it uses the given security world’s KNSO and has KM installed as a module key)
-
hkre is the given security world’s KRE
Key generation certificate verification
Step KGCV1: Verify kcmsg and kcsig under KML (as recovered from the module state certificate). If verification fails, exit with an error.
This yields the application key hash, its key generation parameters and its generation-time ACL.
Step KGCV2: Check that the key hash in kcmsg matches H(pubkeydata). If they do not match, exit with an error.
ACL validation
An nShield ACL consists of a collection of permission groups. In turn each permission group contains a collection of actions.
A permission group may also be marked as requiring authorization from a certifier, meaning a key identified by its nCore key hash. A permission group may contain one or more use limits, applying constraints to how often the actions within it may be used. Actions permit use of the key, e.g. to generate a signature or to create a blob containing the key.
The process of validating an ACL involves iterating through the permission groups and inspecting them. In most cases for each permission group the actions are iterated over.
Trump ops groups
Step ACLV1: If any of the certifier fields (certifier, certmech or certmechex) matches H(KNSO) (from module state certificate) then the permission group must be the 'trump ops' group, i.e. the set of extra actions permitted under ACS authorization to carry out recovery operations. Such groups are disregarded from all the checks below, but the key is marked as recoverable.
Main use actions
The verifier may wish to apply a policy to what the key can be used for, e.g. to accept signature but forbid encryption.
Act_OpPermissions
For Act_OpPermissions the possible bits are categorized as follows:
-
harmless: DuplicateHandle, GetAppData, ReduceACL, GetACL
-
signature: Sign, Verify, SignModuleCert, UseAsCertificate
-
encryption: Encrypt, Decrypt
-
forbidden: ExportAsPlain, SetAppData, ExpandACL, UseAsBlobKey, UseAsKM, UseAsLoaderKey
Step ACLV3: If the action is Act_OpPermissions, inspect the permitted operations according to the table above.
-
If any are forbidden, exit with an error.
-
If any are inconsistent with the verifier’s requirements, exit with an error.
Working blobs (Act_MakeBlob)
Act_MakeBlob actions determine how the key is protected. They can be interpreted according to the following rules:
Step WB1: If neither AllowKmOnly nor kthash_present are set in flags, exit with an error. The protection is incoherent or too loose.
Step WB2: If KM is not trusted (see step WBCV5), or kmhash is not present or kmhash does not match hkm , exit with an error. All application keys must be protected by, at least, KM.
Step WB3: If AllowNullKMToken is present, exit with an error. All application keys must be protected by, at least, KM.
Step WB5: If flags includes AllowKmOnly then the key is module-protected.
Step WB6: If kthash is present, check that ktparams is present. If not, exit with an error. The token parameters are necessary to correctly interpret the key protection type.
Step WB7: If kthash is present, check whether the ktparams flags includes AllowSoftSlots. If it does then the key is softcard-protected; otherwise it is cardset protected.
Recovery blobs (Act_MakeArchiveBlob)
Act_MakeArchiveBlob actions permit the creation of recovery blobs. They can be interpreted according to the following rules:
Step RB1: If KRE is not trusted (see step WBCV4), exit with an error. Either the world is not recoverable or the recovery key is unknown.
Step RB2: If kahash is not present, or does not match hkre, exit with an error. The recover blob would be encrypted with the wrong key.
Step RB3: If the recovery mechanism is wrong for the ciphersuite, exit with an error.
Step RB5: If the above pass, the key is marked recoverable, in the same way as in ACLV1 above.
Outcome of ACL validation
After ACL validation:
-
The key’s recoverability is known, either from step ACLV1 or RB5:
-
ACLV1 indicates a trump ops group. The ACS holders can carry out recovery operations if the key is loaded either via the working blob or the recovery blob.
-
RB5 indicates that a recovery blob exists. The ACS holders can (at a minimum) load and use the key without access to the cardset or softcard protecting it.
-
Only if neither of these hold is the key to not considered to be recoverable.
-
-
The key’s protection type is known, either from step WB5 or WB7.
Step ACLV5: Determine protection type based on WB5 and WB7. If there are multiple Act_MakeBlob actions then there might be an inconsistent set of protection types. This could be reported as an error, or the least secure can be picked (i.e. the first in the list no protection, module protection, softcard protection, cardset protection).
Key validation
A verifier may choose to apply some kind of policy to the key. The fine detail is not part of the core attestation design, since different verifiers will have different requirements, but some broad statements can be made:
Step KV1: Apply local policy to key generation parameters. If they are not suitable, exit with an error.
Step KV2: Apply local policy to public key material. If they are not suitable, exit with an error.
Step KV3: Apply local policy to key protection and recoverability properties. If they are not suitable, exit with an error.
CSR linkage
A key attestation may be embedded in a PKCS#10 Certificate Signing Request (or a similar object). In this case, as well as verifying the attestation and verifying the CSR through the normal CSR verification and validation processes, it’s essential that the two objects be properly linked.
Step CSRL1: pubkeydata should be compared with the public key from the CSR. If they do not match, exit with an error.
Note: Steps ACLV2, WB4 and RB4 existed in earlier versions of the design and were not renumbered when removed.