Internet-Draft EAR November 2026
Fossati, et al. Expires 6 May 2027 [Page]
Workgroup:
Remote ATtestation ProcedureS
Internet-Draft:
draft-ietf-rats-ear-05
Published:
Intended Status:
Standards Track
Expires:
Authors:
T. Fossati
NVIDIA
E. Voit
Cisco
S. Trofimov
Arm Limited
H. Birkholz
Fraunhofer SIT

EAT Attestation Results

Abstract

This document defines the EAT Attestation Result (EAR) message format.

EAR is used by a verifier to encode the result of the appraisal over an attester's evidence. It embeds an AR4SI's "trustworthiness vector" to present a normalized view of the evaluation results, thus easing the task of defining and computing authorization policies by relying parties. Alongside the trustworthiness vector, EAR provides contextual information bound to the appraisal process. This allows a relying party (or an auditor) to reconstruct the frame of reference in which the trustworthiness vector was originally computed. EAR supports simple devices with one attester as well as composite devices that are made of multiple attesters, allowing the state of each attester to be separately examined. EAR can also accommodate registered and unregistered extensions. It can be serialized and protected using either CWT or JWT.

About This Document

This note is to be removed before publishing as an RFC.

The latest revision of this draft can be found at https://thomas-fossati.github.io/draft-ear/draft-fv-rats-ear.html. Status information for this document may be found at https://datatracker.ietf.org/doc/draft-ietf-rats-ear/.

Discussion of this document takes place on the Remote ATtestation ProcedureS Working Group mailing list (mailto:rats@ietf.org), which is archived at https://mailarchive.ietf.org/arch/browse/rats/. Subscribe at https://www.ietf.org/mailman/listinfo/rats/.

Source for this draft and an issue tracker can be found at https://github.com/thomas-fossati/draft-ear.

Status of This Memo

This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.

Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.

Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."

This Internet-Draft will expire on 6 May 2027.

▲

Table of Contents

1. Introduction

This document defines the EAT [RFC9711] Attestation Result (EAR) message format.

EAR is used by a verifier to encode the result of the appraisal over an attester's evidence. It embeds an AR4SI's "trustworthiness vector" [I-D.ietf-rats-ar4si] to present a normalized view of the evaluation results, thus easing the task of defining and computing authorization policies by relying parties. Alongside the trustworthiness vector, EAR provides contextual information bound to the appraisal process. This allows a relying party (or an auditor) to reconstruct the frame of reference in which the trustworthiness vector was originally computed. EAR supports simple devices with one attester as well as composite devices that are made of multiple attesters (see Section 3.3 of [RFC9334]) allowing the state of each attester to be separately examined. EAR can also accommodate registered and unregistered extensions. It can be serialized and protected using either CWT [RFC8392] or JWT [RFC7519].

2. Conventions and Definitions

This document uses terms and concepts defined by the RATS architecture. For a complete glossary see Section 4 of [RFC9334].

The terminology from CBOR [STD94], CDDL [RFC8610] and COSE [STD96] applies; in particular, CBOR diagnostic notation is defined in Section 8 of [STD94] and Appendix G of [RFC8610].

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.

3. EAT Attestation Result

EAR is an EAT token which can be serialized as JWT [RFC7519] or CWT [RFC8392].

The EAR claims-set is as follows:

;# import rfc9711 as eat
;# import ar4si as ar4si
;# import cmw as cmw
;# import eat-measured-component as mc

EAR = {
  eat.profile-label => "tag:ietf.org,2026:rats/ear#05"
  ? status-label => ar4si.trustworthiness-tier
  ? status-details-label => details-type
  eat.iat-claim-label => ~eat.time-int
  ? eat.exp-claim-label => ~eat.time-int
  verifier-id-label => ar4si.verifier-id
  ? raw-evidence-label => cmw-record
  eat.submods-label => { + text => $submod-value }
  ? eat.nonce-label => eat.nonce-type
  ? topology-label => topology-type
  ? input-digest-label => mc.digest
  * $$ear-extension
}

cmw-record = eat.JC<cmw.json-record, cmw.cbor-record>

; A submod carries one of:
;  - EAR-appraisal: the appraisal of a single attester;
;  - EAR: an unsigned EAR claims-set from a sub-verifier, in the same
;    serialization as the enclosing token;
;  - eat.Nested-Token: a complete, signed EAR from a sub-verifier, possibly
;    in a different serialization than the enclosing token (see
;    Section 4.2.18.3 of RFC 9711 for how the nested token is identified).
$submod-value /= EAR-appraisal
$submod-value /= EAR
$submod-value /= eat.Nested-Token

; EAR-specific claims
raw-evidence-label = eat.JC<"ear_raw_evidence", 1002>
verifier-id-label = eat.JC<"ear_verifier_id", 1004>
topology-label = eat.JC<"ear_device_topology", 1007>
input-digest-label = eat.JC<"ear_input_digest", 1008>
Figure 1: EAR (CDDL Definition)

Where:

eat_profile (mandatory)

The EAT profile (Section 6 of [RFC9711]) associated with the EAR claims-set and encodings defined by this document. It MUST be the following tag URI ([RFC4151]) tag:ietf.org,2026:rats/ear#05.

ear_status (optional)

The overall appraisal status for the (composite) attester represented as one of the five trustworthiness tiers (Section 3.2 of [I-D.ietf-rats-ar4si]). The none tier is the neutral element of this computation: it does not affect the result and MUST NOT be used as the value of this claim. The value of this claim MUST be set to a tier of no higher trust than the tier corresponding to the worst status found across all submods, regardless of whether a given submod is represented as an EAR-appraisal, a nested EAR, or a Nested-Token (see Section 3.4). When a submod is a Nested-Token whose contents the verifier cannot parse or independently verify -- for example, because it uses a serialization or a signature scheme the verifier does not support, or because it does not contain an EAR -- the verifier MUST treat that submod as having the incomplete tier (Section 3.2 of [I-D.ietf-rats-ar4si]) for the purposes of computing this claim. That is, the verifier was unable to complete the appraisal of that submod, and therefore cannot vouch for the trustworthiness of the attester it represents. The verifier MUST NOT infer from the opaque submod any tier it has not itself established. Relying Parties that need to know whether the whole tree has been appraised have to inspect the Nested-Token submods individually. This claim exists to help Relying Parties easily determine the overall status of the appraisal without having to inspect each submod.

ear_status_details (optional)

A non-empty array of strings, each giving a reason for the value of ear_status. See Section 3.3 for the rules that apply to all *_details claims.

iat (mandatory)

"Issued At" claim -- the time at which the EAR is issued. See Section 4.1.6 of [RFC7519] and Section 4.3.1 of [RFC9711] for the EAT-specific encoding restrictions (i.e., disallowing the floating point representation).

exp (optional)

"Expiration Time" claim -- the time at which the EAR expires and MUST NOT be accepted for processing. See Section 4.1.4 of [RFC7519]. Similar to iat, an EAR token MUST NOT contain an exp claim in floating-point format. Any recipient of a token with a floating-point format exp claim MUST consider it an error.

ear_verifier_id (mandatory)

Identifying information about the appraising verifier. See Section 3.3 of [I-D.ietf-rats-ar4si] for further details on its structure and serialization.

ear_raw_evidence (optional)

The unabridged evidence submitted for appraisal, including any signed container/envelope, wrapped in a Record CMW (see Section 3.1 of [RFC9999]). This field may be consumed by other Verifiers in multi-stage verification scenarios or by auditors. There are privacy considerations associated with this claim. See Section 8.

submods (mandatory)

A submodule map (Section 4.2.18 of [RFC9711]) holding, for each separately appraised attester or sub-verifier, one of: an EAR-appraisal; a nested EAR claims-set; or a Nested-Token carrying a complete, independently signed EAR produced by a sub-verifier. The map MUST contain at least one entry. For each appraised attester or sub-verifier the verifier chooses a unique label. For example, when evidence is in EAT format, the label could be constructed from the associated EAT profile. A verifier SHOULD publicly and permanently document its labelling scheme for each supported evidence type, unless EAR payloads are produced and consumed entirely within a private deployment. See Section 3.2 for the details about the contents of an EAR-appraisal, and Section 3.4 for the recursive and tunnelled cases.

eat_nonce (optional)

A user supplied nonce that is echoed by the verifier to provide freshness. The nonce is a sequence of bytes between 8 and 64 bytes long. When serialized as JWT, the nonce MUST be base64 encoded, resulting in a string between 12 and 88 bytes long. See Section 4.1 of [RFC9711].

ear_device_topology (optional)

A map that describes the device attester graph using adjacency lists. Attesters are represented by their corresponding labels in the submods claim. Each map key represents an attester in the graph, and the associated map value is an array of labels representing the list of sub-attesters for that attester. If the claim is present, the map MUST contain at least one element.

ear_input_digest (optional)

A cryptographic digest of the appraisal request input that produced this EAR, used to bind the EAR to the exact input the Verifier received. Its value is the digest type defined in Section 4.2 of [I-D.ietf-rats-eat-measured-component]. See Section 3.1 for the details.

