xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/quic/core/crypto/aes_256_gcm_decrypter_test.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright (c) 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "quiche/quic/core/crypto/aes_256_gcm_decrypter.h"
6 
7 #include <memory>
8 #include <string>
9 
10 #include "absl/base/macros.h"
11 #include "absl/strings/escaping.h"
12 #include "absl/strings/string_view.h"
13 #include "quiche/quic/core/quic_utils.h"
14 #include "quiche/quic/platform/api/quic_test.h"
15 #include "quiche/quic/test_tools/quic_test_utils.h"
16 #include "quiche/common/test_tools/quiche_test_utils.h"
17 
18 namespace {
19 
20 // The AES GCM test vectors come from the file gcmDecrypt256.rsp
21 // downloaded from
22 // https://csrc.nist.gov/Projects/Cryptographic-Algorithm-Validation-Program/CAVP-TESTING-BLOCK-CIPHER-MODES#GCMVS
23 // on 2017-09-27. The test vectors in that file look like this:
24 //
25 // [Keylen = 256]
26 // [IVlen = 96]
27 // [PTlen = 0]
28 // [AADlen = 0]
29 // [Taglen = 128]
30 //
31 // Count = 0
32 // Key = f5a2b27c74355872eb3ef6c5feafaa740e6ae990d9d48c3bd9bb8235e589f010
33 // IV = 58d2240f580a31c1d24948e9
34 // CT =
35 // AAD =
36 // Tag = 15e051a5e4a5f5da6cea92e2ebee5bac
37 // PT =
38 //
39 // Count = 1
40 // Key = e5a8123f2e2e007d4e379ba114a2fb66e6613f57c72d4e4f024964053028a831
41 // IV = 51e43385bf533e168427e1ad
42 // CT =
43 // AAD =
44 // Tag = 38fe845c66e66bdd884c2aecafd280e6
45 // FAIL
46 //
47 // ...
48 //
49 // The gcmDecrypt256.rsp file is huge (3.0 MB), so a few test vectors were
50 // selected for this unit test.
51 
52 // Describes a group of test vectors that all have a given key length, IV
53 // length, plaintext length, AAD length, and tag length.
54 struct TestGroupInfo {
55   size_t key_len;
56   size_t iv_len;
57   size_t pt_len;
58   size_t aad_len;
59   size_t tag_len;
60 };
61 
62 // Each test vector consists of six strings of lowercase hexadecimal digits.
63 // The strings may be empty (zero length). A test vector with a nullptr |key|
64 // marks the end of an array of test vectors.
65 struct TestVector {
66   // Input:
67   const char* key;
68   const char* iv;
69   const char* ct;
70   const char* aad;
71   const char* tag;
72 
73   // Expected output:
74   const char* pt;  // An empty string "" means decryption succeeded and
75                    // the plaintext is zero-length. nullptr means decryption
76                    // failed.
77 };
78 
79 const TestGroupInfo test_group_info[] = {
80     {256, 96, 0, 0, 128},     {256, 96, 0, 128, 128},   {256, 96, 128, 0, 128},
81     {256, 96, 408, 160, 128}, {256, 96, 408, 720, 128}, {256, 96, 104, 0, 128},
82 };
83 
84 const TestVector test_group_0[] = {
85     {"f5a2b27c74355872eb3ef6c5feafaa740e6ae990d9d48c3bd9bb8235e589f010",
86      "58d2240f580a31c1d24948e9", "", "", "15e051a5e4a5f5da6cea92e2ebee5bac",
87      ""},
88     {
89         "e5a8123f2e2e007d4e379ba114a2fb66e6613f57c72d4e4f024964053028a831",
90         "51e43385bf533e168427e1ad", "", "", "38fe845c66e66bdd884c2aecafd280e6",
91         nullptr  // FAIL
92     },
93     {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}};
94 
95 const TestVector test_group_1[] = {
96     {"6dfdafd6703c285c01f14fd10a6012862b2af950d4733abb403b2e745b26945d",
97      "3749d0b3d5bacb71be06ade6", "", "c0d249871992e70302ae008193d1e89f",
98      "4aa4cc69f84ee6ac16d9bfb4e05de500", ""},
99     {
100         "2c392a5eb1a9c705371beda3a901c7c61dca4d93b4291de1dd0dd15ec11ffc45",
101         "0723fb84a08f4ea09841f32a", "", "140be561b6171eab942c486a94d33d43",
102         "aa0e1c9b57975bfc91aa137231977d2c", nullptr  // FAIL
103     },
104     {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}};
105 
106 const TestVector test_group_2[] = {
107     {"4c8ebfe1444ec1b2d503c6986659af2c94fafe945f72c1e8486a5acfedb8a0f8",
108      "473360e0ad24889959858995", "d2c78110ac7e8f107c0df0570bd7c90c", "",
109      "c26a379b6d98ef2852ead8ce83a833a7", "7789b41cb3ee548814ca0b388c10b343"},
110     {"3934f363fd9f771352c4c7a060682ed03c2864223a1573b3af997e2ababd60ab",
111      "efe2656d878c586e41c539c4", "e0de64302ac2d04048d65a87d2ad09fe", "",
112      "33cbd8d2fb8a3a03e30c1eb1b53c1d99", "697aff2d6b77e5ed6232770e400c1ead"},
113     {
114         "c997768e2d14e3d38259667a6649079de77beb4543589771e5068e6cd7cd0b14",
115         "835090aed9552dbdd45277e2", "9f6607d68e22ccf21928db0986be126e", "",
116         "f32617f67c574fd9f44ef76ff880ab9f", nullptr  // FAIL
117     },
118     {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}};
119 
120 const TestVector test_group_3[] = {
121     {
122         "e9d381a9c413bee66175d5586a189836e5c20f5583535ab4d3f3e612dc21700e",
123         "23e81571da1c7821c681c7ca",
124         "a25f3f580306cd5065d22a6b7e9660110af7204bb77d370f7f34bee547feeff7b32a59"
125         "6fce29c9040e68b1589aad48da881990",
126         "6f39c9ae7b8e8a58a95f0dd8ea6a9087cbccdfd6",
127         "5b6dcd70eefb0892fab1539298b92a4b",
128         nullptr  // FAIL
129     },
130     {"6450d4501b1e6cfbe172c4c8570363e96b496591b842661c28c2f6c908379cad",
131      "7e4262035e0bf3d60e91668a",
132      "5a99b336fd3cfd82f10fb08f7045012415f0d9a06bb92dcf59c6f0dbe62d433671aacb8a1"
133      "c52ce7bbf6aea372bf51e2ba79406",
134      "f1c522f026e4c5d43851da516a1b78768ab18171",
135      "fe93b01636f7bb0458041f213e98de65",
136      "17449e236ef5858f6d891412495ead4607bfae2a2d735182a2a0242f9d52fc5345ef912db"
137      "e16f3bb4576fe3bcafe336dee6085"},
138     {"90f2e71ccb1148979cb742efc8f921de95457d898c84ce28edeed701650d3a26",
139      "aba58ad60047ba553f6e4c98",
140      "3fc77a5fe9203d091c7916587c9763cf2e4d0d53ca20b078b851716f1dab4873fe342b7b3"
141      "01402f015d00263bf3f77c58a99d6",
142      "2abe465df6e5be47f05b92c9a93d76ae3611fac5",
143      "9cb3d04637048bc0bddef803ffbb56cf",
144      "1d21639640e11638a2769e3fab78778f84be3f4a8ce28dfd99cb2e75171e05ea8e94e30aa"
145      "78b54bb402b39d613616a8ed951dc"},
146     {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}};
147 
148 const TestVector test_group_4[] = {
149     {
150         "e36aca93414b13f5313e76a7244588ee116551d1f34c32859166f2eb0ac1a9b7",
151         "e9e701b1ccef6bddd03391d8",
152         "5b059ac6733b6de0e8cf5b88b7301c02c993426f71bb12abf692e9deeacfac1ff1644c"
153         "87d4df130028f515f0feda636309a24d",
154         "6a08fe6e55a08f283cec4c4b37676e770f402af6102f548ad473ec6236da764f7076ff"
155         "d41bbd9611b439362d899682b7b0f839fc5a68d9df54afd1e2b3c4e7d072454ee27111"
156         "d52193d28b9c4f925d2a8b451675af39191a2cba",
157         "43c7c9c93cc265fc8e192000e0417b5b",
158         nullptr  // FAIL
159     },
160     {"5f72046245d3f4a0877e50a86554bfd57d1c5e073d1ed3b5451f6d0fc2a8507a",
161      "ea6f5b391e44b751b26bce6f",
162      "0e6e0b2114c40769c15958d965a14dcf50b680e0185a4409d77d894ca15b1e698dd83b353"
163      "6b18c05d8cd0873d1edce8150ecb5",
164      "9b3a68c941d42744673fb60fea49075eae77322e7e70e34502c115b6495ebfc796d629080"
165      "7653c6b53cd84281bd0311656d0013f44619d2748177e99e8f8347c989a7b59f9d8dcf00f"
166      "31db0684a4a83e037e8777bae55f799b0d",
167      "fdaaff86ceb937502cd9012d03585800",
168      "b0a881b751cc1eb0c912a4cf9bd971983707dbd2411725664503455c55db25cdb19bc669c"
169      "2654a3a8011de6bf7eff3f9f07834"},
170     {"ab639bae205547607506522bd3cdca7861369e2b42ef175ff135f6ba435d5a8e",
171      "5fbb63eb44bd59fee458d8f6",
172      "9a34c62bed0972285503a32812877187a54dedbd55d2317fed89282bf1af4ba0b6bb9f9e1"
173      "6dd86da3b441deb7841262bc6bd63",
174      "1ef2b1768b805587935ffaf754a11bd2a305076d6374f1f5098b1284444b78f55408a786d"
175      "a37e1b7f1401c330d3585ef56f3e4d35eaaac92e1381d636477dc4f4beaf559735e902d6b"
176      "e58723257d4ac1ed9bd213de387f35f3c4",
177      "e0299e079bff46fd12e36d1c60e41434",
178      "e5a3ce804a8516cdd12122c091256b789076576040dbf3c55e8be3c016025896b8a72532b"
179      "fd51196cc82efca47aa0fd8e2e0dc"},
180     {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}};
181 
182 const TestVector test_group_5[] = {
183     {
184         "8b37c4b8cf634704920059866ad96c49e9da502c63fca4a3a7a4dcec74cb0610",
185         "cb59344d2b06c4ae57cd0ea4", "66ab935c93555e786b775637a3", "",
186         "d8733acbb564d8afaa99d7ca2e2f92a9", nullptr  // FAIL
187     },
188     {"a71dac1377a3bf5d7fb1b5e36bee70d2e01de2a84a1c1009ba7448f7f26131dc",
189      "c5b60dda3f333b1146e9da7c", "43af49ec1ae3738a20755034d6", "",
190      "6f80b6ef2d8830a55eb63680a8dff9e0", "5b87141335f2becac1a559e05f"},
191     {"dc1f64681014be221b00793bbcf5a5bc675b968eb7a3a3d5aa5978ef4fa45ecc",
192      "056ae9a1a69e38af603924fe", "33013a48d9ea0df2911d583271", "",
193      "5b8f9cc22303e979cd1524187e9f70fe", "2a7e05612191c8bce2f529dca9"},
194     {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr}};
195 
196 const TestVector* const test_group_array[] = {
197     test_group_0, test_group_1, test_group_2,
198     test_group_3, test_group_4, test_group_5,
199 };
200 
201 }  // namespace
202 
203 namespace quic {
204 namespace test {
205 
206 // DecryptWithNonce wraps the |Decrypt| method of |decrypter| to allow passing
207 // in an nonce and also to allocate the buffer needed for the plaintext.
DecryptWithNonce(Aes256GcmDecrypter * decrypter,absl::string_view nonce,absl::string_view associated_data,absl::string_view ciphertext)208 QuicData* DecryptWithNonce(Aes256GcmDecrypter* decrypter,
209                            absl::string_view nonce,
210                            absl::string_view associated_data,
211                            absl::string_view ciphertext) {
212   decrypter->SetIV(nonce);
213   std::unique_ptr<char[]> output(new char[ciphertext.length()]);
214   size_t output_length = 0;
215   const bool success =
216       decrypter->DecryptPacket(0, associated_data, ciphertext, output.get(),
217                                &output_length, ciphertext.length());
218   if (!success) {
219     return nullptr;
220   }
221   return new QuicData(output.release(), output_length, true);
222 }
223 
224 class Aes256GcmDecrypterTest : public QuicTest {};
225 
TEST_F(Aes256GcmDecrypterTest,Decrypt)226 TEST_F(Aes256GcmDecrypterTest, Decrypt) {
227   for (size_t i = 0; i < ABSL_ARRAYSIZE(test_group_array); i++) {
228     SCOPED_TRACE(i);
229     const TestVector* test_vectors = test_group_array[i];
230     const TestGroupInfo& test_info = test_group_info[i];
231     for (size_t j = 0; test_vectors[j].key != nullptr; j++) {
232       // If not present then decryption is expected to fail.
233       bool has_pt = test_vectors[j].pt;
234 
235       // Decode the test vector.
236       std::string key;
237       std::string iv;
238       std::string ct;
239       std::string aad;
240       std::string tag;
241       std::string pt;
242       ASSERT_TRUE(absl::HexStringToBytes(test_vectors[j].key, &key));
243       ASSERT_TRUE(absl::HexStringToBytes(test_vectors[j].iv, &iv));
244       ASSERT_TRUE(absl::HexStringToBytes(test_vectors[j].ct, &ct));
245       ASSERT_TRUE(absl::HexStringToBytes(test_vectors[j].aad, &aad));
246       ASSERT_TRUE(absl::HexStringToBytes(test_vectors[j].tag, &tag));
247       if (has_pt) {
248         ASSERT_TRUE(absl::HexStringToBytes(test_vectors[j].pt, &pt));
249       }
250 
251       // The test vector's lengths should look sane. Note that the lengths
252       // in |test_info| are in bits.
253       EXPECT_EQ(test_info.key_len, key.length() * 8);
254       EXPECT_EQ(test_info.iv_len, iv.length() * 8);
255       EXPECT_EQ(test_info.pt_len, ct.length() * 8);
256       EXPECT_EQ(test_info.aad_len, aad.length() * 8);
257       EXPECT_EQ(test_info.tag_len, tag.length() * 8);
258       if (has_pt) {
259         EXPECT_EQ(test_info.pt_len, pt.length() * 8);
260       }
261       std::string ciphertext = ct + tag;
262 
263       Aes256GcmDecrypter decrypter;
264       ASSERT_TRUE(decrypter.SetKey(key));
265 
266       std::unique_ptr<QuicData> decrypted(DecryptWithNonce(
267           &decrypter, iv,
268           // This deliberately tests that the decrypter can
269           // handle an AAD that is set to nullptr, as opposed
270           // to a zero-length, non-nullptr pointer.
271           aad.length() ? aad : absl::string_view(), ciphertext));
272       if (!decrypted) {
273         EXPECT_FALSE(has_pt);
274         continue;
275       }
276       EXPECT_TRUE(has_pt);
277 
278       ASSERT_EQ(pt.length(), decrypted->length());
279       quiche::test::CompareCharArraysWithHexError(
280           "plaintext", decrypted->data(), pt.length(), pt.data(), pt.length());
281     }
282   }
283 }
284 
TEST_F(Aes256GcmDecrypterTest,GenerateHeaderProtectionMask)285 TEST_F(Aes256GcmDecrypterTest, GenerateHeaderProtectionMask) {
286   Aes256GcmDecrypter decrypter;
287   std::string key;
288   std::string sample;
289   std::string expected_mask;
290   ASSERT_TRUE(absl::HexStringToBytes(
291       "ed23ecbf54d426def5c52c3dcfc84434e62e57781d3125bb21ed91b7d3e07788",
292       &key));
293   ASSERT_TRUE(
294       absl::HexStringToBytes("4d190c474be2b8babafb49ec4e38e810", &sample));
295   ASSERT_TRUE(absl::HexStringToBytes("db9ed4e6ccd033af2eae01407199c56e",
296                                      &expected_mask));
297   QuicDataReader sample_reader(sample.data(), sample.size());
298   ASSERT_TRUE(decrypter.SetHeaderProtectionKey(key));
299   std::string mask = decrypter.GenerateHeaderProtectionMask(&sample_reader);
300   quiche::test::CompareCharArraysWithHexError(
301       "header protection mask", mask.data(), mask.size(), expected_mask.data(),
302       expected_mask.size());
303 }
304 
305 }  // namespace test
306 }  // namespace quic
307