Attestation using the QASM

DN: C4A-302-0043

This document covers the design and use of the attestation process implemented by the QASM and the supporting software.

Introduction

There is a need for a QASM to attest to a remote party about its state and that of other internal objects through a set of claims. This is useful when the remote party engages in secure communications with the QASM or intends to verify the authenticity of an object managed by a QASM.

Guiding Principles

The following principles guided the design of this protocol.

Parties and Responsibilities

There are three main parties involved during the attestation process:

img

There is a trust relationship between the consumer and the claiming authority. Ultimately, the consumer trusts the claims because of the signature associated with the public key that was provided by the claiming authority. Therefore:

An example to support the proposed responsibilities can be found in code signing. In this example, the corporation that distributes software is the claiming authority. It controls a private key used to sign new releases of a software. The servers that accepts this software are the consumers. In this simplified example, the process used to sign a new release (automated or manual) support the policies associated with the use and distribution of the software. The attestation message contains a single implicit claim, which is that the software package is integral and can be trusted. The consumers assume that the policies are supported by verifying the claim via the signature.

General Information Flow

This section discusses the general workflow associated with producing attestation messages and consuming them. It introduces a new participant, the Operator, which is the one orchestrating the generation of the attestation message. The operator and consumer could be the same party, specifying both the content of the attestation message and consuming it. It is also important to note that either or both actors, the operator and the consumer, could be automatic processes.

The general information flow is as follows:

  1. An operator creates a set of claims.
  2. The operator submits the set of claims to the QASM while specifying one or multiple attestation keys.
  3. The QASM augments variable claims with the corresponding information.
  4. The QASM validates all the claims in the set.
  5. If all claims are recognized and valid, then the QASM performs the requested signatures. The associated keys must have the appropriate capabilities to perform this operation.
  6. The claims and signature are organized in an attestation message.
  7. The attestation message is returned to the operator.
  8. The operator forwards the attestation message to the consumer.
img

Claims

Each claim has three components:

For example, to attest that a specific key on the QASM has a given fingerprint, the following claim can be built:

Variable Claims

Some claims are not fully defined by the operator. Instead, the operator defines the subject and the predicate. During the attestation process, the QASM inserts the value of the complement. This type of claim is known as a “variable claim”.

For example, if the remote party requests a claim specifying the time at which the attestation was performed, the complement (the time at which the attestation was performed) should be filled by the QASM.

In this section, the claims that are variable in nature are denoted with the designation “variable” in the description.

Types of claims

All claims have a predicate, also known as a type, which is specified using an OID. The type defines the others aspects of the claim such as whether a subject is required or how the complement is represented.

All OIDs introduced in this document fall under the range 1.3.6.1.4.1.39901.6 (reserved under Crypto4A).

id-c4a-claim-type OBJECT IDENTIFIER ::= { id-c4a 6 }

Claim types are broken into three categories; general, system, and object.

General Claims

General claims are ones that do not relate to the device or any of its associated resources (keys, objects).

The general predicates fall under the range 1.3.6.1.4.1.39901.6.0.

id-c4a-claim-type-general OBJECT IDENTIFIER ::= { id-c4a-claim-type 0 }

The following table explains the defined general predicates. The OID column represents the suffix after ‘id-c4a-claim-type’.

OID Label Description Subject Complement
.0.0 false-is-true Always false.
.0.1 true-is-true Always true.
.0.2 challenge Attest a challenge. Octet string containing a challenge (bytes)

System Claims

System claims are those that relate to the attesting device or its internal state.

The system predicates fall under the range 1.3.6.1.4.1.39901.6.1.

id-c4a-claim-type-system OBJECT IDENTIFIER ::= { id-c4a-claim-type 1 }

The following table explains the defined system predicates. The OID column represents the suffix after ‘id-c4a-claim-type’.

