// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

syntax = "proto3";

package state;

option go_package = "github.com/google/go-eventlog/proto/state";

// 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;
}

// 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.
  // Included for backcompat. go-eventlog should NOT set this field.
  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 ExtractOpts{Loader: GRUB} when calling ParseMachineState.
message LinuxKernelState {
  // The kernel command line.
  string command_line = 1;
}

// A parsed event from the source firmware event log. This can be from either
// the firmware TPM event log, the Confidential Computing event log, or any
// other TCG-like event log used by firmware to record its measurements.
message Event {
  // The register this event was extended into. Can be PCR, RTMR, etc.
  // Named pcr_index for backcompat reasons.
  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;
}

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;
}

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;
}

// Enum values come from the TCG Algorithm Registry - v1.27 - Table 3.
enum HashAlgo {
  HASH_INVALID = 0x0000;
  SHA1 = 0x0004;
  SHA256 = 0x000B;
  SHA384 = 0x000C;
  SHA512 = 0x000D;
}

// The verified state of a booted machine, obtained from a UEFI event log.
// The state is extracted from either EFI_TCG2_PROTOCOL or
// EFI_CC_MEASUREMENT_PROTOCOL. Both of these follow the TCG-defined format
// in https://trustedcomputinggroup.org/resource/tcg-efi-protocol-specification/
// The TCG2-related (TPM) logs are structured using TCG_PCR_EVENT (SHA1 format)
// or TCG_PCR_EVENT2 (Crypto Agile format).
// The CC logs are structured using CC_EVENT.
message FirmwareLogState {
  reserved 7;

  PlatformState platform = 1;

  SecureBootState secure_boot = 2;

  // The complete parsed Firmware Event Log, including those events used to
  // create this MachineState.
  repeated Event raw_events = 3;

  // The hash algorithm used to calculate event digests to verify a log entry.
  HashAlgo hash = 4;

  GrubState grub = 5;

  LinuxKernelState linux_kernel = 6;

  EfiState efi = 8;
}

