syntax = "proto3";

package attest;

import "proto/sevsnp.proto";
import "proto/tdx.proto";
import "tpm.proto";

option go_package = "github.com/google/go-tpm-tools/proto/attest";

// Information uniquely identifying a GCE instance. Can be used to create an
// instance URL, which can then be used with GCE APIs. Formatted like:
//   https://www.googleapis.com/compute/v1/projects/{project_id}/zones/{zone}/instances/{instance_name}
message GCEInstanceInfo {
  string zone = 1;
  string project_id = 2;
  uint64 project_number = 3;
  string instance_name = 4;
  uint64 instance_id = 5;
}

message Attestation {
  // Attestation Key (AK) Public Area, encoded as a TPMT_PUBLIC
  bytes ak_pub = 1;
  // Quotes over all supported PCR banks
  repeated tpm.Quote quotes = 2;
  // TCG Event Log, encoded in the raw binary format.
  // Can be SHA-1 or crypto-agile.
  bytes event_log = 3;
  // Optional information about a GCE instance, unused outside of GCE
  GCEInstanceInfo instance_info = 4;
  // A COS event log using the TCG Canonical Event Log format
  bytes canonical_event_log = 5;
  // Attestation Key (AK) Certificate, encoded as ASN.1 DER.
  // Optional.
  bytes ak_cert = 6;
  // Intermediate Certificates for verifying the AK Certificate, encoded as
  // ASN.1 DER. Optional.
  repeated bytes intermediate_certs = 7;
  // Trusted execution environment attestation is a secondary platform
  // attestation that the machine is running within a particular confidential
  // environment.
  oneof tee_attestation {
    sevsnp.Attestation sev_snp_attestation = 8;
    tdx.QuoteV4 tdx_attestation = 9;
  }
}

// For VMs running SEV-SNP with an SVSM-based e-vTPM, this contains a TPM quote
// and all the information needed to verify it.
message SevSnpSvsmAttestation {
  Attestation attestation = 1;
  sevsnp.Attestation sev_snp_attestation = 2;
  // vTPM service manifest is retrieved from configfs-tsm-report via manifest blob
  // See https://github.com/torvalds/linux/blob/v6.16/Documentation/ABI/testing/configfs-tsm-report
  // The manifest format is defined by the SVSM spec at https://www.amd.com/en/developer/sev.html
  bytes vtpm_service_manifest = 3;
  string vtpm_service_manifest_version = 4;
  // This contains a launch endorsement for guest firmware that includes SVSM.
  bytes launch_endorsement = 5;
}

// Type of hardware technology used to protect this instance
enum GCEConfidentialTechnology {
  NONE = 0;
  AMD_SEV = 1;
  AMD_SEV_ES = 2;
  INTEL_TDX = 3;
  AMD_SEV_SNP = 4;
}

// The platform/firmware state for this instance
message PlatformState {
  oneof firmware {
    // Raw S-CRTM version identifier (EV_S_CRTM_VERSION)
    bytes scrtm_version_id = 1;
    // Virtual GCE firmware version (parsed from S-CRTM version id)
    uint32 gce_version = 2;
  }
  // Set to NONE on non-GCE instances or non-Confidential Shielded GCE instances
  GCEConfidentialTechnology technology = 3;
  // Only set for GCE instances
  GCEInstanceInfo instance_info = 4;
}

message GrubFile {
  // The digest of the file (pulled from the raw event digest).
  bytes digest = 1;
  // The event data. This is not measured, so it is untrusted.
  bytes untrusted_filename = 2;
}

message GrubState {
  // All GRUB-read and measured files, including grub.cfg.
  repeated GrubFile files = 1;
  // A list of executed GRUB commands and command lines passed to the kernel
  // and kernel modules.
  repeated string commands = 2;
}

// The state of the Linux kernel.
// At the moment, parsing LinuxKernelState relies on parsing the GrubState.
// To do so, use ParseOpts{Loader: GRUB} when calling ParseMachineState.
message LinuxKernelState {
  // The kernel command line.
  string command_line = 1;
}