OID Label Description Subject Complement
.1.0 qasm-uuid Claiming QASM has UUID. (Variable) Octet string that encodes UUID associated with QASM. (bytes)
.1.1 qasm-serial Claiming QASM has Platform Serial Number. (Variable) UTF-8 string that encodes the serial number associated with the platform. (utf8String)
.1.2 attestation-time Attestation was performed at time.(Variable) General time structure. (time)
.1.3 qasm-firmware-version Claiming QASM has firmware version. (Variable) UTF-8 string that encodes the firmware version associated with the platform. (utf8String)
.1.4 qasm-certified-production Claiming QASM is a certified production HSM.
.1.5 qasm-is-in-fips-mode Claiming QASM is operating in FIPS mode.
.1.6 audit-logs-state Claiming the state of the audit log. (Variable) Octet string that encodes the audit log state structure. (bytes)

Object Claims

Object claims relate to resources (keys or objects) located on the attesting device.

The object predicates fall under the range 1.3.6.1.4.1.39901.6.2.

id-c4a-claim-type-object OBJECT IDENTIFIER ::= { id-c4a-claim-type 2 }

The following table explains the defined object predicates. The OID column represents the suffix after ‘id-c4a-claim-type’.

OID Label Description Subject Complement
.2.0 attestation-keys-are-unique The attestation keys used for signing this attestation are unique to the QASM. This means that the attestation keys were generated on the claiming QASM and can not be transferred in any way out of the QASM.
.2.1 key-spki Key is associated with the subject public key info. (Variable) Key UUID Octet string that encodes the SPKI (SubjectPublicKeyInfo) for the key. (bytes)
.2.2 key-fingerprint Key is associated with the fingerprint. (Variable) Key UUID Octet string that encodes fingerprint associated with key. (bytes)
.2.3 key-spki-sha256 Key is associated with the SHA-256 of the SPKI. Useful when SPKI is large, like McEliece keys. (Variable) Key UUID Octet string that encodes the SHA-256 digest of the SPKI. (bytes)
.2.4 object-class Object is of a specified class. Object UUID Integer value that represents the class of the target object. (value)
.2.5 object-type Object is of a specified type. Object UUID Integer value that represents the type of the target object. (value)
.2.6 object-keystore Object is in the specified key store type. Object UUID Integer value that represents the type of key store where the target object is located. (value)
.2.7 key-is-confined Key is confined to claiming QASM. This means that the subject key was generated on the claiming QASM and can not be transferred in any way out of the QASM. Key UUID
.2.8 key-is-hardware-generated Key is hardware generated. Key has the “local” bit set. Key UUID
.2.9 key-never-extracted Key has never been extracted. Key UUID
.2.10 key-is-managed Key is managed. Key UUID
.2.11 key-is-not-managed Key is not managed. Key UUID
.2.13 key-has-capability Key has the specified capability. Key UUID Integer value that represents a key capability. (value)
.2.14 key-does-not-have-capability Key does not have the specified capability. Key UUID Integer value that represents a key capability. (value)
.2.15 key-is-related-to-authority Key is related to authority structure. (Variable) Key UUID Octet string that encodes the RelatedAuthorities associated with the key. (bytes)
.2.16 key-is-archived-by Key has archiving key. Key UUID Octet string that encodes the UUID of the archiving key. (bytes)

Encoding

This section covers the encoding of an attestation message. The definitions are expressed in ASN.1.

Attestation Message

The attestation message is the overarching structure to carry attestation information. It is constructed of the following components:

AttestationMessage ::= SEQUENCE {
   version                  INTEGER,
   claims                   SetOfClaims,
   signatures               SEQUENCE SIZE (1..MAX) OF SignatureBlock,
   relatedCertificates  [0] IMPLICIT SEQUENCE of Certificate OPTIONAL
                         -- As defined in RFC 5280
}

SignatureBlock  ::= SEQUENCE {
      sid                  SignerIdentifier,
      signatureAlgorithm   AlgorithmIdentifier,
      signatureValue       BIT STRING
}

SignerIdentifier ::= SEQUENCE {
   keyId                [0] EXPLICIT OCTET STRING OPTIONAL,
   subjectKeyIdentifier [1] EXPLICIT SubjectPublicKeyInfo OPTIONAL,
                            -- As defined in RFC 5280
   certificate          [2] EXPLICIT Certificate OPTIONAL
                            -- As defined in RFC 5280
}

