// Copyright 2017 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.
//
////////////////////////////////////////////////////////////////////////////////

// Tink Proto Keyset serialization format.
syntax = "proto3";

package google.crypto.tink;

option java_package = "com.google.crypto.tink.proto";
option java_multiple_files = true;
option go_package = "github.com/tink-crypto/tink-go/v2/proto/tink_go_proto";
option objc_class_prefix = "TINKPB";

// Each instantiation of a Tink primitive is identified by type_url,
// which is a global URL pointing to a *Key-proto that holds key material
// and other parameters of the instantiation.  For standard Tink key types
// the value of type_url follows the structure of type_url-field of
// google.protobuf.Any-protos, and is given as:
//
//   type.googleapis.com/packagename.messagename
//
// For example, for an HMAC key defined in proto google.crypto.tink.HmacKey
// the value of type_url is:
//
//   type.googleapis.com/google.crypto.tink.HmacKey
//
// For each type_url, in addition to the *Key proto, there exist two
// related structures:
//   1. *Params: parameters of an instantiation of the primitive,
//      needed when a key is being used.
//   2. *KeyFormat: parameters needed to generate a new key; these
//      include the corresponding Params, since when a factory generates
//      a key based on KeyFormat, it must add Params to the resulting
//      key proto with the actual key material.
// The actual *KeyFormat proto is wrapped in a KeyTemplate message.
// By convention, the name of the *KeyFormat-proto must be equal
// to the name of the *Key-proto from type_url-field suffixed with "Format".

message KeyTemplate {
  // Required. The type_url of the key type in format
  // type.googleapis.com/packagename.messagename -- see above for details.
  // This is typically the protobuf type URL of the *Key proto. In particular,
  // this is different of the protobuf type URL of the *KeyFormat proto.
  string type_url = 1;

  // Required. The serialized *KeyFormat proto.
  bytes value = 2;

  // Required. The type of prefix used when computing some primitives to
  // identify the ciphertext/signature, etc.
  OutputPrefixType output_prefix_type = 3;
}

enum KeyStatusType {
  UNKNOWN_STATUS = 0;
  ENABLED = 1;    // Can be used for crypto operations.
  DISABLED = 2;   // Cannot be used, but exists and can become ENABLED.
  DESTROYED = 3;  // Key data does not exist in this Keyset any more.
}

// Tink produces and accepts ciphertexts or signatures that consist
// of a prefix and a payload. The payload and its format is determined
// entirely by the primitive, but the prefix has to be one of the following
// 5 types:
//   - Legacy: prefix is 5 bytes, starts with \x00 and followed by a 4-byte
//             key id that is computed from the key material. In addition to
//             that, signature schemes and MACs will add a \x00 byte to the
//             end of the data being signed / MACed when operating on keys
//             with this OutputPrefixType.
//   - Crunchy: prefix is 5 bytes, starts with \x00 and followed by a 4-byte
//             key id that is generated randomly.
//   - Tink  : prefix is 5 bytes, starts with \x01 and followed by 4-byte
//             key id that is generated randomly.
//   - Raw   : prefix is 0 byte, i.e., empty.
//   - WITH_ID_REQUIREMENT: prefix size may vary i.e., empty, 1 byte etc, but
//                         the key is always required to have an ID. This is
//                         used for example for pre-hashing, where the ID is
//                         used to sync with a remote pre-hash signer, but no
//                         prefix is added to the signature.
enum OutputPrefixType {
  UNKNOWN_PREFIX = 0;
  TINK = 1;
  LEGACY = 2;
  RAW = 3;
  CRUNCHY = 4;
  WITH_ID_REQUIREMENT = 5;
}

// Each *Key proto by convention contains a version field, which
// identifies the version of the key.
//   message SomeInstantiationKey {
//     uint32 version = 1;
//     ...
//   }
// If a key type does not mention anything else, only version 0 is currently
// specified. An implementation must only accept keys with versions it knows,
// and must reject all keys with unknown version.

// For public key primitives, the public and private keys are distinct entities
// and represent distinct primitives.  However, by convention, the private key
// of a public-key primitive contains the corresponding public key proto.

// The actual *Key-proto is wrapped in a KeyData message, which in addition
// to this serialized proto contains also type_url identifying the
// definition of *Key-proto (as in KeyFormat-message), and some extra metadata
// about the type key material.
message KeyData {
  // Required.
  string type_url = 1;  // In format type.googleapis.com/packagename.messagename
  // Required.
  // Contains specific serialized *Key proto
  bytes value = 2;  // Placeholder for ctype and debug_redact.
  enum KeyMaterialType {
    UNKNOWN_KEYMATERIAL = 0;
    SYMMETRIC = 1;
    ASYMMETRIC_PRIVATE = 2;
    ASYMMETRIC_PUBLIC = 3;
    REMOTE = 4;  // points to a remote key, i.e., in a KMS.
  }
  // Required.
  KeyMaterialType key_material_type = 3;
}

// A Tink user works usually not with single keys, but with keysets,
// to enable key rotation.  The keys in a keyset can belong to different
// implementations/key types, but must all implement the same primitive.
// Any given keyset (and any given key) can be used for one primitive only.
message Keyset {
  message Key {
    // Contains the actual, instantiation specific key proto.
    // By convention, each key proto contains a version field.
    KeyData key_data = 1;

    KeyStatusType status = 2;

    // Identifies a key within a keyset, is a part of metadata
    // of a ciphertext/signature.
    uint32 key_id = 3;

    // Determines the prefix of the ciphertexts/signatures produced by this key.
    // This value is copied verbatim from the key template.
    OutputPrefixType output_prefix_type = 4;
  }

  // Identifies key used to generate new crypto data (encrypt, sign).
  // Required.
  uint32 primary_key_id = 1;

  // Actual keys in the Keyset.
  // Required.
  repeated Key key = 2;
}

// Represents a "safe" Keyset that doesn't contain any actual key material,
// thus can be used for logging or monitoring. Most fields are copied from
// Keyset.
message KeysetInfo {
  message KeyInfo {
    // the type url of this key,
    // e.g., type.googleapis.com/google.crypto.tink.HmacKey.
    string type_url = 1;

    // See Keyset.Key.status.
    KeyStatusType status = 2;

    // See Keyset.Key.key_id.
    uint32 key_id = 3;

    // See Keyset.Key.output_prefix_type.
    OutputPrefixType output_prefix_type = 4;
  }

  // See Keyset.primary_key_id.
  uint32 primary_key_id = 1;

  // KeyInfos in the KeysetInfo.
  // Each KeyInfo is corresponding to a Key in the corresponding Keyset.
  repeated KeyInfo key_info = 2;
}

// Represents a keyset that is encrypted with a master key.
message EncryptedKeyset {
  // Required.
  bytes encrypted_keyset = 2;
  // Optional.
  KeysetInfo keyset_info = 3;
}
