1*e7b1675dSTing-Kang Chang // Copyright 2017 Google Inc.
2*e7b1675dSTing-Kang Chang //
3*e7b1675dSTing-Kang Chang // Licensed under the Apache License, Version 2.0 (the "License");
4*e7b1675dSTing-Kang Chang // you may not use this file except in compliance with the License.
5*e7b1675dSTing-Kang Chang // You may obtain a copy of the License at
6*e7b1675dSTing-Kang Chang //
7*e7b1675dSTing-Kang Chang // http://www.apache.org/licenses/LICENSE-2.0
8*e7b1675dSTing-Kang Chang //
9*e7b1675dSTing-Kang Chang // Unless required by applicable law or agreed to in writing, software
10*e7b1675dSTing-Kang Chang // distributed under the License is distributed on an "AS IS" BASIS,
11*e7b1675dSTing-Kang Chang // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*e7b1675dSTing-Kang Chang // See the License for the specific language governing permissions and
13*e7b1675dSTing-Kang Chang // limitations under the License.
14*e7b1675dSTing-Kang Chang //
15*e7b1675dSTing-Kang Chang ////////////////////////////////////////////////////////////////////////////////
16*e7b1675dSTing-Kang Chang
17*e7b1675dSTing-Kang Chang #include "tink/aead/aead_wrapper.h"
18*e7b1675dSTing-Kang Chang
19*e7b1675dSTing-Kang Chang #include <stdint.h>
20*e7b1675dSTing-Kang Chang
21*e7b1675dSTing-Kang Chang #include <memory>
22*e7b1675dSTing-Kang Chang #include <string>
23*e7b1675dSTing-Kang Chang #include <utility>
24*e7b1675dSTing-Kang Chang
25*e7b1675dSTing-Kang Chang #include "gmock/gmock.h"
26*e7b1675dSTing-Kang Chang #include "gtest/gtest.h"
27*e7b1675dSTing-Kang Chang #include "absl/container/flat_hash_map.h"
28*e7b1675dSTing-Kang Chang #include "absl/memory/memory.h"
29*e7b1675dSTing-Kang Chang #include "absl/status/status.h"
30*e7b1675dSTing-Kang Chang #include "absl/status/statusor.h"
31*e7b1675dSTing-Kang Chang #include "absl/strings/str_cat.h"
32*e7b1675dSTing-Kang Chang #include "absl/strings/string_view.h"
33*e7b1675dSTing-Kang Chang #include "tink/aead.h"
34*e7b1675dSTing-Kang Chang #include "tink/aead/mock_aead.h"
35*e7b1675dSTing-Kang Chang #include "tink/crypto_format.h"
36*e7b1675dSTing-Kang Chang #include "tink/internal/registry_impl.h"
37*e7b1675dSTing-Kang Chang #include "tink/monitoring/monitoring.h"
38*e7b1675dSTing-Kang Chang #include "tink/monitoring/monitoring_client_mocks.h"
39*e7b1675dSTing-Kang Chang #include "tink/primitive_set.h"
40*e7b1675dSTing-Kang Chang #include "tink/registry.h"
41*e7b1675dSTing-Kang Chang #include "tink/util/status.h"
42*e7b1675dSTing-Kang Chang #include "tink/util/statusor.h"
43*e7b1675dSTing-Kang Chang #include "tink/util/test_matchers.h"
44*e7b1675dSTing-Kang Chang #include "tink/util/test_util.h"
45*e7b1675dSTing-Kang Chang #include "proto/tink.pb.h"
46*e7b1675dSTing-Kang Chang
47*e7b1675dSTing-Kang Chang namespace crypto {
48*e7b1675dSTing-Kang Chang namespace tink {
49*e7b1675dSTing-Kang Chang namespace {
50*e7b1675dSTing-Kang Chang
51*e7b1675dSTing-Kang Chang using ::crypto::tink::test::DummyAead;
52*e7b1675dSTing-Kang Chang using ::crypto::tink::test::IsOk;
53*e7b1675dSTing-Kang Chang using ::crypto::tink::test::StatusIs;
54*e7b1675dSTing-Kang Chang using ::google::crypto::tink::KeysetInfo;
55*e7b1675dSTing-Kang Chang using ::google::crypto::tink::KeyStatusType;
56*e7b1675dSTing-Kang Chang using ::google::crypto::tink::OutputPrefixType;
57*e7b1675dSTing-Kang Chang using ::testing::_;
58*e7b1675dSTing-Kang Chang using ::testing::ByMove;
59*e7b1675dSTing-Kang Chang using ::testing::HasSubstr;
60*e7b1675dSTing-Kang Chang using ::testing::IsNull;
61*e7b1675dSTing-Kang Chang using ::testing::IsSubstring;
62*e7b1675dSTing-Kang Chang using ::testing::Not;
63*e7b1675dSTing-Kang Chang using ::testing::Return;
64*e7b1675dSTing-Kang Chang using ::testing::StrictMock;
65*e7b1675dSTing-Kang Chang using ::testing::Test;
66*e7b1675dSTing-Kang Chang
PopulateKeyInfo(KeysetInfo::KeyInfo * key_info,uint32_t key_id,OutputPrefixType out_prefix_type,KeyStatusType status)67*e7b1675dSTing-Kang Chang void PopulateKeyInfo(KeysetInfo::KeyInfo* key_info, uint32_t key_id,
68*e7b1675dSTing-Kang Chang OutputPrefixType out_prefix_type, KeyStatusType status) {
69*e7b1675dSTing-Kang Chang key_info->set_output_prefix_type(out_prefix_type);
70*e7b1675dSTing-Kang Chang key_info->set_key_id(key_id);
71*e7b1675dSTing-Kang Chang key_info->set_status(status);
72*e7b1675dSTing-Kang Chang }
73*e7b1675dSTing-Kang Chang
74*e7b1675dSTing-Kang Chang // Creates a test keyset info object.
CreateTestKeysetInfo()75*e7b1675dSTing-Kang Chang KeysetInfo CreateTestKeysetInfo() {
76*e7b1675dSTing-Kang Chang KeysetInfo keyset_info;
77*e7b1675dSTing-Kang Chang PopulateKeyInfo(keyset_info.add_key_info(), /*key_id=*/1234543,
78*e7b1675dSTing-Kang Chang OutputPrefixType::TINK,
79*e7b1675dSTing-Kang Chang /*status=*/KeyStatusType::ENABLED);
80*e7b1675dSTing-Kang Chang PopulateKeyInfo(keyset_info.add_key_info(), /*key_id=*/726329,
81*e7b1675dSTing-Kang Chang OutputPrefixType::LEGACY,
82*e7b1675dSTing-Kang Chang /*status=*/KeyStatusType::ENABLED);
83*e7b1675dSTing-Kang Chang PopulateKeyInfo(keyset_info.add_key_info(), /*key_id=*/7213743,
84*e7b1675dSTing-Kang Chang OutputPrefixType::TINK,
85*e7b1675dSTing-Kang Chang /*status=*/KeyStatusType::ENABLED);
86*e7b1675dSTing-Kang Chang return keyset_info;
87*e7b1675dSTing-Kang Chang }
88*e7b1675dSTing-Kang Chang
TEST(AeadSetWrapperTest,WrapNullptr)89*e7b1675dSTing-Kang Chang TEST(AeadSetWrapperTest, WrapNullptr) {
90*e7b1675dSTing-Kang Chang AeadWrapper wrapper;
91*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<Aead>> aead = wrapper.Wrap(nullptr);
92*e7b1675dSTing-Kang Chang EXPECT_THAT(aead, Not(IsOk()));
93*e7b1675dSTing-Kang Chang EXPECT_THAT(aead.status(), StatusIs(absl::StatusCode::kInternal));
94*e7b1675dSTing-Kang Chang EXPECT_PRED_FORMAT2(IsSubstring, "non-NULL",
95*e7b1675dSTing-Kang Chang std::string(aead.status().message()));
96*e7b1675dSTing-Kang Chang }
97*e7b1675dSTing-Kang Chang
TEST(AeadSetWrapperTest,WrapEmpty)98*e7b1675dSTing-Kang Chang TEST(AeadSetWrapperTest, WrapEmpty) {
99*e7b1675dSTing-Kang Chang AeadWrapper wrapper;
100*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<Aead>> aead =
101*e7b1675dSTing-Kang Chang wrapper.Wrap(absl::make_unique<PrimitiveSet<Aead>>());
102*e7b1675dSTing-Kang Chang EXPECT_THAT(aead, Not(IsOk()));
103*e7b1675dSTing-Kang Chang EXPECT_THAT(aead.status(), StatusIs(absl::StatusCode::kInvalidArgument));
104*e7b1675dSTing-Kang Chang EXPECT_PRED_FORMAT2(IsSubstring, "no primary",
105*e7b1675dSTing-Kang Chang std::string(aead.status().message()));
106*e7b1675dSTing-Kang Chang }
107*e7b1675dSTing-Kang Chang
TEST(AeadSetWrapperTest,Basic)108*e7b1675dSTing-Kang Chang TEST(AeadSetWrapperTest, Basic) {
109*e7b1675dSTing-Kang Chang KeysetInfo keyset_info = CreateTestKeysetInfo();
110*e7b1675dSTing-Kang Chang std::string aead_name_0 = "aead0";
111*e7b1675dSTing-Kang Chang std::string aead_name_1 = "aead1";
112*e7b1675dSTing-Kang Chang std::string aead_name_2 = "aead2";
113*e7b1675dSTing-Kang Chang auto aead_set = absl::make_unique<PrimitiveSet<Aead>>();
114*e7b1675dSTing-Kang Chang std::unique_ptr<Aead> aead = absl::make_unique<DummyAead>(aead_name_0);
115*e7b1675dSTing-Kang Chang util::StatusOr<PrimitiveSet<Aead>::Entry<Aead>*> aead_entry =
116*e7b1675dSTing-Kang Chang aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(0));
117*e7b1675dSTing-Kang Chang EXPECT_THAT(aead_entry, IsOk());
118*e7b1675dSTing-Kang Chang aead = absl::make_unique<DummyAead>(aead_name_1);
119*e7b1675dSTing-Kang Chang aead_entry = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(1));
120*e7b1675dSTing-Kang Chang EXPECT_THAT(aead_entry, IsOk());
121*e7b1675dSTing-Kang Chang aead = absl::make_unique<DummyAead>(aead_name_2);
122*e7b1675dSTing-Kang Chang aead_entry = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(2));
123*e7b1675dSTing-Kang Chang EXPECT_THAT(aead_entry, IsOk());
124*e7b1675dSTing-Kang Chang // The last key is the primary.
125*e7b1675dSTing-Kang Chang EXPECT_THAT(aead_set->set_primary(*aead_entry), IsOk());
126*e7b1675dSTing-Kang Chang
127*e7b1675dSTing-Kang Chang // Wrap aead_set and test the resulting Aead.
128*e7b1675dSTing-Kang Chang AeadWrapper wrapper;
129*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<Aead>> aead_result =
130*e7b1675dSTing-Kang Chang wrapper.Wrap(std::move(aead_set));
131*e7b1675dSTing-Kang Chang EXPECT_THAT(aead_result, IsOk());
132*e7b1675dSTing-Kang Chang aead = std::move(*aead_result);
133*e7b1675dSTing-Kang Chang std::string plaintext = "some_plaintext";
134*e7b1675dSTing-Kang Chang std::string aad = "some_aad";
135*e7b1675dSTing-Kang Chang
136*e7b1675dSTing-Kang Chang util::StatusOr<std::string> encrypt_result = aead->Encrypt(plaintext, aad);
137*e7b1675dSTing-Kang Chang EXPECT_THAT(encrypt_result, IsOk());
138*e7b1675dSTing-Kang Chang std::string ciphertext = *encrypt_result;
139*e7b1675dSTing-Kang Chang EXPECT_PRED_FORMAT2(testing::IsSubstring, aead_name_2, ciphertext);
140*e7b1675dSTing-Kang Chang
141*e7b1675dSTing-Kang Chang util::StatusOr<std::string> resulting_plaintext =
142*e7b1675dSTing-Kang Chang aead->Decrypt(ciphertext, aad);
143*e7b1675dSTing-Kang Chang EXPECT_THAT(resulting_plaintext, IsOk());
144*e7b1675dSTing-Kang Chang EXPECT_EQ(*resulting_plaintext, plaintext);
145*e7b1675dSTing-Kang Chang
146*e7b1675dSTing-Kang Chang resulting_plaintext = aead->Decrypt("some bad ciphertext", aad);
147*e7b1675dSTing-Kang Chang EXPECT_THAT(resulting_plaintext, Not(IsOk()));
148*e7b1675dSTing-Kang Chang EXPECT_THAT(resulting_plaintext.status(),
149*e7b1675dSTing-Kang Chang StatusIs(absl::StatusCode::kInvalidArgument));
150*e7b1675dSTing-Kang Chang EXPECT_PRED_FORMAT2(IsSubstring, "decryption failed",
151*e7b1675dSTing-Kang Chang std::string(resulting_plaintext.status().message()));
152*e7b1675dSTing-Kang Chang }
153*e7b1675dSTing-Kang Chang
TEST(AeadSetWrapperTest,DecryptNonPrimary)154*e7b1675dSTing-Kang Chang TEST(AeadSetWrapperTest, DecryptNonPrimary) {
155*e7b1675dSTing-Kang Chang KeysetInfo keyset_info = CreateTestKeysetInfo();
156*e7b1675dSTing-Kang Chang std::string aead_name_0 = "aead0";
157*e7b1675dSTing-Kang Chang std::string aead_name_1 = "aead1";
158*e7b1675dSTing-Kang Chang std::string aead_name_2 = "aead2";
159*e7b1675dSTing-Kang Chang std::unique_ptr<PrimitiveSet<Aead>> aead_set(new PrimitiveSet<Aead>());
160*e7b1675dSTing-Kang Chang std::unique_ptr<Aead> aead = absl::make_unique<DummyAead>(aead_name_0);
161*e7b1675dSTing-Kang Chang
162*e7b1675dSTing-Kang Chang // Encrypt some message with the first aead.s
163*e7b1675dSTing-Kang Chang std::string plaintext = "some_plaintext";
164*e7b1675dSTing-Kang Chang std::string aad = "some_aad";
165*e7b1675dSTing-Kang Chang util::StatusOr<std::string> ciphertext = aead->Encrypt(plaintext, aad);
166*e7b1675dSTing-Kang Chang EXPECT_THAT(ciphertext, IsOk());
167*e7b1675dSTing-Kang Chang util::StatusOr<PrimitiveSet<Aead>::Entry<Aead>*> aead_entry =
168*e7b1675dSTing-Kang Chang aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(0));
169*e7b1675dSTing-Kang Chang ASSERT_THAT(aead_entry, IsOk());
170*e7b1675dSTing-Kang Chang EXPECT_THAT(aead_set->set_primary(*aead_entry), IsOk());
171*e7b1675dSTing-Kang Chang
172*e7b1675dSTing-Kang Chang // The complete ciphertext is of the form: | key_id | ciphertext |.
173*e7b1675dSTing-Kang Chang std::string complete_ciphertext =
174*e7b1675dSTing-Kang Chang absl::StrCat(aead_set->get_primary()->get_identifier(), *ciphertext);
175*e7b1675dSTing-Kang Chang
176*e7b1675dSTing-Kang Chang aead = absl::make_unique<DummyAead>(aead_name_1);
177*e7b1675dSTing-Kang Chang aead_entry = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(1));
178*e7b1675dSTing-Kang Chang EXPECT_THAT(aead_entry, IsOk());
179*e7b1675dSTing-Kang Chang aead = absl::make_unique<DummyAead>(aead_name_2);
180*e7b1675dSTing-Kang Chang aead_entry = aead_set->AddPrimitive(std::move(aead), keyset_info.key_info(2));
181*e7b1675dSTing-Kang Chang EXPECT_THAT(aead_entry, IsOk());
182*e7b1675dSTing-Kang Chang // The last key is the primary.
183*e7b1675dSTing-Kang Chang EXPECT_THAT(aead_set->set_primary(*aead_entry), IsOk());
184*e7b1675dSTing-Kang Chang
185*e7b1675dSTing-Kang Chang // Wrap aead_set and test the resulting Aead.
186*e7b1675dSTing-Kang Chang AeadWrapper wrapper;
187*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<Aead>> aead_wrapped =
188*e7b1675dSTing-Kang Chang wrapper.Wrap(std::move(aead_set));
189*e7b1675dSTing-Kang Chang EXPECT_THAT(aead_wrapped, IsOk());
190*e7b1675dSTing-Kang Chang aead = std::move(*aead_wrapped);
191*e7b1675dSTing-Kang Chang EXPECT_THAT(complete_ciphertext, HasSubstr(aead_name_0));
192*e7b1675dSTing-Kang Chang
193*e7b1675dSTing-Kang Chang // Primary key is different from the one we used to encrypt. This
194*e7b1675dSTing-Kang Chang // should still be decryptable as we have the correct key in the set.
195*e7b1675dSTing-Kang Chang util::StatusOr<std::string> decrypted_plaintext =
196*e7b1675dSTing-Kang Chang aead->Decrypt(complete_ciphertext, aad);
197*e7b1675dSTing-Kang Chang EXPECT_THAT(decrypted_plaintext, IsOk());
198*e7b1675dSTing-Kang Chang }
199*e7b1675dSTing-Kang Chang
200*e7b1675dSTing-Kang Chang // Tests with monitoring enabled.
201*e7b1675dSTing-Kang Chang class AeadSetWrapperTestWithMonitoring : public Test {
202*e7b1675dSTing-Kang Chang protected:
203*e7b1675dSTing-Kang Chang // Perform some common initialization: reset the global registry, set expected
204*e7b1675dSTing-Kang Chang // calls for the mock monitoring factory and the returned clients.
SetUp()205*e7b1675dSTing-Kang Chang void SetUp() override {
206*e7b1675dSTing-Kang Chang Registry::Reset();
207*e7b1675dSTing-Kang Chang auto monitoring_client_factory =
208*e7b1675dSTing-Kang Chang absl::make_unique<MockMonitoringClientFactory>();
209*e7b1675dSTing-Kang Chang
210*e7b1675dSTing-Kang Chang auto encryption_monitoring_client =
211*e7b1675dSTing-Kang Chang absl::make_unique<StrictMock<MockMonitoringClient>>();
212*e7b1675dSTing-Kang Chang encryption_monitoring_client_ptr_ = encryption_monitoring_client.get();
213*e7b1675dSTing-Kang Chang auto decryption_monitoring_client =
214*e7b1675dSTing-Kang Chang absl::make_unique<StrictMock<MockMonitoringClient>>();
215*e7b1675dSTing-Kang Chang decryption_monitoring_client_ptr_ = decryption_monitoring_client.get();
216*e7b1675dSTing-Kang Chang
217*e7b1675dSTing-Kang Chang EXPECT_CALL(*monitoring_client_factory, New(_))
218*e7b1675dSTing-Kang Chang .WillOnce(
219*e7b1675dSTing-Kang Chang Return(ByMove(util::StatusOr<std::unique_ptr<MonitoringClient>>(
220*e7b1675dSTing-Kang Chang std::move(encryption_monitoring_client)))))
221*e7b1675dSTing-Kang Chang .WillOnce(
222*e7b1675dSTing-Kang Chang Return(ByMove(util::StatusOr<std::unique_ptr<MonitoringClient>>(
223*e7b1675dSTing-Kang Chang std::move(decryption_monitoring_client)))));
224*e7b1675dSTing-Kang Chang
225*e7b1675dSTing-Kang Chang ASSERT_THAT(internal::RegistryImpl::GlobalInstance()
226*e7b1675dSTing-Kang Chang .RegisterMonitoringClientFactory(
227*e7b1675dSTing-Kang Chang std::move(monitoring_client_factory)),
228*e7b1675dSTing-Kang Chang IsOk());
229*e7b1675dSTing-Kang Chang ASSERT_THAT(
230*e7b1675dSTing-Kang Chang internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(),
231*e7b1675dSTing-Kang Chang Not(IsNull()));
232*e7b1675dSTing-Kang Chang }
233*e7b1675dSTing-Kang Chang
234*e7b1675dSTing-Kang Chang // Cleanup the registry to avoid mock leaks.
TearDown()235*e7b1675dSTing-Kang Chang void TearDown() override { Registry::Reset(); }
236*e7b1675dSTing-Kang Chang
237*e7b1675dSTing-Kang Chang MockMonitoringClient* encryption_monitoring_client_ptr_;
238*e7b1675dSTing-Kang Chang MockMonitoringClient* decryption_monitoring_client_ptr_;
239*e7b1675dSTing-Kang Chang };
240*e7b1675dSTing-Kang Chang
241*e7b1675dSTing-Kang Chang // Test that successful encrypt/decrypt operations are logged.
TEST_F(AeadSetWrapperTestWithMonitoring,WrapKeysetWithMonitoringEncryptDecryptSuccess)242*e7b1675dSTing-Kang Chang TEST_F(AeadSetWrapperTestWithMonitoring,
243*e7b1675dSTing-Kang Chang WrapKeysetWithMonitoringEncryptDecryptSuccess) {
244*e7b1675dSTing-Kang Chang // Populate a primitive set.
245*e7b1675dSTing-Kang Chang KeysetInfo keyset_info = CreateTestKeysetInfo();
246*e7b1675dSTing-Kang Chang const absl::flat_hash_map<std::string, std::string> kAnnotations = {
247*e7b1675dSTing-Kang Chang {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}};
248*e7b1675dSTing-Kang Chang auto aead_primitive_set = absl::make_unique<PrimitiveSet<Aead>>(kAnnotations);
249*e7b1675dSTing-Kang Chang ASSERT_THAT(aead_primitive_set
250*e7b1675dSTing-Kang Chang ->AddPrimitive(absl::make_unique<DummyAead>("aead0"),
251*e7b1675dSTing-Kang Chang keyset_info.key_info(0))
252*e7b1675dSTing-Kang Chang .status(),
253*e7b1675dSTing-Kang Chang IsOk());
254*e7b1675dSTing-Kang Chang ASSERT_THAT(aead_primitive_set
255*e7b1675dSTing-Kang Chang ->AddPrimitive(absl::make_unique<DummyAead>("aead1"),
256*e7b1675dSTing-Kang Chang keyset_info.key_info(1))
257*e7b1675dSTing-Kang Chang .status(),
258*e7b1675dSTing-Kang Chang IsOk());
259*e7b1675dSTing-Kang Chang // Set the last as primary.
260*e7b1675dSTing-Kang Chang util::StatusOr<PrimitiveSet<Aead>::Entry<Aead>*> last =
261*e7b1675dSTing-Kang Chang aead_primitive_set->AddPrimitive(absl::make_unique<DummyAead>("aead2"),
262*e7b1675dSTing-Kang Chang keyset_info.key_info(2));
263*e7b1675dSTing-Kang Chang ASSERT_THAT(last, IsOk());
264*e7b1675dSTing-Kang Chang ASSERT_THAT(aead_primitive_set->set_primary(*last), IsOk());
265*e7b1675dSTing-Kang Chang // Record the ID of the primary key.
266*e7b1675dSTing-Kang Chang const uint32_t kPrimaryKeyId = keyset_info.key_info(2).key_id();
267*e7b1675dSTing-Kang Chang
268*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<Aead>> aead =
269*e7b1675dSTing-Kang Chang AeadWrapper().Wrap(std::move(aead_primitive_set));
270*e7b1675dSTing-Kang Chang ASSERT_THAT(aead, IsOk());
271*e7b1675dSTing-Kang Chang
272*e7b1675dSTing-Kang Chang constexpr absl::string_view kPlaintext = "This is some plaintext!";
273*e7b1675dSTing-Kang Chang constexpr absl::string_view kAssociatedData = "Some associated data!";
274*e7b1675dSTing-Kang Chang EXPECT_CALL(*encryption_monitoring_client_ptr_,
275*e7b1675dSTing-Kang Chang Log(kPrimaryKeyId, kPlaintext.size()));
276*e7b1675dSTing-Kang Chang util::StatusOr<std::string> ciphertext =
277*e7b1675dSTing-Kang Chang (*aead)->Encrypt(kPlaintext, kAssociatedData);
278*e7b1675dSTing-Kang Chang ASSERT_THAT(ciphertext, IsOk());
279*e7b1675dSTing-Kang Chang
280*e7b1675dSTing-Kang Chang // In the log expect the size of the ciphertext without the non-raw prefix.
281*e7b1675dSTing-Kang Chang auto raw_ciphertext =
282*e7b1675dSTing-Kang Chang absl::string_view(*ciphertext).substr(CryptoFormat::kNonRawPrefixSize);
283*e7b1675dSTing-Kang Chang EXPECT_CALL(*decryption_monitoring_client_ptr_,
284*e7b1675dSTing-Kang Chang Log(kPrimaryKeyId, raw_ciphertext.size()));
285*e7b1675dSTing-Kang Chang EXPECT_THAT((*aead)->Decrypt(*ciphertext, kAssociatedData), IsOk());
286*e7b1675dSTing-Kang Chang }
287*e7b1675dSTing-Kang Chang
288*e7b1675dSTing-Kang Chang // Test that monitoring logs encryption and decryption failures correctly.
TEST_F(AeadSetWrapperTestWithMonitoring,WrapKeysetWithMonitoringEncryptDecryptFailures)289*e7b1675dSTing-Kang Chang TEST_F(AeadSetWrapperTestWithMonitoring,
290*e7b1675dSTing-Kang Chang WrapKeysetWithMonitoringEncryptDecryptFailures) {
291*e7b1675dSTing-Kang Chang // Populate a primitive set.
292*e7b1675dSTing-Kang Chang KeysetInfo keyset_info = CreateTestKeysetInfo();
293*e7b1675dSTing-Kang Chang
294*e7b1675dSTing-Kang Chang const absl::flat_hash_map<std::string, std::string> kAnnotations = {
295*e7b1675dSTing-Kang Chang {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}};
296*e7b1675dSTing-Kang Chang
297*e7b1675dSTing-Kang Chang auto aead_primitive_set = absl::make_unique<PrimitiveSet<Aead>>(kAnnotations);
298*e7b1675dSTing-Kang Chang
299*e7b1675dSTing-Kang Chang // Assume encryption and decryption always fail.
300*e7b1675dSTing-Kang Chang auto mock_aead = absl::make_unique<MockAead>();
301*e7b1675dSTing-Kang Chang constexpr absl::string_view kPlaintext = "A plaintext!!";
302*e7b1675dSTing-Kang Chang constexpr absl::string_view kCiphertext = "A ciphertext!";
303*e7b1675dSTing-Kang Chang constexpr absl::string_view kAssociatedData = "Some associated data!";
304*e7b1675dSTing-Kang Chang ON_CALL(*mock_aead, Encrypt(kPlaintext, kAssociatedData))
305*e7b1675dSTing-Kang Chang .WillByDefault(Return(util::Status(absl::StatusCode::kInternal,
306*e7b1675dSTing-Kang Chang "Oh no encryption failed :(!")));
307*e7b1675dSTing-Kang Chang ON_CALL(*mock_aead, Decrypt(kCiphertext, kAssociatedData))
308*e7b1675dSTing-Kang Chang .WillByDefault(Return(util::Status(absl::StatusCode::kInternal,
309*e7b1675dSTing-Kang Chang "Oh no decryption failed :(!")));
310*e7b1675dSTing-Kang Chang
311*e7b1675dSTing-Kang Chang util::StatusOr<PrimitiveSet<Aead>::Entry<Aead>*> primary =
312*e7b1675dSTing-Kang Chang aead_primitive_set->AddPrimitive(std::move(mock_aead),
313*e7b1675dSTing-Kang Chang keyset_info.key_info(2));
314*e7b1675dSTing-Kang Chang ASSERT_THAT(primary, IsOk());
315*e7b1675dSTing-Kang Chang // Set the only primitive as primary.
316*e7b1675dSTing-Kang Chang ASSERT_THAT(aead_primitive_set->set_primary(*primary), IsOk());
317*e7b1675dSTing-Kang Chang
318*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<Aead>> aead =
319*e7b1675dSTing-Kang Chang AeadWrapper().Wrap(std::move(aead_primitive_set));
320*e7b1675dSTing-Kang Chang ASSERT_THAT(aead, IsOk());
321*e7b1675dSTing-Kang Chang
322*e7b1675dSTing-Kang Chang // Expect encryption failure gets logged.
323*e7b1675dSTing-Kang Chang EXPECT_CALL(*encryption_monitoring_client_ptr_, LogFailure());
324*e7b1675dSTing-Kang Chang util::StatusOr<std::string> ciphertext =
325*e7b1675dSTing-Kang Chang (*aead)->Encrypt(kPlaintext, kAssociatedData);
326*e7b1675dSTing-Kang Chang EXPECT_THAT(ciphertext, Not(IsOk()));
327*e7b1675dSTing-Kang Chang
328*e7b1675dSTing-Kang Chang // We must prepend the identifier to the ciphertext to make sure our mock gets
329*e7b1675dSTing-Kang Chang // called.
330*e7b1675dSTing-Kang Chang util::StatusOr<std::string> key_identifier =
331*e7b1675dSTing-Kang Chang CryptoFormat::GetOutputPrefix(keyset_info.key_info(2));
332*e7b1675dSTing-Kang Chang ASSERT_THAT(key_identifier, IsOk());
333*e7b1675dSTing-Kang Chang std::string ciphertext_with_key_id =
334*e7b1675dSTing-Kang Chang absl::StrCat(*key_identifier, kCiphertext);
335*e7b1675dSTing-Kang Chang
336*e7b1675dSTing-Kang Chang // Expect decryption failure gets logged.
337*e7b1675dSTing-Kang Chang EXPECT_CALL(*decryption_monitoring_client_ptr_, LogFailure());
338*e7b1675dSTing-Kang Chang EXPECT_THAT(
339*e7b1675dSTing-Kang Chang (*aead)->Decrypt(ciphertext_with_key_id, kAssociatedData).status(),
340*e7b1675dSTing-Kang Chang Not(IsOk()));
341*e7b1675dSTing-Kang Chang }
342*e7b1675dSTing-Kang Chang
343*e7b1675dSTing-Kang Chang } // namespace
344*e7b1675dSTing-Kang Chang } // namespace tink
345*e7b1675dSTing-Kang Chang } // namespace crypto
346