AlgorithmIdentifier  ::=  SEQUENCE  {
      algorithm               OBJECT IDENTIFIER,
      parameters              ANY DEFINED BY algorithm OPTIONAL
}

Set of Claims

This section defines the structure containing the claims. This section represents the portion that is signed as part of the attestation message. It contains one or multiple claims. Each claim encodes the subject (if present), predicate, and optional complement. The following sub-sections deal with the encoding of the different types of subjects and complements.

SetOfClaims ::= SEQUENCE {
   version              INTEGER,
   claims               SEQUENCE OF Claim
}

Claim ::= SEQUENCE {
   predicate        OBJECT IDENTIFIER,
   subject      [0] EXPLICIT Subject OPTIONAL,
   complement   [1] EXPLICIT Complement OPTIONAL
}

Subject

This structure is provided for extensibility. Future revisions of this specification may include more subjects.

Subject ::= SEQUENCE {
   uuid       [0] IMPLICIT OCTET STRING OPTIONAL
}

Complement

The complement can be specified in many ways, but is constrained by the predicate: the selected choice should match the one indicated by the predicate.

Complement ::= CHOICE {
   bytes       [0] IMPLICIT OCTET STRING,
   utf8String  [1] IMPLICIT UTF8String,
   time        [2] IMPLICIT GeneralizedTime,
   value       [3] IMPLICIT INTEGER
}

Formatting

There are many types of complement, and the complement encoding varies based on the claim type. Ultimately, each value is converted to one or multiple ASN.1 primitive types. This section deals with the formatting of values into ASN.1.

UUIDs

Within this specification, a UUID is encoded as an Octet String of 16 bytes, with the first byte being the most significant byte of the value for the UUID.

This formatting applies for both subjects, when applicable, and complements.

General Time

When a complement contains a general time, then the general time shall be encoded as the standard ASN.1 type: GeneralizedTime. For the purpose of this specification, the representation of time shall be constrained in a manner identical to the way specified in RFC 5280.

For convenience, this is an excerpt from RFC 5280, section 4.1.2.5.2:

For the purposes of this profile, GeneralizedTime values MUST be expressed in Greenwich Mean Time (Zulu) and MUST include seconds (i.e., times are YYYYMMDDHHMMSSZ), even where the number of seconds is zero.  GeneralizedTime values MUST NOT include fractional seconds.

#### Subject Public Key Info (SPKI)

For the purpose of this specification, subject public key info (SPKI) is formatted according to RFC 5280 section 4.1.2.7.

The SPKI structure is used to identify public and private keys. In the case of private keys, the associated public key is used for purpose of identification.

SPKI SHA-256

If the size of the attestation message is constrained and a subject key is large (McEliece public keys are sizeable in comparison to others), then it is possible to identify a key using the SHA-256 of the SPKI (see claim .2.3).

The formatting of this value is as follows:

  1. Encode SPKI according to RFC 5280 section 4.1.2.7.
  2. Perform a SHA-256 digest using the encoded SPKI as input. The output is used in the next step.
  3. Encode the SHA-256 digest as a 32 byte octet string.

Object Class

When an object class is specified, it should be encoded as an ASN.1 integer. The encoded value shall be represented according to the following table:

Object Class Integer Value
DATA 0x01
CERTIFICATE 0x02
PUBLIC KEY 0x03
PRIVATE KEY 0x04
SECRET KEY 0x05
AUTHORITY 0x07
ENTITLEMENT 0x0A
AUTHORIZATION REQUEST 0x0B
POLICY 0x0C

Object Type

When an object type is specified, it should be encoded as an ASN.1 integer. The encoded value shall be represented according to the following table:

Object Type Integer Value
RSA 0x01
ECC 0x02
HSS 0x03
MCE (McEliece) 0x04
DILITHIUM 0x06
XMSS 0x07
SPHINCS+ 0x08
EDWARDS 0x09
KYBER 0x0A
Generic Secret Key 0x10
AES 0x11
User Authorithy 0x31
Quorum Authority 0x32
Counter Entitlement 0x50
X.509 Certificate 0x60
Trust Anchor Certificate 0x61
Encrypted Trust Anchor Certificate 0x62
Generic Data 0x70
Owner Policy 0x80
Access Policy 0x81

