// Copyright 2020 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 tink_testing_api;

import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";

option java_package = "com.google.crypto.tink.testing.proto";
option java_multiple_files = true;
option go_package = "github.com/google/tink/testing/go/proto/testing_api_go_proto";
// Placeholder for java_stubby_library

// Service providing metadata about the server.
service Metadata {
  // Returns some server information. A test may use this information to verify
  // that it is talking to the right server.
  rpc GetServerInfo(ServerInfoRequest) returns (ServerInfoResponse) {}
}

message ServerInfoRequest {}

message ServerInfoResponse {
  string tink_version = 1;  // For example '1.4'
  string language = 2;      // For example 'cc', 'java', 'go' or 'python'.
}

// Service for Keyset operations.
service Keyset {
  // Generates a key template from a key template name.
  rpc GetTemplate(KeysetTemplateRequest) returns (KeysetTemplateResponse) {}
  // Generates a new keyset from a template.
  rpc Generate(KeysetGenerateRequest) returns (KeysetGenerateResponse) {}
  // Generates a public-key keyset from a private-key keyset.
  rpc Public(KeysetPublicRequest) returns (KeysetPublicResponse) {}
  // Converts a Keyset from Binary to Json Format
  rpc ToJson(KeysetToJsonRequest) returns (KeysetToJsonResponse) {}
  // Converts a Keyset from Json to Binary Format
  rpc FromJson(KeysetFromJsonRequest) returns (KeysetFromJsonResponse) {}
  // Reads an encrypted keyset using KeysetHandle.read() or
  // KeysetHandle.readWithAssociatedData() and the BinaryKeysetReader.
  rpc ReadEncrypted(KeysetReadEncryptedRequest)
      returns (KeysetReadEncryptedResponse) {}
  // Writes an encrypted keyset using KeysetHandle.write() or
  // KeysetHandle.writeWithAssociatedData() and the BinaryKeysetWriter.
  rpc WriteEncrypted(KeysetWriteEncryptedRequest)
      returns (KeysetWriteEncryptedResponse) {}
}

message KeysetTemplateRequest {
  string template_name = 1;  // template name used by Tinkey
}

message KeysetTemplateResponse {
  oneof result {
    bytes key_template = 1;  // serialized google.crypto.tink.KeyTemplate.
    string err = 2;
  }
}

message KeysetGenerateRequest {
  bytes template = 1;  // serialized google.crypto.tink.KeyTemplate.
}

message KeysetGenerateResponse {
  oneof result {
    bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
    string err = 2;
  }
}

message KeysetPublicRequest {
  bytes private_keyset = 1;  // serialized google.crypto.tink.Keyset.
}

message KeysetPublicResponse {
  oneof result {
    bytes public_keyset = 1;  // serialized google.crypto.tink.Keyset.
    string err = 2;
  }
}

message KeysetToJsonRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
}

message KeysetToJsonResponse {
  oneof result {
    string json_keyset = 1;
    string err = 2;
  }
}

message KeysetFromJsonRequest {
  string json_keyset = 1;
}

message KeysetFromJsonResponse {
  oneof result {
    bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
    string err = 2;
  }
}

// Copy of google.protobuf.BytesValue
message BytesValue {
  // The bytes value.
  bytes value = 1;
}

enum KeysetReaderType {
  KEYSET_READER_UNKNOWN = 0;
  KEYSET_READER_BINARY = 1;
  KEYSET_READER_JSON = 2;
}

message KeysetReadEncryptedRequest {
  bytes encrypted_keyset = 1;
  bytes master_keyset = 2;  // serialized google.crypto.tink.Keyset.
  BytesValue associated_data = 3;
  KeysetReaderType keyset_reader_type = 4;
}

message KeysetReadEncryptedResponse {
  oneof result {
    bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
    string err = 2;
  }
}

enum KeysetWriterType {
  KEYSET_WRITER_UNKNOWN = 0;
  KEYSET_WRITER_BINARY = 1;
  KEYSET_WRITER_JSON = 2;
}

message KeysetWriteEncryptedRequest {
  bytes keyset = 1;         // serialized google.crypto.tink.Keyset.
  bytes master_keyset = 2;  // serialized google.crypto.tink.Keyset.
  BytesValue associated_data = 3;
  KeysetWriterType keyset_writer_type = 4;
}