// A parsed event from the TCG event log
message Event {
  // The Platform Control Register (PCR) this event was extended into.
  uint32 pcr_index = 1;
  // The type of this event. Note that this value is not verified, so it should
  // only be used as a hint during event parsing.
  uint32 untrusted_type = 2;
  // The raw data associated to this event. The meaning of this data is
  // specific to the type of the event.
  bytes data = 3;
  // The event digest actually extended into the TPM. This is often the hash of
  // the data field, but in some cases it may have a type-specific calculation.
  bytes digest = 4;
  // This is true if hash(data) == digest.
  bool digest_verified = 5;
}

// Common, publicly-listed certificates by different vendors.
enum WellKnownCertificate {
  UNKNOWN = 0;

  // Microsoft certs:
  // https://go.microsoft.com/fwlink/p/?linkid=321192
  MS_WINDOWS_PROD_PCA_2011 = 1;
  // https://go.microsoft.com/fwlink/p/?linkid=321194
  MS_THIRD_PARTY_UEFI_CA_2011 = 2;
  // https://go.microsoft.com/fwlink/p/?linkid=321185
  MS_THIRD_PARTY_KEK_CA_2011 = 3;

  // GCE certs:
  GCE_DEFAULT_PK = 4;
}

message Certificate {
  // The representation of the certificate. If the certificate matches a
  // well-known certificate above, representation should contain the value in
  // the enum. Otherwise, it will contain the raw DER.
  oneof representation {
    // DER representation of the certificate.
    bytes der = 1;
    WellKnownCertificate well_known = 2;
  }
}

// A Secure Boot database containing lists of hashes and certificates,
// as defined by section 32.4.1 Signature Database in the UEFI spec.
message Database {
  repeated Certificate certs = 1;
  repeated bytes hashes = 2;
}

// The Secure Boot state for this instance.
message SecureBootState {
  // Whether Secure Boot is enabled.
  bool enabled = 1;
  // The Secure Boot signature (allowed) database.
  Database db = 2;
  // The Secure Boot revoked signature (forbidden) database.
  Database dbx = 3;
  // Authority events post-separator. Pre-separator authorities
  // are currently not supported.
  Database authority = 4;
  // The Secure Boot Platform key, used to sign key exchange keys.
  Database pk = 5;
  // The Secure Boot Key Exchange Keys, used to sign db and dbx updates.
  Database kek = 6;
}

// The container's restart policy.
// See the following Kubernetes documentation for more details:
// https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy
// Note that these enum variants do not conform to the standard Protocol Buffers
// Style Guide so that RestartPolicy_name, RestartPolicy_value, and
// RestartPolicy.String() match the values used by Kubernetes and others.
enum RestartPolicy {
  Always = 0;
  OnFailure = 1;
  Never = 2;
}

message ContainerState {
  string image_reference = 1;
  // Digest of the registry's image manifest, which contains a list of the
  // layers comprising the image.
  string image_digest = 2;
  RestartPolicy restart_policy = 3;
  // Digest of the local image configuration object, containing config items
  // such as local layer digests.
  string image_id = 4;
  repeated string args = 5;
  map<string, string> env_vars = 6;
  // Record operator input Env Vars and Args, should be subsets of the above
  // Env Vars and Args.
  repeated string overridden_args = 7;
  map<string, string> overridden_env_vars = 8;
}

message SemanticVersion {
  uint32 major = 1;
  uint32 minor = 2;
  uint32 patch = 3;
}

message HealthMonitoringState {
  // Whether memory monitoring is enabled.
  optional bool memory_enabled = 1;
}

// Confidential Computing mode for GPU device. Reference for these CC mode values: https://developer.nvidia.com/blog/confidential-computing-on-h100-gpus-for-secure-and-trustworthy-ai/#hardware_security_for_nvidia_h100_gpus
enum GPUDeviceCCMode {
  UNSET = 0;
  // The NVIDIA H100 hardware, firmware, and software have fully activated all the confidential computing features.
  ON = 1;
  // None of the confidential computing-specific features are active.
  OFF = 2;
  // The GPU is in a partial CC mode that will match the workflows of CC mode ON, but with security protections disabled.
  DEVTOOLS = 3;
}