Object Keystore

When an object keystore is specified, it should be encoded as an ASN.1 integer. The encoded value shall be represented according to the following table:

Object Keystore Integer Value
IKS 0x100
GLOBAL 0x101
VOLATILE 0x102
PLATFORM 0x103
POST TAMPER 0x104
OWNER 0x105
ACCESS 0x106

Key Capability

When a key capability is specified, it should be encoded as an ASN.1 integer. The encoded value shall be represented according to the following table:

Name Capability Identifier Description
HSM_KEY_CAPABILITY_ENCRYPT 0x101 If set, the associated key can be used in an encrypt function.
HSM_KEY_CAPABILITY_DECRYPT 0x102 If set, the associated key can be used in a decrypt function.
HSM_KEY_CAPABILITY_WRAP 0x103 If set, the associated key can be used in a wrap function.
HSM_KEY_CAPABILITY_UNWRAP 0x104 If set, the associated key can be used in an unwrap function.
HSM_KEY_CAPABILITY_SIGN 0x105 If set, the associated key can be used in a signature function.
HSM_KEY_CAPABILITY_VERIFY 0x106 If set, the associated key can be used in a signature verification.
HSM_KEY_CAPABILITY_DERIVE 0x107 If set, the associated key can be used in a derive function.
HSM_KEY_CAPABILITY_UNAUTHORIZED 0x108 If set, the associated key cannot be used in functions unless authorized.
HSM_KEY_CAPABILITY_PACK 0x109 If set, the associated key can be used in a pack function.
HSM_KEY_CAPABILITY_UNPACK 0x10a If set, the associated key can be used in an unpack function.
HSM_KEY_CAPABILITY_DBSEC_DPK 0x10b If set, the associated key can be used in the role of DPK in DbSec functions.
HSM_KEY_CAPABILITY_DBSEC_DDK 0x10c If set, the associated key can be used in the role of DDK in DbSec functions.
HSM_KEY_CAPABILITY_ARCHIVE 0x11d If set, the associated key is used to archive (back up) other keys via extraction functions. It allows wrap even if a key is not extractable. It allows packing even if a key is not packable. A link “ARCHIVED_BY” is required between the archived key and the associated key. If a key is unpacked or unwrapped using the associated key, the “ARCHIVED_BY” link is added to the recovered key.
HSM_KEY_CAPABILITY_TAMP_APEX 0x10e Not enforced.
HSM_KEY_CAPABILITY_TAMP_PROCESS 0x10f Not enforced.
HSM_KEY_CAPABILITY_FIRMWARE_SIGN 0x110 Not enforced.
HSM_KEY_CAPABILITY_CODE_SIGN 0x111 Not enforced.
HSM_KEY_CAPABILITY_PROOF_OF_ORIGIN 0x112 Not enforced.

RelatedAuthorities

The structure RelatedAuthorities is used to define the set of authorities and keys that are associated with a given object. Some of those keys represent authorities that can approve operations with the key.

For the purpose of this specification, when related authorities are specified, they are first encoded as an ASN.1 structure. Then, the structure is DER encoded and the bytes are used an an octet string.

The remainder of this section explains the ASN.1 encoding of the related authority structure.

PublicKeyInfo  ::=  SEQUENCE {
    algorithm              AlgorithmIdentifier,
    publicKey              BIT STRING  }

User ::= SEQUENCE OF PublicKeyInfo

QuorumMember ::= SEQUENCE {
    weight                 INTEGER,
    authority              Authority }

QuorumMembers ::= SEQUENCE OF QuorumMember

Quorum ::= SEQUENCE {
    threshold              INTEGER,
    members                QuorumMembers }

Authority ::= CHOICE {
    publicKey          [0] IMPLICIT PublicKeyInfo,
    user               [1] IMPLICIT User,
    quorum             [2] IMPLICIT Quorum }