$$ear-extension (optional)

Any registered or unregistered extension. See Section 4 for further details.

3.1. Input Digest

The ear_input_digest claim cryptographically binds an EAR to the exact appraisal request input received by the Verifier, providing a protection that eat_nonce alone does not provide. While eat_nonce establishes freshness and confirms that the Verifier processed the requester's nonce, it does not bind the remainder of the request.

For example, an adversary positioned between the TLS terminator and the Verifier's trust boundary could substitute the evidence carried in the request while leaving the nonce intact. The Relying Party would then receive an EAR with a valid nonce, but for attacker-chosen evidence. ear_input_digest closes this attack by allowing the Relying Party to check that the digest matches the appraisal request input it originally sent (or caused to be sent), exposing any substitution. Other, similar, attacks that rely on tampering with the appraisal request input without affecting the nonce are also expected to be closed by the same mechanism.

The digest is computed over the raw wire bytes of the complete appraisal request input:

  • The sender computes the digest over the encoded request bytes, after encoding and before transmission, and retains those exact bytes for later verification.

  • The Verifier computes the digest over the raw bytes as received on the wire, before any decoding or processing.

Because neither side re-encodes the input before hashing, encoding format and field ordering are irrelevant: the sender and the Verifier are comparing the same bytes -- the ones that were sent on the wire. This also means ear_input_digest is transport-agnostic: it does not matter whether the bytes are carried in an HTTP body, a gRPC message, or any other framing, as long as the sender has access to, and retains, the exact bytes that the Verifier will hash.

When using ear_input_digest, use of CMW ([RFC9999]) as the appraisal request format is RECOMMENDED. CMW provides a well-defined encapsulation boundary that makes it straightforward for both parties to identify which bytes constitute the complete request input, and to apply the hash at the correct point in their respective pipelines.

3.1.1. Applicability

Deployments that produce or verify ear_input_digest MUST satisfy both of the following conditions:

  1. Encapsulation: the appraisal request input MUST be carried in a single, self-delimiting encapsulation; between the sender's encoding step and the Verifier's hashing step, this encapsulation MUST NOT be modified.

  2. Byte access: the sender MUST have access to, and retain, the literal octets of the encoded appraisal request input.

If either condition does not hold, ear_input_digest SHOULD NOT be produced or verified.

When both conditions hold, ear_input_digest provides strong end-to-end request binding, and Relying Parties SHOULD verify it.

3.2. EAR Appraisal Claims

;# import ar4si as ar4si
;# import rfc9711 as eat

EAR-appraisal = {
  ? eat.profile-label => eat.general-uri / eat.general-oid
  status-label => ar4si.trustworthiness-tier
  ? status-details-label => details-type
  ? trustworthiness-vector-label => ar4si.trustworthiness-vector
  ? trustworthiness-vector-details-label => trustworthiness-vector-details
  ? appraisal-policy-ids-label => [ + text ]
  ? eat.nonce-label => eat.nonce-type
  ? attester-claims-label => claims-map-type
  ? verifier-claims-label => claims-map-type
  ? endorser-claims-label => supply-chain-claims-type
  ? reference-value-provider-claims-label => supply-chain-claims-type
  * $$ear-appraisal-extension
}

status-label = eat.JC<"ear_status", 1000>
trustworthiness-vector-label = eat.JC<"ear_trustworthiness_vector", 1001>
status-details-label = eat.JC<"ear_status_details", 1010>
trustworthiness-vector-details-label =
  eat.JC<"ear_trustworthiness_vector_details", 1011>

details-type = [ + text ]

trustworthiness-vector-details = ar4si.non-empty<{
  ? ar4si.instance-identity-label => details-type,
  ? ar4si.configuration-label => details-type,
  ? ar4si.executables-label => details-type,
  ? ar4si.file-system-label => details-type,
  ? ar4si.hardware-label => details-type,
  ? ar4si.runtime-opaque-label => details-type,
  ? ar4si.storage-opaque-label => details-type,
  ? ar4si.sourced-data-label => details-type,
}>
appraisal-policy-ids-label = eat.JC<"ear_appraisal_policy_ids", 1003>
attester-claims-label = eat.JC<"ear_attester_claims", 1005>
verifier-claims-label = eat.JC<"ear_verifier_claims", 1006>
endorser-claims-label = eat.JC<"ear_endorser_claims", 1008>
reference-value-provider-claims-label = eat.JC<"ear_reference_value_provider_claims", 1009>

; supply chain entity name => claims it asserted
supply-chain-claims-type = { + text => claims-map-type }
Figure 2: EAR Appraisal Claims (CDDL Definition)
eat_profile (optional)

The EAT profile (Section 6 of [RFC9711]) associated with the EAR-appraisal claims-set. Note that if multiple EAR-appraisal submods exist within the same EAR token, they may all have different values for this claim. If the EAR-appraisal contains extensions, this claim SHOULD be present unless the profile can be implied by other means (e.g., via the application context or outer protocol elements).

ear_status (mandatory)

The overall appraisal status for this attester represented as one of the five trustworthiness tiers (Section 3.2 of [I-D.ietf-rats-ar4si]). The none tier is the neutral element of this computation: it does not affect the result and MUST NOT be used as the value of this claim. The value of this claim MUST be set to a tier of no higher trust than the tier corresponding to the worst trustworthiness claim across the entire trustworthiness vector.

ear_status_details (optional)

A non-empty array of strings, each giving a reason for the value of ear_status.

ear_trustworthiness_vector (optional)

The AR4SI trustworthiness vector providing the breakdown of the appraisal for this attester. See Section 3.1 of [I-D.ietf-rats-ar4si] for the details.

ear_trustworthiness_vector_details (optional)

A map from trustworthiness vector categories to non-empty arrays of strings, each giving a reason for the value of the corresponding category. Each key MUST be a category that is present in ear_trustworthiness_vector. This claim MUST be present unless the party requesting Evidence appraisal explicitly asks for it to be dropped, e.g., via an API parameter or similar arrangement. Such consumer would therefore rely entirely on the semantics of the ear_status claim. This behaviour is NOT RECOMMENDED because of the resulting loss of quality of the appraisal result.

ear_appraisal_policy_ids (optional)

A list of one or more unique identifiers for appraisal policies used to evaluate the attestation results. The order of the identifiers in the list represents the order in which the policies are applied, with those appearing earlier being applied first. The list MUST NOT be empty.

eat_nonce (optional)

The nonce extracted from Evidence corresponding to this appraisal record. Note that this is entirely distinct from the nonce in Section 3. It reflects evidence freshness rather than attestation results freshness. Specifically, it reflects the freshness of the evidence whose attestation results are contained in this appraisal record. This is useful when the relying party is the challenger in the remote attestation protocol and needs to verify that the nonce in the supplied evidence matches, without having to parse the evidence format. See also Section 4.1 of [RFC9711].

ear_attester_claims (optional)

A map containing claims with Attester authority, i.e., claims extracted from the appraised Evidence.

ear_verifier_claims (optional)

A map containing claims with Verifier authority, i.e., claims added by the Verifier during appraisal and derived from evaluating the Appraisal Policy for Evidence.

ear_endorser_claims (optional)

A map containing claims with Endorser authority, i.e., claims that are not present in the appraised Evidence and that the Verifier added during appraisal using Endorsements. Each key identifies the supply chain entity that asserted the claims in the associated value, which is a map of claims. Identifiers are subject to the rules given under ear_reference_value_provider_claims.

ear_reference_value_provider_claims (optional)

A map containing claims with Reference Value Provider authority, i.e., claims that are present in the appraised Evidence and that the Verifier corroborated using Reference Values. Each key identifies the supply chain entity that provided the Reference Values, and the associated value is a map of the corroborated claims. A corroborated claim MAY be omitted from ear_attester_claims: the complete set of claims extracted from the Evidence is the union of the two maps. The identifier is a human-readable string (e.g., "Arm" or "NVIDIA") that the Verifier derives from the cryptographic identity of the supply chain entity (e.g., the key that signed the Endorsements or Reference Values) when it ingests them, so that Relying Parties do not have to handle keys. The same entity MUST be given the same identifier throughout an EAR, and an identifier MUST NOT be shared by distinct entities. A claim asserted by more than one authority appears under the identifier of each of them. Each occurrence is an independent assertion. To avoid arbitrary values, the Verifier SHOULD derive the identifier from the first of the following sources that is available: the subject name (e.g., the organization or common name attribute) of the certificate of the key that signed the CoRIM conveying the Endorsements or Reference Values, provided the certification path validates to a trust anchor of the Verifier; the entity-name of the entity with the manifest-signer role in the corim-entity-map (Section 4.1.5 of [I-D.ietf-rats-corim]); the signer-name in the corim-signer-map (Section 4.2.3.1 of [I-D.ietf-rats-corim]); a name configured in the Appraisal Policy for Evidence. The entity-name and signer-name are asserted by the signer itself, so the Verifier MUST NOT use them unless it has authenticated the binding between the name and the key that signed the CoRIM.

