Internet-Draft CoRIM-SEV August 2024
Glaze Expires 8 February 2025 [Page]
Workgroup:
Remote ATtestation ProcedureS
Internet-Draft:
draft-deeglaze-amd-sev-snp-corim-profile-00
Published:
Intended Status:
Standards Track
Expires:
Author:
D. Glaze
Google LLC

CoRIM profile for AMD SEV-SNP attestation report

Abstract

AMD Secure Encrypted Virtualization with Secure Nested Pages (SEV-SNP) attestation reports comprise of reference values and cryptographic key material that a Verifier needs in order to appraise Attestation Evidence produced by an AMD SEV-SNP virtual machine. This document specifies the information elements for representing SEV-SNP Reference Values in CoRIM format.

Discussion Venues

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

Source for this draft and an issue tracker can be found at https://github.com/deeglaze/draft-deeglaze-amd-sev-snp-corim-profile.

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 8 February 2025.

Table of Contents

1. Introduction

TODO: write after content.

2. Conventions and Definitions

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.

The reader is assumed to be familiar with the terms defined in [I-D.ietf-rats-corim] and Section 4 of [RFC9334]. The syntax of data descriptions is CDDL as specified in [RFC8610].

3. AMD SEV-SNP Attestation Reports

The AMD SEV-SNP attestation scheme in [SEV-SNP.API] contains measurements of security-relevant configuration of the host environment and the launch configuration of a SEV-SNP VM. This draft documents the normative representation of attestation report Evidence as a CoRIM profile.

AMD-SP: AMD Secure Processor. A separate core that provides the confidentiality and integrity properties of AMD SEV-SNP. The function that is relevant to this document is its construction of signed virtual machine attestation reports.

VCEK: Versioned Chip Endorsement Key. A key for signing the SEV-SNP Attestation Report. The key is derived from a unique device secret as well as the security patch levels of relevant host components.

VLEK: Version Loaded Endorsement Key. An alternative SEV-SNP Attestation Report signing key that is derived from a secret shared between AMD and a Cloud Service Provider. The key is encrypted with a per-device per-version wrapping key that is then decrypted and stored by the AMD-SP.

VEK: Either a VCEK or VLEK.

3.1. AMD SEV-SNP CoRIM Profile

AMD SEV-SNP launch endorsements are carried in one or more CoMIDs inside a CoRIM.

The profile attribute in the CoRIM MUST be present and MUST have a single entry set to the uri http://amd.com/please-permalink-me as shown in Figure 1.

/ corim-map / {
  / corim.profile / 3: [
    32("http://amd.com/please-permalink-me")
  ]
  / ... /
}
Figure 1: SEV-SNP attestation profile version 1, CoRIM profile

3.1.1. AMD SEV-SNP Target Environment

The ATTESTATION_REPORT structure as understood in the RATS Architecture [RFC9334] is a signed collection of Claims that constitute Evidence about the Target Environment. The Attester for the ATTESTATION_REPORT is specialized hardware that will only run AMD-signed firmware.

The class-id for the Target Environment measured by the AMD-SP is the tagged OID #6.111(1.3.6.1.4.1.3704.2.1). The launched VM on SEV-SNP has an ephemeral identifier REPORT_ID. If the VM is the continuation of some instance as carried by a migration agent, there is also a possible REPORT_ID_MA value to identify the instance. The attester, however, is always on the same CHIP_ID. Given that the CHIP_ID is not uniquely identifying for a VM instance, it is better classified as a group. The CSP_ID is similarly better classified as a group. Either the CHIP_ID or the CSP_ID may be represented in the group codepoint as a tagged-bytes. If the SIGNING_KEY bit of the attestation report is 1, then the group MUST be the CSP_ID of the VLEK.

/ environment-map / {
  / class-map / {
    / class-id: / 0 => #6.111(1.3.6.1.4.1.3704.2.1)
  }
  / instance: / 1 => #6.563({
    / report-id: / 0 => REPORT_ID,
    / report-id-ma: / 1 => REPORT_ID_MA
    })
  / group: / 2 => #6.560(CHIP_ID)
}

3.1.2. AMD SEV-SNP Attestation Report measurement values extensions

The fields of an attestation report that have no direct analog in the base CoRIM CDDL are given negative codepoints to be specific to this profile.

The GUEST_POLICY field's least significant 16 bits represent a Major.Minor minimum version number:

sevsnpvm-policy-record = [
  abi-major: byte,
  abi-minor: byte
]

The policy's minimum ABI version is assigned codepoint -1:

$$measurement-values-map-extension //= (
  &(sevsnpvm-policy-abi: -1) => sevsnpvm-policy-record
)

The attestation report's FAMILY_ID and IMAGE_ID are indirectly represented through an extension to $version-scheme as described in Section 3.1.2.1.

The attestation report's VMPL field is assigned codepoint -2:

$$measurement-values-map-extension //= (
  &(sevsnpvm-vmpl: -2) => 0..3
)

The attestation report's HOST_DATA is assigned codepoint -3:

$$measurement-values-map-extension //= (
  &(sevsnpvm-host-data: -3) => bstr .size 32
)

The SEV-SNP firmware build number and Minor.Minor version numbers are provided for both the installed and committed versions of the firmware to account for firmware hotloading. The three values are captured in a record type sevsnphost-sp-fw-version-record:

sevsnphost-sp-fw-version-record = [
  build-number: uint .size 1,
  major: uint .size 1,
  minor: uint .size 1
]

The current build/major/minor of the SP firmware is assigned codepoint -4:

$$measurement-values-map-extension //= (
  &(sevsnphost-sp-fw-current: -4) => sevsnphost-sp-fw-version-record
)

The committed build/major/minor of the SP firmware is assigned codepoint -5:

$$measurement-values-map-extension //= (
  &(sevsnphost-sp-fw-committed: -5) => sevsnphost-sp-fw-version-record
)

The host components other than AMD SP firmware are relevant to VM security posture, so a combination of host components' security patch levels are included as TCB versions. The TCB versions are expressed as a 64-bit number where each byte corresponds to a different component's security patch level. Reference value providers MUST provide an overall minimum value for the combination of components, since lexicographic ordering is vulnerable to downgrade attacks. Tools for human readability MAY present the TCB version a component-wise manner, but that is outside the scope of this document.

The CURRENT_TCB version of the host is assigned codepoint -6:

$$measurement-values-map-extension //= (
  &(sevsnphost-current-tcb: -6) => svn-type-choice
)

The COMMITTED_TCB version of the host is assigned codepoint -7:

$$measurement-values-map-extension //= (
  &(sevsnphost-committed-tcb: -7) => svn-type-choice
)

The LAUNCH_TCB version of the host is assigned codepoint -8:

$$measurement-values-map-extension //= (
  &(sevsnphost-launch-tcb: -8) => svn-type-choice
)