ManagingAuthority ::= SEQUENCE {
    managingLevel          INTEGER,
    authority              Authority }
    
RelatedAuthority ::= CHOICE {
    managingAuthority  [0] IMPLICIT ManagingAuthority }

RelatedAuthorities ::= SEQUENCE OF RelatedAuthority

The field “managingLevel” is a numerical value that establishes the permissions that the authority has on the key. The following table describes the meaning of the value found in this field.

Name Value Description
TRUSTEE 0x01 The authority can authorize operations that discloses the value of the key. This is the ultimate permission on the key. It allows operations to extract the key.
OPERATOR 0x02 The authority can authorize operations that uses the value of the key. This allows operations such as signature or encryption.

Key Capability

For a key to participate in the process of attestation, it must first be marked with the capability “attestation”. An attestation key has the following restrictions:

QASM Functions

This section describes the functions provided by the QASM to support key attestation.

Attest

The Attest function is used to sign a set of claims provided by the caller. It is implemented within the QASM.

The Attest function has the following inputs:

The Attest function has the following outputs:

The Attest function must:

ValidateClaims

The ValidateClaims function is used to verify which claims are deemed valid by the QASM. It is implemented within the QASM. It provides the means to verify why an attestation is failing.

The ValidateClaims function has the following input:

The ValidateClaims function has the following outputs:

Standardized claim templates

This section introduces the concepts of claim templates. To support a specific policy, a number of claim types might be required. With the use of templates, it is possible to specify a pre-defined set of claims instead of specifying individually each one, over and over.

Templates

CA/B forum requirements: Private key is on HSM

The Certificate Authority / Browser (CA/B) forum has mandated that the private keys for certificates issued after June 2023 must be protected by a signing service that uses an HSM to store the keys.

The CA/B forum requirements only state that a signing service storing private keys must have “use of an HSM”, but do not state any additional requirements. The key could be imported to an HSM, copied to it, or copied out subsequently. The QASM has the ability to prove that additional properties about a key are enforced, but we will not require these for signing service keys, allowing the CAs to make their own judgement. Hence, some of these claims will be optional, allowing us to highlight the QASM’s capability to place stricter controls on the keys and encourage better hygiene.

The following required claims prove that a private key object on the HSM has a corresponding public key, which the validator can check against a CSR (Certificate Signing Request).

The following claims are not required by the CA/B forum requirements, and are only included in the attestation message if true.

The verification tool, spa-attest verify --require <template> supports two variants of this template:

Algorithm for attestation on a template

This section describes the pseudo-algorithm employed when attestation templates are requested.

  1. Load the claim template.

  2. Load default attestation keys and certificates, if none provided.

  3. Call QASM’s ValidateClaims on the resulting SetOfClaims.

  4. For each claim in the result:

  5. Using the reduced setOfClaims, call the QASM’s Attest function.

  6. Attach any related certificates to the message.

  7. Bundle the attestation message with the certificates.

CLI Commands

This section deals with the Command Line Interface (CLI) applications that are supporting the attestation process.

spa-key-man attest claim

This command takes some claims and/or claim templates and interacts with the QASM to attest to them, producing an attestation message.

Examples

Produce a test claim that is true (–true-is-true), using the default QASM_AA_ECC attestation key and the C4A_ROOT certificate. The message is output to STDOUT if no output file is specified.

