/* SPDX-FileCopyrightText: 2014 The Chromium Authors
 * SPDX-License-Identifier: BSD-3-Clause
 */

// Contains the request and response messages used in the CryptAuth v2
// Enrollment protocol. Specifically,
//   (1) SyncKeysRequest: The client submits information about their current set
//       of keys to the CryptAuth server. The client can update their
//       client-specific or key-specific metadata at this time as well.
//   (2) SyncKeysResponse: The CryptAuth server responds with instructions such
//       as what existing keys to (de)active, what new keys to create, and the
//       time of the next check-in.
//   (3) EnrollKeysRequest: If new keys were requested in the SyncKeysResponse,
//       the client sends the new key information to CryptAuth in this request.
//   (4) EnrollKeysResponse: If a certificate was generated, it will be provided
//       here; otherwise, this can simply be a signal of a successful
//       enrollment.
syntax = "proto3";

package cryptauthv2;

option optimize_for = LITE_RUNTIME;

import "cryptauth/cryptauth_common.proto";
import "cryptauth/cryptauth_directive.proto";

// The first request in the enrollment protocol. The request contains the
// information including the keys currently held by the client, the latest
// policies received from the server, and the metadata associated with the
// client and keys.
message SyncKeysRequest {
  // The unique name of the application.
  string application_name = 1;
  // The version of the CryptAuth client library.
  string client_version = 2;

  // The request to enroll a key or update the info related to a key.
  message SyncSingleKeyRequest {
    // The purpose/application of the key.
    string key_name = 1;
    // Identifiers of keys currently held by the client.
    repeated bytes key_handles = 2;

    // The policy_reference received in the last KeyDirective.
    PolicyReference policy_reference = 3;
    // Key-specific metadata.
    KeyMetadata key_metadata = 4;
    // A key-specific opaque blob provided by the application.
    bytes key_app_metadata = 5;
  }
  // Per key sync data.
  repeated SyncSingleKeyRequest sync_single_key_requests = 3;

  // The policy_reference received in the last ClientDirective.
  PolicyReference policy_reference = 4;
  // Client-specific metadata.
  ClientMetadata client_metadata = 5;
  // A client-specific opaque blob provided by the application.
  // In the GmsCore case, this is a protobuf of type `ClientAppMetadata`.
  bytes client_app_metadata = 6;
}

// The response to SyncKeysRequest. The response instructs how the client should
// manage existing keys and whether to create a new key.
message SyncKeysResponse {
  // The session indentifer generated by the server, which must be
  // cryptographically random.
  bytes random_session_id = 1;
  // The ephemeral DH public key generated by the server.
  bytes server_ephemeral_dh = 2;

  // The response corresponding to the SyncSingleKeyRequest message.
  message SyncSingleKeyResponse {
    // The actions corresponding to the key handles in SyncKeysRequest.
    enum KeyAction {
      // Default value. A client receiving this should treat it as a noop.
      // (-- But, be wary of b/119886258. --)
      KEY_ACTION_UNSPECIFIED = 0;

      // Keep the key and make it the "active" key.
      ACTIVATE = 1;
      // Keep the key. When enrollment is complete, ensure the key is not
      // "active".
      // (-- But, be wary of b/119886258 and a noop on iOS. --)
      DEACTIVATE = 2;
      // Delete the key.
      DELETE = 3;
    }
    // Key actions with one entry per key handle and in the same order as in the
    // request.
    repeated KeyAction key_actions = 1;

    // The instruction for the client to create a new key.
    enum KeyCreation {
      // Do not create a new key.
      NONE = 0;
      // Create a new key, and then use it as the "active" key.
      ACTIVE = 1;
      // Create a new key, but do not use it as the "active" key.
      // (-- Beware of b/119889101. This doesn't work on Android or iOS. --)
      INACTIVE = 2;
    }
    // Instruction for key creation.
    KeyCreation key_creation = 2;

    // The type of the cryptographic key.
    KeyType key_type = 3;
    // The updated key-specific directives.
    KeyDirective key_directive = 4;
    // A key-specific opaque blob given to the application.
    bytes key_app_directive = 5;

    // The storage level where the key is created and stored.
    enum KeyStorageLevel {
      // Default value. The client is free to decide where to create the key.
      KEY_STORAGE_LEVEL_UNSPECIFIED = 0;

      // The key should be created and stored in software store. E.g. the
      // client may create a key using a crypto library and store it in a
      // file.
      SOFTWARE = 1;

      // The key should be created in a Trusted Execution Environment (TEE).
      // E.g., TrustZone from ARM chips.
      TRUSTED_EXECUTION_ENVIRONMENT = 2;

      // The key should be created in a dedicated hardware that is separate from
      // the main processor. E.g., StrongBox chips in Android devices and Secure
      // Enclave in iOS devices.
      DEDICATED_SECURE_ELEMENT = 3;
    };
    // The storage level to create the key.
    KeyStorageLevel key_storage_level = 6;
    // The newly created key should require hardware backed user presence when
    // using the key.
    bool hardware_user_presence_required = 7;
    // The newly created key should require user verification when using the
    // key.
    bool user_verification_required = 8;
  }
  // Per key sync response.
  repeated SyncSingleKeyResponse sync_single_key_responses = 3;

  // The updated client-specific directives.
  ClientDirective client_directive = 4;
  // A client-specific opaque blob given to the application.
  bytes client_app_directive = 5;

  // The state of the server.
  enum ServerStatus {
    // The server is fine; the rest of SyncKeysResponse should be processed.
    SERVER_OK = 0;
    // The server is overloaded; client_directive should be followed.
    SERVER_OVERLOADED = 1;
  }
  // The status of the server.
  ServerStatus server_status = 6;
}