The REPORTED_TCB version of the host is assigned codepoint -9:

$$measurement-values-map-extension //= (
  &(sevsnphost-reported-tcb: -9) => svn-type-choice
)

The GUEST_POLICY boolean flags are added as extensions to $$flags-map-extension, starting from coedpoint -1.

$$flags-map-extension //= &(
  sevsnpvm-policy-smt-allowed: -1,
  sevsnpvm-policy-migration-agent-allowed: -2,
  sevsnpvm-policy-debug-allowed: -3,
  sevsnpvm-policy-single-socket-only: -4,
  sevsnpvm-policy-cxl-allowed: -5,
  sevsnpvm-policy-mem-aes-256-xts-required: -6,
  sevsnpvm-policy-rapl-must-be-disabled: -7,
  sevsnpvm-policy-ciphertext-hiding-must-be-enabled: -8,
)

There are 47 available bits for selection when the mandatory 1 in position 17 and the ABI Major.Minor values are excluded from the 64-bit GUEST_POLICY. The PLATFORM_INFO bits are host configuration that are added as extensions to $$flags-map-extension starting at -49.

$$flags-map-extension //= &(
  sevsnphost-smt-enabled: -49,
  sevsnphost-tsme-enabled: -50,
  sevsnphost-ecc-mem-reported-enabled:-51,
  sevsnphost-rapl-disabled: -52,
  sevsnphost-ciphertext-hiding-enabled: -53
)
3.1.2.1. Version scheme extension

Extend the $version-scheme type with as follows

$version-scheme /= &(sevsnpvm-familyimageid-hex: -1)

The -1 scheme is a string representation of the two 128-bit identifiers in hexadecimal encoding as separated by /. The scheme allows for fuzzy comparison with _ as a wildcard on either side of the /.

An endorsement provider MAY use a different version scheme for the &(version: 0) codepoint.

3.1.2.2. Notional Instance Identity

A CoRIM instance identifier is universally unique, but there are different notions of identity within a single attestation report that are each unique within their notion. A notional instance identifier is a tagged CBOR map from integer codepoint to opaque bytes.

int-bytes-map = { * int => bytes }

Profiles may restrict which integers are valid codepoints, and may restrict the respective byte string sizes. For this profile, only codepoints 0 and 1 are valid. The expected byte string sizes are 32 bytes. For the int-bytes-map to be an interpretable extension of $instance-id-type-choice, there is tagged-int-bytes-map:

tagged-int-bytes-map = #6.563(int-bytes-map)

3.1.3. AMD SEV-SNP Evidence Translation

The ATTESTATION_REPORT Evidence is converted into a CoRIM endorsed-triple-record using the rules in this section. Fields of ATTESTATION_REPORT are referred to by their assigned names in [SEV-SNP.API]. If the ATTESTATION_REPORT contains ID_BLOCK information, the relevant fields will be represented in a second endorsed-triple-record with a different authorized-by field value, as per the merging rules of [I-D.ietf-rats-corim].

3.1.3.1. environment-map
  • The environment-map / class / class-id field SHALL be set to the BER [X.690] encoding of OID [RFC9090] 1.3.6.1.4.1.3704.2.1 and tagged with #6.111.

  • The environment-map / instance field SHALL be set to an int-bytes-map tagged with #6.111 with at least one codepoint 0 or 1. If codepoint 0 is populated, it SHALL be set to REPORT_ID. If codepoint 1 is populated, it SHALL be set to REPORT_ID_MA.

  • The environment-map / group field SHALL be set to the VLEK csp_id and tagged with #6.111 if SIGNING_KEY is 1. If SIGNING_KEY is 0, the field MAY be set to the VCEK hwid and tagged with #6.111.

3.1.3.2. measurement-map

The mkey is left unset. The authorized-by key SHALL be set to a representation of the VEK that signed the ATTESTATION_REPORT, or a key along the certificate path to a self-signed root, i.e., the ASK, ASVK, or ARK for the product line. The measurement-values-map is set as described in the following section.

3.1.3.3. measurement-values-map

The function is-set(x, b) represents whether the bit at position b is set in the number x.

  • The digests: 2 codepoint SHALL be set to either [ / digest / { alg: 7 val: MEASUREMENT } ] or [ / digest / { alg: "sha-384" val: MEASUREMENT } ] as assigned in [IANA.named-information].

  • The &(flags: 3) / flags-map / sevsnpvm-policy-smt-allowed codepoint SHALL be set to is-set(GUEST_POLICY, 16.

  • The &(flags: 3) / flags-map / sevsnpvm-policy-migration-agent-allowed codepoint SHALL be set to is-set(GUEST_POLICY, 18).

  • The &(flags: 3) / flags-map / sevsnpvm-policy-debug-allowed codepoint SHALL be set to is-set(GUEST_POLICY, 19).

  • The &(flags: 3) / flags-map / sevsnpvm-policy-single-socket-only codepoint SHALL be set to is-set(GUEST_POLICY, 20).

  • The &(flags: 3) / flags-map / sevsnpvm-policy-cxl-allowed codepoint SHALL be set to is-set(GUEST_POLICY, 21).

  • The &(flags: 3) / flags-map / sevsnpvm-policy-mem-aes-256-xts-required codepoint SHALL be set to is-set(GUEST_POLICY, 22).

  • The &(flags: 3) / flags-map / sevsnpvm-policy-rapl-must-be-disabled codepoint SHALL be set to is-set(GUEST_POLICY, 23).

  • The &(flags: 3) / flags-map / sevsnpvm-policy-ciphertext-hiding-must-be-enabled codepoint SHALL be set to is-set(GUEST_POLICY, 24).

  • The &(flags: 3) / flags-map / sevsnphost-smt-enabled codepoint SHALL be set to is-set(PLATFORM_INFO, 0).

  • The &(flags: 3) / flags-map / sevsnphost-tsmu-enabled codepoint SHALL be set to is-set(PLATFORM_INFO, 1).

  • The &(flags: 3) / flags-map / sevsnphost-ecc-mem-reported-enabled codepoint SHALL be set to is-set(PLATFORM_INFO, 2).

  • The &(flags: 3) / flags-map / sevsnphost-rapl-disabled codepoint SHALL be set to is-set(PLATFORM_INFO, 3).

  • The &(flags: 3) / flags-map / sevsnphost-ciphertext-hiding-enabled codepoint SHALL be set to is-set(PLATFORM_INFO, 4).

  • The &(sevsnpvm-policy-abi: -1) codepoint SHALL be set to [ ABI_MAJOR, ABI_MINOR ].

  • The &(sevsnpvm-vmpl: -2) codepoint SHALL be set to VMPL.

  • The &(sevsnpvm-hostdata: -3) codepoint SHALL be set to HOSTDATA if nonzero. It MAY be set to HOSTDATA if all zeroes.

  • The &(sevsnphost-sp-fw-current: -4) codepoint SHALL be set to [ CURRENT_BUILD, CURRENT_MAJOR, CURRENT_MINOR ].

  • The &(sevsnphost-sp-fw-committed: -5) codepoint SHALL be set to [ COMMITTED_BUILD, COMMITTED_MAJOR, COMMITTED_MINOR ].

  • The &(sevsnphost-current-tcb: -6) codepoint SHALL be set to 552(CURRENT_TCB).

  • The &(sevsnphost-committed-tcb: -7) codepoint SHALL be set to 552(COMMITTED_TCB)

  • The &(sevsnphost-launch-tcb: -8) codepoint SHALL be set to 552(LAUNCH_TCB).

  • The &(sevsnphost-reported-tcb: -9) codepoint SHALL be set to 552(REPORTED_TCB).

If ID_BLOCK information is available, it appears in its own endorement-triple-record with additional values in authorized-by beyond the attestation key. The authorized-by field is extended with 32780(ID_KEY_DIGEST), and if AUTHOR_KEY_EN is 1, then it is also extended with 32780(AUTHOR_KEY_DIGEST). The Verifier MAY use a base CDDL CoRIM $crypto-key-type-choice representation if its public key information's digest is equal to the #6.32780-tagged bytes, as described it Section 3.1.3.4.

  • The version: 0 codepoint SHALL be set to ~~~cbor-diag / version-map / { / version: / 0 => hexlify(FAMILY_ID) '/' hexlify(IMAGE_ID) / version-scheme: -1 / => &(sevsnpvm-familyimageid-hex: -1) } ~~~ where hexlify is a function that translates the a byte string to its hexadecimal string encoding.

  • The &(svn: 1) codepoint SHALL be set to 552(GUEST_SVN).

  • The &(digests: 2) codepoint is in the triple record.

  • The &(flags: 3) / flags-map codepoints prefixed by sevsnpvm-policy SHALL be set in the triple's &(flags: 3) entry as per above translation rules.

3.1.3.3.1. TCB comparison

The Verifier SHALL use tho svn-type-choice comparison algorithm from {-rats-corim}}.

