1 // Copyright 2020 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 ////////////////////////////////////////////////////////////////////////////////
16
17 #include "tink/util/fake_kms_client.h"
18
19 #include <cstdlib>
20 #include <string>
21 #include <utility>
22 #include <vector>
23
24 #include "gtest/gtest.h"
25 #include "tink/aead/aead_config.h"
26 #include "tink/aead/aead_key_templates.h"
27 #include "tink/util/status.h"
28 #include "tink/util/statusor.h"
29 #include "tink/util/test_matchers.h"
30 #include "tink/util/test_util.h"
31 #include "proto/kms_aead.pb.h"
32 #include "proto/kms_envelope.pb.h"
33
34 using google::crypto::tink::KeyTemplate;
35 using google::crypto::tink::KmsAeadKeyFormat;
36 using google::crypto::tink::KmsEnvelopeAeadKeyFormat;
37 using google::crypto::tink::OutputPrefixType;
38
39 namespace crypto {
40 namespace tink {
41 namespace test {
42 namespace {
43
44 // TODO(b/174740983) Add this function to aead_key_templates.
NewKmsAeadKeyTemplate(std::string key_uri)45 KeyTemplate NewKmsAeadKeyTemplate(std::string key_uri) {
46 KeyTemplate key_template;
47 key_template.set_type_url(
48 "type.googleapis.com/google.crypto.tink.KmsAeadKey");
49 key_template.set_output_prefix_type(OutputPrefixType::TINK);
50 KmsAeadKeyFormat key_format;
51 key_format.set_key_uri(key_uri);
52 key_format.SerializeToString(key_template.mutable_value());
53 return key_template;
54 }
55
56 // TODO(b/174740983) Add this function to aead_key_templates.
NewKmsEnvelopeKeyTemplate(std::string key_uri,const KeyTemplate & dek_template)57 KeyTemplate NewKmsEnvelopeKeyTemplate(std::string key_uri,
58 const KeyTemplate& dek_template) {
59 KeyTemplate key_template;
60 key_template.set_type_url(
61 "type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey");
62 key_template.set_output_prefix_type(OutputPrefixType::TINK);
63 KmsEnvelopeAeadKeyFormat key_format;
64 key_format.set_kek_uri(key_uri);
65 key_format.mutable_dek_template()->MergeFrom(dek_template);
66 key_format.SerializeToString(key_template.mutable_value());
67 return key_template;
68 }
69
70 class FakeKmsClientTest : public ::testing::Test {
71 protected:
SetUpTestSuite()72 static void SetUpTestSuite() { ASSERT_TRUE(AeadConfig::Register().ok()); }
73 };
74
TEST_F(FakeKmsClientTest,CreateNewAeadSuccess)75 TEST_F(FakeKmsClientTest, CreateNewAeadSuccess) {
76 auto uri_result = FakeKmsClient::CreateFakeKeyUri();
77 EXPECT_TRUE(uri_result.ok()) << uri_result.status();
78 std::string key_uri = uri_result.value();
79
80 auto client_result = FakeKmsClient::New(key_uri, "");
81 EXPECT_TRUE(client_result.ok()) << client_result.status();
82 auto client = std::move(client_result.value());
83 EXPECT_TRUE(client->DoesSupport(key_uri));
84
85 auto aead_result = client->GetAead(key_uri);
86 EXPECT_TRUE(aead_result.ok()) << aead_result.status();
87 auto aead = std::move(aead_result.value());
88
89 std::string plaintext = "some_plaintext";
90 std::string aad = "some_aad";
91 auto encrypt_result = aead->Encrypt(plaintext, aad);
92 EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status();
93 std::string ciphertext = encrypt_result.value();
94 auto decrypt_result = aead->Decrypt(ciphertext, aad);
95 EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status();
96 EXPECT_EQ(plaintext, decrypt_result.value());
97 }
98
TEST_F(FakeKmsClientTest,ClientIsBound)99 TEST_F(FakeKmsClientTest, ClientIsBound) {
100 std::string key_uri =
101 "fake-kms://"
102 "CL3oi0kSVwpMCjB0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5jcnlwdG8udGluay5BZXNF"
103 "YXhLZXkSFhICCBAaEPFnQNgtxEG0vEek8bBfgL8YARABGL3oi0kgAQ";
104 auto client_result = FakeKmsClient::New(key_uri, "");
105 EXPECT_TRUE(client_result.ok()) << client_result.status();
106 auto client = std::move(client_result.value());
107
108 // No other key_uri is accepted, even a valid one.
109 std::string another_key_uri =
110 "fake-kms://"
111 "CO3y2NgHElgKTAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVz"
112 "RWF4S2V5EhYSAggQGhALi4dQMjUR0faRYElRXi__GAEQARjt8tjYByAB";
113 EXPECT_FALSE(client->DoesSupport(another_key_uri));
114 auto aead_result = client->GetAead(another_key_uri);
115 EXPECT_FALSE(aead_result.ok());
116 }
117
TEST_F(FakeKmsClientTest,ClientIsUnbound)118 TEST_F(FakeKmsClientTest, ClientIsUnbound) {
119 auto client_result = FakeKmsClient::New("", "");
120 EXPECT_TRUE(client_result.ok()) << client_result.status();
121 auto client = std::move(client_result.value());
122
123 // All valid 'fake-kms' key_uris are accepted.
124 std::string uri =
125 "fake-kms://"
126 "CL3oi0kSVwpMCjB0eXBlLmdvb2dsZWFwaXMuY29tL2dvb2dsZS5jcnlwdG8udGluay5BZXNF"
127 "YXhLZXkSFhICCBAaEPFnQNgtxEG0vEek8bBfgL8YARABGL3oi0kgAQ";
128 EXPECT_TRUE(client->DoesSupport(uri));
129 auto aead_result = client->GetAead(uri);
130 EXPECT_TRUE(aead_result.ok());
131
132 std::string another_uri =
133 "fake-kms://"
134 "CO3y2NgHElgKTAowdHlwZS5nb29nbGVhcGlzLmNvbS9nb29nbGUuY3J5cHRvLnRpbmsuQWVz"
135 "RWF4S2V5EhYSAggQGhALi4dQMjUR0faRYElRXi__GAEQARjt8tjYByAB";
136 EXPECT_TRUE(client->DoesSupport(another_uri));
137 auto another_aead_result = client->GetAead(another_uri);
138 EXPECT_TRUE(another_aead_result.ok()) << another_aead_result.status();
139 }
140
TEST_F(FakeKmsClientTest,RegisterAndEncryptDecryptWithKmsAead)141 TEST_F(FakeKmsClientTest, RegisterAndEncryptDecryptWithKmsAead) {
142 auto uri_result = FakeKmsClient::CreateFakeKeyUri();
143 EXPECT_TRUE(uri_result.ok()) << uri_result.status();
144 std::string key_uri = uri_result.value();
145 auto status = FakeKmsClient::RegisterNewClient(key_uri, "");
146 EXPECT_THAT(status, IsOk());
147
148 KeyTemplate key_template = NewKmsAeadKeyTemplate(key_uri);
149 auto handle_result = KeysetHandle::GenerateNew(key_template);
150 EXPECT_TRUE(handle_result.ok()) << handle_result.status();
151 auto aead_result = handle_result.value()->GetPrimitive<crypto::tink::Aead>();
152 EXPECT_TRUE(aead_result.ok()) << aead_result.status();
153 auto aead = std::move(aead_result.value());
154
155 std::string plaintext = "some_plaintext";
156 std::string aad = "some_aad";
157 auto encrypt_result = aead->Encrypt(plaintext, aad);
158 EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status();
159 std::string ciphertext = encrypt_result.value();
160 auto decrypt_result = aead->Decrypt(ciphertext, aad);
161 EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status();
162 EXPECT_EQ(plaintext, decrypt_result.value());
163 }
164
TEST_F(FakeKmsClientTest,RegisterAndEncryptDecryptWithKmsEnvelopeAead)165 TEST_F(FakeKmsClientTest, RegisterAndEncryptDecryptWithKmsEnvelopeAead) {
166 auto uri_result = FakeKmsClient::CreateFakeKeyUri();
167 EXPECT_TRUE(uri_result.ok()) << uri_result.status();
168 std::string key_uri = uri_result.value();
169 auto status = FakeKmsClient::RegisterNewClient(key_uri, "");
170 EXPECT_THAT(status, IsOk());
171
172 KeyTemplate key_template =
173 NewKmsEnvelopeKeyTemplate(key_uri, AeadKeyTemplates::Aes128Gcm());
174 auto handle_result = KeysetHandle::GenerateNew(key_template);
175 EXPECT_TRUE(handle_result.ok()) << handle_result.status();
176 auto aead_result = handle_result.value()->GetPrimitive<crypto::tink::Aead>();
177 EXPECT_TRUE(aead_result.ok()) << aead_result.status();
178 auto aead = std::move(aead_result.value());
179
180 std::string plaintext = "some_plaintext";
181 std::string aad = "some_aad";
182 auto encrypt_result = aead->Encrypt(plaintext, aad);
183 EXPECT_TRUE(encrypt_result.ok()) << encrypt_result.status();
184 std::string ciphertext = encrypt_result.value();
185 auto decrypt_result = aead->Decrypt(ciphertext, aad);
186 EXPECT_TRUE(decrypt_result.ok()) << decrypt_result.status();
187 EXPECT_EQ(plaintext, decrypt_result.value());
188 }
189
190 // TODO(b/174740983): Add test where an unbounded KeyClient is registered.
191 // This is not yet implemented as it would break the isolation of the tests:
192 // Once a unbounded client is registered, it can't currently be unregistered.
193
194 } // namespace
195 } // namespace test
196 } // namespace tink
197 } // namespace crypto
198