$$ear-appraisal-extension (optional)

Any registered or unregistered extension. See Section 4 for further details.

3.3. Details Claims

The ear_status_details and ear_trustworthiness_vector_details claims let a Verifier tell the Relying Party the reasons for the values of ear_status and of the trustworthiness vector categories. They are optional, and are intended for values other than affirming.

Each string states one reason, in text meant for people (e.g., logs, diagnostics, support). The text is not standardised: it can change between Verifiers, versions of the same Verifier and, if localised, languages. A Relying Party MUST NOT base automated decisions on it. Those rely entirely on ear_status and ear_trustworthiness_vector, which remain authoritative.

The text can reproduce data controlled by the Attester (e.g., file names found in the Evidence), so a Relying Party MUST treat it as untrusted input (see Section 7). It can also reveal details of the Attester's state, see Section 8.

3.4. Recursive and Tunnelled Submods

In addition to a flat EAR-appraisal, a submod MAY instead carry a nested EAR or a Nested-Token (Section 4.2.18.3 of [RFC9711]). This gives the EAR a recursive structure that can directly reflect the topology of a mesh of cooperating verifiers, e.g., the lead verifier of the Hierarchical pattern defined in [I-D.ietf-rats-multi-verifier], which dispatches the appraisal of composite evidence to one or more sub-verifiers and then collects their results into its own EAR.

The three $submod-value alternatives serve different purposes:

EAR-appraisal

The existing, flat representation. Used when the verifier itself performs the appraisal of the associated attester, or restates a sub-verifier's result as its own appraisal.

EAR

A complete EAR claims-set produced by a sub-verifier, embedded directly, in the same serialization (JSON or CBOR) as the enclosing EAR. This lets a sub-verifier's full result -- including its own submods, potentially several levels deep -- be embedded as plain claims data, integrity-protected only by the enclosing EAR's own signature.

Nested-Token

A complete, independently signed EAR produced by a sub-verifier and tunnelled opaquely, using the nesting mechanics described in Section 4.2.18.3 of [RFC9711]. This is the only alternative that supports a sub-verifier whose EAR uses a different serialization than the enclosing token (e.g., a JWT-serialized sub-EAR nested inside a CWT-serialized top-level EAR, or vice versa). The nested token's encoding is self-describing, so the consumer needs no out-of-band knowledge of it: for CBOR it is given by the CBOR tag found after removing the byte string wrapping, for JSON by the JSON-Selector name (Section 4.2.18 of [RFC9711]). EAR restricts Nested-Token to its "JWT" and "CBOR" forms; the "BUNDLE" and "DIGEST" forms defined by [RFC9711] for detached claims-sets are out of scope for EAR. The content of a Nested-Token MUST be an EAR. The CDDL cannot enforce this, because the token is opaque to the schema; a verifier that finds otherwise treats the submod as incomplete (see ear_status in Section 3).

The existing flat representation of device topology, the ear_device_topology claim (Section 3), is unaffected by, and can be used independently of, the above; it remains the appropriate choice when a single verifier appraises a composite attester made up of several evidence sources without delegating appraisal to other verifiers.

A Relying Party that only consumes the top-level ear_status claim (see Section 3) does not need to understand any of the above: correctness only depends on the verifier correctly rolling up the status of every submod, regardless of its representation, into that claim. A Relying Party that wants a full audit trail, however, needs to be able to recurse into nested EAR submods and to decode Nested-Token submods -- which, per above, may require support for a different serialization or signature scheme than the one used by the enclosing token.

Figure 3 shows a lead verifier's EAR for a confidential computing scenario: a confidential VM ("cvm") running on a confidential platform ("cpu") and using a trusted device ("gpu") to offload a specialized ML workload. Each submod uses a different $submod-value kind, reflecting a realistic split of appraisal responsibilities across independent, vendor-specific verifiers: "cvm" is appraised directly by the lead verifier and carries a flat EAR-appraisal; "cpu" is appraised by Vendor-A's confidential computing verifier, whose full EAR claims-set, including its own "platform" submod, is embedded in-band as a nested EAR, because it happens to use the same (JSON) serialization as the enclosing token; "gpu" is appraised by Vendor-B's confidential computing verifier, whose EAR is tunnelled opaquely as a Nested-Token, JWT-serialized regardless of the serialization of the enclosing token. The lead verifier's ear_status reflects the worst status found across all three; the one it cannot itself parse is accounted for as incomplete.

=============== NOTE: '\' line wrapping per RFC 8792 ================

{
  "eat_profile": "tag:ietf.org,2026:rats/ear#05",
  "iat": 1666529184,
  "ear_status": "warning",
  "ear_verifier_id": {
    "developer": "https://veraison-project.org",
    "build": "vts 0.0.1"
  },
  "submods": {
    "cvm": {
      "ear_status": "affirming",
      "ear_trustworthiness_vector": {
        "instance-identity": 2,
        "executables": 2,
        "configuration": 2
      }
    },
    "cpu": {
      "eat_profile": "tag:ietf.org,2026:rats/ear#05",
      "iat": 1666529150,
      "ear_verifier_id": {
        "developer": "https://vendor-a.example/cc-verifier",
        "build": "cc-verifier 1.2.0"
      },
      "submods": {
        "platform": {
          "ear_status": "warning",
          "ear_trustworthiness_vector": {
            "hardware": 2,
            "configuration": 1
          }
        }
      }
    },
    "gpu": [
      "JWT",
      "eyJhbGciOiJFUzI1NiJ9.\
eyJlYXRfcHJvZmlsZSI6InRhZzppZXRmLm9yZywyMDI2OnJhdHMvZWFyIzA0IiwiaWF0\
IjoxNjY2NTI5MTAwLCJlYXJfc3RhdHVzIjoiYWZmaXJtaW5nIn0.\
                         QjJyZlBoM0tzWjF2WHdRbjlMbURhU3lFb1RjNGdIak0"
    ]
  }
}
Figure 3: JSON claims-set: recursive and tunnelled submods

3.5. JSON Serialisation

3.5.1. Examples

The example in Figure 4 shows an EAR claims-set corresponding to a "contraindicated" appraisal, meaning the verifier has found some problems with the attester's state reported in the submitted evidence. Specifically, the identified issue is related to unauthorized code or configuration loaded in runtime memory (i.e., value 96 in the executables category). The appraisal is for a device with one attester labelled "PSA". Note that in case there is only one attester, the labelling can be freely chosen because there is no ambiguity.

{
  "eat_profile": "tag:ietf.org,2026:rats/ear#05",
  "iat": 1666529184,
  "ear_verifier_id": {
    "developer": "https://veraison-project.org",
    "build": "vts 0.0.1"
  },
  "ear_raw_evidence": [
    "application/vnd.evidence",
    "NzQ3MjY5NzM2NTYzNzQK"
  ],
  "ear_input_digest": [
    "sha-256",
    "TInrSlzsaz9jfL7abgvJ2roo2P93Jozst3x3OU_afNg"
  ],
  "submods": {
    "PSA": {
      "ear_status": "contraindicated",
      "ear_status_details": [
        "The 'executables' category is contraindicated."
      ],
      "ear_trustworthiness_vector": {
        "instance-identity": 2,
        "executables": 96,
        "hardware": 2
      },
      "ear_trustworthiness_vector_details": {
        "executables": [ "unauthorized code found in runtime memory" ]
      },
      "ear_appraisal_policy_ids":
        [ "https://veraison.example/policy/1/60a0068d" ]
    }
  }
}
Figure 4: JSON claims-set: contraindicated appraisal

The breakdown of the trustworthiness vector is as follows:

  • Instance Identity (affirming): recognized and not compromised

  • Configuration (warning): known vulnerabilities

  • Executables (contraindicated): contraindicated run-time

  • File System (none): no claim being made

  • Hardware (affirming): genuine

  • Runtime Opaque (none): no claim being made

  • Storage Opaque (none): no claim being made

  • Sourced Data (none): no claim being made

The example in Figure 5 contains the appraisal for a composite device with two attesters named "CCA Platform" and "CCA Realm" respectively. Both attesters have either "affirming" or (implicit) "none" values in their associated trustworthiness vectors. Note that the "none" values can refer to either an AR4SI category that is unapplicable for the specific attester (ideally, the applicability should be specified by the evidence format itself), or to the genuine lack of information at the attester site regarding the specific category. For example, the reference values for the "CCA Realm" executables (i.e., the confidential computing workload) may not be known to the CCA platform verifier. In such cases, it is up to the downstream entity (typically, the relying party) to complete the partial appraisal.