3.1.3.4. Key digest comparison

When ID_BLOCK is used, the full key information needed for signature verification is provided by the VMM at launch in an ID_AUTH structure. The SNP firmware verifies the signatures and adds digests of the signing key(s) to the attestation report as evidence of successful signature verification. When a Verifier does not have access to the original public key information used in ID_AUTH, the attestation report key digests can still be used as a representation of authority.

The APPENDIX: Digital Signatures section of [SEV-SNP.API] specifies a representation of public keys and signatures. An attestation report key digest will be a SHA-384 digest of the 0x403 byte buffer representation of a public key. If an author key is used, its signature of the ID_KEY is assumed to exist and have passed given the SNP firmware specification.

If a $crypto-key-type-choice key representation specifies an algorithm and parameters that are included in the Digital Signatures appendix, it is comparable to a #6.32780-tagged byte string.

  • Two #6.32780-tagged byte strings match if and only if their encodings are bitwise equal.

  • A thumbprint representation of a key is not comparable to a #6.32780-tagged byte string since the parameters are not extractable.

  • A PKIX public key (#6.554-tagged tstr) or PKIX certificate (#6.555-tagged tstr) MAY be comparable to a #6.32780-tagged byte string.

The [RFC3280] specified AlgorithmIdentifier has optional parameters based on the algorithm identifier. The AMD signature algorithm 1h corresponds to algorithm ecdsa-with-sha384 from section 3.2 of [RFC5758], but the parameters MUST be omitted. The SubjectPublicKeyInfo is therefore id-ecPublicKey from section 2.1.1 of [RFC5480] to further allow the curve to be specified, despite not further specifying that the signature is of a SHA-384 digest. The AMD ECSDA curve name 2h corresponds to named curve secp384r1 from section 2.2 of [RFC5480]. The ECPoint conversion routines in section 2 of [SEC1] provide guidance on how the QX and QY little-endian big integers zero-padded to 72 bytes may be constructed.

3.2. AMD SEV-SNP Launch Event Log

The composition of a SEV-SNP VM may be comprised of measurements from multiple principals, such that no one principal has absolute authority to endorse the overall measurement value represented in the attestation report. If one principal does have that authority, the ID_BLOCK mechanism provides a convenient launch configuration endorsement mechanism without need for distributing a CoRIM. This section documents an event log format the Virtual Machine Monitor (VMM) may construct at launch time and provide in the data pages of an extended guest request, as documented in [GHCB].

The content media type shall be application/vnd.amd.sevsnp.launch-updates+cbor for the encoding of a sevsnp-launch-configuration-map:

sevsnp-launch-configuration-map = {
  ? (fms: 0) => uint
  ? (sevsnpvm-launch-baseline: 1) => bytes .size 48
  ? (sevsnpvm-launch-updates: 2) => [ + sevsnp-launch-update-data-map ]
  ? (bsp-vmsa: 3) => sevsnp-vmsa-type-choice
  ? (ap-vmsa: 4) => sevsnp-ap-vmsa-type-choice
}
  • The fms field if included SHALL contain the CPUID[1]_EAX value masked with 0x0fff3fff to provide chip family, model, stepping information. If not included, the Verifier may reference the VEK certificate's extension for productName.

  • The sevsnpvm-launch-baseline field if not included is SHALL be interpreted as an all zero SHA-384 digest. The calculation of the launch measurement SHALL use the value is the initial PAGE_INFO's DIGEST_CUR value.

  • The sevsnpvm-launch-updates field contains an ordered list of inputs to the SNP_LAUNCH_UPDATE command:

sevsnp-launch-update-sequence-map = [ sevsnp-launch-update-data-map ]

The sevsnp-launch-update-data-map contains all fields of the PAGE_INFO structure that are needed for reconstructing a measurement. If an update repeats many times, such as an application processor VMSA, then that can be compressed with the repeat field.

The content codepoint MUST NOT be present if the page type is neither PAGE_TYPE_NORMAL (01h) nor PAGE_TYPE_VMSA (02h).

For the VMM, there are some updates it does on behalf of a different principal than the firmware vendor, so it may choose to pass through some of the information about the launch measurement circumstances for separate appraisal.

The encoded sevsnp-launch-configuration-map may be found in the extended guest report data table for UUID 8dd67209-971c-4c7f-8be6-4efcb7e24027.

The VMM is expected to provide all fields unless their default corresponds to the value used.

3.2.1. VMSA evidence

The VMM that assembles the initial VM state is also responsible for providing initial state for the vCPUs. The vCPU secure save area is called the VMSA on SEV-ES. The VMSA initial values can vary across VMMs, so it's the VMM provider's responsibility to sign their reference values.

The reset vector from the firmware also influences the VMSAs for application processors' RIP and CS_BASE, so the VMSA is not entirely determined by the VMM. The digest alone for the VMSA launch update command is insufficient to represent the separately specifiable reference values when the GHCB AP boot protocol is not in use.

The bootstrap processor (BSP) and application processors (APs) typically have different initial values. The APs typically all have the same initial value, so the ap-vmsa codepoint MAY be a single sevsnp-vmsa-type-choice to represent its replication. Alternatively, each AP's initial VMSA may be individually specified with a list of sevsnp-vmsa-type-choice.

sevsnp-repeated-vmsa = [ vmsa: sevsnp-vmsa-type-choice repeat: uint }

All VMSA fields are optional. A missing VMSA field in evidence is treated as its default value. A missing VMSA field in a reference value is one less matching condition.

3.2.2. VMSA default values

Unless otherwise stated, each field's default value is 0. The [AMD.SPM] is the definitive source of initial state for CPU registers, so any default value in this specification that diverges is a flaw but still MUST be considered the default for a missing value. Figure Figure 2 is a CBOR representation of the nonzero default values that correspond to initial CPU register values as of the cited revision's Table 14-1.

/ sevsnp-vmsa-map-r1-55 / {
  / es: / 0 => / svm-vmcb-seg-map / { / attrib: / 1 => 0x92 / limit: / 2 => 0xffff }
  / cs: / 1 => / svm-vmcb-seg-map / {
    / selector: / 0 => 0xf000
    / attrib: / 1 => 0x9b
    / limit: / 2 => 0xffff
    / base: / 3 => 0xffff0000
  }
  / ss: / 2 => / svm-vmcb-seg-map / { / attrib: / 1 => 0x92 / limit: / 2 => 0xffff }
  / ds: / 3 => / svm-vmcb-seg-map / { / attrib: / 1 => 0x92 / limit: / 2 => 0xffff }
  / fs: / 4 => / svm-vmcb-seg-map / { / attrib: / 1 => 0x92 / limit: / 2 => 0xffff }
  / gs: / 5 => / svm-vmcb-seg-map / { / attrib: / 1 => 0x92 / limit: / 2 => 0xffff }
  / gdtr: / 6 => / svm-vmcb-seg-map / { / limit: / 2 => 0xffff }
  / ldtr: / 7 => / svm-vmcb-seg-map / { / attrib: / 1 => 0x82 / limit: / 2 => 0xffff }
  / idtr: / 8 => / svm-vmcb-seg-map / { / limit: / 2 => 0xffff }
  / tr: / 9 => / svm-vmcb-seg-map / { / attrib: / 1 => 0x83 / limit: / 2 => 0xffff }
  / cr0: / 33 => 0x10
  / dr7: / 34 => 0x400
  / dr6: / 35 => 0xffff0ff0
  / rflags: / 36 => 0x2
  / rip: / 37 => 0xfff0
  / g_pat: / 63 => 0x7040600070406
  / sev_features: / 91 => 0x1
  / xcr0: / 97 => 0x1
  / mxcsr: / 99 => 0x1f80
  / x87_ftw: / 100 => 0x5555
  / x87_fcw: / 102 => 0x40
}
Figure 2: SEV-SNP default VMSA values

The rdx is expected to be the FMS of the chip and SHOULD match the fms field of the sevsnp-launch-configuration-map. A VMM provider may sign reference values for a sevsnp-launch-configuration-map to specify just the non-default values for the BSP and AP state.

Note: This is the RESET state, not the INIT state.

The sev_features codepoint is not a typical AMD64 INIT state, but specifies that SEV-SNP is in use for the virtual CPU.

3.2.2.1. Example VMM reference values for VMSA

Qemu, AWS Elastic Compute Cloud (EC2), and Google Compute Engine (GCE), all use KVM, which initializes cr4 and efer to non-default values. The values for cr4 and efer are different from the SPM to allow for PSE (page size extension) SVME (secure virtual machine enable).

Only Qemu follows the [AMD.SPM] specification for rdx, which is to match the family/model/stepping of the chip used. GCE provides an rdx of 0x600 regardless (following the Intel spec), and EC2 provides 0 regardless. GCE sets the G_PAT (guest page attribute table) register to 0x70406 to disable PA4-PA7. Both Qemu and GCE set the tr attrib to 0x8b, so it starts as a busy 32-bit TSS instead of the default 16-bit. GCE sets ds, es, fs, gs, and ss attributes to 0x93 since that's the initial state on Intel processors and that works fine too.

Qemu uses the Intel INIT state for the x87 floating point control word (0x37f), but 0 for the x87 floating point tag word.

3.3. AMD SEV-SNP Launch Event Log Appraisal

The sevsnp-launch-configuration-map is translated into a full sequence of SNP_LAUNCH_UPDATE commands on top of a baseline digest value to calculate following [SEV-SNP.API]'s documentation of digest calculation from PAGE_INFO structures.

The first PAGE_INFO structure uses the baseline digest as its DIGEST_CUR. The following pseudocode for the function measurement computes the expected measurement of the endorsement format. If this measurement equals the digests value with VCEK authority, then add the baseline and updates measurement values to the same ECT as the attestation report.

Since the VMM only has to provide the gpa, page type, and digest of the contents, the rest of the fields of a sevsnp-launch-update-data-map have default values when translated to a PAGE_INFO without the DIGEST_CUR field. If the baseline is not provided, it is assumed to be all zeros.

measurement({fms, baseline, updates, bsp, aps}) = iterate(baseline, infos)
  where infos = update-info ++ [bsp-info] ++ ap-info
        update-info = appendmap(mk_page_info(fms), updates)
        bsp-info = mk_vmsa_info(fms)(bsp)
        ap-info = mk_ap_vmsa_info(fms, aps)

The iterate function is applies a sha384 digest update operation on all given PAGE_INFO byte strings:

iterate(digest_cur, []) = digest_cur
iterate(digest_cur, info:infos) = iterate(digest_next , infos)
  where digest_next = sha384(digest_cur || sha384(info))

The appendmap function combines the list results of mapping a function over a list by appending them:

appendmap(f, []) = []
appendmap(f, x:xs) = append(f(x), appendmap(f, xs))

3.3.1. Updates as PAGE_INFO without DIGEST_CUR.

The mk_page_info function translates update components into a singleton list of their PAGE_INFO byte string form:

mk_page_info(fms)({page-type or PAGE_TYPE_NORMAL,
                   contents,
                   gpa,
                   page-data or 0,
                   vmpl-perms or 0}):list[bytes] = [
  contents || {0x70, 0, page-type, page-data} ||
  leuint64(vmpl-data) || leuint64(gpa),
]

The leuint64 function translates a 64-bit unsigned integer into its little endian byte string representation.

3.3.2. VMSAs as PAGE_INFO without DIGEST_CUR.

The bsp-vmsa will always be measured. If the VMM does not provide it, the default values will be used. If the $sevsnp-vmsa-type-choice is a uuid-type or oid-type, the PAGE_INFO fields are "well-known" as published by an entity claiming the identifier. The well-known values are expected to be provided by the Verifier in accordance with the associated published values.

If the $sevsnp-vmsa-type-choice is a tagged-sevsnp-vmsa-map-r1-55, then its PAGE_INFO byte string is to be defined as follows:

mk_vmsa_info(fms)(#6.32781(sevsnp-vmsa-map-r1-55)) =
  sha384(to_vmsa_page(sevsnp-vmsa-map-r1-55)) ||
  {0x70, 0, 0x2, sevsnp-vmsa-map-r1-55 / page-data} ||
  leuint64(sevsnp-vmsa-map-r1-55 / vmpl-perms) ||
  leuint64(top_gpa(fms))

The top_gpa function provides the top-most representable page-aligned address for the chip model:

top_gpa(fms) = ((1UL << bitWidth(fms)) - 1) & PAGE_MASK

PAGE_MASK = 0xfffffffffffff000
bitWidth(fms) = 48 if (fms >> 4) == 0xA00F0 ; Milan
bitWidth(fms) = 52 if (fms >> 4) == 0xA10F0 ; Genoa

The to_vmsa_page function constructs a VMSA 4KiB page with fields written to their respective locations as specified by the [AMD.SPM]. Fields not represented in the map are taken to be their default value from figure Figure 2.

The ap-vmsa will be measured only if present. The list of VMSA type choices is translated to a list of PAGE_INFO with the same operation:

mk_ap_vmsa_info(fms, [ + sevsnp-vmsa-type-choice ]) =
  map(mk_vmsa_info(fms)([ sevsnp-vmsa-type-choice ... ])

The repeated vmsas expand into a list of the same PAGE_INFO byte string repeated:

mk_ap_vmsa_info(fms, #6.32872([vmsa, repeat])) =
  [mk_vmsa_info(fms)(vmsa)]*repeat

3.3.3. Comparisons for reference values

An "any" sequence number matches any sequence number. The uint sequence number starts counting after the baseline matches. If there is no reference baseline, the sequence numbers start at 0. If there is a reference baseline, the VMM's provided baseline gets hash-combined with the provided updates until the digest equals the signed baseline, and the sequence numbers s tart from the following update as if they are 1. If there is no update that leads to a matching baseline value, no updates match.

The other sevsnp-launch-update-data-map codepoints must match all present codepoints with encoding equality. The evidence ECT for the matching values are then split into a separate ECT to account for the added authority.

Note: the VMM may split its baseline and updates at any point, which will drop the specificity of individual updates. The individual updates of a reference value MUST match individual updates from the VMM. It is therefore advantageous to combine as many updates in the reference value into the baseline as is feasible.

3.3.4. Example: OVMF with SevMetadata

The Open Virtual Machine Firmware project directs the VMM to not just load the UEFI at the top of the 4GiB memory range, but also measure referenced addresses with particular SNP_LAUNCH_UPDATE inputs. Given that the firmware may be built by one party, the VMM another, and SEV_KERNEL_HASHES data yet another, the different data spread across the SNP_LAUNCH_UPDATE commands should be signed by the respective parties.

3.3.4.1. OVMF data

The GUID table at the end of the ROM is terminated by the GUID 96b582de-1fb2-45f7-baea-a366c55a082d starting at offset ROM_end - 0x30. At offset ROM_end - 0x32 there is a length in a 16-bit little endian unsigned integer. At offset ROM_end - 0x32 - length there is a table with format

Table 1: OVMF footer GUID table type description
Type Name
* *
UINT8[Length] Data
LE_UINT16 Length
EFI_GUID Name

LE_UINT16 is the type of a little endian 16-bit unsigned integer. EFI_GUID is the UUID format specified in section 4 of [RFC4122]. The footer GUID and length specifies the length of the table of entries itself, which does not include the footer.

Within this table there is an entry that specifies the guest physical address that contains the SevMetadata.

Table 2: SevMetadataOffset GUID table entry description
Type Name
LE_UINT32 Address
LE_UINT16 Length
EFI_GUID dc886566-984a-4798-A75e-5585a7bf67cc

At this address when loaded, or at offset ROM_end - (4GiB - Address), the SevMetadata,

Table 3: SevMetadata type description
Type Name
LE_UINT32 Signature
LE_UINT32 Length
LE_UINT32 Version
LE_UINT32 NumSections
SevMetadataSection[Sections] Sections

The Signature value should be 'A', 'S', 'E', 'V' or "VESA" in big-endian order: 0x56455341. Where SevMetadataSection is

Table 4: SevMetadataSection type description
Type Name
LE_UINT32 Address
LE_UINT32 Length
LE_UINT32 Kind

A section references some slice of guest physical memory that has a certain purpose as labeled by Kind:

Table 5: OVMF section kind to SEV-SNP page type mapping
Value Name PAGE_TYPE
1 OVMF_SECTION_TYPE_SNP_SEC_MEM PAGE_TYPE_UNMEASURED
2 OVMF_SECTION_TYPE_SNP_SECRETS PAGE_TYPE_SECRETS
3 OVMF_SECTION_TYPE_CPUID PAGE_TYPE_CPUID
4 OVMF_SECTION_TYPE_SNP_SVSM_CAA PAGE_TYPE_ZERO
16 OVMF_SECTION_TYPE_KERNEL_HASHES PAGE_TYPE_NORMAL

The memory allocated to the initial UEFI boot phase, SEC, is unmeasured but must be marked for encryption without needing the GHCB or MSR protocol. The SEC_MEM sections contain the initial GHCB pages, page tables, and temporary memory for stack and heap. The secrets section is memory allocated specifically for holding secrets that the AMD-SP populates at launch. The cpuid section is memory allocated to the CPUID source of truth, which shouldn't be measured for portability and host security, but should be verified by AMD-SP for validity. The SVSM calling area address section is to enable the firmware to communicate with a secure VM services module running at VMPL0. The kernel hashes section is populated with expected measurements when boot advances to load Linux directly and must fail if the disk contents' digests disagree with the measured hashes.

The producer of the OVMF binary may therefore decide to sign a verbose representation or a compact representation. A verbose representation would have hundreds of updates given that every 4KiB page must be represented. For an initial example, consider the 2MiB OVMF ROM's 512 4KiB updates as the baseline, and the metadata as individual measurements afterwards.

/ sevsnp-launch-configuration-map / {
  / sevsnp-launch-update-baseline: / 1 =>
    h'70698b35cd5368eb11d27fa2162b7fe5d72d2471efd832598f6815115b08b420259a74fe0954f4dccfa8b9254c1dd4bb'
  / sevsnpvm-launch-updates: / 2 => [
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x800000
      / seq-no: / 5 => 1
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x801000
      / seq-no: / 5 => 2
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x802000
      / seq-no: / 5 => 3
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x803000
      / seq-no: / 5 => 4
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x804000
      / seq-no: / 5 => 5
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x805000
      / seq-no: / 5 => 6
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x806000
      / seq-no: / 5 => 7
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x807000
      / seq-no: / 5 => 8
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x808000
      / seq-no: / 5 => 9
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x80A000
      / seq-no: / 5 => 10
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x80B000
      / seq-no: / 5 => 11
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x80C000
      / seq-no: / 5 => 12
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 5
      / gpa: / 2 => 0x80D000
      / seq-no: / 5 => 13
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 6
      / gpa: / 2 => 0x80E000
      / seq-no: / 5 => 14
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 3
      / gpa: / 2 => 0x80F000
      / seq-no: / 5 => 15
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 1
      / gpa: / 2 => 0x810000
      / seq-no: / 5 => 16
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x811000
      / seq-no: / 5 => 17
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x812000
      / seq-no: / 5 => 18
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x813000
      / seq-no: / 5 => 19
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x814000
      / seq-no: / 5 => 20
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x815000
      / seq-no: / 5 => 21
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x816000
      / seq-no: / 5 => 22
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x817000
      / seq-no: / 5 => 23
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x818000
      / seq-no: / 5 => 24
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x819000
      / seq-no: / 5 => 25
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x81A000
      / seq-no: / 5 => 26
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x81B000
      / seq-no: / 5 => 27
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x81C000
      / seq-no: / 5 => 28
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x81D000
      / seq-no: / 5 => 29
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x81E000
      / seq-no: / 5 => 30
    },
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 4
      / gpa: / 2 => 0x81F000
      / seq-no: / 5 => 31
    },
  ]
  / ap-vmsa: 4 / => #6.32781({
    / cs: / 1 => / svm-vmcb-seg-map / {/ base: / 3 => 0x800000}
    / rip: / 37 => 0xb004
  })
}