// The second request in the enrollment protocol. The second request is
// necessary if the client wants to enroll a new key. The request contains the
// information such as the material of the new key, and necessary proofs for
// verifying the key.
message EnrollKeysRequest {
  // The session identifier copied from the SyncKeysResponse message.
  bytes random_session_id = 1;
  // The ephemeral DH public key generated by the client.
  bytes client_ephemeral_dh = 2;

  // The request to enroll a key, e.g., create a new key or rotate an old one.
  message EnrollSingleKeyRequest {
    // The key_name copied from SyncKeysRequest.
    string key_name = 1;
    // The identifier of the new key.
    bytes new_key_handle = 2;
    // The raw bytes of the new public key or custom data.
    bytes key_material = 3;
    // The public-key signature or MAC tag that shows the client indeed
    // possesses the private or secret key.
    bytes key_proof = 4;

    // Cross-signatures or MAC tags by other keys.
    message KeyCrossproof {
      // The key_name of the cross-signing key.
      string other_key_name = 1;
      // The computed cross-signatures or MAC tags.
      bytes other_key_proof = 2;
    }
    // Cross proofs.
    repeated KeyCrossproof key_crossproofs = 5;

    // Subject to certify.
    repeated CertificateRequest certificate_requests = 6;

    // Attestation of the key.
    message KeyAttestation {
      // The type of the key attestation.
      enum KeyAttestationType {
        // Default value.
        KEY_ATTESTATION_TYPE_UNSPECIFIED = 0;

        // Attestation generated by Android KeyStore API.
        // See
        // https://developer.android.com/training/articles/security-key-attestation
        // The payload should be the concatenation of the X.509
        // certificates returned by KeyStore attestation API encoded in ASN.1
        // DER.
        ANDROID_KEYSTORE_ATTESTATION = 1;
      }
      // The attestation type.
      KeyAttestationType type = 1;

      // The payload of the key attestation. The content of the payload is
      // dependent on the attestation type.
      bytes payload = 2;
    }
    // The attestation of the key if the key supports one.
    KeyAttestation key_attestation = 7;
  }
  // Per key enroll data.
  repeated EnrollSingleKeyRequest enroll_single_key_requests = 3;
}

// The response to EnrollKeysRequest. The response can contain a public-key
// certificate for the client to perform offline authentications.
message EnrollKeysResponse {
  // The response corresponding to the EnrollSingleKeyRequest message.
  message EnrollSingleKeyResponse {
    // The server may produce a certificate and send it to the client.
    repeated Certificate certificate = 1;
  }
  // Per key enroll response.
  repeated EnrollSingleKeyResponse enroll_single_key_responses = 1;
}

// Subject to certify.
message CertificateRequest {
  // The type of subject to certify.
  enum CommonNameType {
    // Reserved.
    UNKNOWN_COMMON_NAME_TYPE = 0;
    // Indicates a phone number needs to be signed.
    PHONE_NUMBER = 1;
  }
  // Type of content to be signed.
  CommonNameType type = 1;
  // Raw data of the content.
  bytes data = 2;
  // Bytes used to verify the validation of data.
  bytes token = 3;
  // Additional data used to help verify data. (e.g. audience)
  bytes additional_data = 4;
}

// The key-specific metadata contained in SyncKeysRequest.
message KeyMetadata {}

// This generic rpc is used by MagicShare, BetterTogether and possibly other
// features in the future to obtain enrollment information from the server.
// This method’s behavior shall be based on the key_name which is supplied.
// The client and server shall set and expect specific data in
// request_key_metadata and response_key_metadata, based on the application_name
// and key_name.
message GetMetadataRequest {
  // The unique name of the application
  string application_name = 1;
  // The version of the CryptAuth client library
  string client_version = 2;

  // The request to get key metadata related to a key name.
  message GetSingleKeyMetadataRequest {
    // The purpose/application of the key.
    string key_name = 1;
    // key specific metadata
    bytes request_key_metadata = 2;
  }
  // Per key request
  repeated GetSingleKeyMetadataRequest get_single_key_metadata_request = 3;

  // InvocationReason, retry count, etc. (same as SyncKeys).
  ClientMetadata client_metadata = 4;

  // A client-specific opaque blob provided by the application.
  bytes app_metadata = 5;
}

// The response to GetMetadataRequest. The response contains key metadata based
// on the application name_and key_name in GetMetadataRequest.
message GetMetadataResponse {
  // The response of GetKeyMetadataRequest.
  message GetSingleKeyMetadataResponse {
    // Key specific response metadtata.
    bytes response_key_metadata = 1;
  }

  // A response for every key_metadata_request above.
  repeated GetSingleKeyMetadataResponse get_single_skey_metadata_response = 1;
}