{
  "eat_profile": "tag:ietf.org,2026:rats/ear#05",
  "iat": 1666529300,
  "ear_verifier_id": {
    "developer": "https://veraison-project.org",
    "build": "vts 0.0.1"
  },
  "ear_raw_evidence": [
    "application/vnd.evidence",
    "NzQ3MjY5NzM2NTYzNzQKNzQ3MjY5NzM2NTYzNzQK"
  ],
  "submods": {
    "CCA Platform": {
      "ear_status": "affirming",
      "ear_trustworthiness_vector": {
        "instance-identity": 2,
        "executables": 2,
        "hardware": 2
      },
      "ear_appraisal_policy_ids":
        [ "https://veraison.example/policy/1/60a0068d" ]
    },
    "CCA Realm": {
      "ear_status": "affirming",
      "ear_trustworthiness_vector": {
        "instance-identity": 2
      },
      "ear_appraisal_policy_ids":
        [ "https://veraison.example/policy/1/60a0068d" ]
    }
  }
}
Figure 5: JSON claims-set: simple affirming appraisal

3.6. CBOR Serialisation

3.6.1. Examples

The example in Figure 6 is semantically equivalent to that in Figure 4. It shows the same "contraindicated" appraisal using the more compact CBOR serialization of the EAR claims-set.

{
  265: "tag:ietf.org,2026:rats/ear#05",
  6: 1666529184,
  1004: {
    0: "https://veraison-project.org",
    1: "vts 0.0.1"
  },
  1002: [
    "application/vnd.evidence",
    h'6C696665626F61746D616E'
  ],
  1008: [
    1,
    h'4c89eb4a5cec6b3f637cbeda6e0bc9daba28d8ff77268cecb77c77394fda7cd8'
  ],
  266: {
    "PSA": {
      1000: 96,
      1010: [ "The 'executables' category is contraindicated." ],
      1001: {
        0: 2,
        2: 96,
        4: 2
      },
      1011: {
        2: [ "unauthorized code found in runtime memory" ]
      },
      1003: [ "https://veraison.example/policy/1/60a0068d" ]
    }
  }
}
Figure 6: CBOR claims-set: contraindicated appraisal

4. EAR Extensions

EAR provides core semantics for describing the result of appraising attestation evidence. However, a given application may offer extra functionality to its relying parties, or tailor the attestation result to the needs of the application (e.g., TEEP [I-D.ietf-teep-protocol]). To accommodate such cases, both EAR and EAR-appraisal claims-sets can be extended by plugging new claims into the $$ear-extension (or $$ear-appraisal-extension, respectively) CDDL socket.

The rules that govern extensibility of EAR are those defined in [RFC8392] and [RFC7519] for CWTs and JWTs respectively.

An extension MUST NOT change the semantics of the EAR and EAR-appraisal claims-sets.

Whether or not an extension requires a new EAR profile identifier depends on whether it must be understood by all consumers of that EAR token.

If an extension is optional, meaning a receiver that does not understand it can safely ignore it while still processing the rest of the EAR correctly, then the existing EAR profile identifier MAY be retained. (This is enabled by the requirement to ignore unknown claims stated in Section 4 of [RFC9711].)

However, if an extension introduces claims that MUST be understood and acted upon by all consumers, i.e., a receiver that does not recognise the extension cannot safely process the EAR, then a new EAT profile identifier MUST be used to signal this requirement. Such a profile identifier would typically be defined in a specification document alongside the mandatory extension claims.

4.1. Unregistered claims

An application-specific extension will normally mint its claim from the "private space" - using integer values less than -65536 for CWT, and Public or Private Claim Names as defined in Sections 4.2 and 4.3 of [RFC7519] when serializing to JWT.

It is RECOMMENDED that JWT EARs use Collision-Resistant Public Claim Names (Section 2 of [RFC7519]) rather than Private Claim Names.

4.2. Registered claims

If an extension will be used across multiple applications, or is intended to be used across multiple environments, the associated extension claims SHOULD be registered in one, or both, the CWT and JWT claim registries.

In general, if the registration policy requires an accompanying specification document (as it is the case for "specification required" and "standards action"), such document SHOULD explicitly say that the extension is expected to be used in EAR claims-sets identified by this profile.

An up-to-date view of the registered claims can be obtained via the [IANA.cwt] and [IANA.jwt] registries.

4.3. Choosing between registered and unregistered claims

If an extension supports functionality of a specific application (e.g. Project Veraison Services), its claims MAY be registered.

If an extension supports a protocol that may be applicable across multiple applications or environments (e.g., TEEP), its claims SHOULD be registered.

Since, in general, there is no guarantee that an application will be confined within an environment, it is RECOMMENDED that extension claims that have meaning outside the application's context are always registered.

It is also possible that claims that start out as application-specific acquire a more stable meaning over time. In such cases, it is RECOMMENDED that new equivalent claims are created in the "public space" and are registered as described in Section 4.2. The original "private space" claims SHOULD then be deprecated by the application.

4.4. Grouping Claims Under a Single Top-Level Key

EAR places no constraint on the type of value carried by an extension claim. An extension may therefore use any CBOR or JSON value type that is appropriate for the information it conveys.

However, when an extension introduces more than one logically related claim and those claims are intended to be registered in the CWT or JWT claim registries, it is RECOMMENDED to group them as members of a single map value carried under one top-level registered key. This minimises consumption of the public codepoint namespace, which is a finite shared resource.

This recommendation does not apply to claims minted from the private space (integer values less than -65536 for CWT, and Private Claim Names as defined in Section 4.3 of [RFC7519] for JWT), where namespace pressure is not a concern.

4.5. TEEP Extension

The TEEP protocol [I-D.ietf-teep-protocol] specifies the required claims that an attestation result must carry for a TAM (Trusted Application Manager) to make decisions on how to remediate a TEE (Trusted Execution Environment) that is out of compliance, or update a TEE that is requesting an authorized change.

The list is provided in Section 4.3.1 of [I-D.ietf-teep-protocol].

EAR defines a TEEP application extension for the purpose of conveying such claims.

;# import rfc9711 as eat
;# import rfc9393

$$ear-appraisal-extension //= (
  ear.teep-claims-label => ear-teep-claims
)

ear-teep-claims = non-empty<{
  ? eat.nonce-label => eat.nonce-type
  ? eat.ueid-label => eat.ueid-type
  ? eat.oemid-label => eat.oemid-pen / eat.oemid-ieee / eat.oemid-random
  ? eat.hardware-model-label => eat.hardware-model-type
  ? eat.hardware-version-label => eat.hardware-version-type
  ? eat.manifests-label => eat.manifests-type
}>

ear.teep-claims-label = eat.JC<"ear_teep_claims", 65000>
Figure 7: TEEP Extension (CDDL Definition)

4.5.1. JSON Serialization Example

{
  "eat_profile": "tag:ietf.org,2026:rats/ear#05",
  "iat": 1666529184,
  "ear_verifier_id": {
    "developer": "https://veraison-project.org",
    "build": "vts 0.0.1"
  },
  "ear_raw_evidence": [
    "application/vnd.evidence",
    "NzQ3MjY5NzM2NTYzNzQK"
  ],
  "submods": {
    "PSA": {
      "ear_status": "contraindicated",
      "ear_trustworthiness_vector": {
        "instance-identity": 2,
        "executables": 96,
        "hardware": 2
      },
      "ear_appraisal_policy_ids":
        [ "https://veraison.example/policy/1/60a0068d" ],
      "ear_teep_claims": {
        "eat_nonce": "80FH7byS7VjfARIq0_KLqu6B9j-F79QtV6p",
        "ueid": "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAh",
        "oemid": "Av8B",
        "hwmodel": "fJYq",
        "hwversion": ["1.2.5", 16384]
      }
    }
  }
}

4.5.2. CBOR Serialization Example

{
  265: "tag:ietf.org,2026:rats/ear#05",
  6: 1666529184,
  1004: {
    0: "https://veraison-project.org",
    1: "vts 0.0.1"
  },
  1002: [
    "application/vnd.evidence",
    h'6C696665626F61746D616E'
  ],
  266: {
    "PSA": {
      1000: 0,
      1001: {
        0: 2,
        1: 2,
        2: 2,
        4: 2
      },
      1003: [ "https://veraison.example/policy/1/60a0068d" ],
      65000: {
        10: h'948f8860d13a463e',
        256: h'0198f50a4ff6c05861c8860d13a638ea',
        258: 64242,
        259: h'ee80f5a66c1fb9742999a8fdab930893',
        260: ["1.2.5", 16384]
      }
    }
  }
}

4.6. Project Veraison Extensions

The Project Veraison verifier defines a private, application-specific extension:

ear_veraison_key_attestation

contains the public key part of a successfully verified attested key. The key is a DER encoded ASN.1 SubjectPublicKeyInfo structure (Section 4.1.2.7 of [RFC5280]).

;# import rfc9711 as eat

$$ear-appraisal-extension //= (
  ear.veraison.key-attestation-label => ear-veraison-key-attestation
)

ear-veraison-key-attestation = {
  "akpub" => eat.binary-data
}

ear.veraison.key-attestation-label = eat.JC<"ear_veraison_key_attestation", -70002>
Figure 8: Project Veraison Extension (CDDL Definition)

4.6.1. JSON Serialization Examples