In this example the SEV-ES reset vector is located at 0x80b004. The AP RIP is the lower word and the CS_BASE is the upper word. The first unmeasured section is for the SEC stage page tables up to GHCB at address 0x800000, which has 9 pages accounted for in sequence. The second unmeasured section is for the GHCB page up to secrets at address 0x80A000, which has 3 pages accounted for in sequence. The secrets page is at address 0x80D000. The CPUID page is at address rx80E000. The svsm calling area page address is 0x80F000. The launch secrets and kernel hashes are at address 0x810000 and fit in 1 page. The location of the final unmeasured pages are for the APIC page tables and PEI temporary memory. The final section after the svsm calling area and kernel hashes up to the PEI firmware volume base, so 0x811000 up to 0x820000 for another 15 pages.

A more compact representation can take advantage of the fact that several of the first update commands are driven entirely by the firmware. The firmware author may then decide to reorder the section processing to ensure the kernel hashes are last, as there is no requirement for sequential GPAs. The baseline contains the initial ROM plus all the sections that don't have a dependency on external measured information. Thanks to the section reordering, only the SEV_KERNEL_HASHES need to be called out in the signed configuration.

/ sevsnp-launch-configuration-map / {
  / sevsnp-launch-update-baseline: / 1 =>
    h'5b01655cda55211f900fbd073ec36882400453eec9dba3ed63be7353798850ae561625a0f6e5f136e8c4e196fcbca45f'
  / sevsnpvm-launch-updates: / 2 => [
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 1
      / gpa: / 2 => 0x810000
      / seq-no: / 5 => 1
    },
  ]
  / ap-vmsa: 4 / => #6.32781({
    / cs: / 1 => / svm-vmcb-seg-map / {/ base: / 3 => 0x800000}
    / rip: / 37 => 0xb004
  })
}
3.3.4.2. Kernel data