$ spa-key-man attest claim --true-is-true
-----BEGIN ATTESTATION MESSAGE-----
MIIHYwIBATAUAgEBMA8wDQYLKwYBBAGCt10GAAEwggK9MIICuTCCAj+gEgQQmrrz
fJKLFkY/a6C9XuxaxqKCAicwggIjMIIBqKADAgECAhRSLwDfIc3tYXTYlyGn2R+k
k61awDAKBggqhkjOPQQDAzAcMRowGAYDVQQDDBFDNEFfU0NBX0Zha2VNYW5DQTAg
Fw0yMzAyMjcyMTQ0MzBaGA85OTk5MTIzMTIzNTk1OVowMzExMC8GA1UEAwwoSFNN
RW11bGF0b3IwMDAwMDAgQXNzZXJ0aW9uIEF1dGhvcml0eSBFQzB2MBAGByqGSM49
AgEGBSuBBAAiA2IABET0UyPDJHQti/es+7HIYZreJyu6axMXEqTCtgJi2/maRTca
yci0JvE8Y+exnB4Pz44aNX17FR1YjDsS5JKQrrVF3kkYn6WqG0z8lgRCMgmYQHyb
4RGqqhcA9NyBR3mL8qOBkTCBjjAdBgNVHQ4EFgQUCTWGWnqviQE/1NC13+YSpjhZ
9AowHwYDVR0jBBgwFoAUzodfGY1cdAYG8VDlV4JwglBv+Q8wDgYDVR0PAQH/BAQD
AgeAMCQGA1UdEQQdMBugGQYJKwYBBAGCt10DoAwGCisGAQQBgrddAwEwFgYDVR0l
BA8wDQYLKwYBBAGCt10EAQEwCgYIKoZIzj0EAwMDaQAwZgIxAIkg2qPXphiJfBUO
rs1u9KlYODeFGNxd1lnhkZQstk4Q7ff7L5AKsdlcX2P5AFWRFQIxAPTkGZi8raxL
9qzAz8/b/aZ4iojp+usWf3dvt2HRx/SLec4VR+Ol5A2v557RSd5XIjAKBggqhkjO
PQQDAwNoADBlAjB9B5ax128DnOg47RKpFIDMJ6chVRHaREmZ6jPUSy1gqqdFLILh
ung7yb1ECqu2+OcCMQD9vQLxiHBURHMHWXNakwsGR8Eh7fn+xQ/aKi0ZO4kU+cgT
wd9BiSwestVqayRIoaOgggSFMIICXjCCAeSgAwIBAgIULVEQ5ZbF4R/s686p0nUT
SDTPhwcwCgYIKoZIzj0EAwMwXjEPMA0GA1UEBgwGQ2FuYWRhMRAwDgYDVQQIDAdP
bnRhcmlvMQ8wDQYDVQQHDAZPdHRhd2ExETAPBgNVBAoMCENyeXB0bzRBMRUwEwYD
VQQDDAxDNEFfUkNBX0ZBS0UwHhcNMjIwOTA2MTk1MTU3WhcNNDcwOTA2MTk1MTU3
WjBeMQ8wDQYDVQQGDAZDYW5hZGExEDAOBgNVBAgMB09udGFyaW8xDzANBgNVBAcM
Bk90dGF3YTERMA8GA1UECgwIQ3J5cHRvNEExFTATBgNVBAMMDEM0QV9SQ0FfRkFL
RTB2MBAGByqGSM49AgEGBSuBBAAiA2IABEEqITyWwvFOD9N7fAPOnO1rnslG1rXK
9BcJMoQEHY0C1LdS1S/5q6bJsxMlg6QmDbuiv7+rUy+eEtBSqQL5L5uVFOApBHHZ
Uabluux8gnM7a93fNMkgAYIS6se9baKiLqNjMGEwDwYDVR0TAQH/BAUwAwEB/zAO
BgNVHQ8BAf8EBAMCAQYwHwYDVR0jBBgwFoAUy/ABUVh4K3dgmrN0YBDgAjx8L2Yw
HQYDVR0OBBYEFMvwAVFYeCt3YJqzdGAQ4AI8fC9mMAoGCCqGSM49BAMDA2gAMGUC
MBJaN/Qi1FgbHdasygkefsX6L7ZgbJ3kbTvFx1kYQlWLbgi6GBwPb0mINcCN/YvW
HQIxAI5QVMrXIZDx9H8u6iWp+dJPVLqD3/vl9ADxlGOZiI1dQ34wZGBTETqGvnhA
NfkV2DCCAh8wggGloAMCAQICFGwULjmrv1u53zBf2OWPqb//9e0OMAoGCCqGSM49
BAMDMF4xDzANBgNVBAYMBkNhbmFkYTEQMA4GA1UECAwHT250YXJpbzEPMA0GA1UE
BwwGT3R0YXdhMREwDwYDVQQKDAhDcnlwdG80QTEVMBMGA1UEAwwMQzRBX1JDQV9G
QUtFMB4XDTIyMDkwNjIwMDAwM1oXDTQyMDkwNjIwMDAwM1owHDEaMBgGA1UEAwwR
QzRBX1NDQV9GYWtlTWFuQ0EwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAARWZmvXkAFM
serfnptjHYHqlk7fNkT9fa33eIU57IHQOK3uslesQQLw572BUhlyrs3ghwM0aWau
s5iW20fP+dbvM/5Ny9sB+URCM04alBePdD9m8WJOm/JvFI/bPYUARNujZjBkMBIG
A1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMB8GA1UdIwQYMBaAFMvw
AVFYeCt3YJqzdGAQ4AI8fC9mMB0GA1UdDgQWBBTOh18ZjVx0BgbxUOVXgnCCUG/5
DzAKBggqhkjOPQQDAwNoADBlAjBnFK3MOZ3zO4RlvGaM3oncUL12t8/0bW3Qy5vr
+NQ9rJqJLEFlUVQkwh4fC8lcoEECMQDXcnDNUuJLXthZcNQveujIZOC8Jol5f/3k
S+/MSxgZhts1eiAs5uMjvRf8PXqYNBQ=
-----END ATTESTATION MESSAGE-----

