// Copyright 2026 The Trusted Computations Platform Authors.
//
// 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 fcp.confidentialcompute;

import "fcp/protos/confidentialcompute/payload_transparency.proto";
import "proto/session/session.proto";

option java_multiple_files = true;
option java_outer_classname = "AttestationTransparencyServiceOuterClass";
option java_package = "com.google.intelligence.fcp.confidentialcompute";

// The AttestationTransparencyService (ATS) enables the creation of a
// fcp.confidentialcompute.SignedPayload message with a signature chain rooted
// in a publicly inspectable binary running in a Trusted Execution Environment
// (TEE) with a hardware root of trust. Additionally, the ATS guarantees that if
// any of these claims are untrue (e.g. the binary doesn't have publicly
// available code or the enclave isn't secure), sufficient information has been
// published to a transparency log such that anyone -- not just the receipient
// of the SignedPayload message -- can detect the issue.
//
// The ATS works as follows:
//
//  1. The ATS creates an in-memory-only signing key (ATS signing key) and signs
//     the corresponding verifying key using its Oak application signing key,
//     forming a signature chain back to hardware-rooted attestation evidence.
//
//  2. The signed ATS verifying key is uploaded to one or more transparency logs
//     along with the signature chain and hardware attestation evidence. Anyone
//     monitoring the transparency logs can verify (or falsify) the claim that
//     the signatures were generated by a TEE with specific firmware and
//     software versions. (Transparency log interactions happen outside the
//     enclave and therefore aren't part of the service implementation.)
//
//  3. The ATS signing key is used to sign various payloads produced by other
//     microservices running in the same process. A client application
//     inspecting the resulting SignedPayload messages can verify that enough
//     information was uploaded to a transparency log to verify the claims from
//     (2). In other words, clients can verify that it is publicly discoverable
//     if the server is operating in a non-transparent or malicious way.
//
// In practice, a service operator will run many replicas of the ATS. Creating
// transparency log entries for each is wasteful and scales poorly, so the ATS
// also supports sharing an existing ATS signing key between *equivalent*
// instances. Two instances are considered equivalent if they're running in
// enclaves with identical sercurity-relevant attributes (e.g. hardware family,
// firmware versions, and software versions); attributes like CPU serial number
// and VM RAM size may differ. This allows the number of transparency log
// entries to scale with the number of unique hardware and software
// configurations, not the number of replicas.
service AttestationTransparencyService {
  // Returns the current status of the service, such as whether a signing key
  // has been created/loaded.
  rpc GetStatus(GetStatusRequest) returns (GetStatusResponse) {}

  // Creates a new signing key and sets it active.
  //
  // This is a multi-stage process:
  //   1. the caller initializes the stream and sends a CreateKey request.
  //   2. the server responds with an UnpublishedKey message containing the new
  //      verifying key, signed by the enclave's Oak application signing key.
  //   3. the caller writes the enclave's EndorsedEvidence to
  //      https://federatedcompute-pa.googleapis.com/data/transparency and
  //      uploads the signature along with the evidence to one or more
  //      transparency logs.
  //   4. the caller sends a CommitKey request with a SignedPayload containing
  //      the transparency log entries. The caller may also cancel the stream if
  //      step 3 fails.
  //   5. The server closes the stream successfully. The new signing key is now
  //      active.
  rpc CreateSigningKey(stream CreateSigningKeyRequest)
      returns (stream CreateSigningKeyResponse) {}

  // Loads a signing key from an equivalent ATS instance.
  //
  // Callers should initiate LoadSigningKey and ShareSigningKey operations on
  // the two instances and forward requests and responses until both streams
  // close successfully. Since (by definition) this RPC will only work between
  // servers running the same code, the semantics of the requests and responses
  // are intentionally left unspecified and may change without notice.
  rpc LoadSigningKey(stream oak.session.v1.SessionResponse)
      returns (stream oak.session.v1.SessionRequest) {}

  // Shares the active signing key with an equivalent ATS. This method will fail
  // with an UNAVAILABLE error if the server does not currently have a signing
  // key.
  rpc ShareSigningKey(stream oak.session.v1.SessionRequest)
      returns (stream oak.session.v1.SessionResponse) {}
}

message GetStatusRequest {}

message GetStatusResponse {
  // A fingerprint of the software and firmware versions of the enclave. Two
  // ATS instances should be able to share keys if and only if they have the
  // same version fingerprint -- or there's a hash collision, in which case
  // sharing will fail. This value can be used to avoid attempting to share keys
  // between incompatible instances.
  //
  // Callers must treat this value as opaque. The digest algorithm used -- and
  // therefore the length of the fingerprint -- may change without notice.
  bytes version_fprint = 1;

  // The signed payload containing the verifying key and transparency log
  // entries for the service's active signing key. This will be unset if no
  // signing key has been created.
  SignedPayload verifying_key = 2;
}

message CreateSigningKeyRequest {
  // The stage of the CreateSigningKey RPC; see the CreateSigningKey RPC docs.
  oneof kind {
    CreateKey create_key = 1;
    CommitKey commit_key = 2;
  }

  // Initializes the CreateSigningKey flow. This is empty now, but may be
  // extended with signing key creation options in the future.
  message CreateKey {}

  // Commits the key, overwriting any previously generated key.
  message CommitKey {
    // The signed payload containing the verifying key and transparency log
    // entries. It's an error if the payload does not match what was provided in
    // the CreateSigningKeyResponse.UnpublishedKey.
    SignedPayload verifying_key = 1;
  }
}

message CreateSigningKeyResponse {
  // The stage of the CreateSigningKey RPC; see the CreateSigningKey RPC docs.
  oneof kind {
    UnpublishedKey unpublished_key = 1;
  }

  // A verifying key that has not yet been published to a transparency log.
  message UnpublishedKey {
    // A serialized Key message containing the verifying key.
    bytes verifying_key = 1;

    // A signature of the verifying key using enclave's Oak application signing
    // key. The signature's headers will contain a hash of the endorsed
    // evidence.
    SignedPayload.Signature signature = 2;

    // The serialized oak.session.v1.EndorsedEvidence message for the key.
    bytes endorsed_evidence = 3;
  }
}