The OVMF image may be provided by a different vendor than the OS disk image. The user of the VM platform may not have direct access to reference values ahead of time to countersign their combination. The kernel hashes become an input to the control plane that are then fed to the construction of the VM launch. The provider of the OS disk image then is responsible for signing the reference values for kernel hashes. The order in which kernel hashes are loaded, and at which address is irrelevant provided the attestation policy requires some signed value in the end, so the signer does not provide either the gpa or seq-no values.

/ sevsnp-launch-configuration-map / {
  / sevsnpvm-launch-updates: / 2 => [
    / sevsnp-launch-update-data-map / {
      / page-type: / 0 => 1
      / content: / 2 => / digest / [ 7, h'111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111' ]
    }
  ]
}

The digest is of a Qemu data structure that contains different digests of content from the command line.

4. IANA Considerations

4.1. New CBOR Tags

IANA is requested to allocate the following tags in the "CBOR Tags" registry [IANA.cbor-tags]. The choice of the CoRIM-earmarked value is intentional.

Table 6: Added CBOR tags
Tag Data Item Semantics Reference
563 map Keys are always int, values are opaque bytes, see Section 3.1.2.2 RFCthis
32780 bytes A digest of an AMD public key format that compares with other keys Section 3.1.3.4 RFCthis
32781 map A map of virtual machine vCPU registers (VMSA) to initial values Section 3.2.1 RFCthis
32782 array A record of a single VMSA and a count of how many times it repeats Section 3.2.1 RFCthis