{
  "eat_profile": "tag:ietf.org,2026:rats/ear#05",
  "iat": 1666529184,
  "ear_verifier_id": {
    "developer": "https://veraison-project.org",
    "build": "vts 0.0.1"
  },
  "ear_raw_evidence": [
    "application/vnd.evidence",
    "NzQ3MjY5NzM2NTYzNzQK"
  ],
  "submods": {
    "PSA_IOT": {
      "ear_status": "contraindicated",
      "ear_trustworthiness_vector": {
        "instance-identity": 2,
        "executables": 96,
        "hardware": 2
      },
      "ear_appraisal_policy_ids":
        [ "https://veraison.example/policy/1/60a0068d" ],
      "ear_attester_claims": {
        "eat-profile": "http://arm.com/psa/2.0.0",
        "psa-client-id": 1,
        "psa-security-lifecycle": 12288,
        "psa-implementation-id":
          "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=",
        "psa-software-components": [
          {
            "measurement-value":
              "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=",
            "signer-id":
              "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="
          },
          {
            "measurement-value":
              "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=",
            "signer-id":
              "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="
          }
        ],
        "psa-nonce":
          "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=",
        "psa-instance-id":
          "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAh",
        "psa-certification-reference": "1234567890123-12345"
      },
      "ear_endorser_claims": {
        "ACME Security Lab": {
          "psa-certified": {
            "certificate-number": "1234567890123-12345",
            "date-of-issue": "23/06/2022",
            "test-lab": "Riscure",
            "certification-holder": "ACME Inc.",
            "certified-product": "RoadRunner",
            "hardware-version": "Gizmo v1.0.2",
            "software-version": "TrustedFirmware-M v1.0.6",
            "certification-type": "PSA Certified Level 1 v2.1",
            "developer-type": "PSA Certified – Device"
          }
        }
      },
      "ear_reference_value_provider_claims": {
        "Arm": {
          "psa-implementation-id":
            "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="
        }
      }
    }
  }
}
{
  "eat_profile": "tag:ietf.org,2026:rats/ear#05",
  "iat": 1666529184,
  "ear_verifier_id": {
    "developer": "https://veraison-project.org",
    "build": "vts 0.0.1"
  },
  "ear_raw_evidence": [
    "application/vnd.evidence",
    "NzQ3MjY5NzM2NTYzNzQK"
  ],
  "submods": {
    "PARSEC_TPM": {
      "ear_status": "affirming",
      "ear_trustworthiness_vector": {
        "instance-identity": 2,
        "executables": 2,
        "hardware": 2
      },
      "ear_appraisal_policy_ids":
        [ "https://veraison.example/policy/1/60a0068d" ],
      "ear_veraison_key_attestation": {
        "akpub":
          "MFkwEwYHKoZIzj0CAQYIKoZIz___"
      }
    }
  }
}

4.6.2. CBOR Serialization Example

{
  265: "tag:ietf.org,2026:rats/ear#05",
  6: 1666529184,
  1004: {
    0: "https://veraison-project.org",
    1: "vts 0.0.1"
  },
  1002: [
    "application/vnd.evidence",
    h'6C696665626F61746D616E'
  ],
  266: {
    "PSA_IOT": {
      1000: 0,
      1001: {
        0: 2,
        1: 2,
        2: 2,
        4: 2
      },
      1003: [ "https://veraison.example/policy/1/60a0068d" ],
      1005: {
        "eat-profile": "http://arm.com/psa/2.0.0",
        "psa-client-id": 1,
        "psa-security-lifecycle": 12288,
        "psa-implementation-id":
          "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=",
        "psa-software-components": [
          {
            "measurement-value":
              "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=",
            "signer-id":
              "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="
          },
          {
            "measurement-value":
              "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=",
            "signer-id":
              "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="
          }
        ],
        "psa-nonce":
          "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA=",
        "psa-instance-id":
          "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyAh",
        "psa-certification-reference": "1234567890123-12345"
      },
      1008: {
        "ACME Security Lab": {
          "psa-certified": {
            "certificate-number": "1234567890123-12345",
            "date-of-issue": "23/06/2022",
            "test-lab": "Riscure",
            "certification-holder": "ACME Inc.",
            "certified-product": "RoadRunner",
            "hardware-version": "Gizmo v1.0.2",
            "software-version": "TrustedFirmware-M v1.0.6",
            "certification-type": "PSA Certified Level 1 v2.1",
            "developer-type": "PSA Certified – Device"
          }
        }
      },
      1009: {
        "Arm": {
          "psa-implementation-id":
            "AQIDBAUGBwgJCgsMDQ4PEBESExQVFhcYGRobHB0eHyA="
        }
      }
    }
  }
}

5. Media Types

Media types for EAR are automatically derived from the base EAT media type [RFC9782] using the profile string defined in Section 3.

For example, a JWT serialization would use:

application/eat-jwt; eat_profile="tag:ietf.org,2026:rats/ear#05"

A CWT serialization would instead use:

application/eat-cwt; eat_profile="tag:ietf.org,2026:rats/ear#05"

6. Implementation Status

This section records the status of known implementations of the protocol defined by this specification at the time of posting of this Internet-Draft, and is based on a proposal described in [RFC7942]. The description of implementations in this section is intended to assist the IETF in its decision processes in progressing drafts to RFCs. Please note that the listing of any individual implementation here does not imply endorsement by the IETF. Furthermore, no effort has been spent to verify the information presented here that was supplied by IETF contributors. This is not intended as, and must not be construed to be, a catalog of available implementations or their features. Readers are advised to note that other implementations may exist.

According to [RFC7942], "this will allow reviewers and working groups to assign due consideration to documents that have the benefit of running code, which may serve as evidence of valuable experimentation and feedback that have made the implemented protocols more mature. It is up to the individual working groups to use this information as they see fit".

6.1. Project Veraison

The organization responsible for this implementation is Project Veraison, a Linux Foundation project hosted at the Confidential Computing Consortium.

The organization currently provides three separate implementations: one in Golang, one in Rust and another in C17.

The developers can be contacted on the Zulip channel: https://veraison.zulipchat.com/#narrow/stream/357929-EAR/.

6.1.1. github.com/veraison/ear

The software, hosted at https://github.com/veraison/ear, provides a Golang package that allows encoding, decoding, signing and verification of EAR payloads together with a CLI (arc) to create, verify and visualize EARs on the command line. The maturity level is currently alpha, and only the JWT serialization is implemented. The license is Apache 2.0. The package is used by the Project Veraison verifier to produce attestation results.

6.1.2. github.com/veraison/c-ear

The software, hosted at https://github.com/veraison/c-ear, provides a C17 library that allows verification and partial decoding of EAR payloads. The maturity level is currently pre-alpha, and only the JWT serialization is implemented. The license is Apache 2.0. The library targets relying party applications that need to verify attestation results.

6.1.3. github.com/veraison/rust-ear

The software, hosted at https://github.com/veraison/rust-ear, provides a Rust (2021 edition) library that allows verification and partial decoding of EAR payloads. The maturity level is currently pre-alpha, with limitted algorithm support. Both JWT and COSE serializations are implemented. The license is Apache 2.0. The library targets verifiers that need to produce attestation results as well as relying party applications that need to verify and consume attestation results.

7. Security Considerations

EAR is a profile of the EAT specification [RFC9711], it also reuses the CWT specification [RFC8392]. The security considerations of these specifications therefore apply here too.

Any textual fields (e.g., the strings in ear_status_details and ear_trustworthiness_vector_details) that are stored in a file, inserted into a database, or displayed to humans must be properly sanitized to prevent attacks and undesirable behavior. Further discussion and references on this topic can be found in Section 7 of [RFC9839].

The ear_endorser_claims and ear_reference_value_provider_claims claims attribute claims to supply chain entities. The attribution is the Verifier's. Relying Parties cannot see or check the keys and signatures on which it is based. Consequently, they rely on the Verifier's mapping from cryptographic identities to identifiers and on the integrity protection of the EAR.

7.1. Binding EAR to the Appraisal Request

eat_nonce alone only proves that the Verifier processed a request carrying a given nonce; it does not prove that the request contained the evidence (or any other input) that the requester actually sent. An on-path attacker able to tamper with the appraisal request without disturbing the nonce -- for example, by substituting the evidence while leaving the nonce intact -- can therefore cause a Relying Party to accept an EAR that has a valid nonce but does not reflect the evidence the Relying Party asked to have appraised.

The ear_input_digest claim (see Section 3.1), when applicable, mitigates this class of attack by binding the EAR to the exact wire bytes of the appraisal request the Verifier received. Implementers and deployers are strongly encouraged to read Section 3.1 in full before deciding to produce or verify ear_input_digest, since an inappropriate deployment topology can silently negate its security benefit.

8. Privacy Considerations

EAR is designed to expose as little identifying information as possible about the attester. However, certain EAR claims have direct privacy implications. Implementations should therefore allow applying privacy-preserving techniques to those claims, for example allowing their redaction, anonymisation or outright removal. Specifically:

