Internet-Draft | CoRIM-SEV | August 2024 |
Glaze | Expires 8 February 2025 | [Page] |
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.¶
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.¶
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.¶
Copyright (c) 2024 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
TODO: write after content.¶
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].¶
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.¶
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.¶
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) }¶
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 )¶
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.¶
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)¶
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].¶
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.¶
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.¶
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.¶
The Verifier SHALL use tho svn-type-choice
comparison algorithm from {-rats-corim}}.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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.¶
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))¶
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.¶
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¶
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.¶
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.¶
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¶
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
.¶
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
,¶
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¶
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
:¶
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 }) }¶
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.¶
$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¶
Yogesh Deshpande contributed to the data model by providing advice about CoRIM founding principles.¶