5. References

5.1. Normative References

[IANA.cbor-tags]
IANA, "Concise Binary Object Representation (CBOR) Tags", <https://www.iana.org/assignments/cbor-tags>.
[IANA.named-information]
IANA, "Named Information", <https://www.iana.org/assignments/named-information>.
[RFC3280]
Housley, R., Polk, W., Ford, W., and D. Solo, "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile", RFC 3280, DOI 10.17487/RFC3280, , <https://www.rfc-editor.org/rfc/rfc3280>.
[RFC4122]
Leach, P., Mealling, M., and R. Salz, "A Universally Unique IDentifier (UUID) URN Namespace", RFC 4122, DOI 10.17487/RFC4122, , <https://www.rfc-editor.org/rfc/rfc4122>.
[RFC5480]
Turner, S., Brown, D., Yiu, K., Housley, R., and T. Polk, "Elliptic Curve Cryptography Subject Public Key Information", RFC 5480, DOI 10.17487/RFC5480, , <https://www.rfc-editor.org/rfc/rfc5480>.
[RFC5758]
Dang, Q., Santesson, S., Moriarty, K., Brown, D., and T. Polk, "Internet X.509 Public Key Infrastructure: Additional Algorithms and Identifiers for DSA and ECDSA", RFC 5758, DOI 10.17487/RFC5758, , <https://www.rfc-editor.org/rfc/rfc5758>.
[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>.
[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>.
[RFC9090]
Bormann, C., "Concise Binary Object Representation (CBOR) Tags for Object Identifiers", RFC 9090, DOI 10.17487/RFC9090, , <https://www.rfc-editor.org/rfc/rfc9090>.
[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>.
[X.690]
International Telecommunications Union, "Information technology — ASN.1 encoding rules: Specification of Basic Encoding Rules (BER), Canonical Encoding Rules (CER) and Distinguished Encoding Rules (DER)", ITU-T Recommendation X.690, , <https://www.itu.int/rec/T-REC-X.690>.

5.2. Informative References

[AMD.SPM]
Advanced Micro Devices Inc., "AMD64 Architecture Programmer’s Manual, Volume 2: System Programming", Revision 3.42 , , <https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24593.pdf>.
[GHCB]
Advanced Micro Devices Inc., "SEV-ES Guest-Hypervisor Communication Block Standardization", Revision 2.03 , , <https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56421.pdf>.
[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-05, , <https://datatracker.ietf.org/doc/html/draft-ietf-rats-corim-05>.
[SEC1]
Certicom Corp., "Standards for Efficient Cryptography Group (SECG), "SEC1: Elliptic Curve Cryptography"", Version 1.0 , , <https://www.secg.org/SEC1-Ver-1.0.pdf>.
[SEV-SNP.API]
Advanced Micro Devices Inc., "SEV Secure Nested Paging Firmware ABI Specification", Revision 1.55 , , <https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56860.pdf>.
[VCEK]
Advanced Micro Devices Inc., "Versioned Chip Endorsement Key (VCEK) Certificate and KDS Interface Specification", Revision 0.51 , , <https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/57230.pdf>.
[VLEK]
Advanced Micro Devices Inc., "Versioned Loaded Endorsement Key (VLEK) Certificate Definition", Revision 0.10 , , <https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/user-guides/58369-010-versioned-loaded-endorsement-key-certificate-definition.pdf>.

Appendix A. CoRIM Extensions CDDL

$crypto-key-type-choice /= #6.32780(bytes .size 48)

digest = [
  alg: (int / text),
  val: bytes
]

int-bytes-map = { * int => bytes }

non-empty<M> = (M) .and ({ + any => any })

sevsnp-launch-configuration-map = {
  ? (fms: 0) => uint
  ? (sevsnpvm-launch-baseline: 1) => bytes .size 48
  ? (sevsnpvm-launch-updates: 2) => [ + sevsnp-launch-update-data-map ]
  ? (bsp-vmsa: 3) => sevsnp-vmsa-type-choice
  ? (ap-vmsa: 4) => sevsnp-ap-vmsa-type-choice
}

sevsnp-launch-update-data-map = non-empty<{
  ? &(page-type: 0) => 1..6
  ? &(content: 1) => digest
  ? &(gpa: 2) => uint
  ? &(page-data: 3) => byte .bits sev-snp-page-data
  ? &(vmpl-perms: 4) => uint64
  ? &(seq-no: 5) => uint
}>

sevsnp-launch-update-sequence-map = [ sevsnp-launch-update-data-map ]

sev-snp-page-data = &(
  imi-page: 0
)

sevsnp-repeated-vmsa = [
  vmsa: sevsnp-vmsa-type-choice
  repeat: uint
}

sevsnp-ap-vmsa-type-choice = [ + sevsnp-vmsa-type-choice ] / tagged-sevsnp-repeated-vmsa

$$flags-map-extension //= &(
  sevsnpvm-policy-smt-allowed: -1,
  sevsnpvm-policy-migration-agent-allowed: -2,
  sevsnpvm-policy-debug-allowed: -3,
  sevsnpvm-policy-single-socket-only: -4,
  sevsnpvm-policy-cxl-allowed: -5,
  sevsnpvm-policy-mem-aes-256-xts-required: -6,
  sevsnpvm-policy-rapl-must-be-disabled: -7,
  sevsnpvm-policy-ciphertext-hiding-must-be-enabled: -8,
)

$$measurement-values-map-extension //= (
  &(sevsnpvm-host-data: -3) => bstr .size 32
)

$$measurement-values-map-extension //= (
  &(sevsnpvm-policy-abi: -1) => sevsnpvm-policy-record
)

sevsnpvm-policy-record = [
  abi-major: byte,
  abi-minor: byte
]

$version-scheme /= &(sevsnpvm-familyimageid-hex: -1)

$$measurement-values-map-extension //= (
  &(sevsnpvm-vmpl: -2) => 0..3
)