The following example shows how to claim that a key with UUID <uuid> is managed and has the sign capability, producing two attestation signatures with the specified keys and certificates:

$ spa-key-man attest claim --attesting-key <ec-key-uuid> --certificate <ec-cert-uuid> --attesting-key <hss-key-uuid> --certificate <hss-cert-path> ---managed <uuid> --key-has-capability <uuid>=sign --out attestation.pem

In this example, the template private-key-is-on-hsm provides some required and some optional claims. Any valid claims are included in the attestation message.

$ spa-key-man attest claim --private-key-is-on-hsm <private-key-uuid> --out message.pem

spa-key-man attest validate-claims

This command interacts with the QASM to validate a set of claims. It takes the same attestation options as attest claim, and produces a report explaining which claims are valid, and the reason why any claim is invalid.

Examples

$ spa-key-man attest validate-claims --true-is-true --key-has-capability 92f83f5d-2db6-8c43-73c1-e403e7d1e8be=sign
Claim: TRUE_IS_TRUE
        Valid

Subject:    92f83f5d-2db6-8c43-73c1-e403e7d1e8be
        Claim: KEY_HAS_CAPABILITY
                Subject:    92f83f5d-2db6-8c43-73c1-e403e7d1e8be
                Complement: 261
                Error:      HSM_RET_INVALID_OBJECT_CLASS

JSON format output is also supported, in the same format as spa-attest verify --format json, with the addition of the HSM return code.

$ spa-key-man attest validate-claims --true-is-true --key-has-capability 92f83f5d-2db6-8c43-73c1-e403e7d1e8be=sign --format json
{"claims": {
    "global": [{
        "predicate": "true-is-true",
        "returnCode": 0
    }],
    "object": {"92f83f5d-2db6-8c43-73c1-e403e7d1e8be": [{
        "predicate": "key-has-capability",
        "returnCode": 26,
        "subject": "92f83f5d-2db6-8c43-73c1-e403e7d1e8be",
        "complement": 261
    }]}
}}

spa-attest verify

Spa-attest is a new CLI application to support third parties that wish to consume the claims generated by the attestation process.

This command verifies an attestation message and provides a human-readable explanation of its contents. Without a template option, which adds the display of optional claims, verify only shows claims that actually exist in the bundle. Verify returns a non-zero exit code if any mandatory claims for the template are missing or the signatures are not valid.

The csr option takes a CSR and requires the public key information to match a claim about a public key in the attestation message. For simplicity, in this mode, we only allow the attestation message to contain claims about a single key, which must match the CSR.

