1 // Copyright 2022 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/mac/internal/chunked_mac_impl.h"
18
19 #include <memory>
20 #include <string>
21 #include <utility>
22
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "tink/chunked_mac.h"
26 #include "tink/subtle/mac/stateful_mac.h"
27 #include "tink/util/status.h"
28 #include "tink/util/statusor.h"
29 #include "tink/util/test_matchers.h"
30 #include "proto/aes_cmac.pb.h"
31 #include "proto/common.pb.h"
32 #include "proto/hmac.pb.h"
33
34 namespace crypto {
35 namespace tink {
36 namespace internal {
37 namespace {
38
39 using ::crypto::tink::test::IsOk;
40 using ::crypto::tink::test::IsOkAndHolds;
41 using ::crypto::tink::test::StatusIs;
42 using ::google::crypto::tink::AesCmacKey;
43 using ::google::crypto::tink::AesCmacParams;
44 using ::google::crypto::tink::HashType;
45 using ::google::crypto::tink::HmacKey;
46 using ::google::crypto::tink::HmacParams;
47 using ::testing::_;
48 using ::testing::ByMove;
49 using ::testing::Return;
50
51 class MockStatefulMac : public subtle::StatefulMac {
52 public:
53 MOCK_METHOD(util::Status, Update, (absl::string_view), (override));
54 MOCK_METHOD(util::StatusOr<std::string>, Finalize, (), (override));
55 };
56
57 class MockStatefulMacFactory : public subtle::StatefulMacFactory {
58 public:
59 MOCK_METHOD(util::StatusOr<std::unique_ptr<subtle::StatefulMac>>, Create, (),
60 (const, override));
61 };
62
TEST(ChunkedMacFactoryTest,NewChunkedCmacSucceeds)63 TEST(ChunkedMacFactoryTest, NewChunkedCmacSucceeds) {
64 AesCmacParams params;
65 params.set_tag_size(16);
66 AesCmacKey key;
67 *key.mutable_params() = params;
68
69 EXPECT_THAT(NewChunkedCmac(key), IsOk());
70 }
71
TEST(ChunkedMacFactoryTest,NewChunkedCmacWithMissingKeyParamsFails)72 TEST(ChunkedMacFactoryTest, NewChunkedCmacWithMissingKeyParamsFails) {
73 EXPECT_THAT(NewChunkedCmac(AesCmacKey()).status(),
74 StatusIs(absl::StatusCode::kInvalidArgument));
75 }
76
TEST(ChunkedMacFactoryTest,NewChunkedHmacSucceeds)77 TEST(ChunkedMacFactoryTest, NewChunkedHmacSucceeds) {
78 HmacParams params;
79 params.set_hash(HashType::SHA256);
80 params.set_tag_size(16);
81 HmacKey key;
82 *key.mutable_params() = params;
83
84 EXPECT_THAT(NewChunkedHmac(key), IsOk());
85 }
86
TEST(ChunkedMacFactoryTest,NewChunkedHmacWithMissingKeyParamsFails)87 TEST(ChunkedMacFactoryTest, NewChunkedHmacWithMissingKeyParamsFails) {
88 EXPECT_THAT(NewChunkedHmac(HmacKey()).status(),
89 StatusIs(absl::StatusCode::kInvalidArgument));
90 }
91
TEST(ChunkedMacImplTest,CreateComputationSucceeds)92 TEST(ChunkedMacImplTest, CreateComputationSucceeds) {
93 auto factory = absl::make_unique<MockStatefulMacFactory>();
94 auto stateful_mac = absl::make_unique<MockStatefulMac>();
95 EXPECT_CALL(*factory, Create())
96 .WillOnce(
97 Return(ByMove(util::StatusOr<std::unique_ptr<subtle::StatefulMac>>(
98 std::move(stateful_mac)))));
99 ChunkedMacImpl chunked_mac(std::move(factory));
100
101 EXPECT_THAT(chunked_mac.CreateComputation(), IsOk());
102 }
103
TEST(ChunkedMacImplTest,CreateComputationWithFactoryErrorFails)104 TEST(ChunkedMacImplTest, CreateComputationWithFactoryErrorFails) {
105 auto factory = absl::make_unique<MockStatefulMacFactory>();
106 util::StatusOr<std::unique_ptr<subtle::StatefulMac>> error_status =
107 util::Status(absl::StatusCode::kInternal, "Internal error.");
108 EXPECT_CALL(*factory, Create())
109 .WillOnce(Return(ByMove(std::move(error_status))));
110 ChunkedMacImpl chunked_mac(std::move(factory));
111
112 EXPECT_THAT(chunked_mac.CreateComputation().status(),
113 StatusIs(absl::StatusCode::kInternal));
114 }
115
TEST(ChunkedMacImplTest,CreateVerificationSucceeds)116 TEST(ChunkedMacImplTest, CreateVerificationSucceeds) {
117 auto factory = absl::make_unique<MockStatefulMacFactory>();
118 auto stateful_mac = absl::make_unique<MockStatefulMac>();
119 EXPECT_CALL(*factory, Create())
120 .WillOnce(
121 Return(ByMove(util::StatusOr<std::unique_ptr<subtle::StatefulMac>>(
122 std::move(stateful_mac)))));
123 ChunkedMacImpl chunked_mac(std::move(factory));
124
125 EXPECT_THAT(chunked_mac.CreateVerification("tag"), IsOk());
126 }
127
TEST(ChunkedMacImplTest,CreateVerificationWithFactoryErrorFails)128 TEST(ChunkedMacImplTest, CreateVerificationWithFactoryErrorFails) {
129 auto factory = absl::make_unique<MockStatefulMacFactory>();
130 util::StatusOr<std::unique_ptr<subtle::StatefulMac>> error_status =
131 util::Status(absl::StatusCode::kInternal, "Internal error.");
132 EXPECT_CALL(*factory, Create())
133 .WillOnce(Return(ByMove(std::move(error_status))));
134 ChunkedMacImpl chunked_mac(std::move(factory));
135
136 EXPECT_THAT(chunked_mac.CreateVerification("tag").status(),
137 StatusIs(absl::StatusCode::kInternal));
138 }
139
TEST(ChunkedMacComputationImplTest,UpdateSucceeds)140 TEST(ChunkedMacComputationImplTest, UpdateSucceeds) {
141 auto stateful_mac = absl::make_unique<MockStatefulMac>();
142 EXPECT_CALL(*stateful_mac, Update(_)).WillOnce(Return(util::OkStatus()));
143 ChunkedMacComputationImpl mac_computation(std::move(stateful_mac));
144
145 EXPECT_THAT(mac_computation.Update("data"), IsOk());
146 }
147
TEST(ChunkedMacComputationImplTest,UpdateFails)148 TEST(ChunkedMacComputationImplTest, UpdateFails) {
149 auto stateful_mac = absl::make_unique<MockStatefulMac>();
150 util::Status error_status =
151 util::Status(absl::StatusCode::kInternal, "Internal error.");
152 EXPECT_CALL(*stateful_mac, Update(_)).WillOnce(Return(error_status));
153 ChunkedMacComputationImpl mac_computation(std::move(stateful_mac));
154
155 EXPECT_THAT(mac_computation.Update("data"), StatusIs(error_status.code()));
156 }
157
TEST(ChunkedMacComputationImplTest,OperationsFailAfterComputeMac)158 TEST(ChunkedMacComputationImplTest, OperationsFailAfterComputeMac) {
159 auto stateful_mac = absl::make_unique<MockStatefulMac>();
160 util::StatusOr<std::string> tag = std::string("tag");
161 EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag));
162 ChunkedMacComputationImpl mac_computation(std::move(stateful_mac));
163
164 EXPECT_THAT(mac_computation.ComputeMac(), IsOkAndHolds(*tag));
165
166 EXPECT_THAT(mac_computation.Update("data"),
167 StatusIs(absl::StatusCode::kFailedPrecondition));
168 EXPECT_THAT(mac_computation.ComputeMac().status(),
169 StatusIs(absl::StatusCode::kFailedPrecondition));
170 }
171
TEST(ChunkedMacComputationImplTest,ComputeMacSucceeds)172 TEST(ChunkedMacComputationImplTest, ComputeMacSucceeds) {
173 auto stateful_mac = absl::make_unique<MockStatefulMac>();
174 util::StatusOr<std::string> tag = std::string("tag");
175 EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag));
176 ChunkedMacComputationImpl mac_computation(std::move(stateful_mac));
177
178 EXPECT_THAT(mac_computation.ComputeMac(), IsOkAndHolds(*tag));
179 }
180
TEST(ChunkedMacComputationImplTest,ComputeMacFails)181 TEST(ChunkedMacComputationImplTest, ComputeMacFails) {
182 auto stateful_mac = absl::make_unique<MockStatefulMac>();
183 util::Status error_status =
184 util::Status(absl::StatusCode::kInternal, "Internal error.");
185 EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(error_status));
186 ChunkedMacComputationImpl mac_computation(std::move(stateful_mac));
187
188 EXPECT_THAT(mac_computation.ComputeMac().status(),
189 StatusIs(error_status.code()));
190 }
191
TEST(ChunkedMacVerificationImplTest,UpdateSucceeds)192 TEST(ChunkedMacVerificationImplTest, UpdateSucceeds) {
193 auto stateful_mac = absl::make_unique<MockStatefulMac>();
194 EXPECT_CALL(*stateful_mac, Update(_)).WillOnce(Return(util::OkStatus()));
195 ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), "tag");
196
197 EXPECT_THAT(mac_verification.Update("data"), IsOk());
198 }
199
TEST(ChunkedMacVerificationImplTest,UpdateFails)200 TEST(ChunkedMacVerificationImplTest, UpdateFails) {
201 auto stateful_mac = absl::make_unique<MockStatefulMac>();
202 util::Status error_status =
203 util::Status(absl::StatusCode::kInternal, "Internal error.");
204 EXPECT_CALL(*stateful_mac, Update(_)).WillOnce(Return(error_status));
205 ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), "tag");
206
207 EXPECT_THAT(mac_verification.Update("data"), StatusIs(error_status.code()));
208 }
209
TEST(ChunkedMacVerificationImplTest,VerifyMacSucceeds)210 TEST(ChunkedMacVerificationImplTest, VerifyMacSucceeds) {
211 auto stateful_mac = absl::make_unique<MockStatefulMac>();
212 util::StatusOr<std::string> tag = std::string("tag");
213 EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag));
214 ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), *tag);
215
216 EXPECT_THAT(mac_verification.VerifyMac(), IsOk());
217 }
218
TEST(ChunkedMacVerificationImplTest,VerifyMacFailsWithInvalidSameLengthTag)219 TEST(ChunkedMacVerificationImplTest, VerifyMacFailsWithInvalidSameLengthTag) {
220 auto stateful_mac = absl::make_unique<MockStatefulMac>();
221 util::StatusOr<std::string> tag = std::string("tag123");
222 EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag));
223 ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac),
224 "tag456");
225
226 EXPECT_THAT(mac_verification.VerifyMac(),
227 StatusIs(absl::StatusCode::kInvalidArgument));
228 }
229
TEST(ChunkedMacVerificationImplTest,VerifyMacFailsWithDifferentLengthTag)230 TEST(ChunkedMacVerificationImplTest, VerifyMacFailsWithDifferentLengthTag) {
231 auto stateful_mac = absl::make_unique<MockStatefulMac>();
232 util::StatusOr<std::string> tag = std::string("tag");
233 EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag));
234 ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac),
235 "tag456");
236
237 EXPECT_THAT(mac_verification.VerifyMac(),
238 StatusIs(absl::StatusCode::kInvalidArgument));
239 }
240
TEST(ChunkedMacVerificationImplTest,VerifyMacFailsWithFinalizeError)241 TEST(ChunkedMacVerificationImplTest, VerifyMacFailsWithFinalizeError) {
242 auto stateful_mac = absl::make_unique<MockStatefulMac>();
243 util::Status error_status =
244 util::Status(absl::StatusCode::kInternal, "Internal error.");
245 EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(error_status));
246 ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), "tag");
247
248 EXPECT_THAT(mac_verification.VerifyMac(), StatusIs(error_status.code()));
249 }
250
TEST(ChunkedMacVerificationImplTest,OperationsFailAfterVerifyMac)251 TEST(ChunkedMacVerificationImplTest, OperationsFailAfterVerifyMac) {
252 auto stateful_mac = absl::make_unique<MockStatefulMac>();
253 util::StatusOr<std::string> tag = std::string("tag");
254 EXPECT_CALL(*stateful_mac, Finalize()).WillOnce(Return(tag));
255 ChunkedMacVerificationImpl mac_verification(std::move(stateful_mac), *tag);
256
257 EXPECT_THAT(mac_verification.VerifyMac(), IsOk());
258
259 EXPECT_THAT(mac_verification.Update("data"),
260 StatusIs(absl::StatusCode::kFailedPrecondition));
261 EXPECT_THAT(mac_verification.VerifyMac(),
262 StatusIs(absl::StatusCode::kFailedPrecondition));
263 }
264
265 } // namespace
266 } // namespace internal
267 } // namespace tink
268 } // namespace crypto
269