message KeysetWriteEncryptedResponse {
  oneof result {
    bytes encrypted_keyset = 1;
    string err = 2;
  }
}

message AnnotatedKeyset {
  bytes serialized_keyset = 1;  // serialized google.crypto.tink.Keyset.
  map<string, string> annotations = 2;
}

message CreationRequest {
  AnnotatedKeyset annotated_keyset = 1;
}

message CreationResponse {
  // Empty means no error
  string err = 1;
}

// Service for AEAD encryption and decryption
service Aead {
  // Creates an Aead object without using it.
  rpc Create(CreationRequest) returns (CreationResponse) {}
  // Encrypts a plaintext with the provided keyset. The client must call
  // "Create" first to see if creation succeeds before calling this.
  rpc Encrypt(AeadEncryptRequest) returns (AeadEncryptResponse) {}
  // Decrypts a ciphertext with the provided keyset. The client must call
  // "Create" first to see if creation succeeds before calling this.
  rpc Decrypt(AeadDecryptRequest) returns (AeadDecryptResponse) {}
}

message AeadEncryptRequest {
  AnnotatedKeyset annotated_keyset = 1;
  bytes plaintext = 2;
  bytes associated_data = 3;
}

message AeadEncryptResponse {
  oneof result {
    bytes ciphertext = 1;
    string err = 2;
  }
}

message AeadDecryptRequest {
  AnnotatedKeyset annotated_keyset = 1;
  bytes ciphertext = 2;
  bytes associated_data = 3;
}

message AeadDecryptResponse {
  oneof result {
    bytes plaintext = 1;
    string err = 2;
  }
}

// Service for Deterministic AEAD encryption and decryption
service DeterministicAead {
  // Creates a Deterministic AEAD object without using it.
  rpc Create(CreationRequest) returns (CreationResponse) {}
  // Encrypts a plaintext with the provided keyset. The client must call
  // "Create" first to see if creation succeeds before calling
  // this.
  rpc EncryptDeterministically(DeterministicAeadEncryptRequest)
      returns (DeterministicAeadEncryptResponse) {}
  // Decrypts a ciphertext with the provided keyset. The client must call
  // "Create" first to see if creation succeeds before calling
  // this.
  rpc DecryptDeterministically(DeterministicAeadDecryptRequest)
      returns (DeterministicAeadDecryptResponse) {}
}

message DeterministicAeadEncryptRequest {
  AnnotatedKeyset annotated_keyset = 1;
  bytes plaintext = 2;
  bytes associated_data = 3;
}

message DeterministicAeadEncryptResponse {
  oneof result {
    bytes ciphertext = 1;
    string err = 2;
  }
}

message DeterministicAeadDecryptRequest {
  AnnotatedKeyset annotated_keyset = 1;
  bytes ciphertext = 2;
  bytes associated_data = 3;
}

message DeterministicAeadDecryptResponse {
  oneof result {
    bytes plaintext = 1;
    string err = 2;
  }
}

// Service for Streaming AEAD encryption and decryption
service StreamingAead {
  // Creates a StreamingAead object without using it.
  rpc Create(CreationRequest) returns (CreationResponse) {}

  // Encrypts a plaintext with the provided keyset. The client must call
  // "Create" first to see if creation succeeds before calling this.
  rpc Encrypt(StreamingAeadEncryptRequest)
      returns (StreamingAeadEncryptResponse) {}
  // Decrypts a ciphertext with the provided keyset. The client must call
  // "Create" first to see if creation succeeds before calling this.
  rpc Decrypt(StreamingAeadDecryptRequest)
      returns (StreamingAeadDecryptResponse) {}
}

message StreamingAeadEncryptRequest {
  AnnotatedKeyset annotated_keyset = 1;
  bytes plaintext = 2;
  bytes associated_data = 3;
}

message StreamingAeadEncryptResponse {
  oneof result {
    bytes ciphertext = 1;
    string err = 2;
  }
}

message StreamingAeadDecryptRequest {
  AnnotatedKeyset annotated_keyset = 1;
  bytes ciphertext = 2;
  bytes associated_data = 3;
}

message StreamingAeadDecryptResponse {
  oneof result {
    bytes plaintext = 1;
    string err = 2;
  }
}

