1 // Copyright 2017 Google Inc.
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/subtle/aes_cmac_boringssl.h"
18
19 #include <memory>
20 #include <string>
21 #include <utility>
22
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "absl/status/status.h"
26 #include "absl/strings/escaping.h"
27 #include "absl/strings/string_view.h"
28 #include "tink/config/tink_fips.h"
29 #include "tink/mac.h"
30 #include "tink/subtle/common_enums.h"
31 #include "tink/util/secret_data.h"
32 #include "tink/util/status.h"
33 #include "tink/util/statusor.h"
34 #include "tink/util/test_matchers.h"
35
36 namespace crypto {
37 namespace tink {
38 namespace subtle {
39 namespace {
40
41 using ::crypto::tink::test::IsOk;
42 using ::crypto::tink::test::StatusIs;
43 using ::testing::Not;
44 using ::testing::SizeIs;
45
46 constexpr uint32_t kTagSize = 16;
47 constexpr uint32_t kSmallTagSize = 10;
48
49 constexpr absl::string_view kKey256Hex =
50 "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f";
51
52 constexpr absl::string_view kMessage = "Some data to test.";
53
TEST(AesCmacBoringSslTest,Basic)54 TEST(AesCmacBoringSslTest, Basic) {
55 if (IsFipsModeEnabled()) {
56 GTEST_SKIP() << "Not supported in FIPS-only mode";
57 }
58
59 util::SecretData key =
60 util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex));
61 util::StatusOr<std::unique_ptr<Mac>> cmac =
62 AesCmacBoringSsl::New(key, kTagSize);
63 ASSERT_THAT(cmac, IsOk());
64 { // Test with some example data.
65 util::StatusOr<std::string> tag = (*cmac)->ComputeMac(kMessage);
66 EXPECT_THAT(tag, IsOk());
67 EXPECT_THAT(*tag, SizeIs(kTagSize));
68 EXPECT_THAT((*cmac)->VerifyMac(*tag, kMessage), IsOk())
69 << "tag:" << absl::BytesToHexString(*tag);
70 }
71 { // Test with empty example data.
72 absl::string_view data;
73 util::StatusOr<std::string> tag = (*cmac)->ComputeMac(data);
74 EXPECT_THAT(tag, IsOk());
75 EXPECT_THAT(*tag, SizeIs(kTagSize));
76 EXPECT_THAT((*cmac)->VerifyMac(*tag, data), IsOk())
77 << "tag:" << absl::BytesToHexString(*tag);
78 }
79 }
80
TEST(AesCmacBoringSslTest,Modification)81 TEST(AesCmacBoringSslTest, Modification) {
82 if (IsFipsModeEnabled()) {
83 GTEST_SKIP() << "Not supported in FIPS-only mode";
84 }
85
86 util::SecretData key =
87 util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex));
88 util::StatusOr<std::unique_ptr<Mac>> cmac =
89 AesCmacBoringSsl::New(key, kTagSize);
90 ASSERT_THAT(cmac, IsOk());
91 util::StatusOr<std::string> tag = (*cmac)->ComputeMac(kMessage);
92 ASSERT_THAT(tag, IsOk());
93 EXPECT_THAT((*cmac)->VerifyMac(*tag, kMessage), IsOk());
94 const size_t num_bits = tag->size() * 8;
95 for (size_t i = 0; i < num_bits; i++) {
96 std::string modified_tag = *tag;
97 modified_tag[i / 8] ^= 1 << (i % 8);
98 EXPECT_THAT((*cmac)->VerifyMac(modified_tag, kMessage), Not(IsOk()))
99 << "tag:" << absl::BytesToHexString(*tag)
100 << " modified:" << absl::BytesToHexString(modified_tag);
101 }
102 }
103
TEST(AesCmacBoringSslTest,Truncation)104 TEST(AesCmacBoringSslTest, Truncation) {
105 if (IsFipsModeEnabled()) {
106 GTEST_SKIP() << "Not supported in FIPS-only mode";
107 }
108
109 util::SecretData key =
110 util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex));
111 util::StatusOr<std::unique_ptr<Mac>> cmac =
112 AesCmacBoringSsl::New(key, kTagSize);
113 ASSERT_THAT(cmac, IsOk());
114 util::StatusOr<std::string> tag = (*cmac)->ComputeMac(kMessage);
115 ASSERT_THAT(tag, IsOk());
116 EXPECT_THAT((*cmac)->VerifyMac(*tag, kMessage), IsOk());
117 for (size_t i = 0; i < tag->size(); i++) {
118 std::string modified_tag(*tag, 0, i);
119 EXPECT_FALSE((*cmac)->VerifyMac(modified_tag, kMessage).ok())
120 << "tag:" << absl::BytesToHexString(*tag)
121 << " modified:" << absl::BytesToHexString(modified_tag);
122 }
123 }
124
TEST(AesCmacBoringSslTest,BasicSmallTag)125 TEST(AesCmacBoringSslTest, BasicSmallTag) {
126 if (IsFipsModeEnabled()) {
127 GTEST_SKIP() << "Not supported in FIPS-only mode";
128 }
129
130 util::SecretData key =
131 util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex));
132 util::StatusOr<std::unique_ptr<Mac>> cmac =
133 AesCmacBoringSsl::New(key, kSmallTagSize);
134 EXPECT_THAT(cmac, IsOk());
135 { // Test with some example data.
136 std::string data = "Some data to test.";
137 util::StatusOr<std::string> tag = (*cmac)->ComputeMac(data);
138 EXPECT_THAT(tag, IsOk());
139 EXPECT_EQ(kSmallTagSize, tag->size());
140 EXPECT_THAT((*cmac)->VerifyMac(*tag, data), IsOk())
141 << "tag:" << absl::BytesToHexString(*tag);
142 }
143 { // Test with empty example data.
144 absl::string_view data;
145 util::StatusOr<std::string> tag = (*cmac)->ComputeMac(data);
146 EXPECT_THAT(tag, IsOk());
147 EXPECT_EQ(kSmallTagSize, tag->size());
148 EXPECT_THAT((*cmac)->VerifyMac(*tag, data), IsOk())
149 << "tag:" << absl::BytesToHexString(*tag);
150 }
151 }
152
TEST(AesCmacBoringSslTest,ModificationSmallTag)153 TEST(AesCmacBoringSslTest, ModificationSmallTag) {
154 if (IsFipsModeEnabled()) {
155 GTEST_SKIP() << "Not supported in FIPS-only mode";
156 }
157
158 util::SecretData key =
159 util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex));
160 util::StatusOr<std::unique_ptr<Mac>> cmac =
161 AesCmacBoringSsl::New(key, kSmallTagSize);
162 ASSERT_THAT(cmac, IsOk());
163 util::StatusOr<std::string> tag = (*cmac)->ComputeMac(kMessage);
164 ASSERT_THAT(tag, IsOk());
165 auto status = (*cmac)->VerifyMac(*tag, kMessage);
166 EXPECT_THAT((*cmac)->VerifyMac(*tag, kMessage), IsOk());
167 size_t num_bits = tag->size() * 8;
168 for (size_t i = 0; i < num_bits; i++) {
169 std::string modified_tag = *tag;
170 modified_tag[i / 8] ^= 1 << (i % 8);
171 EXPECT_THAT((*cmac)->VerifyMac(modified_tag, kMessage), Not(IsOk()))
172 << "tag:" << absl::BytesToHexString(*tag)
173 << " modified:" << absl::BytesToHexString(modified_tag);
174 }
175 }
176
TEST(AesCmacBoringSslTest,TruncationOrAdditionSmallTag)177 TEST(AesCmacBoringSslTest, TruncationOrAdditionSmallTag) {
178 if (IsFipsModeEnabled()) {
179 GTEST_SKIP() << "Not supported in FIPS-only mode";
180 }
181
182 util::SecretData key =
183 util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex));
184 util::StatusOr<std::unique_ptr<Mac>> cmac =
185 AesCmacBoringSsl::New(key, kSmallTagSize);
186 ASSERT_THAT(cmac, IsOk());
187 util::StatusOr<std::string> tag = (*cmac)->ComputeMac(kMessage);
188 ASSERT_THAT(tag, IsOk());
189 EXPECT_THAT((*cmac)->VerifyMac(*tag, kMessage), IsOk());
190 for (size_t i = 0; i < kSmallTagSize; i++) {
191 std::string modified_tag(*tag, 0, i);
192 EXPECT_THAT((*cmac)->VerifyMac(modified_tag, kMessage), Not(IsOk()))
193 << "tag:" << absl::BytesToHexString(*tag)
194 << " modified:" << absl::BytesToHexString(modified_tag);
195 }
196 for (size_t i = kSmallTagSize + 1; i < kTagSize; i++) {
197 std::string modified_tag(*tag + std::string(i - kSmallTagSize, 'x'));
198 EXPECT_THAT((*cmac)->VerifyMac(modified_tag, kMessage), Not(IsOk()))
199 << "tag:" << absl::BytesToHexString(*tag)
200 << " modified:" << absl::BytesToHexString(modified_tag);
201 }
202 }
203
TEST(AesCmacBoringSslTest,InvalidKeySizes)204 TEST(AesCmacBoringSslTest, InvalidKeySizes) {
205 if (IsFipsModeEnabled()) {
206 GTEST_SKIP() << "Not supported in FIPS-only mode";
207 }
208
209 for (int keysize = 0; keysize < 65; keysize++) {
210 util::SecretData key(keysize, 'x');
211 util::StatusOr<std::unique_ptr<Mac>> cmac =
212 AesCmacBoringSsl::New(key, kTagSize);
213 if (keysize == 16 || keysize == 32) {
214 EXPECT_THAT(cmac, IsOk());
215 } else {
216 EXPECT_THAT(cmac, Not(IsOk()));
217 }
218 }
219 }
220
TEST(AesCmacBoringSslTest,InvalidTagSizes)221 TEST(AesCmacBoringSslTest, InvalidTagSizes) {
222 if (IsFipsModeEnabled()) {
223 GTEST_SKIP() << "Not supported in FIPS-only mode";
224 }
225
226 for (int tagsize = 0; tagsize < 65; tagsize++) {
227 util::SecretData key(32, 'x');
228 util::StatusOr<std::unique_ptr<Mac>> cmac =
229 AesCmacBoringSsl::New(key, tagsize);
230 if (tagsize <= 16) {
231 EXPECT_THAT(cmac, IsOk());
232 } else {
233 EXPECT_THAT(cmac, Not(IsOk()));
234 }
235 }
236 }
237
238 class AesCmacBoringSslTestVectorTest
239 : public ::testing::TestWithParam<std::pair<int, std::string>> {
240 public:
241 // Utility to simplify testing with test vectors. Parameters are in
242 // hexadecimal.
ExpectCmacVerifyHex(absl::string_view key_hex,absl::string_view tag_hex,absl::string_view data_hex)243 void ExpectCmacVerifyHex(absl::string_view key_hex, absl::string_view tag_hex,
244 absl::string_view data_hex) {
245 util::SecretData key =
246 util::SecretDataFromStringView(absl::HexStringToBytes(key_hex));
247 std::string tag = absl::HexStringToBytes(tag_hex);
248 std::string data = absl::HexStringToBytes(data_hex);
249 util::StatusOr<std::unique_ptr<Mac>> cmac =
250 AesCmacBoringSsl::New(key, kTagSize);
251 EXPECT_THAT(cmac, IsOk());
252 EXPECT_THAT((*cmac)->VerifyMac(tag, data), IsOk());
253 }
254 };
255
TEST_P(AesCmacBoringSslTestVectorTest,RfcTestVectors)256 TEST_P(AesCmacBoringSslTestVectorTest, RfcTestVectors) {
257 if (IsFipsModeEnabled()) {
258 GTEST_SKIP() << "Not supported in FIPS-only mode";
259 }
260
261 // Test vectors from RFC 4493.
262 std::string key("2b7e151628aed2a6abf7158809cf4f3c");
263 std::string data(
264 "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46"
265 "a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710");
266 ExpectCmacVerifyHex(key, GetParam().second,
267 data.substr(0, 2 * GetParam().first));
268 }
269 INSTANTIATE_TEST_SUITE_P(
270 RfcTest, AesCmacBoringSslTestVectorTest,
271 testing::Values(std::make_pair(0, "bb1d6929e95937287fa37d129b756746"),
272 std::make_pair(16, "070a16b46b4d4144f79bdd9dd04a287c"),
273 std::make_pair(40, "dfa66747de9ae63030ca32611497c827"),
274 std::make_pair(64, "51f0bebf7e3b9d92fc49741779363cfe")));
275
TEST(AesCmacBoringSslTest,TestFipsOnly)276 TEST(AesCmacBoringSslTest, TestFipsOnly) {
277 if (!IsFipsModeEnabled()) {
278 GTEST_SKIP() << "Only supported in FIPS-only mode";
279 }
280
281 util::SecretData key128 = util::SecretDataFromStringView(
282 absl::HexStringToBytes("000102030405060708090a0b0c0d0e0f"));
283 util::SecretData key256 =
284 util::SecretDataFromStringView(absl::HexStringToBytes(kKey256Hex));
285
286 EXPECT_THAT(subtle::AesCmacBoringSsl::New(key128, kTagSize).status(),
287 StatusIs(absl::StatusCode::kInternal));
288 EXPECT_THAT(subtle::AesCmacBoringSsl::New(key256, kTagSize).status(),
289 StatusIs(absl::StatusCode::kInternal));
290 }
291 } // namespace
292 } // namespace subtle
293 } // namespace tink
294 } // namespace crypto
295