EAR is an EAT, therefore the privacy considerations in Section 8 of [RFC9711] apply.

9. IANA Considerations

9.1. New EAT Claims

This specification adds the following values to the "JSON Web Token Claims" registry [IANA.jwt] and the "CBOR Web Token Claims" registry [IANA.cwt].

Each entry below is an addition to both registries.

The "Claim Description", "Change Controller" and "Specification Documents" are common and equivalent for the JWT and CWT registries. The "Claim Key" and "Claim Value Types(s)" are for the CWT registry only. The "Claim Name" is as defined for the CWT registry, not the JWT registry. The "JWT Claim Name" is equivalent to the "Claim Name" in the JWT registry.

9.1.1. EAR Status

  • Claim Name: ear_status

  • Claim Description: EAR Status

  • JWT Claim Name: ear_status

  • Claim Key: 1000 (suggested)

  • Claim Value Type(s): unsigned integer (0, 2, 32, 96)

  • Change Controller: IESG

  • Specification Document(s): Section 3.2 of RFCthis

9.1.2. Trustworthiness Vector

  • Claim Name: ear_trustworthiness_vector

  • Claim Description: EAR Trustworthiness Vector

  • JWT Claim Name: ear_trustworthiness_vector

  • Claim Key: 1001 (suggested)

  • Claim Value Type(s): map

  • Change Controller: IESG

  • Specification Document(s): Section 3.2 of RFCthis

9.1.3. Status Details

  • Claim Name: ear_status_details

  • Claim Description: EAR Status Details

  • JWT Claim Name: ear_status_details

  • Claim Key: 1010 (suggested)

  • Claim Value Type(s): array

  • Change Controller: IESG

  • Specification Document(s): Section 3 and Section 3.2 of RFCthis

9.1.4. Trustworthiness Vector Details

  • Claim Name: ear_trustworthiness_vector_details

  • Claim Description: EAR Trustworthiness Vector Details

  • JWT Claim Name: ear_trustworthiness_vector_details

  • Claim Key: 1011 (suggested)

  • Claim Value Type(s): map

  • Change Controller: IESG

  • Specification Document(s): Section 3.2 of RFCthis

9.1.5. EAR Raw Evidence

  • Claim Name: ear_raw_evidence

  • Claim Description: EAR Raw Evidence as CMW

  • JWT Claim Name: ear_raw_evidence

  • Claim Key: 1002 (suggested)

  • Claim Value Type(s): array

  • Change Controller: IESG

  • Specification Document(s): Section 3 of RFCthis

9.1.6. EAR Appraisal Policy Identifier

  • Claim Name: ear_appraisal_policy_ids

  • Claim Description: EAR Appraisal Policy Identifiers

  • JWT Claim Name: ear_appraisal_policy_ids

  • Claim Key: 1003 (suggested)

  • Claim Value Type(s): array

  • Change Controller: IESG

  • Specification Document(s): Section 3.2 of RFCthis

9.1.7. Verifier Software Identifier

  • Claim Name: ear_verifier_id

  • Claim Description: AR4SI Verifier Software Identifier

  • JWT Claim Name: ear_verifier_id

  • Claim Key: 1004 (suggested)

  • Claim Value Type(s): map

  • Change Controller: IESG

  • Specification Document(s): Section 3 of RFCthis

9.1.8. Attester Claims

  • Claim Name: ear_attester_claims

  • Claim Description: Attester Claims

  • JWT Claim Name: ear_attester_claims

  • Claim Key: 1005 (suggested)

  • Claim Value Type(s): map

  • Change Controller: IESG

  • Specification Document(s): Section 3.2 of RFCthis

9.1.9. Verifier Claims

  • Claim Name: ear_verifier_claims

  • Claim Description: Verifier Claims

  • JWT Claim Name: ear_verifier_claims

  • Claim Key: 1006 (suggested)

  • Claim Value Type(s): map

  • Change Controller: IESG

  • Specification Document(s): Section 3.2 of RFCthis

9.1.10. Endorser Claims

  • Claim Name: ear_endorser_claims

  • Claim Description: Endorser Claims

  • JWT Claim Name: ear_endorser_claims

  • Claim Key: 1008 (suggested)

  • Claim Value Type(s): map

  • Change Controller: IESG

  • Specification Document(s): Section 3.2 of RFCthis

9.1.11. Reference Value Provider Claims

  • Claim Name: ear_reference_value_provider_claims

  • Claim Description: Reference Value Provider Claims

  • JWT Claim Name: ear_reference_value_provider_claims

  • Claim Key: 1009 (suggested)

  • Claim Value Type(s): map

  • Change Controller: IESG

  • Specification Document(s): Section 3.2 of RFCthis

9.1.12. Device Topology

  • Claim Name: ear_device_topology

  • Claim Description: Device Attesters Arrangement

  • JWT Claim Name: ear_device_topology

  • Claim Key: 1007 (suggested)

  • Claim Value Type(s): map

  • Change Controller: IESG

  • Specification Document(s): Section 3 of RFCthis

9.1.13. EAR Input Digest

  • Claim Name: ear_input_digest

  • Claim Description: Digest of the EAR Appraisal Request Input

  • JWT Claim Name: ear_input_digest

  • Claim Key: 1008 (suggested)

  • Claim Value Type(s): array

  • Change Controller: IESG

  • Specification Document(s): Section 3.1 of RFCthis

10. References

10.1. Normative References

[I-D.ietf-rats-ar4si]
Voit, E., Birkholz, H., Hardjono, T., Fossati, T., and V. Scarlata, "Attestation Results for Secure Interactions", Work in Progress, Internet-Draft, draft-ietf-rats-ar4si-11, , <https://datatracker.ietf.org/doc/html/draft-ietf-rats-ar4si-11>.
[I-D.ietf-rats-eat-measured-component]
Frost, S., Fossati, T., Tschofenig, H., and H. Birkholz, "Entity Attestation Token (EAT) Measured Component", Work in Progress, Internet-Draft, draft-ietf-rats-eat-measured-component-12, , <https://datatracker.ietf.org/doc/html/draft-ietf-rats-eat-measured-component-12>.
[I-D.ietf-teep-protocol]
Tschofenig, H., Pei, M., Wheeler, D. M., Thaler, D., and A. Tsukamoto, "Trusted Execution Environment Provisioning (TEEP) Protocol", Work in Progress, Internet-Draft, draft-ietf-teep-protocol-26, , <https://datatracker.ietf.org/doc/html/draft-ietf-teep-protocol-26>.
[RFC2119]
Bradner, S., "Key words for use in RFCs to Indicate Requirement Levels", BCP 14, RFC 2119, DOI 10.17487/RFC2119, , <https://www.rfc-editor.org/rfc/rfc2119>.
[RFC5280]
Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and W. Polk, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, , <https://www.rfc-editor.org/rfc/rfc5280>.
[RFC7519]
Jones, M., Bradley, J., and N. Sakimura, "JSON Web Token (JWT)", RFC 7519, DOI 10.17487/RFC7519, , <https://www.rfc-editor.org/rfc/rfc7519>.
[RFC8174]
Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174, , <https://www.rfc-editor.org/rfc/rfc8174>.
[RFC8392]
Jones, M., Wahlstroem, E., Erdtman, S., and H. Tschofenig, "CBOR Web Token (CWT)", RFC 8392, DOI 10.17487/RFC8392, , <https://www.rfc-editor.org/rfc/rfc8392>.
[RFC8610]
Birkholz, H., Vigano, C., and C. Bormann, "Concise Data Definition Language (CDDL): A Notational Convention to Express Concise Binary Object Representation (CBOR) and JSON Data Structures", RFC 8610, DOI 10.17487/RFC8610, , <https://www.rfc-editor.org/rfc/rfc8610>.
[RFC9711]
Lundblade, L., Mandyam, G., O'Donoghue, J., and C. Wallace, "The Entity Attestation Token (EAT)", RFC 9711, DOI 10.17487/RFC9711, , <https://www.rfc-editor.org/rfc/rfc9711>.
[RFC9782]
Lundblade, L., Birkholz, H., and T. Fossati, "Entity Attestation Token (EAT) Media Types", RFC 9782, DOI 10.17487/RFC9782, , <https://www.rfc-editor.org/rfc/rfc9782>.
[RFC9999]
Birkholz, H., Smith, N., Fossati, T., and H. Tschofenig, "Remote ATtestation procedureS (RATS) Conceptual Message Wrapper (CMW)", RFC 9999, DOI 10.17487/RFC9999, , <https://www.rfc-editor.org/rfc/rfc9999>.
[STD94]
Bormann, C. and P. Hoffman, "Concise Binary Object Representation (CBOR)", STD 94, RFC 8949, DOI 10.17487/RFC8949, , <https://www.rfc-editor.org/rfc/rfc8949>.
[STD96]
Schaad, J., "CBOR Object Signing and Encryption (COSE): Structures and Process", STD 96, RFC 9052, DOI 10.17487/RFC9052, , <https://www.rfc-editor.org/rfc/rfc9052>.

