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/mac/mac_wrapper.h"
18*e7b1675dSTing-Kang Chang
19*e7b1675dSTing-Kang Chang #include <memory>
20*e7b1675dSTing-Kang Chang #include <string>
21*e7b1675dSTing-Kang Chang #include <utility>
22*e7b1675dSTing-Kang Chang
23*e7b1675dSTing-Kang Chang #include "gtest/gtest.h"
24*e7b1675dSTing-Kang Chang #include "absl/strings/str_cat.h"
25*e7b1675dSTing-Kang Chang #include "tink/crypto_format.h"
26*e7b1675dSTing-Kang Chang #include "tink/internal/registry_impl.h"
27*e7b1675dSTing-Kang Chang #include "tink/mac.h"
28*e7b1675dSTing-Kang Chang #include "tink/mac/failing_mac.h"
29*e7b1675dSTing-Kang Chang #include "tink/monitoring/monitoring.h"
30*e7b1675dSTing-Kang Chang #include "tink/monitoring/monitoring_client_mocks.h"
31*e7b1675dSTing-Kang Chang #include "tink/primitive_set.h"
32*e7b1675dSTing-Kang Chang #include "tink/util/status.h"
33*e7b1675dSTing-Kang Chang #include "tink/util/test_matchers.h"
34*e7b1675dSTing-Kang Chang #include "tink/util/test_util.h"
35*e7b1675dSTing-Kang Chang #include "proto/tink.pb.h"
36*e7b1675dSTing-Kang Chang
37*e7b1675dSTing-Kang Chang namespace crypto {
38*e7b1675dSTing-Kang Chang namespace tink {
39*e7b1675dSTing-Kang Chang namespace {
40*e7b1675dSTing-Kang Chang
41*e7b1675dSTing-Kang Chang using ::crypto::tink::test::DummyMac;
42*e7b1675dSTing-Kang Chang using ::crypto::tink::test::IsOk;
43*e7b1675dSTing-Kang Chang using ::crypto::tink::test::IsOkAndHolds;
44*e7b1675dSTing-Kang Chang using ::crypto::tink::test::StatusIs;
45*e7b1675dSTing-Kang Chang using ::google::crypto::tink::KeysetInfo;
46*e7b1675dSTing-Kang Chang using ::google::crypto::tink::KeyStatusType;
47*e7b1675dSTing-Kang Chang using ::google::crypto::tink::OutputPrefixType;
48*e7b1675dSTing-Kang Chang using ::testing::_;
49*e7b1675dSTing-Kang Chang using ::testing::ByMove;
50*e7b1675dSTing-Kang Chang using ::testing::IsNull;
51*e7b1675dSTing-Kang Chang using ::testing::NiceMock;
52*e7b1675dSTing-Kang Chang using ::testing::Not;
53*e7b1675dSTing-Kang Chang using ::testing::NotNull;
54*e7b1675dSTing-Kang Chang using ::testing::Return;
55*e7b1675dSTing-Kang Chang using ::testing::Test;
56*e7b1675dSTing-Kang Chang
TEST(MacWrapperTest,WrapNullptr)57*e7b1675dSTing-Kang Chang TEST(MacWrapperTest, WrapNullptr) {
58*e7b1675dSTing-Kang Chang auto mac_result = MacWrapper().Wrap(nullptr);
59*e7b1675dSTing-Kang Chang EXPECT_FALSE(mac_result.ok());
60*e7b1675dSTing-Kang Chang EXPECT_EQ(absl::StatusCode::kInternal, mac_result.status().code());
61*e7b1675dSTing-Kang Chang EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-NULL",
62*e7b1675dSTing-Kang Chang std::string(mac_result.status().message()));
63*e7b1675dSTing-Kang Chang }
64*e7b1675dSTing-Kang Chang
TEST(MacWrapperTest,WrapEmpty)65*e7b1675dSTing-Kang Chang TEST(MacWrapperTest, WrapEmpty) {
66*e7b1675dSTing-Kang Chang std::unique_ptr<PrimitiveSet<Mac>> mac_set(new PrimitiveSet<Mac>());
67*e7b1675dSTing-Kang Chang auto mac_result = MacWrapper().Wrap(std::move(mac_set));
68*e7b1675dSTing-Kang Chang EXPECT_FALSE(mac_result.ok());
69*e7b1675dSTing-Kang Chang EXPECT_EQ(absl::StatusCode::kInvalidArgument, mac_result.status().code());
70*e7b1675dSTing-Kang Chang EXPECT_PRED_FORMAT2(testing::IsSubstring, "no primary",
71*e7b1675dSTing-Kang Chang std::string(mac_result.status().message()));
72*e7b1675dSTing-Kang Chang }
73*e7b1675dSTing-Kang Chang
TEST(MacWrapperTest,Basic)74*e7b1675dSTing-Kang Chang TEST(MacWrapperTest, Basic) {
75*e7b1675dSTing-Kang Chang KeysetInfo::KeyInfo* key_info;
76*e7b1675dSTing-Kang Chang KeysetInfo keyset_info;
77*e7b1675dSTing-Kang Chang
78*e7b1675dSTing-Kang Chang uint32_t key_id_0 = 1234543;
79*e7b1675dSTing-Kang Chang key_info = keyset_info.add_key_info();
80*e7b1675dSTing-Kang Chang key_info->set_output_prefix_type(OutputPrefixType::TINK);
81*e7b1675dSTing-Kang Chang key_info->set_key_id(key_id_0);
82*e7b1675dSTing-Kang Chang key_info->set_status(KeyStatusType::ENABLED);
83*e7b1675dSTing-Kang Chang
84*e7b1675dSTing-Kang Chang uint32_t key_id_1 = 726329;
85*e7b1675dSTing-Kang Chang key_info = keyset_info.add_key_info();
86*e7b1675dSTing-Kang Chang key_info->set_output_prefix_type(OutputPrefixType::LEGACY);
87*e7b1675dSTing-Kang Chang key_info->set_key_id(key_id_1);
88*e7b1675dSTing-Kang Chang key_info->set_status(KeyStatusType::ENABLED);
89*e7b1675dSTing-Kang Chang
90*e7b1675dSTing-Kang Chang uint32_t key_id_2 = 7213743;
91*e7b1675dSTing-Kang Chang key_info = keyset_info.add_key_info();
92*e7b1675dSTing-Kang Chang key_info->set_output_prefix_type(OutputPrefixType::TINK);
93*e7b1675dSTing-Kang Chang key_info->set_key_id(key_id_2);
94*e7b1675dSTing-Kang Chang key_info->set_status(KeyStatusType::ENABLED);
95*e7b1675dSTing-Kang Chang
96*e7b1675dSTing-Kang Chang std::string mac_name_0 = "mac0";
97*e7b1675dSTing-Kang Chang std::string mac_name_1 = "mac1";
98*e7b1675dSTing-Kang Chang std::string mac_name_2 = "mac2";
99*e7b1675dSTing-Kang Chang std::unique_ptr<PrimitiveSet<Mac>> mac_set(new PrimitiveSet<Mac>());
100*e7b1675dSTing-Kang Chang auto entry_result = mac_set->AddPrimitive(
101*e7b1675dSTing-Kang Chang absl::make_unique<DummyMac>(mac_name_0), keyset_info.key_info(0));
102*e7b1675dSTing-Kang Chang ASSERT_TRUE(entry_result.ok());
103*e7b1675dSTing-Kang Chang entry_result = mac_set->AddPrimitive(absl::make_unique<DummyMac>(mac_name_1),
104*e7b1675dSTing-Kang Chang keyset_info.key_info(1));
105*e7b1675dSTing-Kang Chang ASSERT_TRUE(entry_result.ok());
106*e7b1675dSTing-Kang Chang entry_result = mac_set->AddPrimitive(absl::make_unique<DummyMac>(mac_name_2),
107*e7b1675dSTing-Kang Chang keyset_info.key_info(2));
108*e7b1675dSTing-Kang Chang ASSERT_TRUE(entry_result.ok());
109*e7b1675dSTing-Kang Chang // The last key is the primary.
110*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_set->set_primary(entry_result.value()), IsOk());
111*e7b1675dSTing-Kang Chang
112*e7b1675dSTing-Kang Chang // Wrap mac_set and test the resulting Mac.
113*e7b1675dSTing-Kang Chang auto mac_result = MacWrapper().Wrap(std::move(mac_set));
114*e7b1675dSTing-Kang Chang EXPECT_TRUE(mac_result.ok()) << mac_result.status();
115*e7b1675dSTing-Kang Chang std::unique_ptr<Mac> mac = std::move(mac_result.value());
116*e7b1675dSTing-Kang Chang std::string data = "some_data_for_mac";
117*e7b1675dSTing-Kang Chang
118*e7b1675dSTing-Kang Chang auto compute_mac_result = mac->ComputeMac(data);
119*e7b1675dSTing-Kang Chang EXPECT_TRUE(compute_mac_result.ok()) << compute_mac_result.status();
120*e7b1675dSTing-Kang Chang std::string mac_value = compute_mac_result.value();
121*e7b1675dSTing-Kang Chang EXPECT_PRED_FORMAT2(testing::IsSubstring, mac_name_2, mac_value);
122*e7b1675dSTing-Kang Chang
123*e7b1675dSTing-Kang Chang util::Status status = mac->VerifyMac(mac_value, data);
124*e7b1675dSTing-Kang Chang EXPECT_TRUE(status.ok()) << status;
125*e7b1675dSTing-Kang Chang
126*e7b1675dSTing-Kang Chang status = mac->VerifyMac("some bad mac", data);
127*e7b1675dSTing-Kang Chang EXPECT_FALSE(status.ok());
128*e7b1675dSTing-Kang Chang EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code());
129*e7b1675dSTing-Kang Chang EXPECT_PRED_FORMAT2(testing::IsSubstring, "verification failed",
130*e7b1675dSTing-Kang Chang std::string(status.message()));
131*e7b1675dSTing-Kang Chang }
132*e7b1675dSTing-Kang Chang
TEST(MacWrapperTest,testLegacyAuthentication)133*e7b1675dSTing-Kang Chang TEST(MacWrapperTest, testLegacyAuthentication) {
134*e7b1675dSTing-Kang Chang // Prepare a set for the wrapper.
135*e7b1675dSTing-Kang Chang KeysetInfo::KeyInfo key_info;
136*e7b1675dSTing-Kang Chang uint32_t key_id = 1234543;
137*e7b1675dSTing-Kang Chang key_info.set_output_prefix_type(OutputPrefixType::LEGACY);
138*e7b1675dSTing-Kang Chang key_info.set_key_id(key_id);
139*e7b1675dSTing-Kang Chang key_info.set_status(KeyStatusType::ENABLED);
140*e7b1675dSTing-Kang Chang std::string mac_name = "SomeLegacyMac";
141*e7b1675dSTing-Kang Chang
142*e7b1675dSTing-Kang Chang std::unique_ptr<PrimitiveSet<Mac>> mac_set(new PrimitiveSet<Mac>());
143*e7b1675dSTing-Kang Chang std::unique_ptr<Mac> mac(new DummyMac(mac_name));
144*e7b1675dSTing-Kang Chang auto entry_result = mac_set->AddPrimitive(std::move(mac), key_info);
145*e7b1675dSTing-Kang Chang ASSERT_TRUE(entry_result.ok());
146*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_set->set_primary(entry_result.value()), IsOk());
147*e7b1675dSTing-Kang Chang
148*e7b1675dSTing-Kang Chang // Wrap mac_set and test the resulting Mac.
149*e7b1675dSTing-Kang Chang auto mac_result = MacWrapper().Wrap(std::move(mac_set));
150*e7b1675dSTing-Kang Chang EXPECT_TRUE(mac_result.ok()) << mac_result.status();
151*e7b1675dSTing-Kang Chang mac = std::move(mac_result.value());
152*e7b1675dSTing-Kang Chang std::string data = "Some data to authenticate";
153*e7b1675dSTing-Kang Chang
154*e7b1675dSTing-Kang Chang // Compute and verify MAC via wrapper.
155*e7b1675dSTing-Kang Chang auto compute_mac_result = mac->ComputeMac(data);
156*e7b1675dSTing-Kang Chang EXPECT_TRUE(compute_mac_result.ok()) << compute_mac_result.status();
157*e7b1675dSTing-Kang Chang std::string mac_value = compute_mac_result.value();
158*e7b1675dSTing-Kang Chang EXPECT_PRED_FORMAT2(testing::IsSubstring, mac_name, mac_value);
159*e7b1675dSTing-Kang Chang auto status = mac->VerifyMac(mac_value, data);
160*e7b1675dSTing-Kang Chang EXPECT_TRUE(status.ok()) << status;
161*e7b1675dSTing-Kang Chang
162*e7b1675dSTing-Kang Chang // Try verifying on raw Mac-primitive using original data.
163*e7b1675dSTing-Kang Chang std::unique_ptr<Mac> raw_mac(new DummyMac(mac_name)); // same as in wrapper
164*e7b1675dSTing-Kang Chang std::string raw_mac_value = mac_value.substr(CryptoFormat::kNonRawPrefixSize);
165*e7b1675dSTing-Kang Chang status = raw_mac->VerifyMac(raw_mac_value, data);
166*e7b1675dSTing-Kang Chang EXPECT_FALSE(status.ok());
167*e7b1675dSTing-Kang Chang EXPECT_EQ(absl::StatusCode::kInvalidArgument, status.code());
168*e7b1675dSTing-Kang Chang
169*e7b1675dSTing-Kang Chang // Verify on raw Mac-primitive using legacy-formatted data.
170*e7b1675dSTing-Kang Chang std::string legacy_data = data;
171*e7b1675dSTing-Kang Chang legacy_data.append(1, CryptoFormat::kLegacyStartByte);
172*e7b1675dSTing-Kang Chang status = raw_mac->VerifyMac(raw_mac_value, legacy_data);
173*e7b1675dSTing-Kang Chang EXPECT_TRUE(status.ok()) << status;
174*e7b1675dSTing-Kang Chang }
175*e7b1675dSTing-Kang Chang
176*e7b1675dSTing-Kang Chang // Produces a mac which starts in the same way as a legacy non-raw signature.
177*e7b1675dSTing-Kang Chang class TryBreakLegacyMac : public Mac {
178*e7b1675dSTing-Kang Chang public:
ComputeMac(absl::string_view data) const179*e7b1675dSTing-Kang Chang crypto::tink::util::StatusOr<std::string> ComputeMac(
180*e7b1675dSTing-Kang Chang absl::string_view data) const override {
181*e7b1675dSTing-Kang Chang return absl::StrCat(std::string("\x00", 1), "\xff\xff\xff\xff", data);
182*e7b1675dSTing-Kang Chang }
183*e7b1675dSTing-Kang Chang
VerifyMac(absl::string_view mac,absl::string_view data) const184*e7b1675dSTing-Kang Chang crypto::tink::util::Status VerifyMac(absl::string_view mac,
185*e7b1675dSTing-Kang Chang absl::string_view data) const override {
186*e7b1675dSTing-Kang Chang if (mac != ComputeMac(data).value()) {
187*e7b1675dSTing-Kang Chang return absl::InvalidArgumentError("Wrong mac");
188*e7b1675dSTing-Kang Chang }
189*e7b1675dSTing-Kang Chang return util::OkStatus();
190*e7b1675dSTing-Kang Chang }
191*e7b1675dSTing-Kang Chang };
192*e7b1675dSTing-Kang Chang
193*e7b1675dSTing-Kang Chang // Checks that a raw tag can be verified after a legacy tag is verified with
194*e7b1675dSTing-Kang Chang // the same output prefix. (To prevent regression of b/173013224).
TEST(MacWrapperTest,VerifyRawAfterLegacy)195*e7b1675dSTing-Kang Chang TEST(MacWrapperTest, VerifyRawAfterLegacy) {
196*e7b1675dSTing-Kang Chang std::unique_ptr<PrimitiveSet<Mac>> mac_set(new PrimitiveSet<Mac>());
197*e7b1675dSTing-Kang Chang
198*e7b1675dSTing-Kang Chang KeysetInfo::KeyInfo key_info_0;
199*e7b1675dSTing-Kang Chang key_info_0.set_output_prefix_type(OutputPrefixType::RAW);
200*e7b1675dSTing-Kang Chang key_info_0.set_key_id(1234);
201*e7b1675dSTing-Kang Chang key_info_0.set_status(KeyStatusType::ENABLED);
202*e7b1675dSTing-Kang Chang ASSERT_THAT(
203*e7b1675dSTing-Kang Chang mac_set->AddPrimitive(absl::make_unique<TryBreakLegacyMac>(), key_info_0)
204*e7b1675dSTing-Kang Chang .status(),
205*e7b1675dSTing-Kang Chang IsOk());
206*e7b1675dSTing-Kang Chang
207*e7b1675dSTing-Kang Chang KeysetInfo::KeyInfo key_info_1;
208*e7b1675dSTing-Kang Chang key_info_1.set_output_prefix_type(OutputPrefixType::LEGACY);
209*e7b1675dSTing-Kang Chang key_info_1.set_key_id(0xffffffff);
210*e7b1675dSTing-Kang Chang key_info_1.set_status(KeyStatusType::ENABLED);
211*e7b1675dSTing-Kang Chang
212*e7b1675dSTing-Kang Chang auto entry1 =
213*e7b1675dSTing-Kang Chang mac_set->AddPrimitive(absl::make_unique<DummyMac>(""), key_info_1);
214*e7b1675dSTing-Kang Chang ASSERT_THAT(entry1, IsOk());
215*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_set->set_primary(entry1.value()), IsOk());
216*e7b1675dSTing-Kang Chang
217*e7b1675dSTing-Kang Chang // Wrap mac_set and test the resulting Mac.
218*e7b1675dSTing-Kang Chang auto wrapped_mac = MacWrapper().Wrap(std::move(mac_set));
219*e7b1675dSTing-Kang Chang EXPECT_THAT(wrapped_mac, IsOk());
220*e7b1675dSTing-Kang Chang
221*e7b1675dSTing-Kang Chang std::string data = "some data";
222*e7b1675dSTing-Kang Chang std::string mac_tag = TryBreakLegacyMac().ComputeMac(data).value();
223*e7b1675dSTing-Kang Chang EXPECT_THAT(wrapped_mac.value()->VerifyMac(mac_tag, data), IsOk());
224*e7b1675dSTing-Kang Chang }
225*e7b1675dSTing-Kang Chang
PopulateKeyInfo(uint32_t key_id,OutputPrefixType out_prefix_type,KeyStatusType status)226*e7b1675dSTing-Kang Chang KeysetInfo::KeyInfo PopulateKeyInfo(uint32_t key_id,
227*e7b1675dSTing-Kang Chang OutputPrefixType out_prefix_type,
228*e7b1675dSTing-Kang Chang KeyStatusType status) {
229*e7b1675dSTing-Kang Chang KeysetInfo::KeyInfo key_info;
230*e7b1675dSTing-Kang Chang key_info.set_output_prefix_type(out_prefix_type);
231*e7b1675dSTing-Kang Chang key_info.set_key_id(key_id);
232*e7b1675dSTing-Kang Chang key_info.set_status(status);
233*e7b1675dSTing-Kang Chang return key_info;
234*e7b1675dSTing-Kang Chang }
235*e7b1675dSTing-Kang Chang
236*e7b1675dSTing-Kang Chang // Creates a test keyset info object.
CreateTestKeysetInfo()237*e7b1675dSTing-Kang Chang KeysetInfo CreateTestKeysetInfo() {
238*e7b1675dSTing-Kang Chang KeysetInfo keyset_info;
239*e7b1675dSTing-Kang Chang *keyset_info.add_key_info() =
240*e7b1675dSTing-Kang Chang PopulateKeyInfo(/*key_id=*/1234543, OutputPrefixType::TINK,
241*e7b1675dSTing-Kang Chang /*status=*/KeyStatusType::ENABLED);
242*e7b1675dSTing-Kang Chang *keyset_info.add_key_info() =
243*e7b1675dSTing-Kang Chang PopulateKeyInfo(/*key_id=*/726329, OutputPrefixType::LEGACY,
244*e7b1675dSTing-Kang Chang /*status=*/KeyStatusType::ENABLED);
245*e7b1675dSTing-Kang Chang *keyset_info.add_key_info() =
246*e7b1675dSTing-Kang Chang PopulateKeyInfo(/*key_id=*/7213743, OutputPrefixType::TINK,
247*e7b1675dSTing-Kang Chang /*status=*/KeyStatusType::ENABLED);
248*e7b1675dSTing-Kang Chang return keyset_info;
249*e7b1675dSTing-Kang Chang }
250*e7b1675dSTing-Kang Chang
251*e7b1675dSTing-Kang Chang // Tests for the monitoring behavior.
252*e7b1675dSTing-Kang Chang class MacSetWrapperWithMonitoringTest : public Test {
253*e7b1675dSTing-Kang Chang protected:
254*e7b1675dSTing-Kang Chang // Perform some common initialization: reset the global registry, set expected
255*e7b1675dSTing-Kang Chang // calls for the mock monitoring factory and the returned clients.
SetUp()256*e7b1675dSTing-Kang Chang void SetUp() override {
257*e7b1675dSTing-Kang Chang Registry::Reset();
258*e7b1675dSTing-Kang Chang
259*e7b1675dSTing-Kang Chang // Setup mocks for catching Monitoring calls.
260*e7b1675dSTing-Kang Chang auto monitoring_client_factory =
261*e7b1675dSTing-Kang Chang absl::make_unique<MockMonitoringClientFactory>();
262*e7b1675dSTing-Kang Chang auto compute_monitoring_client =
263*e7b1675dSTing-Kang Chang absl::make_unique<NiceMock<MockMonitoringClient>>();
264*e7b1675dSTing-Kang Chang compute_monitoring_client_ = compute_monitoring_client.get();
265*e7b1675dSTing-Kang Chang auto verify_monitoring_client =
266*e7b1675dSTing-Kang Chang absl::make_unique<NiceMock<MockMonitoringClient>>();
267*e7b1675dSTing-Kang Chang verify_monitoring_client_ = verify_monitoring_client.get();
268*e7b1675dSTing-Kang Chang
269*e7b1675dSTing-Kang Chang // Monitoring tests expect that the client factory will create the
270*e7b1675dSTing-Kang Chang // corresponding MockMonitoringClients.
271*e7b1675dSTing-Kang Chang EXPECT_CALL(*monitoring_client_factory, New(_))
272*e7b1675dSTing-Kang Chang .WillOnce(
273*e7b1675dSTing-Kang Chang Return(ByMove(util::StatusOr<std::unique_ptr<MonitoringClient>>(
274*e7b1675dSTing-Kang Chang std::move(compute_monitoring_client)))))
275*e7b1675dSTing-Kang Chang .WillOnce(
276*e7b1675dSTing-Kang Chang Return(ByMove(util::StatusOr<std::unique_ptr<MonitoringClient>>(
277*e7b1675dSTing-Kang Chang std::move(verify_monitoring_client)))));
278*e7b1675dSTing-Kang Chang
279*e7b1675dSTing-Kang Chang ASSERT_THAT(internal::RegistryImpl::GlobalInstance()
280*e7b1675dSTing-Kang Chang .RegisterMonitoringClientFactory(
281*e7b1675dSTing-Kang Chang std::move(monitoring_client_factory)),
282*e7b1675dSTing-Kang Chang IsOk());
283*e7b1675dSTing-Kang Chang ASSERT_THAT(
284*e7b1675dSTing-Kang Chang internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(),
285*e7b1675dSTing-Kang Chang Not(IsNull()));
286*e7b1675dSTing-Kang Chang }
287*e7b1675dSTing-Kang Chang
288*e7b1675dSTing-Kang Chang // Cleanup the registry to avoid mock leaks.
~MacSetWrapperWithMonitoringTest()289*e7b1675dSTing-Kang Chang ~MacSetWrapperWithMonitoringTest() override { Registry::Reset(); }
290*e7b1675dSTing-Kang Chang
291*e7b1675dSTing-Kang Chang MockMonitoringClient* compute_monitoring_client_;
292*e7b1675dSTing-Kang Chang MockMonitoringClient* verify_monitoring_client_;
293*e7b1675dSTing-Kang Chang };
294*e7b1675dSTing-Kang Chang
295*e7b1675dSTing-Kang Chang // Tests that successful ComputeMac operations are logged.
TEST_F(MacSetWrapperWithMonitoringTest,WrapKeysetWithMonitoringComputeSuccess)296*e7b1675dSTing-Kang Chang TEST_F(MacSetWrapperWithMonitoringTest,
297*e7b1675dSTing-Kang Chang WrapKeysetWithMonitoringComputeSuccess) {
298*e7b1675dSTing-Kang Chang // Create a primitive set and fill it with some entries
299*e7b1675dSTing-Kang Chang KeysetInfo keyset_info = CreateTestKeysetInfo();
300*e7b1675dSTing-Kang Chang const absl::flat_hash_map<std::string, std::string> annotations = {
301*e7b1675dSTing-Kang Chang {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}};
302*e7b1675dSTing-Kang Chang auto mac_primitive_set = absl::make_unique<PrimitiveSet<Mac>>(annotations);
303*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set
304*e7b1675dSTing-Kang Chang ->AddPrimitive(absl::make_unique<DummyMac>("mac0"),
305*e7b1675dSTing-Kang Chang keyset_info.key_info(0))
306*e7b1675dSTing-Kang Chang .status(),
307*e7b1675dSTing-Kang Chang IsOk());
308*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set
309*e7b1675dSTing-Kang Chang ->AddPrimitive(absl::make_unique<DummyMac>("mac1"),
310*e7b1675dSTing-Kang Chang keyset_info.key_info(1))
311*e7b1675dSTing-Kang Chang .status(),
312*e7b1675dSTing-Kang Chang IsOk());
313*e7b1675dSTing-Kang Chang // Set the last as primary.
314*e7b1675dSTing-Kang Chang util::StatusOr<PrimitiveSet<Mac>::Entry<Mac>*> last =
315*e7b1675dSTing-Kang Chang mac_primitive_set->AddPrimitive(absl::make_unique<DummyMac>("mac2"),
316*e7b1675dSTing-Kang Chang keyset_info.key_info(2));
317*e7b1675dSTing-Kang Chang ASSERT_THAT(last.status(), IsOk());
318*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set->set_primary(*last), IsOk());
319*e7b1675dSTing-Kang Chang // Record the ID of the primary key.
320*e7b1675dSTing-Kang Chang const uint32_t primary_key_id = keyset_info.key_info(2).key_id();
321*e7b1675dSTing-Kang Chang
322*e7b1675dSTing-Kang Chang // Create a MAC and compute an authentication tag
323*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<Mac>> mac =
324*e7b1675dSTing-Kang Chang MacWrapper().Wrap(std::move(mac_primitive_set));
325*e7b1675dSTing-Kang Chang ASSERT_THAT(mac, IsOkAndHolds(NotNull()));
326*e7b1675dSTing-Kang Chang
327*e7b1675dSTing-Kang Chang constexpr absl::string_view message = "This is some message!";
328*e7b1675dSTing-Kang Chang
329*e7b1675dSTing-Kang Chang // Check that calling ComputeMac triggers a Log() call.
330*e7b1675dSTing-Kang Chang EXPECT_CALL(*compute_monitoring_client_, Log(primary_key_id, message.size()));
331*e7b1675dSTing-Kang Chang EXPECT_THAT((*mac)->ComputeMac(message).status(), IsOk());
332*e7b1675dSTing-Kang Chang }
333*e7b1675dSTing-Kang Chang
334*e7b1675dSTing-Kang Chang // Test that successful VerifyMac operations are logged.
TEST_F(MacSetWrapperWithMonitoringTest,WrapKeysetWithMonitoringVerifySuccess)335*e7b1675dSTing-Kang Chang TEST_F(MacSetWrapperWithMonitoringTest,
336*e7b1675dSTing-Kang Chang WrapKeysetWithMonitoringVerifySuccess) {
337*e7b1675dSTing-Kang Chang // Create a primitive set and fill it with some entries
338*e7b1675dSTing-Kang Chang KeysetInfo keyset_info = CreateTestKeysetInfo();
339*e7b1675dSTing-Kang Chang const absl::flat_hash_map<std::string, std::string> annotations = {
340*e7b1675dSTing-Kang Chang {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}};
341*e7b1675dSTing-Kang Chang auto mac_primitive_set = absl::make_unique<PrimitiveSet<Mac>>(annotations);
342*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set
343*e7b1675dSTing-Kang Chang ->AddPrimitive(absl::make_unique<DummyMac>("mac0"),
344*e7b1675dSTing-Kang Chang keyset_info.key_info(0))
345*e7b1675dSTing-Kang Chang .status(),
346*e7b1675dSTing-Kang Chang IsOk());
347*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set
348*e7b1675dSTing-Kang Chang ->AddPrimitive(absl::make_unique<DummyMac>("mac1"),
349*e7b1675dSTing-Kang Chang keyset_info.key_info(1))
350*e7b1675dSTing-Kang Chang .status(),
351*e7b1675dSTing-Kang Chang IsOk());
352*e7b1675dSTing-Kang Chang // Set the last as primary.
353*e7b1675dSTing-Kang Chang util::StatusOr<PrimitiveSet<Mac>::Entry<Mac>*> last =
354*e7b1675dSTing-Kang Chang mac_primitive_set->AddPrimitive(absl::make_unique<DummyMac>("mac2"),
355*e7b1675dSTing-Kang Chang keyset_info.key_info(2));
356*e7b1675dSTing-Kang Chang ASSERT_THAT(last.status(), IsOk());
357*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set->set_primary(*last), IsOk());
358*e7b1675dSTing-Kang Chang // Record the ID of the primary key.
359*e7b1675dSTing-Kang Chang const uint32_t primary_key_id = keyset_info.key_info(2).key_id();
360*e7b1675dSTing-Kang Chang
361*e7b1675dSTing-Kang Chang // Create a MAC, compute a Mac and verify it.
362*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<Mac>> mac =
363*e7b1675dSTing-Kang Chang MacWrapper().Wrap(std::move(mac_primitive_set));
364*e7b1675dSTing-Kang Chang ASSERT_THAT(mac, IsOkAndHolds(NotNull()));
365*e7b1675dSTing-Kang Chang
366*e7b1675dSTing-Kang Chang constexpr absl::string_view message = "This is some message!";
367*e7b1675dSTing-Kang Chang
368*e7b1675dSTing-Kang Chang // Check that calling VerifyMac triggers a Log() call.
369*e7b1675dSTing-Kang Chang util::StatusOr<std::string> tag = (*mac)->ComputeMac(message);
370*e7b1675dSTing-Kang Chang EXPECT_THAT(tag.status(), IsOk());
371*e7b1675dSTing-Kang Chang
372*e7b1675dSTing-Kang Chang // In the log expect the size of the message without the non-raw prefix.
373*e7b1675dSTing-Kang Chang EXPECT_CALL(*verify_monitoring_client_, Log(primary_key_id, message.size()));
374*e7b1675dSTing-Kang Chang EXPECT_THAT((*mac)->VerifyMac(*tag, message), IsOk());
375*e7b1675dSTing-Kang Chang }
376*e7b1675dSTing-Kang Chang
TEST_F(MacSetWrapperWithMonitoringTest,WrapKeysetWithMonitoringComputeFailures)377*e7b1675dSTing-Kang Chang TEST_F(MacSetWrapperWithMonitoringTest,
378*e7b1675dSTing-Kang Chang WrapKeysetWithMonitoringComputeFailures) {
379*e7b1675dSTing-Kang Chang // Create a primitive set and fill it with some entries.
380*e7b1675dSTing-Kang Chang KeysetInfo keyset_info = CreateTestKeysetInfo();
381*e7b1675dSTing-Kang Chang const absl::flat_hash_map<std::string, std::string> annotations = {
382*e7b1675dSTing-Kang Chang {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}};
383*e7b1675dSTing-Kang Chang auto mac_primitive_set = absl::make_unique<PrimitiveSet<Mac>>(annotations);
384*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set
385*e7b1675dSTing-Kang Chang ->AddPrimitive(CreateAlwaysFailingMac("mac "),
386*e7b1675dSTing-Kang Chang keyset_info.key_info(0))
387*e7b1675dSTing-Kang Chang .status(),
388*e7b1675dSTing-Kang Chang IsOk());
389*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set
390*e7b1675dSTing-Kang Chang ->AddPrimitive(CreateAlwaysFailingMac("mac "),
391*e7b1675dSTing-Kang Chang keyset_info.key_info(1))
392*e7b1675dSTing-Kang Chang .status(),
393*e7b1675dSTing-Kang Chang IsOk());
394*e7b1675dSTing-Kang Chang // Set the last as primary.
395*e7b1675dSTing-Kang Chang util::StatusOr<PrimitiveSet<Mac>::Entry<Mac>*> last =
396*e7b1675dSTing-Kang Chang mac_primitive_set->AddPrimitive(CreateAlwaysFailingMac("mac "),
397*e7b1675dSTing-Kang Chang keyset_info.key_info(2));
398*e7b1675dSTing-Kang Chang ASSERT_THAT(last.status(), IsOk());
399*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set->set_primary(*last), IsOk());
400*e7b1675dSTing-Kang Chang
401*e7b1675dSTing-Kang Chang // Create a MAC and compute a tag.
402*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<Mac>> mac =
403*e7b1675dSTing-Kang Chang MacWrapper().Wrap(std::move(mac_primitive_set));
404*e7b1675dSTing-Kang Chang ASSERT_THAT(mac, IsOkAndHolds(NotNull()));
405*e7b1675dSTing-Kang Chang
406*e7b1675dSTing-Kang Chang constexpr absl::string_view message = "This is some message!";
407*e7b1675dSTing-Kang Chang
408*e7b1675dSTing-Kang Chang // Check that calling ComputeMac triggers a LogFailure() call.
409*e7b1675dSTing-Kang Chang EXPECT_CALL(*compute_monitoring_client_, LogFailure());
410*e7b1675dSTing-Kang Chang EXPECT_THAT((*mac)->ComputeMac(message).status(),
411*e7b1675dSTing-Kang Chang StatusIs(absl::StatusCode::kInternal));
412*e7b1675dSTing-Kang Chang }
413*e7b1675dSTing-Kang Chang
414*e7b1675dSTing-Kang Chang // Test that monitoring logs verify failures correctly.
TEST_F(MacSetWrapperWithMonitoringTest,WrapKeysetWithMonitoringVerifyFailures)415*e7b1675dSTing-Kang Chang TEST_F(MacSetWrapperWithMonitoringTest,
416*e7b1675dSTing-Kang Chang WrapKeysetWithMonitoringVerifyFailures) {
417*e7b1675dSTing-Kang Chang // Create a primitive set and fill it with some entries.
418*e7b1675dSTing-Kang Chang KeysetInfo keyset_info = CreateTestKeysetInfo();
419*e7b1675dSTing-Kang Chang const absl::flat_hash_map<std::string, std::string> annotations = {
420*e7b1675dSTing-Kang Chang {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}};
421*e7b1675dSTing-Kang Chang auto mac_primitive_set = absl::make_unique<PrimitiveSet<Mac>>(annotations);
422*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set
423*e7b1675dSTing-Kang Chang ->AddPrimitive(CreateAlwaysFailingMac("mac "),
424*e7b1675dSTing-Kang Chang keyset_info.key_info(0))
425*e7b1675dSTing-Kang Chang .status(),
426*e7b1675dSTing-Kang Chang IsOk());
427*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set
428*e7b1675dSTing-Kang Chang ->AddPrimitive(CreateAlwaysFailingMac("mac "),
429*e7b1675dSTing-Kang Chang keyset_info.key_info(1))
430*e7b1675dSTing-Kang Chang .status(),
431*e7b1675dSTing-Kang Chang IsOk());
432*e7b1675dSTing-Kang Chang // Set the last as primary.
433*e7b1675dSTing-Kang Chang util::StatusOr<PrimitiveSet<Mac>::Entry<Mac>*> last =
434*e7b1675dSTing-Kang Chang mac_primitive_set->AddPrimitive(CreateAlwaysFailingMac("mac "),
435*e7b1675dSTing-Kang Chang keyset_info.key_info(2));
436*e7b1675dSTing-Kang Chang ASSERT_THAT(last.status(), IsOk());
437*e7b1675dSTing-Kang Chang ASSERT_THAT(mac_primitive_set->set_primary(*last), IsOk());
438*e7b1675dSTing-Kang Chang
439*e7b1675dSTing-Kang Chang // Create a MAC and verify a tag.
440*e7b1675dSTing-Kang Chang util::StatusOr<std::unique_ptr<Mac>> mac =
441*e7b1675dSTing-Kang Chang MacWrapper().Wrap(std::move(mac_primitive_set));
442*e7b1675dSTing-Kang Chang ASSERT_THAT(mac, IsOkAndHolds(NotNull()));
443*e7b1675dSTing-Kang Chang
444*e7b1675dSTing-Kang Chang constexpr absl::string_view message = "This is some message!";
445*e7b1675dSTing-Kang Chang constexpr absl::string_view tag = "some invalid tag!";
446*e7b1675dSTing-Kang Chang
447*e7b1675dSTing-Kang Chang // Check that calling VerifyMac triggers a LogFailure() call.
448*e7b1675dSTing-Kang Chang EXPECT_CALL(*verify_monitoring_client_, LogFailure());
449*e7b1675dSTing-Kang Chang EXPECT_THAT((*mac)->VerifyMac(tag, message),
450*e7b1675dSTing-Kang Chang StatusIs(absl::StatusCode::kInvalidArgument));
451*e7b1675dSTing-Kang Chang }
452*e7b1675dSTing-Kang Chang
453*e7b1675dSTing-Kang Chang } // namespace
454*e7b1675dSTing-Kang Chang } // namespace tink
455*e7b1675dSTing-Kang Chang } // namespace crypto
456