$$measurement-values-map-extension //= (
  &(sevsnphost-committed-tcb: -7) => svn-type-choice
)

$$measurement-values-map-extension //= (
  &(sevsnphost-current-tcb: -6) => svn-type-choice
)

$$measurement-values-map-extension //= (
  &(sevsnphost-launch-tcb: -8) => svn-type-choice
)

$$flags-map-extension //= &(
  sevsnphost-smt-enabled: -49,
  sevsnphost-tsme-enabled: -50,
  sevsnphost-ecc-mem-reported-enabled:-51,
  sevsnphost-rapl-disabled: -52,
  sevsnphost-ciphertext-hiding-enabled: -53
)

$$measurement-values-map-extension //= (
  &(sevsnphost-reported-tcb: -9) => svn-type-choice
)

sevsnphost-sp-fw-version-record = [
  build-number: uint .size 1,
  major: uint .size 1,
  minor: uint .size 1
]

$$measurement-values-map-extension //= (
  &(sevsnphost-sp-fw-current: -4) => sevsnphost-sp-fw-version-record
)

$$measurement-values-map-extension //= (
  &(sevsnphost-sp-fw-committed: -5) => sevsnphost-sp-fw-version-record
)

sevsnp-tcb-version-type-choice = sevsnphost-tcb-map / svn-type-choice

sevsnphost-tcb-map = {
  &(blspl: 0) => uint
  &(teespl: 1) => svn-type
  ? &(spl4: 2) => svn-type
  ? &(spl5: 3) => svn-type
  ? &(spl6: 4) => svn-type
  ? &(spl7: 5) => svn-type
  &(snpspl: 6) => svn-type
  &(ucodespl: 7) => svn-type
}


sevsnp-vmsa-map-r1-55 = { sevsnp-vmsa-r1-55 }

