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

option java_package = "com.google.crypto.tink.proto.testing";
option java_multiple_files = true;

// 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 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) {}
}

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

// Service for AEAD encryption and decryption
service Aead {
  // Encrypts a plaintext with the provided keyset
  rpc Encrypt(AeadEncryptRequest) returns (AeadEncryptResponse) {}
  // Decrypts a ciphertext with the provided keyset
  rpc Decrypt(AeadDecryptRequest) returns (AeadDecryptResponse) {}
}

message AeadEncryptRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
  bytes plaintext = 2;
  bytes associated_data = 3;
}

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

message AeadDecryptRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
  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 {
  // Encrypts a plaintext with the provided keyset
  rpc EncryptDeterministically(DeterministicAeadEncryptRequest)
      returns (DeterministicAeadEncryptResponse) {}
  // Decrypts a ciphertext with the provided keyset
  rpc DecryptDeterministically(DeterministicAeadDecryptRequest)
      returns (DeterministicAeadDecryptResponse) {}
}

message DeterministicAeadEncryptRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
  bytes plaintext = 2;
  bytes associated_data = 3;
}

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

message DeterministicAeadDecryptRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
  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 {
  // Encrypts a plaintext with the provided keyset
  rpc Encrypt(StreamingAeadEncryptRequest)
      returns (StreamingAeadEncryptResponse) {}
  // Decrypts a ciphertext with the provided keyset
  rpc Decrypt(StreamingAeadDecryptRequest)
      returns (StreamingAeadDecryptResponse) {}
}

message StreamingAeadEncryptRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
  bytes plaintext = 2;
  bytes associated_data = 3;
}

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

message StreamingAeadDecryptRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
  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 {
  // Computes a MAC for given data
  rpc ComputeMac(ComputeMacRequest) returns (ComputeMacResponse) {}
  // Verifies the validity of the MAC value, no error means success
  rpc VerifyMac(VerifyMacRequest) returns (VerifyMacResponse) {}
}

message ComputeMacRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
  bytes data = 2;
}

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

message VerifyMacRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
  bytes mac_value = 2;
  bytes data = 3;
}

message VerifyMacResponse {
  string err = 1;
}

// Service to hybrid encrypt and decrypt
service Hybrid {
  // Encrypts plaintext binding context_info to the resulting ciphertext
  rpc Encrypt(HybridEncryptRequest) returns (HybridEncryptResponse) {}
  // Decrypts ciphertext verifying the integrity of context_info
  rpc Decrypt(HybridDecryptRequest) returns (HybridDecryptResponse) {}
}

message HybridEncryptRequest {
  bytes public_keyset = 1;  // serialized google.crypto.tink.Keyset.
  bytes plaintext = 2;
  bytes context_info = 3;
}

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

message HybridDecryptRequest {
  bytes private_keyset = 1;  // serialized google.crypto.tink.Keyset.
  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 {
  // Computes the signature for data
  rpc Sign(SignatureSignRequest) returns (SignatureSignResponse) {}
  // Verifies that signature is a digital signature for data
  rpc Verify(SignatureVerifyRequest) returns (SignatureVerifyResponse) {}
}

message SignatureSignRequest {
  bytes private_keyset = 1;  // serialized google.crypto.tink.Keyset.
  bytes data = 2;
}

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

message SignatureVerifyRequest {
  bytes public_keyset = 1;  // serialized google.crypto.tink.Keyset.
  bytes signature = 2;
  bytes data = 3;
}

message SignatureVerifyResponse {
  string err = 1;
}

// Service for PrfSet computation
service PrfSet {
  // Returns the key ids and the primary key id in the keyset.
  rpc KeyIds(PrfSetKeyIdsRequest) returns (PrfSetKeyIdsResponse) {}
  // Computes the output of the PRF with the given key_id in the PrfSet.
  rpc Compute(PrfSetComputeRequest) returns (PrfSetComputeResponse) {}
}

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

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

message PrfSetComputeRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset.
  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 {
  // 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) {}
}

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

// TODO(b/179867503): Remove these copies of Timestamp, Duration and StringValue

// Copied from timestamp.proto
message Timestamp {
  // Represents seconds of UTC time since Unix epoch
  // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
  // 9999-12-31T23:59:59Z inclusive.
  int64 seconds = 1;

  // Non-negative fractions of a second at nanosecond resolution. Negative
  // second values with fractions must still have non-negative nanos values
  // that count forward in time. Must be from 0 to 999,999,999
  // inclusive.
  int32 nanos = 2;
}

// Copied from duration.proto
message Duration {
  // Signed seconds of the span of time. Must be from -315,576,000,000
  // to +315,576,000,000 inclusive. Note: these bounds are computed from:
  // 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
  int64 seconds = 1;

  // Signed fractions of a second at nanosecond resolution of the span
  // of time. Durations less than one second are represented with a 0
  // `seconds` field and a positive or negative `nanos` field. For durations
  // of one second or more, a non-zero value for the `nanos` field must be
  // of the same sign as the `seconds` field. Must be from -999,999,999
  // to +999,999,999 inclusive.
  int32 nanos = 2;
}

// Copied from wrappers.proto
message StringValue {
  // The string value.
  string value = 1;
}

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 {
  StringValue issuer = 1;
  StringValue subject = 2;
  repeated string audiences = 3;
  StringValue jwt_id = 4;
  Timestamp expiration = 5;
  Timestamp not_before = 6;
  Timestamp issued_at = 7;
  map<string, JwtClaimValue> custom_claims = 8;
}

message JwtValidator {
  StringValue issuer = 1;
  StringValue subject = 2;
  StringValue audience = 3;
  Timestamp now = 5;
  Duration clock_skew = 6;
}

message JwtSignRequest {
  bytes keyset = 1;  // serialized google.crypto.tink.Keyset
  JwtToken raw_jwt = 2;
}

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

message JwtVerifyRequest {
  bytes keyset = 1;    // serialized google.crypto.tink.Keyset
  string signed_compact_jwt = 2;
  JwtValidator validator = 3;
}

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

