xref: /aosp_15_r20/external/tink/cc/subtle/aes_cmac_boringssl_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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