blob: 351f3b3ef765548b2ea32135e174ef2e691f5fa2 [file] [log] [blame]
// 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.
//
///////////////////////////////////////////////////////////////////////////////
// Implementation of a Keyset Service.
#include "keyset_impl.h"
#include <ostream>
#include <memory>
#include <sstream>
#include <string>
#include <utility>
#include "tink/aead/aead_key_templates.h"
#include "tink/binary_keyset_reader.h"
#include "tink/binary_keyset_writer.h"
#include "tink/cleartext_keyset_handle.h"
#include "tink/daead/deterministic_aead_key_templates.h"
#include "tink/hybrid/hybrid_key_templates.h"
#include "tink/json_keyset_reader.h"
#include "tink/json_keyset_writer.h"
#include "tink/jwt/jwt_key_templates.h"
#include "tink/keyset_handle.h"
#include "tink/mac/mac_key_templates.h"
#include "tink/prf/prf_key_templates.h"
#include "tink/signature/signature_key_templates.h"
#include "tink/streamingaead/streaming_aead_key_templates.h"
#include "proto/tink.pb.h"
namespace tink_testing_api {
using ::crypto::tink::BinaryKeysetReader;
using ::crypto::tink::BinaryKeysetWriter;
using ::crypto::tink::CleartextKeysetHandle;
using ::crypto::tink::JsonKeysetReader;
using ::crypto::tink::JsonKeysetWriter;
using ::crypto::tink::KeysetHandle;
using ::crypto::tink::KeysetReader;
using ::crypto::tink::KeysetWriter;
using ::crypto::tink::util::StatusOr;
using ::google::crypto::tink::KeyTemplate;
KeysetImpl::KeysetImpl() {
key_templates_["AES128_EAX"] = crypto::tink::AeadKeyTemplates::Aes128Eax();
key_templates_["AES256_EAX"] = crypto::tink::AeadKeyTemplates::Aes256Eax();
key_templates_["AES128_GCM"] = crypto::tink::AeadKeyTemplates::Aes128Gcm();
key_templates_["AES128_GCM_RAW"] =
crypto::tink::AeadKeyTemplates::Aes128GcmNoPrefix();
key_templates_["AES256_GCM"] = crypto::tink::AeadKeyTemplates::Aes256Gcm();
key_templates_["AES256_GCM_RAW"] =
crypto::tink::AeadKeyTemplates::Aes256GcmNoPrefix();
key_templates_["AES128_GCM_SIV"] =
crypto::tink::AeadKeyTemplates::Aes128GcmSiv();
key_templates_["AES256_GCM_SIV"] =
crypto::tink::AeadKeyTemplates::Aes256GcmSiv();
key_templates_["AES128_CTR_HMAC_SHA256"] =
crypto::tink::AeadKeyTemplates::Aes128CtrHmacSha256();
key_templates_["AES256_CTR_HMAC_SHA256"] =
crypto::tink::AeadKeyTemplates::Aes256CtrHmacSha256();
key_templates_["CHACHA20_POLY1305"] =
crypto::tink::AeadKeyTemplates::XChaCha20Poly1305();
key_templates_["XCHACHA20_POLY1305"] =
crypto::tink::AeadKeyTemplates::XChaCha20Poly1305();
key_templates_["AES256_SIV"] =
crypto::tink::DeterministicAeadKeyTemplates::Aes256Siv();
key_templates_["AES128_CTR_HMAC_SHA256_4KB"] =
crypto::tink::StreamingAeadKeyTemplates::Aes128CtrHmacSha256Segment4KB();
key_templates_["AES256_CTR_HMAC_SHA256_4KB"] =
crypto::tink::StreamingAeadKeyTemplates::Aes256CtrHmacSha256Segment4KB();
key_templates_["AES128_GCM_HKDF_4KB"] =
crypto::tink::StreamingAeadKeyTemplates::Aes128GcmHkdf4KB();
key_templates_["AES256_GCM_HKDF_4KB"] =
crypto::tink::StreamingAeadKeyTemplates::Aes256GcmHkdf4KB();
key_templates_["AES256_GCM_HKDF_1MB"] =
crypto::tink::StreamingAeadKeyTemplates::Aes256GcmHkdf1MB();
key_templates_["ECIES_P256_HKDF_HMAC_SHA256_AES128_GCM"] =
crypto::tink::HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm();
key_templates_["ECIES_P256_COMPRESSED_HKDF_HMAC_SHA256_AES128_GCM"] = crypto::
tink::HybridKeyTemplates::EciesP256CompressedHkdfHmacSha256Aes128Gcm();
key_templates_["ECIES_P256_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256"] =
crypto::tink::HybridKeyTemplates::
EciesP256HkdfHmacSha256Aes128CtrHmacSha256();
key_templates_
["ECIES_P256_COMPRESSED_HKDF_HMAC_SHA256_AES128_CTR_HMAC_SHA256"] =
crypto::tink::HybridKeyTemplates::
EciesP256CompressedHkdfHmacSha256Aes128CtrHmacSha256();
key_templates_["DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM"] =
crypto::tink::HybridKeyTemplates::HpkeX25519HkdfSha256Aes128Gcm();
key_templates_["DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_128_GCM_RAW"] =
crypto::tink::HybridKeyTemplates::HpkeX25519HkdfSha256Aes128GcmRaw();
key_templates_["DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM"] =
crypto::tink::HybridKeyTemplates::HpkeX25519HkdfSha256Aes256Gcm();
key_templates_["DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_AES_256_GCM_RAW"] =
crypto::tink::HybridKeyTemplates::HpkeX25519HkdfSha256Aes256GcmRaw();
key_templates_["DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305"] =
crypto::tink::HybridKeyTemplates::HpkeX25519HkdfSha256ChaCha20Poly1305();
key_templates_["DHKEM_X25519_HKDF_SHA256_HKDF_SHA256_CHACHA20_POLY1305_RAW"] =
crypto::tink::HybridKeyTemplates::
HpkeX25519HkdfSha256ChaCha20Poly1305Raw();
key_templates_["AES_CMAC"] = crypto::tink::MacKeyTemplates::AesCmac();
key_templates_["HMAC_SHA256_128BITTAG"] =
crypto::tink::MacKeyTemplates::HmacSha256HalfSizeTag();
key_templates_["HMAC_SHA256_256BITTAG"] =
crypto::tink::MacKeyTemplates::HmacSha256();
key_templates_["HMAC_SHA512_256BITTAG"] =
crypto::tink::MacKeyTemplates::HmacSha512HalfSizeTag();
key_templates_["HMAC_SHA512_512BITTAG"] =
crypto::tink::MacKeyTemplates::HmacSha512();
key_templates_["ECDSA_P256"] =
crypto::tink::SignatureKeyTemplates::EcdsaP256();
key_templates_["ECDSA_P256_RAW"] =
crypto::tink::SignatureKeyTemplates::EcdsaP256Raw();
key_templates_["ECDSA_P384"] =
crypto::tink::SignatureKeyTemplates::EcdsaP384();
key_templates_["ECDSA_P384_SHA384"] =
crypto::tink::SignatureKeyTemplates::EcdsaP384Sha384();
key_templates_["ECDSA_P384_SHA512"] =
crypto::tink::SignatureKeyTemplates::EcdsaP384Sha512();
key_templates_["ECDSA_P521"] =
crypto::tink::SignatureKeyTemplates::EcdsaP521();
key_templates_["ECDSA_P256_IEEE_P1363"] =
crypto::tink::SignatureKeyTemplates::EcdsaP256Ieee();
key_templates_["ECDSA_P384_IEEE_P1363"] =
crypto::tink::SignatureKeyTemplates::EcdsaP384Ieee();
key_templates_["ECDSA_P521_IEEE_P1363"] =
crypto::tink::SignatureKeyTemplates::EcdsaP521Ieee();
key_templates_["ED25519"] = crypto::tink::SignatureKeyTemplates::Ed25519();
key_templates_["RSA_SSA_PKCS1_3072_SHA256_F4"] =
crypto::tink::SignatureKeyTemplates::RsaSsaPkcs13072Sha256F4();
key_templates_["RSA_SSA_PKCS1_4096_SHA512_F4"] =
crypto::tink::SignatureKeyTemplates::RsaSsaPkcs14096Sha512F4();
key_templates_["RSA_SSA_PSS_3072_SHA256_SHA256_32_F4"] =
crypto::tink::SignatureKeyTemplates::RsaSsaPss3072Sha256Sha256F4();
key_templates_["RSA_SSA_PSS_4096_SHA512_SHA512_64_F4"] =
crypto::tink::SignatureKeyTemplates::RsaSsaPss4096Sha512Sha512F4();
key_templates_["AES_CMAC_PRF"] = crypto::tink::PrfKeyTemplates::AesCmac();
key_templates_["HMAC_SHA256_PRF"] =
crypto::tink::PrfKeyTemplates::HmacSha256();
key_templates_["HMAC_SHA512_PRF"] =
crypto::tink::PrfKeyTemplates::HmacSha512();
key_templates_["HKDF_SHA256"] = crypto::tink::PrfKeyTemplates::HkdfSha256();
key_templates_["JWT_HS256"] = crypto::tink::JwtHs256Template();
key_templates_["JWT_HS256_RAW"] = crypto::tink::RawJwtHs256Template();
key_templates_["JWT_HS384"] = crypto::tink::JwtHs384Template();
key_templates_["JWT_HS384_RAW"] = crypto::tink::RawJwtHs384Template();
key_templates_["JWT_HS512"] = crypto::tink::JwtHs512Template();
key_templates_["JWT_HS512_RAW"] = crypto::tink::RawJwtHs512Template();
key_templates_["JWT_ES256"] = crypto::tink::JwtEs256Template();
key_templates_["JWT_ES256_RAW"] = crypto::tink::RawJwtEs256Template();
key_templates_["JWT_ES384"] = crypto::tink::JwtEs384Template();
key_templates_["JWT_ES384_RAW"] = crypto::tink::RawJwtEs384Template();
key_templates_["JWT_ES512"] = crypto::tink::JwtEs512Template();
key_templates_["JWT_ES512_RAW"] = crypto::tink::RawJwtEs512Template();
key_templates_["JWT_RS256_2048_F4"] =
crypto::tink::JwtRs256_2048_F4_Template();
key_templates_["JWT_RS256_2048_F4_RAW"] =
crypto::tink::RawJwtRs256_2048_F4_Template();
key_templates_["JWT_RS256_3072_F4"] =
crypto::tink::JwtRs256_3072_F4_Template();
key_templates_["JWT_RS256_3072_F4_RAW"] =
crypto::tink::RawJwtRs256_3072_F4_Template();
key_templates_["JWT_RS384_3072_F4"] =
crypto::tink::JwtRs384_3072_F4_Template();
key_templates_["JWT_RS384_3072_F4_RAW"] =
crypto::tink::RawJwtRs384_3072_F4_Template();
key_templates_["JWT_RS512_4096_F4"] =
crypto::tink::JwtRs512_4096_F4_Template();
key_templates_["JWT_RS512_4096_F4_RAW"] =
crypto::tink::RawJwtRs512_4096_F4_Template();
key_templates_["JWT_PS256_2048_F4"] =
crypto::tink::JwtPs256_2048_F4_Template();
key_templates_["JWT_PS256_2048_F4_RAW"] =
crypto::tink::RawJwtPs256_2048_F4_Template();
key_templates_["JWT_PS256_3072_F4"] =
crypto::tink::JwtPs256_3072_F4_Template();
key_templates_["JWT_PS256_3072_F4_RAW"] =
crypto::tink::RawJwtPs256_3072_F4_Template();
key_templates_["JWT_PS384_3072_F4"] =
crypto::tink::JwtPs384_3072_F4_Template();
key_templates_["JWT_PS384_3072_F4_RAW"] =
crypto::tink::RawJwtPs384_3072_F4_Template();
key_templates_["JWT_PS512_4096_F4"] =
crypto::tink::JwtPs512_4096_F4_Template();
key_templates_["JWT_PS512_4096_F4_RAW"] =
crypto::tink::RawJwtPs512_4096_F4_Template();
}
// Returns the key template for the given template name.
grpc::Status KeysetImpl::GetTemplate(grpc::ServerContext* context,
const KeysetTemplateRequest* request,
KeysetTemplateResponse* response) {
auto it = key_templates_.find(request->template_name());
if (it == key_templates_.end()) {
response->set_err(
absl::StrCat("key template not found: ", request->template_name()));
return grpc::Status::OK;
}
std::string templ;
if (!it->second.SerializeToString(&templ)) {
response->set_err("Failed to serialize template.");
return grpc::Status::OK;
}
response->set_key_template(templ);
return grpc::Status::OK;
}
// Generates a new keyset with one key from a template.
grpc::Status KeysetImpl::Generate(grpc::ServerContext* context,
const KeysetGenerateRequest* request,
KeysetGenerateResponse* response) {
KeyTemplate key_template;
if (!key_template.ParseFromString(request->template_())) {
response->set_err("Could not parse the key template");
return grpc::Status::OK;
}
auto handle_result = KeysetHandle::GenerateNew(key_template);
if (!handle_result.ok()) {
response->set_err(std::string(handle_result.status().message()));
return grpc::Status::OK;
}
std::stringbuf keyset;
auto writer_result =
BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&keyset));
if (!writer_result.ok()) {
response->set_err(std::string(writer_result.status().message()));
return grpc::Status::OK;
}
auto status = CleartextKeysetHandle::Write(writer_result.value().get(),
*handle_result.value());
if (!status.ok()) {
response->set_err(std::string(status.message()));
return grpc::Status::OK;
}
response->set_keyset(keyset.str());
return grpc::Status::OK;
}
// Returns a public keyset for a given private keyset.
grpc::Status KeysetImpl::Public(grpc::ServerContext* context,
const KeysetPublicRequest* request,
KeysetPublicResponse* response) {
auto reader_result = BinaryKeysetReader::New(request->private_keyset());
if (!reader_result.ok()) {
response->set_err(std::string(reader_result.status().message()));
return grpc::Status::OK;
}
auto private_handle_result =
CleartextKeysetHandle::Read(std::move(reader_result.value()));
if (!private_handle_result.ok()) {
response->set_err(std::string(private_handle_result.status().message()));
return grpc::Status::OK;
}
auto public_handle_result =
private_handle_result.value()->GetPublicKeysetHandle();
if (!public_handle_result.ok()) {
response->set_err(std::string(public_handle_result.status().message()));
return grpc::Status::OK;
}
std::stringbuf public_keyset;
auto writer_result =
BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&public_keyset));
if (!writer_result.ok()) {
response->set_err(std::string(writer_result.status().message()));
return grpc::Status::OK;
}
auto status = CleartextKeysetHandle::Write(writer_result.value().get(),
*public_handle_result.value());
if (!status.ok()) {
response->set_err(std::string(status.message()));
return grpc::Status::OK;
}
response->set_public_keyset(public_keyset.str());
return grpc::Status::OK;
}
// Converts a keyset from binary to JSON format.
grpc::Status KeysetImpl::ToJson(grpc::ServerContext* context,
const KeysetToJsonRequest* request,
KeysetToJsonResponse* response) {
auto reader_result = BinaryKeysetReader::New(request->keyset());
if (!reader_result.ok()) {
response->set_err(std::string(reader_result.status().message()));
return grpc::Status::OK;
}
auto handle_result =
CleartextKeysetHandle::Read(std::move(reader_result.value()));
if (!handle_result.ok()) {
response->set_err(std::string(handle_result.status().message()));
return grpc::Status::OK;
}
std::stringbuf json_keyset;
auto writer_result =
JsonKeysetWriter::New(absl::make_unique<std::ostream>(&json_keyset));
if (!writer_result.ok()) {
response->set_err(std::string(writer_result.status().message()));
return grpc::Status::OK;
}
auto status = CleartextKeysetHandle::Write(writer_result.value().get(),
*handle_result.value());
if (!status.ok()) {
response->set_err(std::string(status.message()));
return grpc::Status::OK;
}
response->set_json_keyset(json_keyset.str());
return grpc::Status::OK;
}
// Converts a keyset from JSON to binary format.
grpc::Status KeysetImpl::FromJson(grpc::ServerContext* context,
const KeysetFromJsonRequest* request,
KeysetFromJsonResponse* response) {
auto reader_result = JsonKeysetReader::New(request->json_keyset());
if (!reader_result.ok()) {
response->set_err(std::string(reader_result.status().message()));
return grpc::Status::OK;
}
auto handle_result =
CleartextKeysetHandle::Read(std::move(reader_result.value()));
if (!handle_result.ok()) {
response->set_err(std::string(handle_result.status().message()));
return grpc::Status::OK;
}
std::stringbuf keyset;
auto writer_result =
BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&keyset));
if (!writer_result.ok()) {
response->set_err(std::string(writer_result.status().message()));
return grpc::Status::OK;
}
auto status = CleartextKeysetHandle::Write(writer_result.value().get(),
*handle_result.value());
if (!status.ok()) {
response->set_err(std::string(status.message()));
return grpc::Status::OK;
}
response->set_keyset(keyset.str());
return grpc::Status::OK;
}
grpc::Status KeysetImpl::WriteEncrypted(
grpc::ServerContext* context, const KeysetWriteEncryptedRequest* request,
KeysetWriteEncryptedResponse* response) {
StatusOr<std::unique_ptr<KeysetReader>>
master_keyset_reader = BinaryKeysetReader::New(request->master_keyset());
if (!master_keyset_reader.ok()) {
response->set_err(std::string(master_keyset_reader.status().message()));
return grpc::Status::OK;
}
StatusOr<std::unique_ptr<KeysetHandle>> master_keyset_handle =
CleartextKeysetHandle::Read(*std::move(master_keyset_reader));
if (!master_keyset_handle.ok()) {
response->set_err(std::string(master_keyset_handle.status().message()));
return grpc::Status::OK;
}
StatusOr<std::unique_ptr<crypto::tink::Aead>> master_aead =
(*master_keyset_handle)->GetPrimitive<crypto::tink::Aead>();
if (!master_aead.ok()) {
response->set_err(std::string(master_aead.status().message()));
return grpc::Status::OK;
}
StatusOr<std::unique_ptr<KeysetReader>> keyset_reader =
BinaryKeysetReader::New(request->keyset());
if (!keyset_reader.ok()) {
response->set_err(std::string(keyset_reader.status().message()));
return grpc::Status::OK;
}
StatusOr<std::unique_ptr<KeysetHandle>> keyset_handle =
CleartextKeysetHandle::Read(*std::move(keyset_reader));
if (!keyset_handle.ok()) {
response->set_err(std::string(keyset_handle.status().message()));
return grpc::Status::OK;
}
std::stringbuf encrypted_keyset;
std::unique_ptr<KeysetWriter> keyset_writer;
if (request->keyset_writer_type() == KEYSET_WRITER_BINARY) {
StatusOr<std::unique_ptr<BinaryKeysetWriter>> binary_keyset_writer =
BinaryKeysetWriter::New(
absl::make_unique<std::ostream>(&encrypted_keyset));
if (!binary_keyset_writer.ok()) {
response->set_err(std::string(binary_keyset_writer.status().message()));
return grpc::Status::OK;
}
keyset_writer = *std::move(binary_keyset_writer);
} else if (request->keyset_writer_type() == KEYSET_WRITER_JSON) {
StatusOr<std::unique_ptr<JsonKeysetWriter>> json_keyset_writer =
JsonKeysetWriter::New(
absl::make_unique<std::ostream>(&encrypted_keyset));
if (!json_keyset_writer.ok()) {
response->set_err(std::string(json_keyset_writer.status().message()));
return grpc::Status::OK;
}
keyset_writer = *std::move(json_keyset_writer);
} else {
return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
"unknown keyset_writer_type");
}
if (request->has_associated_data()) {
crypto::tink::util::Status status =
(*keyset_handle)
->WriteWithAssociatedData(keyset_writer.get(), **master_aead,
request->associated_data().value());
if (!status.ok()) {
response->set_err(std::string(status.message()));
return grpc::Status::OK;
}
} else {
crypto::tink::util::Status status =
(*keyset_handle)->Write(keyset_writer.get(), **master_aead);
if (!status.ok()) {
response->set_err(std::string(status.message()));
return grpc::Status::OK;
}
}
response->set_encrypted_keyset(encrypted_keyset.str());
return grpc::Status::OK;
}
grpc::Status KeysetImpl::ReadEncrypted(
grpc::ServerContext* context, const KeysetReadEncryptedRequest* request,
KeysetReadEncryptedResponse* response) {
StatusOr<std::unique_ptr<KeysetReader>> master_keyset_reader =
BinaryKeysetReader::New(request->master_keyset());
if (!master_keyset_reader.ok()) {
response->set_err(std::string(master_keyset_reader.status().message()));
return grpc::Status::OK;
}
StatusOr<std::unique_ptr<KeysetHandle>> master_keyset_handle =
CleartextKeysetHandle::Read(*std::move(master_keyset_reader));
if (!master_keyset_handle.ok()) {
response->set_err(std::string(master_keyset_handle.status().message()));
return grpc::Status::OK;
}
StatusOr<std::unique_ptr<crypto::tink::Aead>> master_aead =
(*master_keyset_handle)->GetPrimitive<crypto::tink::Aead>();
if (!master_aead.ok()) {
response->set_err(std::string(master_aead.status().message()));
return grpc::Status::OK;
}
std::unique_ptr<KeysetReader> keyset_reader;
if (request->keyset_reader_type() == KEYSET_READER_BINARY) {
StatusOr<std::unique_ptr<KeysetReader>> binary_keyset_reader =
BinaryKeysetReader::New(request->encrypted_keyset());
if (!binary_keyset_reader.ok()) {
response->set_err(std::string(binary_keyset_reader.status().message()));
return grpc::Status::OK;
}
keyset_reader = *std::move(binary_keyset_reader);
} else if (request->keyset_reader_type() == KEYSET_READER_JSON) {
StatusOr<std::unique_ptr<KeysetReader>> json_keyset_reader =
JsonKeysetReader::New(request->encrypted_keyset());
if (!json_keyset_reader.ok()) {
response->set_err(std::string(json_keyset_reader.status().message()));
return grpc::Status::OK;
}
keyset_reader = *std::move(json_keyset_reader);
} else {
return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
"unknown keyset_writer_type");
}
std::unique_ptr<KeysetHandle> keyset_handle;
if (request->has_associated_data()) {
StatusOr<std::unique_ptr<KeysetHandle>> read_result =
KeysetHandle::ReadWithAssociatedData(
std::move(keyset_reader), **master_aead,
request->associated_data().value());
if (!read_result.ok()) {
response->set_err(std::string(read_result.status().message()));
return grpc::Status::OK;
}
keyset_handle = *std::move(read_result);
} else {
StatusOr<std::unique_ptr<KeysetHandle>> read_result =
KeysetHandle::Read(std::move(keyset_reader), **master_aead);
if (!read_result.ok()) {
response->set_err(std::string(read_result.status().message()));
return grpc::Status::OK;
}
keyset_handle = *std::move(read_result);
}
std::stringbuf keyset;
StatusOr<std::unique_ptr<BinaryKeysetWriter>> keyset_writer =
BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&keyset));
if (!keyset_writer.ok()) {
response->set_err(std::string(keyset_writer.status().message()));
return grpc::Status::OK;
}
crypto::tink::util::Status status =
CleartextKeysetHandle::Write(keyset_writer->get(), *keyset_handle);
if (!status.ok()) {
response->set_err(std::string(status.message()));
return grpc::Status::OK;
}
response->set_keyset(keyset.str());
return grpc::Status::OK;
}
} // namespace tink_testing_api