From e4b7827ca4a094a103c4209e71c4c3eb5aea9005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Tremblay?= <1619947+marctrem@users.noreply.github.com> Date: Thu, 2 Jul 2026 12:03:19 -0400 Subject: [PATCH] attestation/v1: add Intel TDX and AMD SEV-SNP arms + measurement endorsements Adds IntelTDXAttestation/AMDSEVSNPAttestation (evidence) and their AttestationResult counterparts (verified fields) to the attestation union, plus MeasurementEndorsement/EndorsementPayload/MeasurementConstraint for pinning release identity on platforms that have no image-embedded signing signature. --- .../v1/amd_sev_snp_attestation.proto | 30 +++++++++ .../v1/amd_sev_snp_attestation_result.proto | 42 +++++++++++++ .../splitsecure/attestation/v1/generic.proto | 4 ++ .../v1/intel_tdx_attestation.proto | 31 ++++++++++ .../v1/intel_tdx_attestation_result.proto | 43 +++++++++++++ .../v1/measurement_endorsement.proto | 61 +++++++++++++++++++ proto/splitsecure/attestation/v1/result.proto | 4 ++ 7 files changed, 215 insertions(+) create mode 100644 proto/splitsecure/attestation/v1/amd_sev_snp_attestation.proto create mode 100644 proto/splitsecure/attestation/v1/amd_sev_snp_attestation_result.proto create mode 100644 proto/splitsecure/attestation/v1/intel_tdx_attestation.proto create mode 100644 proto/splitsecure/attestation/v1/intel_tdx_attestation_result.proto create mode 100644 proto/splitsecure/attestation/v1/measurement_endorsement.proto diff --git a/proto/splitsecure/attestation/v1/amd_sev_snp_attestation.proto b/proto/splitsecure/attestation/v1/amd_sev_snp_attestation.proto new file mode 100644 index 0000000..0cbe836 --- /dev/null +++ b/proto/splitsecure/attestation/v1/amd_sev_snp_attestation.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; +package splitsecure.attestation.v1; + +import "google/protobuf/timestamp.proto"; +import "splitsecure/attestation/v1/measurement_endorsement.proto"; +import "splitsecure/hybridkeyset/v1/signature.proto"; + +// AMDSEVSNPAttestation contains AMD Secure Encrypted Virtualization - +// Secure Nested Paging (SEV-SNP) attestation data. +message AMDSEVSNPAttestation { + // Raw SEV-SNP attestation report. + bytes report = 1; + + // Certificate chain for the report signer: VCEK or VLEK, plus the + // intermediate ASK and root ARK certificates. + bytes vcek_chain = 2; + + MeasurementEndorsement endorsement = 3; + + // Timestamp bound into the report's REPORT_DATA. Verifiers derive the + // validity window from this value. + google.protobuf.Timestamp issued_at = 4; + + // Instance-level HKS signature over (authenticated || separator || identity_vertex). + // Binds a virtual enclave's identity to the physically attested SEV-SNP instance. + splitsecure.hybridkeyset.v1.Signature instance_identity_binding_sig = 5; + + // Full instance HKS public keys (serialized HybridKeySetWithDetachedKeys, public only). + bytes instance_hks_pub = 6; +} diff --git a/proto/splitsecure/attestation/v1/amd_sev_snp_attestation_result.proto b/proto/splitsecure/attestation/v1/amd_sev_snp_attestation_result.proto new file mode 100644 index 0000000..db438b2 --- /dev/null +++ b/proto/splitsecure/attestation/v1/amd_sev_snp_attestation_result.proto @@ -0,0 +1,42 @@ +syntax = "proto3"; +package splitsecure.attestation.v1; + +// AMDSEVSNPAttestationResult contains the result of verifying an AMD +// SEV-SNP attestation. +message AMDSEVSNPAttestationResult { + // Equals the report's REPORT_DATA. This is a per-attestation commitment + // that rotates every attestation because a timestamp is folded into it; + // it is NOT a stable identifier. + bytes key_id = 1; + + bytes measurement = 2; + bytes host_data = 3; + bytes id_key_digest = 4; + bytes author_key_digest = 5; + + string endorsement_tier = 6; + string endorsement_deployment = 7; + + string tcb_status = 8; + + // SHA3-512 of instance_hks_pub. Stable across attestations from the same + // instance, for audit/dedup purposes. + bytes instance_id = 9; + + // Lowercase-hex SHA-384 of the endorsement signing certificate's DER + // encoding, matched against the verifier's embedded trusted set. + string endorsement_cert = 10; + + // TCB_VERSION SVNs matched to the VCEK/VLEK used to sign the report. This + // is SEV-SNP's rollback-floor primitive. + AMDSEVSNPTcbVersion tcb_version = 11; +} + +// AMDSEVSNPTcbVersion holds the individual security version numbers that +// make up an SEV-SNP TCB_VERSION. +message AMDSEVSNPTcbVersion { + uint32 bootloader = 1; + uint32 tee = 2; + uint32 snp = 3; + uint32 microcode = 4; +} diff --git a/proto/splitsecure/attestation/v1/generic.proto b/proto/splitsecure/attestation/v1/generic.proto index 5cb7985..5177e7d 100644 --- a/proto/splitsecure/attestation/v1/generic.proto +++ b/proto/splitsecure/attestation/v1/generic.proto @@ -1,9 +1,11 @@ syntax = "proto3"; package splitsecure.attestation.v1; +import "splitsecure/attestation/v1/amd_sev_snp_attestation.proto"; import "splitsecure/attestation/v1/android_key_attestation.proto"; import "splitsecure/attestation/v1/apple_device_check_attestation.proto"; import "splitsecure/attestation/v1/aws_nitro_attestation.proto"; +import "splitsecure/attestation/v1/intel_tdx_attestation.proto"; // Generic represents platform attestation data from any supported platform. message Generic { @@ -12,5 +14,7 @@ message Generic { AppleDeviceCheckAttestation apple_dc = 2; AWSNitroAttestation aws_nitro = 3; AndroidKeyAttestation android_ka = 4; + IntelTDXAttestation intel_tdx = 5; + AMDSEVSNPAttestation amd_sev_snp = 6; } } diff --git a/proto/splitsecure/attestation/v1/intel_tdx_attestation.proto b/proto/splitsecure/attestation/v1/intel_tdx_attestation.proto new file mode 100644 index 0000000..7b70009 --- /dev/null +++ b/proto/splitsecure/attestation/v1/intel_tdx_attestation.proto @@ -0,0 +1,31 @@ +syntax = "proto3"; +package splitsecure.attestation.v1; + +import "google/protobuf/timestamp.proto"; +import "splitsecure/attestation/v1/measurement_endorsement.proto"; +import "splitsecure/hybridkeyset/v1/signature.proto"; + +// IntelTDXAttestation contains Intel Trust Domain Extensions (TDX) +// attestation data. +message IntelTDXAttestation { + // Raw TDX quote (v4 or v5). The PCK leaf and intermediate certificates + // ride in the quote's cert_data. + bytes quote = 1; + + // Intel PCS collateral bundle for offline verification: TCB info and + // issuer chain, QE identity, and CRLs. + bytes collateral = 2; + + MeasurementEndorsement endorsement = 3; + + // Timestamp bound into the quote's REPORTDATA. Verifiers derive the + // validity window from this value. + google.protobuf.Timestamp issued_at = 4; + + // Instance-level HKS signature over (authenticated || separator || identity_vertex). + // Binds a virtual enclave's identity to the physically attested TDX instance. + splitsecure.hybridkeyset.v1.Signature instance_identity_binding_sig = 5; + + // Full instance HKS public keys (serialized HybridKeySetWithDetachedKeys, public only). + bytes instance_hks_pub = 6; +} diff --git a/proto/splitsecure/attestation/v1/intel_tdx_attestation_result.proto b/proto/splitsecure/attestation/v1/intel_tdx_attestation_result.proto new file mode 100644 index 0000000..1eda8b5 --- /dev/null +++ b/proto/splitsecure/attestation/v1/intel_tdx_attestation_result.proto @@ -0,0 +1,43 @@ +syntax = "proto3"; +package splitsecure.attestation.v1; + +// IntelTDXAttestationResult contains the result of verifying an Intel TDX +// attestation. +message IntelTDXAttestationResult { + // Equals the quote's REPORTDATA. This is a per-attestation commitment that + // rotates every attestation because a timestamp is folded into it; it is + // NOT a stable identifier. + bytes key_id = 1; + + bytes mrtd = 2; + bytes rtmr0 = 3; + bytes rtmr1 = 4; + bytes rtmr2 = 5; + bytes rtmr3 = 6; + bytes mrowner = 7; + bytes mrconfigid = 8; + + string endorsement_tier = 9; + string endorsement_deployment = 10; + + string tcb_status = 11; + + // SHA3-512 of instance_hks_pub. Stable across attestations from the same + // instance, for audit/dedup purposes. + bytes instance_id = 12; + + // Lowercase-hex SHA-384 of the endorsement signing certificate's DER + // encoding, matched against the verifier's embedded trusted set. + string endorsement_cert = 13; + + // TCB evaluation data number from the verified TCB info. Policy enforces a + // monotonic floor on this value as a defense against collateral rollback. + uint32 tcb_eval_number = 14; + + // crlNumber of the verified PCK CA CRL. Policy enforces a monotonic floor + // as a defense against CRL rollback. + uint32 pck_crl_number = 15; + + // crlNumber of the verified Root CA CRL. + uint32 root_crl_number = 16; +} diff --git a/proto/splitsecure/attestation/v1/measurement_endorsement.proto b/proto/splitsecure/attestation/v1/measurement_endorsement.proto new file mode 100644 index 0000000..87288d5 --- /dev/null +++ b/proto/splitsecure/attestation/v1/measurement_endorsement.proto @@ -0,0 +1,61 @@ +syntax = "proto3"; +package splitsecure.attestation.v1; + +import "google/protobuf/timestamp.proto"; + +// MeasurementEndorsement is a signed statement pinning the identity of a +// release, independent of the underlying attestation platform. Confidential +// VM platforms such as Intel TDX and AMD SEV-SNP measure the guest image +// into hardware registers but do not embed a signature over that +// measurement the way some other platforms do, so this message carries an +// out-of-band signature over the set of measurements a release is expected +// to produce. +message MeasurementEndorsement { + // Deterministic-marshaled EndorsementPayload. Verifiers unmarshal this and + // check the signature over these exact bytes. + bytes payload = 1; + + // ECDSA P-384 signature (DER) over payload, produced by a release signing + // certificate. + bytes signature = 2; + + // Lowercase-hex SHA-384 digest of the signing certificate's DER encoding. + // Verifiers look this digest up in a compiled-in trusted set and reject + // any endorsement whose digest is not present; the certificate itself + // never rides in the message. + string signing_cert_der_sha384 = 3; +} + +// EndorsementPayload describes the measurements a specific release build is +// expected to produce, along with metadata identifying that release. +message EndorsementPayload { + // Platform this endorsement applies to: "intel-tdx" or "amd-sev-snp". Must + // equal the attestation arm being verified. + string platform = 1; + + // Deployment tier: "prod", "staging", or "develop". + string tier = 2; + + // Per-tier/region label, e.g. "us". + string deployment = 3; + + repeated MeasurementConstraint constraints = 4; + + google.protobuf.Timestamp signed_at = 5; + + // Audit trail: identifies which image build this endorsement covers. + string image_ref = 6; +} + +// MeasurementConstraint pins one platform measurement register to a set of +// acceptable values. +message MeasurementConstraint { + // Register name, e.g. "mrtd", "rtmr0".."rtmr3", or "measurement". + string register = 1; + + // Set of acceptable values for this register; at least one entry. + // Represented as a set (rather than a single value) to allow for + // legitimate variation, e.g. several acceptable host-firmware + // measurements. + repeated bytes acceptable = 2; +} diff --git a/proto/splitsecure/attestation/v1/result.proto b/proto/splitsecure/attestation/v1/result.proto index da4586d..f0ba257 100644 --- a/proto/splitsecure/attestation/v1/result.proto +++ b/proto/splitsecure/attestation/v1/result.proto @@ -2,9 +2,11 @@ syntax = "proto3"; package splitsecure.attestation.v1; import "google/protobuf/timestamp.proto"; +import "splitsecure/attestation/v1/amd_sev_snp_attestation_result.proto"; import "splitsecure/attestation/v1/android_key_attestation_result.proto"; import "splitsecure/attestation/v1/apple_device_check_attestation_result.proto"; import "splitsecure/attestation/v1/aws_nitro_attestation_result.proto"; +import "splitsecure/attestation/v1/intel_tdx_attestation_result.proto"; // Result is the result of verifying an attestation. message Result { @@ -18,6 +20,8 @@ message Result { AppleDeviceCheckAttestationResult apple_dc = 1; AWSNitroAttestationResult aws_nitro = 2; AndroidKeyAttestationResult android_key = 3; + IntelTDXAttestationResult intel_tdx = 4; + AMDSEVSNPAttestationResult amd_sev_snp = 5; } } }