message GpuDeviceState {
  // Whether Confidential Computing mode is enabled for GPU.
  GPUDeviceCCMode cc_mode = 1;
}


message AttestedCosState {
  ContainerState container = 1;
  SemanticVersion cos_version = 2;
  SemanticVersion launcher_version = 3;
  HealthMonitoringState health_monitoring = 4;
  GpuDeviceState gpu_device_state = 5;
}

message EfiApp {
  // The PE/COFF digest of the EFI application (pulled from the raw event digest).
  bytes digest = 1;
}

// The verified state of EFI Applications. Policy usage on this machine state
// should check the entire set of EFI App digests matches, not a subset.
message EfiState {
  // UEFI's OS Loader code is required to measure attempts to load and execute
  // UEFI applications.
  // UEFI applications are typically bootloaders such as shim and GRUB.
  // These run and are measured using the UEFI LoadImage() service.
  repeated EfiApp apps = 1;
  // The EFI drivers,
  // obtained from https://trustedcomputinggroup.org/wp-content/uploads/TCG_EFI_Platform_1_22_Final_-v15.pdf#page=22.
  // The EFI Boot Services Drivers from adapter or loaded bydriver in adapter.
  repeated EfiApp boot_services_drivers = 2;
  // The EFI Runtime Drivers from adapter or loaded bydriver in adapter.
  repeated EfiApp runtime_services_drivers = 3;
}

// The verified state of a booted machine, obtained from an Attestation
message MachineState {
  PlatformState platform = 1;

  SecureBootState secure_boot = 2;

  // The complete parsed TCG Event Log, including those events used to
  // create the PlatformState.
  repeated Event raw_events = 3;
  // The hash algorithm used when verifying the Attestation. This indicates:
  //   - which PCR bank was used for for quote validation and event log replay
  //   - the hash algorithm used to calculate event digests
  tpm.HashAlgo hash = 4;

  GrubState grub = 5;

  LinuxKernelState linux_kernel = 6;

  AttestedCosState cos = 7;

  EfiState efi = 8;

  // Attestation/Quote representations from TEEs whose signatures are already
  // verified.
  oneof tee_attestation {
    sevsnp.Attestation sev_snp_attestation = 9;
    tdx.QuoteV4 tdx_attestation = 10;
  }
}

// A policy dictating which values of PlatformState to allow
message PlatformPolicy {
  // If PlatformState.firmware contains a scrtm_version_id, it must appear
  // in this list. For use with a GCE VM, minimum_gce_firmware_version is
  // often a better alternative.
  repeated bytes allowed_scrtm_version_ids = 1;
  // If PlatformState.firmware contains a minimum_gce_firmware_version, it must
  // be greater than or equal to this value. Currently, the max version is 1.
  uint32 minimum_gce_firmware_version = 2;
  // The PlatformState's technology must be at least as secure as
  // the specified minimum_technology (i.e. AMD_SEV_ES > AMD_SEV > NONE).
  GCEConfidentialTechnology minimum_technology = 3;
}

// A policy about what parts of a RIM to compare against machine state as
// reflected in a quote or (verified) event log. Reference measurements for
// a component are expected to be addressable by the machine state's reported
// digest, or otherwise presented as cached collateral with the attestation
// itself. The method of delivery is vendor-specific.
message RIMPolicy {
  // If true, the signed measurement must be available (by means that can be
  // vendor-specific), and the target measurement must be among the listed
  // signed measurements.  If false, then only error if there is a problem
  // verifying the signed measurements when they are available.
  bool require_signed = 1;
  // x.509 certificates in ASN.1 DER format.
  repeated bytes root_certs = 2;
}

// Represent minimal decisions about attestation fields until necessary to
// add for policy reasons.
message SevSnpPolicy {
  // The policy for checking the signed reference values for the UEFI at launch.
  RIMPolicy uefi = 1;
}

// A policy dictating which type of MachineStates to allow
message Policy {
  PlatformPolicy platform = 1;

  // SecureBootPolicy secure_boot = 2;

  // When the attestation is on SEV-SNP, this is the policy. Unset means no
  // constraints.
  SevSnpPolicy sev_snp = 3;
}