// Service to compute and verify MACs
service Mac {
  // Creates a Mac object without using it.
  rpc Create(CreationRequest) returns (CreationResponse) {}
  // Computes a MAC for given data. The client must call "Create" first to see
  // if creation succeeds before calling this.
  rpc ComputeMac(ComputeMacRequest) returns (ComputeMacResponse) {}
  // Verifies the validity of the MAC value, no error means success. The client
  // must call "Create" first to see if creation succeeds before calling this.
  rpc VerifyMac(VerifyMacRequest) returns (VerifyMacResponse) {}
}

message ComputeMacRequest {
  AnnotatedKeyset annotated_keyset = 1;
  bytes data = 2;
}

message ComputeMacResponse {
  oneof result {
    bytes mac_value = 1;
    string err = 2;
  }
}

message VerifyMacRequest {
  AnnotatedKeyset annotated_keyset = 1;
  bytes mac_value = 2;
  bytes data = 3;
}

message VerifyMacResponse {
  string err = 1;
}

// Service to hybrid encrypt and decrypt
service Hybrid {
  // Creates a HybridEncrypt object without using it.
  rpc CreateHybridEncrypt(CreationRequest) returns (CreationResponse) {}
  // Creates a HybridDecrypt object without using it.
  rpc CreateHybridDecrypt(CreationRequest) returns (CreationResponse) {}

  // Encrypts plaintext binding context_info to the resulting ciphertext. The
  // client must call "CreateHybridEncrypt" first to see if creation succeeds
  // before calling this.
  rpc Encrypt(HybridEncryptRequest) returns (HybridEncryptResponse) {}
  // Decrypts ciphertext verifying the integrity of context_info. The client
  // must call "CreateHybridDecrypt" first to see if creation succeeds before
  // calling this.
  rpc Decrypt(HybridDecryptRequest) returns (HybridDecryptResponse) {}
}

message HybridEncryptRequest {
  AnnotatedKeyset public_annotated_keyset = 1;
  bytes plaintext = 2;
  bytes context_info = 3;
}

message HybridEncryptResponse {
  oneof result {
    bytes ciphertext = 1;
    string err = 2;
  }
}

message HybridDecryptRequest {
  AnnotatedKeyset private_annotated_keyset = 1;
  bytes ciphertext = 2;
  bytes context_info = 3;
}

message HybridDecryptResponse {
  oneof result {
    bytes plaintext = 1;
    string err = 2;
  }
}

// Service to sign and verify signatures.
service Signature {
  // Creates a PublicKeySign object without using it.
  rpc CreatePublicKeySign(CreationRequest) returns (CreationResponse) {}
  // Creates a PublicKeyVerify object without using it.
  rpc CreatePublicKeyVerify(CreationRequest) returns (CreationResponse) {}

  // Computes the signature for data. The client must call "CreatePublicKeySign"
  // first to see if creation succeeds before calling this.
  rpc Sign(SignatureSignRequest) returns (SignatureSignResponse) {}
  // Verifies that signature is a digital signature for data. The client must
  // call "CreatePublicKeyVerify" first to see if creation succeeds before
  // calling this.
  rpc Verify(SignatureVerifyRequest) returns (SignatureVerifyResponse) {}
}

message SignatureSignRequest {
  AnnotatedKeyset private_annotated_keyset = 1;
  bytes data = 2;
}

message SignatureSignResponse {
  oneof result {
    bytes signature = 1;
    string err = 2;
  }
}

message SignatureVerifyRequest {
  AnnotatedKeyset public_annotated_keyset = 1;
  bytes signature = 2;
  bytes data = 3;
}

message SignatureVerifyResponse {
  string err = 1;
}

// Service for PrfSet computation
service PrfSet {
  // Creates a PrfSet object without using it.
  rpc Create(CreationRequest) returns (CreationResponse) {}

  // Returns the key ids and the primary key id in the keyset.The client must
  // call "Create" first to see if creation succeeds before calling this.
  rpc KeyIds(PrfSetKeyIdsRequest) returns (PrfSetKeyIdsResponse) {}
  // Computes the output of the PRF with the given key_id in the PrfSet.The
  // client must call "Create" first to see if creation succeeds before calling
  // this.
  rpc Compute(PrfSetComputeRequest) returns (PrfSetComputeResponse) {}
}