10.2. Informative References

[I-D.ietf-rats-corim]
Birkholz, H., Fossati, T., Deshpande, Y., Smith, N., and W. Pan, "Concise Reference Integrity Manifest", Work in Progress, Internet-Draft, draft-ietf-rats-corim-12, , <https://datatracker.ietf.org/doc/html/draft-ietf-rats-corim-12>.
[I-D.ietf-rats-multi-verifier]
Deshpande, Y., jun, Z., Labiod, H., and H. Birkholz, "Remote Attestation with Multiple Verifiers", Work in Progress, Internet-Draft, draft-ietf-rats-multi-verifier-01, , <https://datatracker.ietf.org/doc/html/draft-ietf-rats-multi-verifier-01>.
[IANA.cwt]
IANA, "CBOR Web Token (CWT) Claims", <https://www.iana.org/assignments/cwt>.
[IANA.jwt]
IANA, "JSON Web Token (JWT)", <https://www.iana.org/assignments/jwt>.
[RFC4151]
Kindberg, T. and S. Hawke, "The 'tag' URI Scheme", RFC 4151, DOI 10.17487/RFC4151, , <https://www.rfc-editor.org/rfc/rfc4151>.
[RFC7942]
Sheffer, Y. and A. Farrel, "Improving Awareness of Running Code: The Implementation Status Section", BCP 205, RFC 7942, DOI 10.17487/RFC7942, , <https://www.rfc-editor.org/rfc/rfc7942>.
[RFC9334]
Birkholz, H., Thaler, D., Richardson, M., Smith, N., and W. Pan, "Remote ATtestation procedureS (RATS) Architecture", RFC 9334, DOI 10.17487/RFC9334, , <https://www.rfc-editor.org/rfc/rfc9334>.
[RFC9839]
Bray, T. and P. Hoffman, "Unicode Character Repertoire Subsets", RFC 9839, DOI 10.17487/RFC9839, , <https://www.rfc-editor.org/rfc/rfc9839>.

Appendix A. Collated CDDL

=============== NOTE: '\' line wrapping per RFC 8792 ================

;;; *** undefined: $$ear-extension
;;; *** undefined: $$ear-appraisal-extension
EAR = {
  eat.profile-label => "tag:ietf.org,2026:rats/ear#05",
  ? status-label => ar4si.trustworthiness-tier,
  ? status-details-label => details-type,
  eat.iat-claim-label => ~eat.time-int,
  ? eat.exp-claim-label => ~eat.time-int,
  verifier-id-label => ar4si.verifier-id,
  ? raw-evidence-label => cmw-record,
  eat.submods-label => {+ text => $submod-value},
  ? eat.nonce-label => eat.nonce-type,
  ? topology-label => topology-type,
  ? input-digest-label => mc.digest,
  * $$ear-extension,
}
cmw-record = eat.JC<cmw.json-record, cmw.cbor-record>
$submod-value /= EAR-appraisal / EAR / eat.Nested-Token
raw-evidence-label = eat.JC<"ear_raw_evidence", 1002>
verifier-id-label = eat.JC<"ear_verifier_id", 1004>
topology-label = eat.JC<"ear_device_topology", 1007>
input-digest-label = eat.JC<"ear_input_digest", 1008>
EAR-appraisal = {
  ? eat.profile-label => eat.general-uri / eat.general-oid,
  status-label => ar4si.trustworthiness-tier,
  ? status-details-label => details-type,
  ? trustworthiness-vector-label => ar4si.trustworthiness-vector,
  ? trustworthiness-vector-details-label => trustworthiness-vector-\
                                                             details,
  ? appraisal-policy-ids-label => [+ text],
  ? eat.nonce-label => eat.nonce-type,
  ? attester-claims-label => claims-map-type,
  ? verifier-claims-label => claims-map-type,
  ? endorser-claims-label => supply-chain-claims-type,
  ? reference-value-provider-claims-label => supply-chain-claims-\
                                                                type,
  * $$ear-appraisal-extension,
}
status-label = eat.JC<"ear_status", 1000>
trustworthiness-vector-label = eat.JC<"ear_trustworthiness_vector", \
                                                                1001>
status-details-label = eat.JC<"ear_status_details", 1010>
trustworthiness-vector-details-label = eat.JC<"\
                           ear_trustworthiness_vector_details", 1011>
details-type = [+ text]
trustworthiness-vector-details = ar4si.non-empty<{
    ? ar4si.instance-identity-label => details-type,
    ? ar4si.configuration-label => details-type,
    ? ar4si.executables-label => details-type,
    ? ar4si.file-system-label => details-type,
    ? ar4si.hardware-label => details-type,
    ? ar4si.runtime-opaque-label => details-type,
    ? ar4si.storage-opaque-label => details-type,
    ? ar4si.sourced-data-label => details-type,
}>
appraisal-policy-ids-label = eat.JC<"ear_appraisal_policy_ids", 1003>
attester-claims-label = eat.JC<"ear_attester_claims", 1005>
verifier-claims-label = eat.JC<"ear_verifier_claims", 1006>
endorser-claims-label = eat.JC<"ear_endorser_claims", 1008>
reference-value-provider-claims-label = eat.JC<"\
                          ear_reference_value_provider_claims", 1009>
supply-chain-claims-type = {+ text => claims-map-type}
claims-map-type = eat.JC<claims-map-type-json, claims-map-type-cbor>
claims-map-type-json = {+ text => any}
claims-map-type-cbor = {+ (text / int) => any}
topology-type = {+ text => [+ text]}
eat.JC<J, C> = eat.JSON-ONLY<J> / eat.CBOR-ONLY<C>
eat.JSON-ONLY<J> = J .feature "json"
eat.CBOR-ONLY<C> = C .feature "cbor"
ar4si.non-empty<M> = M .within ({+ any => any})
ar4si.trustworthiness-tier /= ar4si.trustworthiness-tier-none-label \
/ ar4si.trustworthiness-tier-affirming-label / ar4si.trustworthiness\
-tier-warning-label / ar4si.trustworthiness-tier-contraindicated-\
                  label / ar4si.trustworthiness-tier-incomplete-label
ar4si.verifier-id = {
  ar4si.developer-label => text,
  ar4si.build-label => text,
}
ar4si.trustworthiness-vector = ar4si.non-empty<{
    ? ar4si.instance-identity-label => ar4si.trustworthiness-claim,
    ? ar4si.configuration-label => ar4si.trustworthiness-claim,
    ? ar4si.executables-label => ar4si.trustworthiness-claim,
    ? ar4si.file-system-label => ar4si.trustworthiness-claim,
    ? ar4si.hardware-label => ar4si.trustworthiness-claim,
    ? ar4si.runtime-opaque-label => ar4si.trustworthiness-claim,
    ? ar4si.storage-opaque-label => ar4si.trustworthiness-claim,
    ? ar4si.sourced-data-label => ar4si.trustworthiness-claim,
}>
ar4si.instance-identity-label = ar4si.JC<"instance-identity", 0>
ar4si.configuration-label = ar4si.JC<"configuration", 1>
ar4si.executables-label = ar4si.JC<"executables", 2>
ar4si.file-system-label = ar4si.JC<"file-system", 3>
ar4si.hardware-label = ar4si.JC<"hardware", 4>
ar4si.runtime-opaque-label = ar4si.JC<"runtime-opaque", 5>
ar4si.storage-opaque-label = ar4si.JC<"storage-opaque", 6>
ar4si.sourced-data-label = ar4si.JC<"sourced-data", 7>
ar4si.JC<J, C> = ar4si.JSON-ONLY<J> / ar4si.CBOR-ONLY<C>
ar4si.JSON-ONLY<J> = J .feature "json"
ar4si.CBOR-ONLY<C> = C .feature "cbor"
ar4si.trustworthiness-tier-none-label = ar4si.JC<"none", 0>
ar4si.trustworthiness-tier-affirming-label = ar4si.JC<"affirming", 2>
ar4si.trustworthiness-tier-warning-label = ar4si.JC<"warning", 32>
ar4si.trustworthiness-tier-contraindicated-label = ar4si.JC<"\
                                                contraindicated", 96>
ar4si.trustworthiness-tier-incomplete-label = ar4si.JC<"incomplete"\
                                                               , 127>
ar4si.developer-label = ar4si.JC<"developer", 0>
ar4si.build-label = ar4si.JC<"build", 1>
ar4si.trustworthiness-claim = -128 .. 127
cmw.json-record = [
  type: cmw.media-type,
  value: cmw.base64url-string,
  ? ind: uint .bits cmw.cm-type,
]
cmw.cbor-record = [
  type: cmw.coap-content-format-type / cmw.media-type,
  value: bytes,
  ? ind: uint .bits cmw.cm-type,
]
cmw.media-type = text .abnf ("Content-Type" .cat cmw.Content-Type-\
                                                                ABNF)
