xref: /aosp_15_r20/external/tink/cc/subtle/stateful_hmac_boringssl_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2020 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/subtle/stateful_hmac_boringssl.h"
18 
19 #include <cstddef>
20 #include <string>
21 #include <utility>
22 
23 #include "gmock/gmock.h"
24 #include "gtest/gtest.h"
25 #include "absl/memory/memory.h"
26 #include "absl/status/status.h"
27 #include "tink/subtle/common_enums.h"
28 #include "tink/subtle/wycheproof_util.h"
29 #include "tink/util/secret_data.h"
30 #include "tink/util/status.h"
31 #include "tink/util/statusor.h"
32 #include "tink/util/test_matchers.h"
33 #include "tink/util/test_util.h"
34 
35 namespace crypto {
36 namespace tink {
37 namespace subtle {
38 namespace {
39 
40 constexpr size_t kTagSize = 16;
41 constexpr size_t kSmallTagSize = 10;
42 
43 using ::crypto::tink::test::IsOk;
44 using ::crypto::tink::test::StatusIs;
45 using ::testing::HasSubstr;
46 using ::testing::StrEq;
47 
EmptyHmac(HashType hash_type,uint32_t tag_size,std::string key,std::string expected)48 void EmptyHmac(HashType hash_type, uint32_t tag_size, std::string key,
49                std::string expected) {
50   auto hmac_result = StatefulHmacBoringSsl::New(
51       hash_type, tag_size, util::SecretDataFromStringView(key));
52   EXPECT_THAT(hmac_result, IsOk());
53   auto hmac = std::move(hmac_result.value());
54   auto result = hmac->Finalize();
55   EXPECT_THAT(result, IsOk());
56 
57   auto tag = result.value();
58   EXPECT_EQ(tag.size(), tag_size);
59   EXPECT_EQ(tag, expected);
60 }
61 
TEST(StatefulHmacBoringSslTest,testEmpty)62 TEST(StatefulHmacBoringSslTest, testEmpty) {
63   std::string key(test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f"));
64 
65   std::string expected_256(
66       test::HexDecodeOrDie("07eff8b326b7798c9ccfcbdbe579489a"));
67   EmptyHmac(HashType::SHA256, kTagSize, key, expected_256);
68 
69   std::string expected_512(
70       test::HexDecodeOrDie("2fec800ca276c44985a35aec92067e5e"));
71   EmptyHmac(HashType::SHA512, kTagSize, key, expected_512);
72 
73   std::string expected_256_small(test::HexDecodeOrDie("07eff8b326b7798c9ccf"));
74   EmptyHmac(HashType::SHA256, kSmallTagSize, key, expected_256_small);
75 
76   std::string expected_512_small(test::HexDecodeOrDie("2fec800ca276c44985a3"));
77   EmptyHmac(HashType::SHA512, kSmallTagSize, key, expected_512_small);
78 }
79 
BasicHmac(HashType hash_type,uint32_t tag_size,std::string key,std::string data,std::string expected)80 void BasicHmac(HashType hash_type, uint32_t tag_size, std::string key,
81                std::string data, std::string expected) {
82   auto hmac_result = StatefulHmacBoringSsl::New(
83       hash_type, tag_size, util::SecretDataFromStringView(key));
84   EXPECT_THAT(hmac_result, IsOk());
85   auto hmac = std::move(hmac_result.value());
86 
87   auto update_result = hmac->Update(data);
88   EXPECT_THAT(update_result, IsOk());
89   auto result = hmac->Finalize();
90   EXPECT_THAT(result, IsOk());
91 
92   auto tag = result.value();
93   EXPECT_EQ(tag.size(), tag_size);
94   EXPECT_EQ(tag, expected);
95 }
96 
TEST(StatefulHmacBoringSslTest,testBasic)97 TEST(StatefulHmacBoringSslTest, testBasic) {
98   std::string key(test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f"));
99   std::string data = "Some data to test.";
100 
101   std::string expected_256(
102       test::HexDecodeOrDie("1d6eb74bc283f7947e92c72bd985ce6e"));
103   BasicHmac(HashType::SHA256, kTagSize, key, data, expected_256);
104 
105   std::string expected_512(
106       test::HexDecodeOrDie("72b8ff800f57f9aeec41265a29b69b6a"));
107   BasicHmac(HashType::SHA512, kTagSize, key, data, expected_512);
108 
109   std::string expected_256_small(test::HexDecodeOrDie("1d6eb74bc283f7947e92"));
110   BasicHmac(HashType::SHA256, kSmallTagSize, key, data, expected_256_small);
111 
112   std::string expected_512_small(test::HexDecodeOrDie("72b8ff800f57f9aeec41"));
113   BasicHmac(HashType::SHA512, kSmallTagSize, key, data, expected_512_small);
114 }
115 
MultipleUpdateHmac(HashType hash_type,uint32_t tag_size,std::string key,std::string data1,std::string data2,std::string data3,std::string data4,std::string expected)116 void MultipleUpdateHmac(HashType hash_type, uint32_t tag_size, std::string key,
117                         std::string data1, std::string data2, std::string data3,
118                         std::string data4, std::string expected) {
119   auto hmac_result = StatefulHmacBoringSsl::New(
120       hash_type, tag_size, util::SecretDataFromStringView(key));
121   EXPECT_THAT(hmac_result, IsOk());
122   auto hmac = std::move(hmac_result.value());
123 
124   auto update_1 = hmac->Update(data1);
125   EXPECT_THAT(update_1, IsOk());
126   auto update_2 = hmac->Update(data2);
127   EXPECT_THAT(update_2, IsOk());
128   auto update_3 = hmac->Update(data3);
129   EXPECT_THAT(update_3, IsOk());
130   auto update_4 = hmac->Update(data4);
131   EXPECT_THAT(update_4, IsOk());
132 
133   auto result = hmac->Finalize();
134   EXPECT_THAT(result, IsOk());
135 
136   auto tag = result.value();
137   EXPECT_EQ(tag.size(), tag_size);
138   EXPECT_EQ(tag, expected);
139 }
140 
TEST(StatefulHmacBoringSslTest,testMultipleUpdates)141 TEST(StatefulHmacBoringSslTest, testMultipleUpdates) {
142   std::string key(test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f"));
143   std::string data1 = "Some ", data2 = "data ", data3 = "to ", data4 = "test.";
144 
145   // The tags are the same as the tags in testBasic, since they have the same
146   // key and the same input, but testMultipleUpdates uses multiple updates.
147 
148   std::string expected_256(
149       test::HexDecodeOrDie("1d6eb74bc283f7947e92c72bd985ce6e"));
150   MultipleUpdateHmac(HashType::SHA256, kTagSize, key, data1, data2, data3,
151                      data4, expected_256);
152 
153   std::string expected_512(
154       test::HexDecodeOrDie("72b8ff800f57f9aeec41265a29b69b6a"));
155   MultipleUpdateHmac(HashType::SHA512, kTagSize, key, data1, data2, data3,
156                      data4, expected_512);
157 
158   std::string expected_256_small(test::HexDecodeOrDie("1d6eb74bc283f7947e92"));
159   MultipleUpdateHmac(HashType::SHA256, kSmallTagSize, key, data1, data2, data3,
160                      data4, expected_256_small);
161 
162   std::string expected_512_small(test::HexDecodeOrDie("72b8ff800f57f9aeec41"));
163   MultipleUpdateHmac(HashType::SHA512, kSmallTagSize, key, data1, data2, data3,
164                      data4, expected_512_small);
165 }
166 
TEST(StatefulHmacBoringSslTest,testInvalidKeySizes)167 TEST(StatefulHmacBoringSslTest, testInvalidKeySizes) {
168   size_t tag_size = 16;
169 
170   for (int keysize = 0; keysize < 65; keysize++) {
171     std::string key(keysize, 'x');
172     auto hmac_result = StatefulHmacBoringSsl::New(
173         HashType::SHA256, tag_size, util::SecretDataFromStringView(key));
174     if (keysize >= 16) {
175       EXPECT_THAT(hmac_result, IsOk());
176     } else {
177       EXPECT_THAT(hmac_result.status(),
178                   StatusIs(absl::StatusCode::kInvalidArgument,
179                            HasSubstr("invalid key size")));
180     }
181   }
182 }
183 
TEST(StatefulCmacFactoryTest,createsObjects)184 TEST(StatefulCmacFactoryTest, createsObjects) {
185   std::string key(test::HexDecodeOrDie("000102030405060708090a0b0c0d0e0f"));
186   std::string data = "Some data to test.";
187 
188   std::string expected(
189       test::HexDecodeOrDie("1d6eb74bc283f7947e92c72bd985ce6e"));
190   BasicHmac(HashType::SHA256, kTagSize, key, data, expected);
191   auto factory = absl::make_unique<StatefulHmacBoringSslFactory>(
192       HashType::SHA256, kTagSize, util::SecretDataFromStringView(key));
193   auto stateful_hmac_or = factory->Create();
194   ASSERT_THAT(stateful_hmac_or, IsOk());
195   auto stateful_hmac = std::move(stateful_hmac_or.value());
196   EXPECT_THAT(stateful_hmac->Update(data), IsOk());
197   auto output_or = stateful_hmac->Finalize();
198   ASSERT_THAT(output_or, IsOk());
199   auto output = output_or.value();
200   EXPECT_THAT(output, StrEq(expected));
201 }
202 
203 class StatefulHmacBoringSslTestVectorTest
204     : public ::testing::TestWithParam<std::pair<int, std::string>> {
205  public:
206   // Utility to simplify testing with test vectors.
207   // Arguments and result are hexadecimal.
StatefulHmacVerifyHex(const std::string & key_hex,const std::string & msg_hex,const std::string & tag_hex)208   void StatefulHmacVerifyHex(const std::string &key_hex,
209                              const std::string &msg_hex,
210                              const std::string &tag_hex) {
211     std::string key = test::HexDecodeOrDie(key_hex);
212     std::string tag = test::HexDecodeOrDie(tag_hex);
213     std::string msg = test::HexDecodeOrDie(msg_hex);
214     auto create_result = StatefulHmacBoringSsl::New(
215         HashType::SHA1, tag.size(), util::SecretDataFromStringView(key));
216     EXPECT_THAT(create_result, IsOk());
217     auto hmac = std::move(create_result.value());
218 
219     auto update_result = hmac->Update(msg);
220     EXPECT_THAT(update_result, IsOk());
221 
222     auto finalize_result = hmac->Finalize();
223     EXPECT_THAT(finalize_result, IsOk());
224     auto result = finalize_result.value();
225 
226     EXPECT_EQ(result, tag);
227   }
228 };
229 
230 // Wycheproof HMAC tests are not enabled because the test vectors are in
231 // "rc" (release candidate) state, and are not yet exported for use.
232 // TODO(cathieyun): re-enable Wycheproof HMAC tests once vectors are exported.
233 
234 /*
235 // Test with test vectors from Wycheproof project.
236 bool WycheproofTest(const rapidjson::Document &root, HashType hash_type) {
237   int errors = 0;
238   for (const rapidjson::Value &test_group : root["testGroups"].GetArray()) {
239     // Get the key size in bytes. Wycheproof contains tests for keys smaller
240     // than MIN_KEY_SIZE, which is 16, so the test will skip those.
241     if (test_group["keySize"].GetInt() / 8 < 16) {
242       continue;
243     }
244     for (const rapidjson::Value &test : test_group["tests"].GetArray()) {
245       std::string comment = test["comment"].GetString();
246       std::string key = WycheproofUtil::GetBytes(test["key"]);
247       std::string msg = WycheproofUtil::GetBytes(test["msg"]);
248       std::string tag = WycheproofUtil::GetBytes(test["tag"]);
249       std::string id = absl::StrCat(test["tcId"].GetInt());
250       std::string expected = test["result"].GetString();
251 
252       auto create_result =
253           StatefulHmacBoringSsl::New(hash_type, tag.length(), key);
254       EXPECT_THAT(create_result, IsOk());
255       auto hmac = std::move(create_result.value());
256 
257       auto update_result = hmac->Update(msg);
258       EXPECT_THAT(update_result, IsOk());
259 
260       auto finalize_result = hmac->Finalize();
261       auto result = finalize_result.value();
262 
263       bool success = result == tag;
264       if (success) {
265         // std::string result_tag = result.value();
266         if (expected == "invalid") {
267           ADD_FAILURE() << "verified incorrect tag:" << id;
268           errors++;
269         }
270       } else {
271         if (expected == "valid") {
272           ADD_FAILURE() << "Could not create tag for test with tcId:" << id
273                         << " tag_size:" << tag.length()
274                         << " key_size:" << key.length() << " error:" << result;
275           errors++;
276         }
277       }
278     }
279   }
280   return errors == 0;
281 }
282 
283 TEST_F(StatefulHmacBoringSslTest, TestVectors) {
284   // Test Hmac with SHA256
285   std::unique_ptr<rapidjson::Document> root256 =
286       WycheproofUtil::ReadTestVectors("hmac_sha256_test.json");
287   ASSERT_TRUE(WycheproofTest(*root256, HashType::SHA256));
288 
289   // Test Hmac with SHA512
290   std::unique_ptr<rapidjson::Document> root512 =
291       WycheproofUtil::ReadTestVectors("hmac_sha512_test.json");
292   ASSERT_TRUE(WycheproofTest(*root512, HashType::SHA512));
293 }
294 */
295 
296 }  // namespace
297 }  // namespace subtle
298 }  // namespace tink
299 }  // namespace crypto
300