1 // Copyright 2019 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/aead/kms_envelope_aead_key_manager.h"
18
19 #include <stdlib.h>
20
21 #include <memory>
22 #include <string>
23
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "absl/memory/memory.h"
27 #include "absl/status/status.h"
28 #include "tink/aead.h"
29 #include "tink/aead/aead_config.h"
30 #include "tink/aead/aead_key_templates.h"
31 #include "tink/aead/aes_eax_key_manager.h"
32 #include "tink/aead/kms_envelope_aead.h"
33 #include "tink/kms_client.h"
34 #include "tink/kms_clients.h"
35 #include "tink/mac/mac_key_templates.h"
36 #include "tink/registry.h"
37 #include "tink/subtle/aead_test_util.h"
38 #include "tink/util/fake_kms_client.h"
39 #include "tink/util/status.h"
40 #include "tink/util/statusor.h"
41 #include "tink/util/test_matchers.h"
42 #include "tink/util/test_util.h"
43 #include "proto/kms_envelope.pb.h"
44 #include "proto/tink.pb.h"
45
46 namespace crypto {
47 namespace tink {
48
49 using ::crypto::tink::test::DummyAead;
50 using ::crypto::tink::test::DummyKmsClient;
51 using ::crypto::tink::test::IsOk;
52 using ::crypto::tink::test::IsOkAndHolds;
53 using ::crypto::tink::test::StatusIs;
54 using ::google::crypto::tink::KeyTemplate;
55 using ::google::crypto::tink::KmsEnvelopeAeadKey;
56 using ::google::crypto::tink::KmsEnvelopeAeadKeyFormat;
57 using ::testing::Eq;
58 using ::testing::Not;
59
60 namespace {
61
TEST(KmsEnvelopeAeadKeyManagerTest,Basics)62 TEST(KmsEnvelopeAeadKeyManagerTest, Basics) {
63 EXPECT_THAT(KmsEnvelopeAeadKeyManager().get_version(), Eq(0));
64 EXPECT_THAT(KmsEnvelopeAeadKeyManager().get_key_type(),
65 Eq("type.googleapis.com/google.crypto.tink.KmsEnvelopeAeadKey"));
66 EXPECT_THAT(KmsEnvelopeAeadKeyManager().key_material_type(),
67 Eq(google::crypto::tink::KeyData::REMOTE));
68 }
69
TEST(KmsEnvelopeAeadKeyManagerTest,ValidateEmptyKey)70 TEST(KmsEnvelopeAeadKeyManagerTest, ValidateEmptyKey) {
71 EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKey(KmsEnvelopeAeadKey()),
72 StatusIs(absl::StatusCode::kInvalidArgument));
73 }
74
TEST(KmsEnvelopeAeadKeyManagerTest,ValidateValidKey)75 TEST(KmsEnvelopeAeadKeyManagerTest, ValidateValidKey) {
76 KmsEnvelopeAeadKey key;
77 key.set_version(0);
78 key.mutable_params()->set_kek_uri("Some uri");
79 *(key.mutable_params()->mutable_dek_template()) =
80 AeadKeyTemplates::Aes128Eax();
81
82 EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKey(key), IsOk());
83 }
84
TEST(KmsEnvelopeAeadKeyManagerTest,ValidateWrongVersion)85 TEST(KmsEnvelopeAeadKeyManagerTest, ValidateWrongVersion) {
86 KmsEnvelopeAeadKey key;
87 key.set_version(1);
88 key.mutable_params()->set_kek_uri("Some uri");
89 *(key.mutable_params()->mutable_dek_template()) =
90 AeadKeyTemplates::Aes128Eax();
91 EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKey(key), Not(IsOk()));
92 }
93
TEST(KmsEnvelopeAeadKeyManagerTest,ValidateNoUri)94 TEST(KmsEnvelopeAeadKeyManagerTest, ValidateNoUri) {
95 KmsEnvelopeAeadKey key;
96 key.set_version(1);
97 *(key.mutable_params()->mutable_dek_template()) =
98 AeadKeyTemplates::Aes128Eax();
99 EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKey(key), Not(IsOk()));
100 }
101
TEST(KmsEnvelopeAeadKeyManagerTest,ValidateKeyFormatEmptyKey)102 TEST(KmsEnvelopeAeadKeyManagerTest, ValidateKeyFormatEmptyKey) {
103 EXPECT_THAT(
104 KmsEnvelopeAeadKeyManager().ValidateKeyFormat(KmsEnvelopeAeadKeyFormat()),
105 StatusIs(absl::StatusCode::kInvalidArgument));
106 }
107
TEST(KmsEnvelopeAeadKeyManagerTest,ValidateKeyFormatValidKey)108 TEST(KmsEnvelopeAeadKeyManagerTest, ValidateKeyFormatValidKey) {
109 KmsEnvelopeAeadKeyFormat key_format;
110 key_format.set_kek_uri("Some uri");
111 *key_format.mutable_dek_template() = AeadKeyTemplates::Aes128Eax();
112 EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKeyFormat(key_format),
113 IsOk());
114 }
115
TEST(KmsEnvelopeAeadKeyManagerTest,ValidateKeyFormatNoUri)116 TEST(KmsEnvelopeAeadKeyManagerTest, ValidateKeyFormatNoUri) {
117 KmsEnvelopeAeadKeyFormat key_format;
118 *key_format.mutable_dek_template() = AeadKeyTemplates::Aes128Eax();
119 EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKeyFormat(key_format),
120 Not(IsOk()));
121 }
122
TEST(KmsEnvelopeAeadKeyManagerTest,ValidateKeyFormatNoTemplate)123 TEST(KmsEnvelopeAeadKeyManagerTest, ValidateKeyFormatNoTemplate) {
124 KmsEnvelopeAeadKeyFormat key_format;
125 key_format.set_kek_uri("Some uri");
126 EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKeyFormat(key_format),
127 Not(IsOk()));
128 }
129
TEST(KmsEnvelopeAeadKeyManagerTest,ValidateKeyFormatInvalidDekTemplate)130 TEST(KmsEnvelopeAeadKeyManagerTest, ValidateKeyFormatInvalidDekTemplate) {
131 KmsEnvelopeAeadKeyFormat key_format;
132 key_format.set_kek_uri("Some uri");
133 *key_format.mutable_dek_template() = MacKeyTemplates::HmacSha256();
134 EXPECT_THAT(KmsEnvelopeAeadKeyManager().ValidateKeyFormat(key_format),
135 Not(IsOk()));
136 }
137
TEST(KmsEnvelopeAeadKeyManagerTest,CreateKey)138 TEST(KmsEnvelopeAeadKeyManagerTest, CreateKey) {
139 KmsEnvelopeAeadKeyFormat key_format;
140 key_format.set_kek_uri("Some uri");
141 *key_format.mutable_dek_template() = AeadKeyTemplates::Aes128Eax();
142 auto key_or = KmsEnvelopeAeadKeyManager().CreateKey(key_format);
143 ASSERT_THAT(key_or, IsOk());
144 EXPECT_THAT(key_or.value().params().kek_uri(), Eq(key_format.kek_uri()));
145 EXPECT_THAT(key_or.value().params().dek_template().value(),
146 Eq(key_format.dek_template().value()));
147 }
148
149 class KmsEnvelopeAeadKeyManagerCreateTest : public ::testing::Test {
150 public:
151 // The KmsClients class has a global variable which keeps the registered
152 // clients. To reflect that in the test, we set them up in the SetUpTestSuite
153 // function.
SetUpTestSuite()154 static void SetUpTestSuite() {
155 if (!KmsClients::Add(
156 absl::make_unique<DummyKmsClient>("prefix1", "prefix1:some_key1"))
157 .ok())
158 abort();
159 if (!KmsClients::Add(absl::make_unique<DummyKmsClient>("prefix2", "")).ok())
160 abort();
161
162 if (!Registry::RegisterKeyTypeManager(absl::make_unique<AesEaxKeyManager>(),
163 true)
164 .ok())
165 abort();
166 }
167 };
168
TEST_F(KmsEnvelopeAeadKeyManagerCreateTest,CreateAead)169 TEST_F(KmsEnvelopeAeadKeyManagerCreateTest, CreateAead) {
170 KmsEnvelopeAeadKey key;
171 key.set_version(0);
172 key.mutable_params()->set_kek_uri("prefix1:some_key1");
173 *(key.mutable_params()->mutable_dek_template()) =
174 AeadKeyTemplates::Aes128Eax();
175
176 auto kms_aead = KmsEnvelopeAeadKeyManager().GetPrimitive<Aead>(key);
177 ASSERT_THAT(kms_aead, IsOk());
178
179 auto direct_aead =
180 KmsEnvelopeAead::New(key.params().dek_template(),
181 absl::make_unique<DummyAead>("prefix1:some_key1"));
182 ASSERT_THAT(direct_aead, IsOk());
183
184 EXPECT_THAT(EncryptThenDecrypt(*kms_aead.value(), *direct_aead.value(),
185 "plaintext", "aad"),
186 IsOk());
187 }
188
TEST_F(KmsEnvelopeAeadKeyManagerCreateTest,CreateAeadWrongKeyName)189 TEST_F(KmsEnvelopeAeadKeyManagerCreateTest, CreateAeadWrongKeyName) {
190 KmsEnvelopeAeadKey key;
191 key.set_version(0);
192 key.mutable_params()->set_kek_uri("prefix1:some_other_key");
193 *(key.mutable_params()->mutable_dek_template()) =
194 AeadKeyTemplates::Aes128Eax();
195
196 auto kms_aead = KmsEnvelopeAeadKeyManager().GetPrimitive<Aead>(key);
197 ASSERT_THAT(kms_aead, Not(IsOk()));
198 }
199
TEST_F(KmsEnvelopeAeadKeyManagerCreateTest,CreateAeadWrongTypeUrl)200 TEST_F(KmsEnvelopeAeadKeyManagerCreateTest, CreateAeadWrongTypeUrl) {
201 KmsEnvelopeAeadKey key;
202 key.set_version(0);
203 key.mutable_params()->set_kek_uri("prefix1:some_other_key");
204 *(key.mutable_params()->mutable_dek_template()) =
205 AeadKeyTemplates::Aes128Eax();
206 key.mutable_params()->mutable_dek_template()->set_type_url(
207 "Some unkonwn type url");
208
209 auto kms_aead = KmsEnvelopeAeadKeyManager().GetPrimitive<Aead>(key);
210 ASSERT_THAT(kms_aead, Not(IsOk()));
211 }
212
TEST_F(KmsEnvelopeAeadKeyManagerCreateTest,CreateAeadWrongPrefix)213 TEST_F(KmsEnvelopeAeadKeyManagerCreateTest, CreateAeadWrongPrefix) {
214 KmsEnvelopeAeadKey key;
215 key.set_version(0);
216 key.mutable_params()->set_kek_uri("non-existing-prefix:some_key1");
217 *(key.mutable_params()->mutable_dek_template()) =
218 AeadKeyTemplates::Aes128Eax();
219
220 auto kms_aead = KmsEnvelopeAeadKeyManager().GetPrimitive<Aead>(key);
221 ASSERT_THAT(kms_aead, Not(IsOk()));
222 }
223
TEST_F(KmsEnvelopeAeadKeyManagerCreateTest,CreateAeadUnboundKey)224 TEST_F(KmsEnvelopeAeadKeyManagerCreateTest, CreateAeadUnboundKey) {
225 KmsEnvelopeAeadKey key;
226 key.set_version(0);
227 key.mutable_params()->set_kek_uri("prefix2:some_key2");
228 *(key.mutable_params()->mutable_dek_template()) =
229 AeadKeyTemplates::Aes128Eax();
230
231 auto kms_aead = KmsEnvelopeAeadKeyManager().GetPrimitive<Aead>(key);
232 ASSERT_THAT(kms_aead, IsOk());
233
234 auto direct_aead =
235 KmsEnvelopeAead::New(key.params().dek_template(),
236 absl::make_unique<DummyAead>("prefix2:some_key2"));
237 ASSERT_THAT(direct_aead, IsOk());
238
239 EXPECT_THAT(EncryptThenDecrypt(*kms_aead.value(), *direct_aead.value(),
240 "plaintext", "aad"),
241 IsOk());
242 }
243
244 class KmsEnvelopeAeadKeyManagerDekTemplatesTest
245 : public testing::TestWithParam<KeyTemplate> {
SetUp()246 void SetUp() override { ASSERT_THAT(AeadConfig::Register(), IsOk()); }
247 };
248
TEST_P(KmsEnvelopeAeadKeyManagerDekTemplatesTest,EncryptDecryp)249 TEST_P(KmsEnvelopeAeadKeyManagerDekTemplatesTest, EncryptDecryp) {
250 util::StatusOr<std::string> kek_uri_result =
251 test::FakeKmsClient::CreateFakeKeyUri();
252 ASSERT_THAT(kek_uri_result, IsOk());
253 std::string kek_uri = kek_uri_result.value();
254 util::Status register_fake_kms_client_status =
255 test::FakeKmsClient::RegisterNewClient(kek_uri, /*credentials_path=*/"");
256 ASSERT_THAT(register_fake_kms_client_status, IsOk());
257
258 KeyTemplate dek_template = GetParam();
259 KeyTemplate env_template =
260 AeadKeyTemplates::KmsEnvelopeAead(kek_uri, dek_template);
261 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
262 KeysetHandle::GenerateNew(env_template);
263 ASSERT_THAT(handle, IsOk());
264 util::StatusOr<std::unique_ptr<Aead>> envelope_aead =
265 (*handle)->GetPrimitive<Aead>();
266 ASSERT_THAT(envelope_aead, IsOk());
267
268 std::string plaintext = "plaintext";
269 std::string associated_data = "associated_data";
270 util::StatusOr<std::string> ciphertext =
271 (*envelope_aead)->Encrypt(plaintext, associated_data);
272 ASSERT_THAT(ciphertext, IsOk());
273 util::StatusOr<std::string> decrypted =
274 (*envelope_aead)->Decrypt(ciphertext.value(), associated_data);
275 EXPECT_THAT(decrypted, IsOkAndHolds(plaintext));
276
277 std::string invalid_associated_data = "invalid_associated_data";
278 util::StatusOr<std::string> decrypted_with_invalid_associated_data =
279 (*envelope_aead)->Decrypt(ciphertext.value(), invalid_associated_data);
280 EXPECT_THAT(decrypted_with_invalid_associated_data.status(), Not(IsOk()));
281 }
282
283 INSTANTIATE_TEST_SUITE_P(
284 KmsEnvelopeAeadKeyManagerDekTemplatesTest,
285 KmsEnvelopeAeadKeyManagerDekTemplatesTest,
286 testing::Values(AeadKeyTemplates::Aes128Gcm(),
287 AeadKeyTemplates::Aes256Gcm(),
288 AeadKeyTemplates::Aes128CtrHmacSha256(),
289 AeadKeyTemplates::Aes128Eax(),
290 AeadKeyTemplates::Aes128GcmNoPrefix()));
291
292 } // namespace
293 } // namespace tink
294 } // namespace crypto
295