cmw.base64url-string = text .regexp "[A-Za-z0-9_-]+"
cmw.cm-type = &(
  reference-values: 0,
  endorsements: 1,
  evidence: 2,
  attestation-results: 3,
  appraisal-policy: 4,
)
cmw.coap-content-format-type = uint .size 2
cmw.Content-Type-ABNF = '

Content-Type   = Media-Type-Name *( *SP ";" *SP parameter )
parameter      = token "=" ( token / quoted-string )

token          = 1*tchar
tchar          = "!" / "#" / "$" / "%" / "&" / "\'" / "*"
               / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
               / DIGIT / ALPHA
quoted-string  = %x22 *( qdtext / quoted-pair ) %x22
qdtext         = SP / %x21 / %x23-5B / %x5D-7E
quoted-pair    = "\\" ( SP / VCHAR )

Media-Type-Name = type-name "/" subtype-name

type-name = restricted-name
subtype-name = restricted-name

restricted-name = restricted-name-first *126restricted-name-chars
restricted-name-first  = ALPHA / DIGIT
restricted-name-chars  = ALPHA / DIGIT / "!" / "#" /
                         "$" / "&" / "-" / "^" / "_"
restricted-name-chars =/ "." ; Characters before first dot always
                             ; specify a facet name
restricted-name-chars =/ "+" ; Characters after last plus always
                             ; specify a structured syntax suffix

DIGIT     =  %x30-39           ; 0 - 9
POS-DIGIT =  %x31-39           ; 1 - 9
ALPHA     =  %x41-5A / %x61-7A ; A - Z / a - z
SP        =  %x20
VCHAR     =  %x21-7E           ; printable ASCII (no SP)
'
mc.digest = [
  alg: int / text,
  val: mc.digest-value-type,
]
mc.digest-value-type = mc.eat.JC<mc.bytes-b64u, bytes>
mc.eat.JC<J, C> = mc.eat.JSON-ONLY<J> / mc.eat.CBOR-ONLY<C>
mc.eat.JSON-ONLY<J> = J .feature "json"
mc.eat.CBOR-ONLY<C> = C .feature "cbor"
mc.bytes-b64u = text .b64u bytes
eat.profile-label = eat.JC<"eat_profile", 265>
eat.iat-claim-label = eat.JC<"iat", 6>
eat.time-int = #6.1(int)
eat.exp-claim-label = eat.JC<"exp", 4>
eat.submods-label = eat.JC<"submods", 266>
eat.nonce-label = eat.JC<"eat_nonce", 10>
eat.nonce-type = eat.JC<tstr .size (8 .. 88), bstr .size (8 .. 64)>
eat.Nested-Token = eat.CBOR-Nested-Token / eat.JSON-Selector
eat.general-uri = eat.JC<text, ~uri>
eat.general-oid = eat.JC<eat.json-oid, ~eat.oid>
eat.CBOR-Nested-Token = eat.JSON-Token-Inside-CBOR-Token / eat.CBOR-\
                                              Token-Inside-CBOR-Token
eat.JSON-Selector = eat.$JSON-Selector
eat.json-oid = tstr .regexp "([0-2])((\\.0)|(\\.[1-9][0-9]*))*"
eat.oid = #6.111(bstr)
eat.JSON-Token-Inside-CBOR-Token = tstr
eat.CBOR-Token-Inside-CBOR-Token = bstr .cbor eat.$CBOR-Tagged-Token
eat.$JSON-Selector /= [
    type: "JWT",
    nested-token: eat.JWT-Message,
] / [
    type: "CBOR",
    nested-token: eat.CBOR-Token-Inside-JSON-Token,
]
eat.$CBOR-Tagged-Token /= #6.61(bstr) / #6.18(bstr) / #6.17(bstr) / \
                                                          #6.16(bstr)
eat.JWT-Message = tstr .regexp "[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A\
                                                        -Za-z0-9_-]*"
eat.CBOR-Token-Inside-JSON-Token = eat.base64-url-text
eat.base64-url-text = tstr .regexp "[A-Za-z0-9_-]+"

Appendix B. Open Policy Agent Example

Open Policy Agent OPA is a popular and flexible policy engine that is used in a variety of contexts, from cloud to IoT. OPA policies are written using a purpose-built, declarative programming language called Rego. Rego has been designed to handle JSON claim-sets and their JWT envelopes as first class objects, which makes it an excellent fit for dealing with JWT EARs.

The following example illustrates an OPA policy that a Relying Party would use to make decisions based on a JWT EAR received from a trusted verifier.

package ear

ear_appraisal = {
    "verified": signature_verified,
    "appraisal-status": status,
    "trustworthiness-vector": trust_vector,
} {
    # verify EAR signature is correct and from one of the known and
    # trusted verifiers
    signature_verified := io.jwt.verify_es256(
        input.ear_token,
        json.marshal(input.trusted_verifiers)
    )

    # extract the EAR claims-set
    [_, payload, _] := io.jwt.decode(input.ear_token)

    # access the attester-specific appraisal record
    app_rec := payload.submods.PARSEC_TPM
    status := app_rec["ear_status"] == "affirming"

    # extract the trustworhiness vector for further inspection
    trust_vector := app_rec["ear_trustworthiness_vector"]
}

# add further conditions on the trust_vector here
# ...

The result of the policy appraisal is the following JSON object:

{
    "ear_appraisal": {
        "appraisal-status": true,
        "trustworthiness-vector": {
            "executables": 2,
            "hardware": 2,
            "instance-identity": 2
        },
        "verified": true
    }
}

For completeness, the trusted verifier public key and the EAR JWT used in the example are provided below.

=============== NOTE: '\' line wrapping per RFC 8792 ================
{
    "ear_token": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJlYXIucmF3L\
WV2aWRlbmNlIjoiTnpRM01qWTVOek0yTlRZek56UUsiLCJlYXIudmVyaWZpZXItaWQiO\
nsiYnVpbGQiOiJ2dHMgMC4wLjEiLCJkZXZlbG9wZXIiOiJodHRwczovL3ZlcmFpc29uL\
XByb2plY3Qub3JnIn0sImVhdF9wcm9maWxlIjoidGFnOmdpdGh1Yi5jb20sMjAyMzp2Z\
XJhaXNvbi9lYXIiLCJpYXQiOjEuNjY2NTI5MTg0ZSswOSwianRpIjoiNTViOGIzZmFkO\
GRkMWQ4ZWFjNGU0OGYxMTdmZTUwOGIxMWY4NDRkOWYwMTg5YmZlZDliODc1MTVhNjc1N\
DI2NCIsIm5iZiI6MTY3NzI0Nzg3OSwic3VibW9kcyI6eyJQQVJTRUNfVFBNIjp7ImVhc\
i5hcHByYWlzYWwtcG9saWN5LWlkIjoiaHR0cHM6Ly92ZXJhaXNvbi5leGFtcGxlL3Bvb\
GljeS8xLzYwYTAwNjhkIiwiZWFyLnN0YXR1cyI6ImFmZmlybWluZyIsImVhci50cnVzd\
HdvcnRoaW5lc3MtdmVjdG9yIjp7ImV4ZWN1dGFibGVzIjoyLCJoYXJkd2FyZSI6Miwia\
W5zdGFuY2UtaWRlbnRpdHkiOjJ9LCJlYXIudmVyYWlzb24ua2V5LWF0dGVzdGF0aW9uI\
jp7ImFrcHViIjoiTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFY2pTc\
DhfTVdNM2d5OFR1Z1dPMVRwUVNqX3ZJa3NMcEMtZzhsNVMzbHBHYjdQV1dHb0NBakVQO\
F9BNTlWWndMWGd3b1p6TjBXeHVCUGpwYVdpV3NmQ1EifX19fQ.3Ym-f1LEgamxePUM7h\
6Y2RJDGh9eeL0xKor0n1wE9jdAnLNwm3rTKFV2S2LbqVFoDtK9QGalT2t5RnUdfwZNmg\
",
    "trusted_verifiers": {
        "keys": [
            {
                "alg": "ES256",
                "crv": "P-256",
                "kty": "EC",
                "x": "usWxHK2PmfnHKwXPS54m0kTcGJ90UiglWiGahtagnv8",
                "y": "IBOL-C3BttVivg-lSreASjpkttcsz-1rb7btKLv8EX4"
            }
        ]
    }
}

Appendix C. Open Issues

Note to RFC Editor: please remove before publication.

The list of currently open issues for this document can be found at https://github.com/thomas-fossati/draft-ear/issues.

Acknowledgments

Many thanks to Dave Thaler, Dhawal Kumar, Ding Ma, Greg Kostal, Jerry Yu, Raghuram Yeluri, Simon Frost, Tobin Feldman-Fitzthum, Yogesh Deshpande for helpful comments and discussions that have shaped this document.

Authors' Addresses

Thomas Fossati
NVIDIA
Eric Voit
Cisco
Sergei Trofimov
Arm Limited
Henk Birkholz
Fraunhofer SIT
Rheinstrasse 75
64295 Darmstadt
Germany