sevsnp-vmsa-r1-55 = &(
  ? &(page-data: -2) => byte .bits sev-snp-page-data
  ? &(vmpl-perms: -1) => uint64
  ? &(es: 0) => svm-vmcb-seg-map
  ? &(cs: 1) => svm-vmcb-seg-map
  ? &(ss: 2) => svm-vmcb-seg-map
  ? &(ds: 3) => svm-vmcb-seg-map
  ? &(fs: 4) => svm-vmcb-seg-map
  ? &(gs: 5) => svm-vmcb-seg-map
  ? &(ldtr: 6) => svm-vmcb-seg-map
  ? &(gdtr: 7) => svm-vmcb-seg-map
  ? &(idtr: 8) => svm-vmcb-seg-map
  ? &(tr: 9) => svm-vmcb-seg-map
  ? &(pl0_ssp: 10) => uint64
  ? &(pl1_ssp: 11) => uint64
  ? &(pl2_ssp: 12) => uint64
  ? &(pl3_ssp: 13) => uint64
  ? &(u_cet: 14) => uint64
  ? &(vmpl: 15) => byte
  ? &(cpl: 16) => byte
  ? &(efer: 17) => uint64
  ? &(perf_ctl0: 18) => uint64
  ? &(perf_ctr0: 19) => uint64
  ? &(perf_ctl1: 20) => uint64
  ? &(perf_ctr1: 21) => uint64
  ? &(perf_ctl2: 22) => uint64
  ? &(perf_ctr2: 23) => uint64
  ? &(perf_ctl3: 24) => uint64
  ? &(perf_ctr3: 25) => uint64
  ? &(perf_ctl4: 26) => uint64
  ? &(perf_ctr4: 27) => uint64
  ? &(perf_ctl5: 28) => uint64
  ? &(perf_ctr5: 29) => uint64
  ? &(xss: 30) => uint64
  ? &(cr4: 31) => uint64
  ? &(cr3: 32) => uint64
  ? &(cr0: 33) => uint64
  ? &(dr7: 34) => uint64
  ? &(dr6: 35) => uint64
  ? &(rflags: 36) => uint64
  ? &(rip: 37) => uint64
  ? &(dr0: 38) => uint64
  ? &(dr1: 39) => uint64
  ? &(dr2: 40) => uint64
  ? &(dr3: 41) => uint64
  ? &(dr0_addr_mask: 42) => uint64
  ? &(dr1_addr_mask: 43) => uint64
  ? &(dr2_addr_mask: 44) => uint64
  ? &(dr3_addr_mask: 45) => uint64
  ? &(instr_retired_ctr: 46) => uint64
  ? &(perf_ctr_global_sts: 47) => uint64
  ? &(perf_ctr_global_ctl: 48) => uint64
  ? &(rsp: 49) => uint64
  ? &(s_cet: 50) => uint64
  ? &(ssp: 51) => uint64
  ? &(isst_addr: 52) => uint64
  ? &(rax: 53) => uint64
  ? &(star: 54) => uint64
  ? &(lstar: 55) => uint64
  ? &(cstar: 56) => uint64
  ? &(sfmask: 57) => uint64
  ? &(kernel_gs_base: 58) => uint64
  ? &(sysenter_cs: 59) => uint64
  ? &(sysenter_esp: 60) => uint64
  ? &(sysenter_eip: 61) => uint64
  ? &(cr2: 62) => uint64
  ? &(g_pat: 63) => uint64
  ? &(dbgctl: 64) => uint64
  ? &(br_from: 65) => uint64
  ? &(br_to: 66) => uint64
  ? &(last_excp_from: 67) => uint64
  ? &(last_excp_to: 68) => uint64
  ? &(dbgextngfg: 69) => uint64
  ? &(spec_ctrl: 70) => uint64
  ? &(pkru: 71) => uint64
  ? &(tsc_aux: 72) => uint64
  ? &(guest_tsc_scale: 73) => uint64
  ? &(guest_tsc_offset: 74) => uint64
  ? &(reg_prot_nonce: 75) => uint64
  ? &(rcx: 76) => uint64
  ? &(rdx: 77) => uint64
  ? &(rbx: 78) => uint64
  ? &(secure_avic_ctl: 79) => uint64
  ? &(rbp: 80) => uint64
  ? &(rsi: 81) => uint64
  ? &(rdi: 82) => uint64
  ? &(r8: 83) => uint64
  ? &(r9: 84) => uint64
  ? &(r10: 85) => uint64
  ? &(r11: 86) => uint64
  ? &(r12: 87) => uint64
  ? &(r13: 88) => uint64
  ? &(r14: 89) => uint64
  ? &(r15: 90) => uint64
  ? &(sev_features: 91) => uint64
  ? &(vintr_ctrl: 92) => uint64
  ? &(virtual_tom: 93) => uint64
  ? &(tlb_id: 94) => uint64
  ? &(pcpu_id: 95) => uint64
  ? &(event_inj: 96) => uint64
  ? &(xcr0: 97) => uint64
  ? &(x87_dp: 98) => uint64
  ? &(mxcsr: 99) => uint32
  ? &(x87_ftw: 100) => uint16
  ? &(x87_fsw: 101) => uint16
  ? &(x87_fcw: 102) => uint16
  ? &(x87_fop: 103) => uint16
  ? &(x87_ds: 104) => uint16
  ? &(x87_rip: 105) => uint64
  ? &(fpreg_87: 106) => bytes .size 80
  ? &(fpreg_xmm: 107) => bytes .size 256
  ? &(fpreg_ymm: 108) => bytes .size 256
  ? &(lbr_stack: 109) => bytes .size 256
  ? &(lbr_select: 110) => uint64
  ? &(ibs_fetch_ctl: 111) => uint64
  ? &(ibs_fetch_linaddr: 112) => uint64
  ? &(ibs_op_ctl: 113) => uint64
  ? &(ibs_op_rip: 114) => uint64
  ? &(ibs_op_data: 115) => uint64
  ? &(ibs_op_data2: 116) => uint64
  ? &(ibs_op_data3: 117) => uint64
  ? &(ibs_dc_linaddr: 118) => uint64
  ? &(bp_ibstgt_rip: 119) => uint64
  ? &(ic_ibs_extd_ctl: 120) => uint64
)

$sevsnp-vmsa-type-choice = tagged-sevsnp-vmsa-map-r1-55 / uuid-type / oid-type

svm-vmcb-seg-map = {
  ? &(selector: 0) => uint16
  ? &(attrib: 1) => uint16
  ? &(limit: 2) => uint32
  ? &(base: 3) => uint64
}

svn-type = uint
svn = svn-type
min-svn = svn-type
tagged-svn = #6.552(svn)
tagged-min-svn = #6.553(min-svn)
svn-type-choice = tagged-svn / tagged-min-svn

tagged-int-bytes-map = #6.563(int-bytes-map)

tagged-sevsnp-repeated-vmsa = #6.32872(sevsnp-repeated-vmsa)

tagged-sevsnp-vmsa-map-r1-55 = #6.32781(sevsnp-vmsa-map-r1-55)

uint16 = 0..65535

uint32 = 0..4294967295

uint64 = 0..18446744073709551615

Contributors

Yogesh Deshpande
arm

Yogesh Deshpande contributed to the data model by providing advice about CoRIM founding principles.

Author's Address

Dionna Glaze
Google LLC