Usage:
  spa-attest verify <attestation-message-file> [flags]

Flags:
      --assume-valid-signer             Only do a partial validation, assuming that the certificate or public key provided in the signature identifier is valid. Default: false.
      --csr string                      Path to a CSR to match against this attestation message.
      --dev-insecure                    Use DEV_INSECURE root certificates for verification by default.
      --format plaintext|json           Output format. (default plaintext)
  -h, --help                            help for verify
      --intermediate-cert stringArray   Paths to intermediate certificates.
      --require string                  Require that certain claims be present in the attestation.
      --root stringArray                Paths to accepted root certificates.

Global Flags:
      --debug           Debug log level
      --error           Error log level
      --info            Info log level (default true)
      --logDir string   Location of the logs directory.
      --trace           Trace log level
      --warning         Warning log level

Examples

$ spa-attest verify message.att
 ✔ Attestation was performed at Feb 20, 2023 15:39:29 GMT
 ✔ QASM is a production certified HSM

eea309ed-c5bc-49d0-9c35-70ecfbe76751
  ✔ Private key
  ✔ Has SubjectPublicKeyInfo: ab cd ef
  ✔ Key is in the independent keystore
  ✔ Key is hardware generated
  ✔ Key has the sign capability

If a CSR is provided, then the CSR must match the SPKI of one of the objects in the attestation message.

$ spa-attest verify --csr cert.csr message.att
 ✔ Attestation was performed at Feb 20, 2023 15:39:29 GMT
 ✔ QASM is a production certified HSM

Cert.csr == eea309ed-c5bc-49d0-9c35-70ecfbe76751
  ✔ Private key
  ✔ Matches the public key in the CSR
  ✔ Key is in the independent keystore
  ✔ Key is hardware generated
  ✔ Key has the sign capability

This example verifies a message and additionally asserts that the attestation message contains the claims needed to verify HSM storage of the private key behind the given CSR.

$ spa-attest verify --require private-key-is-on-hsm --csr cert.csr attestation.pem
 ✔ Attestation was performed at Feb 20, 2023 15:39:29 GMT
 ✔ QASM is a production certified HSM

Cert.csr == eea309ed-c5bc-49d0-9c35-70ecfbe76751
  ✔ Object is a private key
  ✔ Matches the public key in the CSR
  ✔ Key is in the independent keystore
  ✘  Key is confined to the claiming QASM
  ✔ Key is hardware generated
  ✘  Key has never been extracted
  ✔ Key has the sign capability

The verify command takes options to set the root certificate and certificate pool, which allows users to generate their own attestation keys and verify certificates of those keys using their own certificate chain.

$ spa-attest verify --root root.pem --intermediate-cert intermediate.pem <attestation>

Alternatively, the tool may perform a partial validation, which only checks the signature of the certificate or SPKI provided in signerIdentifier.

$ spa-attest verify --assume-valid-signer

For testing against the emulator or on DEV_INSECURE QASMs, use --dev-insecure to validate against the C4A_ROOT shipped with the emulator.

$ spa-key-man attest claim --true-is-true --key-has-capability 979fadd4-7f7c-e744-e9c3-d770507482c4=sign --out test.pem
Output written to test.pem

$ spa-attest verify --dev-insecure test.pem
  ✔  Claim is true (debug claim)

979fadd4-7f7c-e744-e9c3-d770507482c4
    ✔  Key has the sign capability

$ spa-attest verify --dev-insecure test.pem --format json
{
  "claims": {
    "global": [
      {
        "predicate": "true-is-true"
      }
    ],
    "object": {
      "979fadd4-7f7c-e744-e9c3-d770507482c4": [
        {
          "predicate": "key-has-capability",
          "subject": "979fadd4-7f7c-e744-e9c3-d770507482c4",
          "complement": 261
        }
      ]
    }
  }
}

Verification pseudo-algorithm

This following bullets explain the verification process used by “spa-attest verify”:

The preceding bullets explain the full verification. There also exists an option for partial verification, which is enabled by --assume-valid-signer. Partial verification is restricted to verifying only the signature blocks.