message PrfSetKeyIdsRequest {
  AnnotatedKeyset annotated_keyset = 1;
}

message PrfSetKeyIdsResponse {
  message Output {
    uint32 primary_key_id = 1;
    repeated uint32 key_id = 2;
  }
  oneof result {
    Output output = 1;
    string err = 2;
  }
}

message PrfSetComputeRequest {
  AnnotatedKeyset annotated_keyset = 1;
  uint32 key_id = 2;
  bytes input_data = 3;
  int32 output_length = 4;
}

message PrfSetComputeResponse {
  oneof result {
    bytes output = 1;
    string err = 2;
  }
}

// Service for JSON Web Tokens (JWT)
service Jwt {
  // Creates a JwtMac object without using it.
  rpc CreateJwtMac(CreationRequest) returns (CreationResponse) {}
  // Creates a JwtPublicKeySign object without using it.
  rpc CreateJwtPublicKeySign(CreationRequest) returns (CreationResponse) {}
  // Creates a JwtPublicKeyVerify object without using it.
  rpc CreateJwtPublicKeyVerify(CreationRequest) returns (CreationResponse) {}

  // Computes a signed compact JWT token.
  rpc ComputeMacAndEncode(JwtSignRequest) returns (JwtSignResponse) {}
  // Verifies the validity of the signed compact JWT token
  rpc VerifyMacAndDecode(JwtVerifyRequest) returns (JwtVerifyResponse) {}
  // Computes a signed compact JWT token.
  rpc PublicKeySignAndEncode(JwtSignRequest) returns (JwtSignResponse) {}
  // Verifies the validity of the signed compact JWT token
  rpc PublicKeyVerifyAndDecode(JwtVerifyRequest) returns (JwtVerifyResponse) {}
  // Converts a Keyset from Tink Binary to JWK Set Format
  rpc ToJwkSet(JwtToJwkSetRequest) returns (JwtToJwkSetResponse) {}
  // Converts a Keyset from JWK Set to Tink Binary Format
  rpc FromJwkSet(JwtFromJwkSetRequest) returns (JwtFromJwkSetResponse) {}
}

//  Used to represent the JSON null value.
enum NullValue {
  NULL_VALUE = 0;
}

message JwtClaimValue {
  oneof kind {
    NullValue null_value = 2;
    double number_value = 3;
    string string_value = 4;
    bool bool_value = 5;
    string json_object_value = 6;
    string json_array_value = 7;
  }
}

message JwtToken {
  google.protobuf.StringValue issuer = 1;
  google.protobuf.StringValue subject = 2;
  repeated string audiences = 3;
  google.protobuf.StringValue jwt_id = 4;
  google.protobuf.Timestamp expiration = 5;
  google.protobuf.Timestamp not_before = 6;
  google.protobuf.Timestamp issued_at = 7;
  map<string, JwtClaimValue> custom_claims = 8;
  google.protobuf.StringValue type_header = 9;
}

message JwtValidator {
  google.protobuf.StringValue expected_type_header = 7;
  google.protobuf.StringValue expected_issuer = 1;
  google.protobuf.StringValue expected_audience = 3;
  bool ignore_type_header = 8;
  bool ignore_issuer = 9;
  bool ignore_audience = 11;
  bool allow_missing_expiration = 12;
  bool expect_issued_in_the_past = 13;
  google.protobuf.Timestamp now = 5;
  google.protobuf.Duration clock_skew = 6;
}

message JwtSignRequest {
  AnnotatedKeyset annotated_keyset = 1;
  JwtToken raw_jwt = 2;
}

message JwtSignResponse {
  oneof result {
    string signed_compact_jwt = 1;
    string err = 2;
  }
}

message JwtVerifyRequest {
  AnnotatedKeyset annotated_keyset = 1;
  string signed_compact_jwt = 2;
  JwtValidator validator = 3;
}

message JwtVerifyResponse {
  oneof result {
    JwtToken verified_jwt = 1;
    string err = 2;
  }
}

message JwtToJwkSetRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
}

message JwtToJwkSetResponse {
  oneof result {
    string jwk_set = 1;
    string err = 2;
  }
}

message JwtFromJwkSetRequest {
  string jwk_set = 1;
}

message JwtFromJwkSetResponse {
  oneof result {
    bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
    string err = 2;
  }
}
