xref: /aosp_15_r20/external/tink/cc/aead/internal/ssl_aead_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2021 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 #include "tink/aead/internal/ssl_aead.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <iostream>
21 #include <iterator>
22 #include <limits>
23 #include <memory>
24 #include <string>
25 #include <unordered_set>
26 #include <vector>
27 
28 #include "gmock/gmock.h"
29 #include "gtest/gtest.h"
30 #include "absl/container/flat_hash_set.h"
31 #include "absl/status/status.h"
32 #include "absl/strings/escaping.h"
33 #include "absl/strings/str_cat.h"
34 #include "absl/strings/string_view.h"
35 #include "absl/types/span.h"
36 #include "tink/aead/internal/wycheproof_aead.h"
37 #include "tink/internal/fips_utils.h"
38 #include "tink/internal/ssl_util.h"
39 #include "tink/subtle/subtle_util.h"
40 #include "tink/util/secret_data.h"
41 #include "tink/util/statusor.h"
42 #include "tink/util/test_matchers.h"
43 
44 namespace crypto {
45 namespace tink {
46 namespace internal {
47 namespace {
48 
49 using ::crypto::tink::test::IsOk;
50 using ::crypto::tink::test::StatusIs;
51 using ::testing::AllOf;
52 using ::testing::Eq;
53 using ::testing::Not;
54 using ::testing::TestParamInfo;
55 using ::testing::TestWithParam;
56 using ::testing::ValuesIn;
57 
58 constexpr absl::string_view kMessage = "Some data to encrypt.";
59 constexpr absl::string_view kAssociatedData = "Some associated data.";
60 // 128 bits key.
61 constexpr absl::string_view k128Key = "000102030405060708090a0b0c0d0e0f";
62 // 256 bits key.
63 constexpr absl::string_view k256Key =
64     "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
65 // 12 bytes IV.
66 constexpr absl::string_view kAesGcmIvHex = "0123456789012345678901234";
67 // 24 bytes IV.
68 constexpr absl::string_view kXchacha20Poly1305IvHex =
69     "012345678901234567890123456789012345678901234567";
70 
71 enum CipherType {
72   kAesGcm,
73   kAesGcmSiv,
74   kXchacha20Poly1305,
75 };
76 
77 struct SslOneShotAeadTestParams {
78   std::string test_name;
79   CipherType cipher;
80   int tag_size;
81   absl::string_view iv_hex;
82   absl::string_view key_hex;
83 };
84 
85 // Returns a SslOneShotAead from `cipher_name` and `key`.
CipherFromName(CipherType cipher,const util::SecretData & key)86 util::StatusOr<std::unique_ptr<SslOneShotAead>> CipherFromName(
87     CipherType cipher, const util::SecretData& key) {
88   switch (cipher) {
89     case CipherType::kAesGcm: {
90       return CreateAesGcmOneShotCrypter(key);
91     }
92     case CipherType::kAesGcmSiv: {
93       return CreateAesGcmSivOneShotCrypter(key);
94     }
95     case CipherType::kXchacha20Poly1305: {
96       return CreateXchacha20Poly1305OneShotCrypter(key);
97     }
98   }
99 }
100 
101 using SslOneShotAeadTest = TestWithParam<SslOneShotAeadTestParams>;
102 
TEST_P(SslOneShotAeadTest,CiphertextPlaintextSize)103 TEST_P(SslOneShotAeadTest, CiphertextPlaintextSize) {
104   SslOneShotAeadTestParams test_param = GetParam();
105   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead = CipherFromName(
106       test_param.cipher, util::SecretDataFromStringView(
107                              absl::HexStringToBytes(test_param.key_hex)));
108   ASSERT_THAT(aead, IsOk());
109 
110   EXPECT_EQ((*aead)->CiphertextSize(kMessage.size()),
111             kMessage.size() + test_param.tag_size);
112   EXPECT_EQ((*aead)->PlaintextSize(kMessage.size() + test_param.tag_size),
113             kMessage.size());
114   // Minimum size.
115   EXPECT_EQ((*aead)->PlaintextSize(test_param.tag_size), 0);
116   // Smaller than the minumum.
117   EXPECT_EQ((*aead)->PlaintextSize(0), 0);
118 }
119 
120 // Tests that encryption of `message` with `associated_data`, and `iv` succeeds;
121 // writes the result in `ciphertext_buffer`.
DoTestEncrypt(SslOneShotAead * aead,absl::string_view message,absl::string_view associated_data,size_t tag_size,absl::string_view iv,absl::Span<char> ciphertext_buffer)122 void DoTestEncrypt(SslOneShotAead* aead, absl::string_view message,
123                    absl::string_view associated_data, size_t tag_size,
124                    absl::string_view iv, absl::Span<char> ciphertext_buffer) {
125   ASSERT_GE(ciphertext_buffer.size(), message.size() + tag_size);
126   util::StatusOr<int64_t> res = aead->Encrypt(
127       message, associated_data, iv, absl::MakeSpan(ciphertext_buffer));
128   ASSERT_THAT(res, IsOk());
129   EXPECT_EQ(*res, message.size() + tag_size);
130 }
131 
132 // Tests that decryption of `ciphertext_buffer` with `associated_data` and `iv`
133 // succeeds and equals `message`.
DoTestDecrypt(SslOneShotAead * aead,absl::string_view message,absl::string_view associated_data,absl::string_view iv,absl::string_view ciphertext_buffer)134 void DoTestDecrypt(SslOneShotAead* aead, absl::string_view message,
135                    absl::string_view associated_data, absl::string_view iv,
136                    absl::string_view ciphertext_buffer) {
137   std::string plaintext_buff;
138   subtle::ResizeStringUninitialized(&plaintext_buff, message.size());
139   util::StatusOr<int64_t> written_bytes = aead->Decrypt(
140       ciphertext_buffer, associated_data, iv, absl::MakeSpan(plaintext_buff));
141   ASSERT_THAT(written_bytes, IsOk());
142   EXPECT_EQ(*written_bytes, message.size());
143   EXPECT_EQ(plaintext_buff, message);
144 }
145 
TEST_P(SslOneShotAeadTest,EncryptDecrypt)146 TEST_P(SslOneShotAeadTest, EncryptDecrypt) {
147   SslOneShotAeadTestParams test_param = GetParam();
148   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead = CipherFromName(
149       test_param.cipher, util::SecretDataFromStringView(
150                              absl::HexStringToBytes(test_param.key_hex)));
151   ASSERT_THAT(aead, IsOk());
152 
153   std::string iv = absl::HexStringToBytes(test_param.iv_hex);
154   std::string ciphertext_buffer;
155   // Length of the message + tag.
156   subtle::ResizeStringUninitialized(&ciphertext_buffer,
157                                     (*aead)->CiphertextSize(kMessage.size()));
158   DoTestEncrypt(aead->get(), kMessage, kAssociatedData, test_param.tag_size, iv,
159                 absl::MakeSpan(ciphertext_buffer));
160   DoTestDecrypt(aead->get(), kMessage, kAssociatedData, iv, ciphertext_buffer);
161 }
162 
163 // Calculates a new string with the `position`'s byte modified.
ModifyString(absl::string_view input_str,int position)164 std::string ModifyString(absl::string_view input_str, int position) {
165   std::string modified(input_str.data(), input_str.size());
166   modified[position / 8] ^= 1 << (position % 8);
167   return modified;
168 }
169 
170 // Tests encryption/decryption with a modified ciphertext.
DoTestEncryptDecryptWithModifiedCiphertext(SslOneShotAead * aead,size_t tag_size,absl::string_view iv)171 void DoTestEncryptDecryptWithModifiedCiphertext(SslOneShotAead* aead,
172                                                 size_t tag_size,
173                                                 absl::string_view iv) {
174   std::string ciphertext_buffer;
175   // Length of the message + tag.
176   subtle::ResizeStringUninitialized(&ciphertext_buffer,
177                                     kMessage.size() + tag_size);
178 
179   util::StatusOr<int64_t> written_bytes = aead->Encrypt(
180       kMessage, kAssociatedData, iv, absl::MakeSpan(ciphertext_buffer));
181   ASSERT_THAT(written_bytes, IsOk());
182   EXPECT_EQ(*written_bytes, kMessage.size() + tag_size);
183   std::string plaintext_buffer;
184   subtle::ResizeStringUninitialized(&plaintext_buffer, kMessage.size());
185 
186   // Modify the ciphertext.
187   for (size_t i = 0; i < ciphertext_buffer.size() * 8; i++) {
188     EXPECT_THAT(
189         aead->Decrypt(ModifyString(ciphertext_buffer, i), kAssociatedData, iv,
190                       absl::MakeSpan(plaintext_buffer))
191             .status(),
192         Not(IsOk()))
193         << i;
194   }
195   // Modify the associated data.
196   for (size_t i = 0; i < kAssociatedData.size() * 8; i++) {
197     EXPECT_THAT(
198         aead->Decrypt(ciphertext_buffer, ModifyString(kAssociatedData, i), iv,
199                       absl::MakeSpan(plaintext_buffer))
200             .status(),
201         Not(IsOk()))
202         << i;
203   }
204   // Truncate the ciphertext.
205   for (size_t i = 0; i < ciphertext_buffer.size(); i++) {
206     std::string truncated_ct(ciphertext_buffer, 0, i);
207     EXPECT_THAT(aead->Decrypt(truncated_ct, kAssociatedData, iv,
208                               absl::MakeSpan(plaintext_buffer))
209                     .status(),
210                 Not(IsOk()))
211         << i;
212   }
213 }
214 
TEST_P(SslOneShotAeadTest,TestModification)215 TEST_P(SslOneShotAeadTest, TestModification) {
216   if (IsFipsModeEnabled()) {
217     GTEST_SKIP() << "Not supported in FIPS-only mode";
218   }
219 
220   SslOneShotAeadTestParams test_param = GetParam();
221   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead = CipherFromName(
222       test_param.cipher, util::SecretDataFromStringView(
223                              absl::HexStringToBytes(test_param.key_hex)));
224   ASSERT_THAT(aead, IsOk());
225 
226   DoTestEncryptDecryptWithModifiedCiphertext(
227       aead->get(), test_param.tag_size,
228       absl::HexStringToBytes(test_param.iv_hex));
229 }
230 
231 // Make sure that the buffer passed in to the Decrypt routine is cleared if
232 // decryption fails.
TEST_P(SslOneShotAeadTest,TestBufferClearsIfDecryptionFails)233 TEST_P(SslOneShotAeadTest, TestBufferClearsIfDecryptionFails) {
234   if (IsFipsModeEnabled()) {
235     GTEST_SKIP() << "Not supported in FIPS-only mode";
236   }
237 
238   SslOneShotAeadTestParams test_param = GetParam();
239   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead = CipherFromName(
240       test_param.cipher, util::SecretDataFromStringView(
241                              absl::HexStringToBytes(test_param.key_hex)));
242   ASSERT_THAT(aead, IsOk());
243 
244   const int64_t kCiphertextSize = kMessage.size() + test_param.tag_size;
245   std::string ciphertext_buffer;
246   // Length of the message + tag.
247   subtle::ResizeStringUninitialized(&ciphertext_buffer, kCiphertextSize);
248   std::string iv = absl::HexStringToBytes(test_param.iv_hex);
249   util::StatusOr<int64_t> written_bytes = (*aead)->Encrypt(
250       kMessage, kAssociatedData, iv, absl::MakeSpan(ciphertext_buffer));
251   ASSERT_THAT(written_bytes, IsOk());
252   EXPECT_EQ(*written_bytes, kCiphertextSize);
253 
254   std::string plaintext_buffer;
255   subtle::ResizeStringUninitialized(&plaintext_buffer, kMessage.size());
256   const std::string kExpectedClearedPlaintext(plaintext_buffer.size(), '\0');
257   // Alter the tag.
258   for (int i = kCiphertextSize - test_param.tag_size; i < kCiphertextSize;
259        i++) {
260     std::string modified_ciphertext = ModifyString(ciphertext_buffer, i);
261     EXPECT_THAT((*aead)
262                     ->Decrypt(modified_ciphertext, kAssociatedData, iv,
263                               absl::MakeSpan(plaintext_buffer))
264                     .status(),
265                 Not(IsOk()));
266     EXPECT_EQ(plaintext_buffer, kExpectedClearedPlaintext);
267   }
268 }
269 
TestDecryptWithEmptyAssociatedData(SslOneShotAead * aead,absl::string_view ciphertext,absl::string_view iv)270 void TestDecryptWithEmptyAssociatedData(SslOneShotAead* aead,
271                                         absl::string_view ciphertext,
272                                         absl::string_view iv) {
273   if (IsFipsModeEnabled()) {
274     GTEST_SKIP() << "Not supported in FIPS-only mode";
275   }
276   std::string plaintext_buffer;
277   subtle::ResizeStringUninitialized(&plaintext_buffer, kMessage.size());
278   const absl::string_view empty_associated_data;
279   std::vector<absl::string_view> values = {empty_associated_data,
280                                            absl::string_view(), ""};
281   for (auto& associated_data : values) {
282     DoTestDecrypt(aead, kMessage, associated_data, iv, ciphertext);
283   }
284 }
285 
DoTestWithEmptyAssociatedData(SslOneShotAead * aead,absl::string_view iv,size_t tag_size)286 void DoTestWithEmptyAssociatedData(SslOneShotAead* aead, absl::string_view iv,
287                                    size_t tag_size) {
288   const absl::string_view empty_associated_data;
289   std::vector<absl::string_view> values = {empty_associated_data,
290                                            absl::string_view(), ""};
291   for (auto& associated_data : values) {
292     std::string ciphertext_buffer;
293     subtle::ResizeStringUninitialized(&ciphertext_buffer,
294                                       kMessage.size() + tag_size);
295     DoTestEncrypt(aead, kMessage, associated_data, tag_size, iv,
296                   absl::MakeSpan(ciphertext_buffer));
297     TestDecryptWithEmptyAssociatedData(aead, ciphertext_buffer, iv);
298   }
299 }
300 
TEST_P(SslOneShotAeadTest,EmptyAssociatedData)301 TEST_P(SslOneShotAeadTest, EmptyAssociatedData) {
302   if (IsFipsModeEnabled()) {
303     GTEST_SKIP() << "Not supported in FIPS-only mode";
304   }
305   SslOneShotAeadTestParams test_param = GetParam();
306   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead = CipherFromName(
307       test_param.cipher, util::SecretDataFromStringView(
308                              absl::HexStringToBytes(test_param.key_hex)));
309   ASSERT_THAT(aead, IsOk());
310   DoTestWithEmptyAssociatedData(aead->get(),
311                                 absl::HexStringToBytes(test_param.iv_hex),
312                                 test_param.tag_size);
313 }
314 
315 // string_views, with `iv` and `associated_data`.
DoTestEmptyMessageEncryptDecrypt(SslOneShotAead * aead,absl::string_view iv,size_t tag_size,absl::string_view associated_data=kAssociatedData)316 void DoTestEmptyMessageEncryptDecrypt(
317     SslOneShotAead* aead, absl::string_view iv, size_t tag_size,
318     absl::string_view associated_data = kAssociatedData) {
319   std::string ciphertext_buffer;
320   subtle::ResizeStringUninitialized(&ciphertext_buffer, tag_size);
321   {  // Message is a null string_view.
322     const absl::string_view message;
323     DoTestEncrypt(aead, message, associated_data, tag_size, iv,
324                   absl::MakeSpan(ciphertext_buffer));
325     DoTestDecrypt(aead, "", associated_data, iv, ciphertext_buffer);
326   }
327   {  // Message is an empty string.
328     const std::string message = "";
329     DoTestEncrypt(aead, message, associated_data, tag_size, iv,
330                   absl::MakeSpan(ciphertext_buffer));
331     DoTestDecrypt(aead, "", associated_data, iv, ciphertext_buffer);
332   }
333   {  // Message is a default-constructed string_view.
334     DoTestEncrypt(aead, absl::string_view(), associated_data, tag_size, iv,
335                   absl::MakeSpan(ciphertext_buffer));
336     DoTestDecrypt(aead, "", associated_data, iv, ciphertext_buffer);
337   }
338 }
339 
TEST_P(SslOneShotAeadTest,EmptyMessage)340 TEST_P(SslOneShotAeadTest, EmptyMessage) {
341   if (IsFipsModeEnabled()) {
342     GTEST_SKIP() << "Not supported in FIPS-only mode";
343   }
344   SslOneShotAeadTestParams test_param = GetParam();
345   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead = CipherFromName(
346       test_param.cipher, util::SecretDataFromStringView(
347                              absl::HexStringToBytes(test_param.key_hex)));
348   ASSERT_THAT(aead, IsOk());
349   std::string iv = absl::HexStringToBytes(test_param.iv_hex);
350   DoTestEmptyMessageEncryptDecrypt(aead->get(), iv, test_param.tag_size);
351 }
352 
TEST_P(SslOneShotAeadTest,EmptyMessageAndAssociatedData)353 TEST_P(SslOneShotAeadTest, EmptyMessageAndAssociatedData) {
354   if (IsFipsModeEnabled()) {
355     GTEST_SKIP() << "Not supported in FIPS-only mode";
356   }
357   SslOneShotAeadTestParams test_param = GetParam();
358   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead = CipherFromName(
359       test_param.cipher, util::SecretDataFromStringView(
360                              absl::HexStringToBytes(test_param.key_hex)));
361   ASSERT_THAT(aead, IsOk());
362   std::string iv = absl::HexStringToBytes(test_param.iv_hex);
363   const absl::string_view default_associated_data;
364   const absl::string_view empty_associated_data = "";
365   DoTestEmptyMessageEncryptDecrypt(aead->get(), iv, test_param.tag_size,
366                                    default_associated_data);
367   DoTestEmptyMessageEncryptDecrypt(aead->get(), iv, test_param.tag_size,
368                                    /*associated_data=*/absl::string_view());
369   DoTestEmptyMessageEncryptDecrypt(aead->get(), iv, test_param.tag_size,
370                                    empty_associated_data);
371 }
372 
TEST_P(SslOneShotAeadTest,BufferOverlapEncryptFails)373 TEST_P(SslOneShotAeadTest, BufferOverlapEncryptFails) {
374   SslOneShotAeadTestParams test_param = GetParam();
375   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead = CipherFromName(
376       test_param.cipher, util::SecretDataFromStringView(
377                              absl::HexStringToBytes(test_param.key_hex)));
378   ASSERT_THAT(aead, IsOk());
379 
380   std::string ciphertext_buffer(kMessage.data(), kMessage.size());
381   subtle::ResizeStringUninitialized(&ciphertext_buffer,
382                                     (*aead)->CiphertextSize(kMessage.size()));
383 
384   EXPECT_THAT(
385       (*aead)
386           ->Encrypt(
387               absl::string_view(ciphertext_buffer).substr(0, kMessage.size()),
388               kAssociatedData, test_param.iv_hex,
389               absl::MakeSpan(ciphertext_buffer))
390           .status(),
391       StatusIs(absl::StatusCode::kInvalidArgument));
392 }
393 
TEST_P(SslOneShotAeadTest,BufferOverlapDecryptFails)394 TEST_P(SslOneShotAeadTest, BufferOverlapDecryptFails) {
395   SslOneShotAeadTestParams test_param = GetParam();
396   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead = CipherFromName(
397       test_param.cipher, util::SecretDataFromStringView(
398                              absl::HexStringToBytes(test_param.key_hex)));
399   ASSERT_THAT(aead, IsOk());
400 
401   std::string iv = absl::HexStringToBytes(test_param.iv_hex);
402   std::string ciphertext_buffer;
403   // Length of the message + tag.
404   subtle::ResizeStringUninitialized(&ciphertext_buffer,
405                                     (*aead)->CiphertextSize(kMessage.size()));
406   DoTestEncrypt(aead->get(), kMessage, kAssociatedData, test_param.tag_size, iv,
407                 absl::MakeSpan(ciphertext_buffer));
408 
409   EXPECT_THAT(
410       (*aead)
411           ->Decrypt(
412               ciphertext_buffer, kAssociatedData, iv,
413               absl::MakeSpan(ciphertext_buffer).subspan(0, kMessage.size()))
414           .status(),
415       StatusIs(absl::StatusCode::kInvalidArgument));
416 }
417 
GetSslOneShotAeadTestParams()418 std::vector<SslOneShotAeadTestParams> GetSslOneShotAeadTestParams() {
419   std::vector<SslOneShotAeadTestParams> params = {
420       {/*test_name=*/"AesGcm256", /*cipher=*/CipherType::kAesGcm,
421        /*tag_size=*/kAesGcmTagSizeInBytes,
422        /*iv_hex=*/kAesGcmIvHex,
423        /*key_hex=*/k256Key},
424       {/*test_name=*/"AesGcm128", /*cipher=*/CipherType::kAesGcm,
425        /*tag_size=*/kAesGcmTagSizeInBytes,
426        /*iv_hex=*/kAesGcmIvHex,
427        /*key_hex=*/k128Key}};
428   if (IsBoringSsl()) {
429     params.push_back({/*test_name=*/"AesGcmSiv256",
430                       /*cipher=*/CipherType::kAesGcmSiv,
431                       /*tag_size=*/kAesGcmTagSizeInBytes,
432                       /*iv_hex=*/kAesGcmIvHex,
433                       /*key_hex=*/k256Key});
434     params.push_back({/*test_name=*/"AesGcmSiv128",
435                       /*cipher=*/CipherType::kAesGcmSiv,
436                       /*tag_size=*/kAesGcmTagSizeInBytes,
437                       /*iv_hex=*/kAesGcmIvHex,
438                       /*key_hex=*/k128Key});
439     params.push_back({/*test_name=*/"Xchacha20Poly1305",
440                       /*cipher=*/CipherType::kXchacha20Poly1305,
441                       /*tag_size=*/kXchacha20Poly1305TagSizeInBytes,
442                       /*iv_hex=*/kXchacha20Poly1305IvHex,
443                       /*key_hex=*/k256Key});
444   }
445   return params;
446 }
447 
448 INSTANTIATE_TEST_SUITE_P(
449     SslOneShotAeadTests, SslOneShotAeadTest,
450     testing::ValuesIn(GetSslOneShotAeadTestParams()),
__anond5b904b60202(const TestParamInfo<SslOneShotAeadTest::ParamType>& info) 451     [](const TestParamInfo<SslOneShotAeadTest::ParamType>& info) {
452       return info.param.test_name;
453     });
454 
TEST(SslOneShotAeadTest,AesGcmTestInvalidKeySizes)455 TEST(SslOneShotAeadTest, AesGcmTestInvalidKeySizes) {
456   if (IsFipsModeEnabled()) {
457     GTEST_SKIP() << "Not supported in FIPS-only mode";
458   }
459 
460   for (int keysize = 0; keysize < 65; keysize++) {
461     util::SecretData key(keysize, 'x');
462     util::StatusOr<std::unique_ptr<SslOneShotAead>> aead =
463         CreateAesGcmOneShotCrypter(key);
464     if (keysize == 16 || keysize == 32) {
465       EXPECT_THAT(aead, IsOk()) << "with key size " << keysize;
466     } else {
467       EXPECT_THAT(aead, Not(IsOk())) << "with key size " << keysize;
468     }
469   }
470 }
471 
TEST(SslOneShotAeadTest,AesGcmSivTestInvalidKeySizes)472 TEST(SslOneShotAeadTest, AesGcmSivTestInvalidKeySizes) {
473   if (!IsBoringSsl()) {
474     GTEST_SKIP() << "AES-GCM-SIV not supported with OpenSSL";
475   }
476   if (IsFipsModeEnabled()) {
477     GTEST_SKIP() << "Not supported in FIPS-only mode";
478   }
479 
480   for (int keysize = 0; keysize < 65; keysize++) {
481     util::SecretData key(keysize, 'x');
482     util::StatusOr<std::unique_ptr<SslOneShotAead>> aead =
483         CreateAesGcmSivOneShotCrypter(key);
484     if (keysize == 16 || keysize == 32) {
485       EXPECT_THAT(aead, IsOk()) << "with key size " << keysize;
486     } else {
487       EXPECT_THAT(aead, Not(IsOk())) << "with key size " << keysize;
488     }
489   }
490 }
491 
TEST(SslOneShotAeadTest,Xchacha20Poly1305TestInvalidKeySizes)492 TEST(SslOneShotAeadTest, Xchacha20Poly1305TestInvalidKeySizes) {
493   if (!IsBoringSsl()) {
494     GTEST_SKIP() << "Xchacha20-Poly1305 not supported with OpenSSL";
495   }
496   if (IsFipsModeEnabled()) {
497     GTEST_SKIP() << "Not supported in FIPS-only mode";
498   }
499 
500   for (int keysize = 0; keysize < 65; keysize++) {
501     util::SecretData key(keysize, 'x');
502     util::StatusOr<std::unique_ptr<SslOneShotAead>> aead =
503         CreateXchacha20Poly1305OneShotCrypter(key);
504     if (keysize == 32) {
505       EXPECT_THAT(aead, IsOk()) << "with key size " << keysize;
506     } else {
507       EXPECT_THAT(aead, Not(IsOk())) << "with key size " << keysize;
508     }
509   }
510 }
511 
TEST(SslOneShotAeadTest,Xchacha20Poly1305TestFipsOnly)512 TEST(SslOneShotAeadTest, Xchacha20Poly1305TestFipsOnly) {
513   if (!IsBoringSsl()) {
514     GTEST_SKIP() << "Xchacha20-Poly1305 not supported with OpenSSL";
515   }
516   if (!IsFipsModeEnabled()) {
517     GTEST_SKIP() << "Only supported in FIPS-only mode";
518   }
519 
520   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead =
521       CreateXchacha20Poly1305OneShotCrypter(
522           util::SecretDataFromStringView(absl::HexStringToBytes(k256Key)));
523   EXPECT_THAT(aead.status(), StatusIs(absl::StatusCode::kInternal));
524 }
525 
TEST(SslOneShotAeadTest,AesGcmTestFipsOnly)526 TEST(SslOneShotAeadTest, AesGcmTestFipsOnly) {
527   if (IsFipsModeEnabled() && !IsFipsEnabledInSsl()) {
528     GTEST_SKIP() << "Test should not run in FIPS mode when BoringCrypto is "
529                     "unavailable.";
530   }
531 
532   util::SecretData key_128 =
533       util::SecretDataFromStringView(absl::HexStringToBytes(k128Key));
534   util::SecretData key_256 =
535       util::SecretDataFromStringView(absl::HexStringToBytes(k256Key));
536 
537   EXPECT_THAT(CreateAesGcmOneShotCrypter(key_128), IsOk());
538   EXPECT_THAT(CreateAesGcmOneShotCrypter(key_256), IsOk());
539 }
540 
TEST(SslOneShotAeadTest,AesGcmTestTestFipsFailWithoutBoringCrypto)541 TEST(SslOneShotAeadTest, AesGcmTestTestFipsFailWithoutBoringCrypto) {
542   if (!IsFipsModeEnabled() || IsFipsEnabledInSsl()) {
543     GTEST_SKIP()
544         << "Test assumes kOnlyUseFips but BoringCrypto is unavailable.";
545   }
546 
547   util::SecretData key_128 =
548       util::SecretDataFromStringView(absl::HexStringToBytes(k128Key));
549   util::SecretData key_256 =
550       util::SecretDataFromStringView(absl::HexStringToBytes(k256Key));
551 
552   EXPECT_THAT(CreateAesGcmOneShotCrypter(key_128).status(),
553               StatusIs(absl::StatusCode::kInternal));
554   EXPECT_THAT(CreateAesGcmOneShotCrypter(key_256).status(),
555               StatusIs(absl::StatusCode::kInternal));
556 }
557 
TEST(AesGcmSivBoringSslTest,AesGcmTestSivTestFipsOnly)558 TEST(AesGcmSivBoringSslTest, AesGcmTestSivTestFipsOnly) {
559   if (!IsFipsModeEnabled()) {
560     GTEST_SKIP() << "Only supported in FIPS-only mode";
561   }
562 
563   util::SecretData key_128 =
564       util::SecretDataFromStringView(absl::HexStringToBytes(k128Key));
565   util::SecretData key_256 =
566       util::SecretDataFromStringView(absl::HexStringToBytes(k256Key));
567 
568   EXPECT_THAT(CreateAesGcmSivOneShotCrypter(key_128).status(),
569               StatusIs(absl::StatusCode::kInternal));
570   EXPECT_THAT(CreateAesGcmSivOneShotCrypter(key_256).status(),
571               StatusIs(absl::StatusCode::kInternal));
572 }
573 
574 // Parameters for SslOneShotAeadWycheproofTest.
575 struct SslOneShotAeadWycheproofTestParams {
576   std::string test_name;
577   CipherType cipher;
578   int nonce_size;
579   int tag_size;
580   absl::flat_hash_set<int> key_sizes;
581   WycheproofTestVector test_vector;
582 };
583 
584 class SslOneShotAeadWycheproofTest
585     : public TestWithParam<SslOneShotAeadWycheproofTestParams> {
586  public:
SetUp()587   void SetUp() override {
588     if (IsFipsModeEnabled()) {
589       GTEST_SKIP() << "Not supported in FIPS-only mode";
590     }
591     SslOneShotAeadWycheproofTestParams params = GetParam();
592     const WycheproofTestVector& test_vector = params.test_vector;
593 
594     if (!params.key_sizes.contains(test_vector.key.size()) ||
595         test_vector.nonce.size() != params.nonce_size ||
596         test_vector.tag.size() != params.tag_size) {
597       GTEST_SKIP() << "Unsupported parameters; key size: "
598                    << test_vector.key.size()
599                    << " nonce size: " << test_vector.nonce.size()
600                    << " tag size: " << test_vector.tag.size();
601     }
602   }
603 };
604 
TEST_P(SslOneShotAeadWycheproofTest,Encrypt)605 TEST_P(SslOneShotAeadWycheproofTest, Encrypt) {
606   SslOneShotAeadWycheproofTestParams params = GetParam();
607   const WycheproofTestVector& test_vector = params.test_vector;
608   util::SecretData key = util::SecretDataFromStringView(test_vector.key);
609   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead =
610       CipherFromName(params.cipher, key);
611   ASSERT_THAT(aead, IsOk());
612   std::string ciphertext_and_tag =
613       absl::StrCat(test_vector.ct, test_vector.tag);
614   std::string ciphertext_buffer;
615   subtle::ResizeStringUninitialized(
616       &ciphertext_buffer, (*aead)->CiphertextSize(test_vector.msg.size()));
617   util::StatusOr<int64_t> written_bytes =
618       (*aead)->Encrypt(test_vector.msg, test_vector.aad, test_vector.nonce,
619                        absl::MakeSpan(ciphertext_buffer));
620 
621   std::string expected_ciphertext =
622       absl::StrCat(test_vector.ct, test_vector.tag);
623 
624   std::cout << test_vector.expected << "\n";
625 
626   if (test_vector.expected == "valid" || test_vector.expected == "acceptable") {
627     ASSERT_THAT(written_bytes, IsOk());
628     EXPECT_EQ(ciphertext_buffer, expected_ciphertext);
629   } else {  // invalid.
630     // In this case, if the resulting ciphertext/tag are different, the
631     // testcase is correct.
632     if (written_bytes.ok()) {
633       EXPECT_THAT(ciphertext_buffer, Not(Eq(expected_ciphertext)));
634     } else {
635       GTEST_SUCCEED();
636     }
637   }
638 }
639 
TEST_P(SslOneShotAeadWycheproofTest,Decrypt)640 TEST_P(SslOneShotAeadWycheproofTest, Decrypt) {
641   SslOneShotAeadWycheproofTestParams params = GetParam();
642   const WycheproofTestVector& test_vector = params.test_vector;
643   util::SecretData key = util::SecretDataFromStringView(test_vector.key);
644   util::StatusOr<std::unique_ptr<SslOneShotAead>> aead =
645       CipherFromName(params.cipher, key);
646   ASSERT_THAT(aead, IsOk());
647   std::string ciphertext_and_tag =
648       absl::StrCat(test_vector.ct, test_vector.tag);
649   std::string plaintext_buffer;
650   subtle::ResizeStringUninitialized(
651       &plaintext_buffer, (*aead)->PlaintextSize(ciphertext_and_tag.size()));
652   util::StatusOr<int64_t> written_bytes = (*aead)->Decrypt(
653       absl::StrCat(test_vector.ct, test_vector.tag), test_vector.aad,
654       test_vector.nonce, absl::MakeSpan(plaintext_buffer));
655 
656   if (written_bytes.ok()) {
657     EXPECT_NE(test_vector.expected, "invalid");
658     EXPECT_EQ(plaintext_buffer, test_vector.msg);
659   } else {
660     EXPECT_THAT(test_vector.expected, Not(AllOf(Eq("valid"), Eq("acceptable"))))
661         << "Could not decrypt valid/acceptable tId: " << test_vector.id
662         << " iv_size: " << test_vector.nonce.size()
663         << " tag_size: " << test_vector.tag.size()
664         << " key_size: " << key.size() << "; error: " << written_bytes.status();
665   }
666 }
667 
GetWycheproofTestParams()668 std::vector<SslOneShotAeadWycheproofTestParams> GetWycheproofTestParams() {
669   std::vector<SslOneShotAeadWycheproofTestParams> params;
670   for (const WycheproofTestVector& test_vector :
671        ReadWycheproofTestVectors("aes_gcm_test.json")) {
672     params.push_back({/*test_name=*/"AesGcm",
673                       /*cipher_name=*/CipherType::kAesGcm,
674                       /*nonce_size=*/12,
675                       /*tag_size=*/16,
676                       /*key_sizes=*/{16, 32}, test_vector});
677   }
678   if (IsBoringSsl()) {
679     for (const WycheproofTestVector& test_vector :
680          ReadWycheproofTestVectors("aes_gcm_siv_test.json")) {
681       params.push_back({/*test_name=*/"AesGcmSiv",
682                         /*cipher_name=*/CipherType::kAesGcmSiv,
683                         /*nonce_size=*/12,
684                         /*tag_size=*/16,
685                         /*key_sizes=*/{16, 32}, test_vector});
686     }
687     for (const WycheproofTestVector& test_vector :
688          ReadWycheproofTestVectors("xchacha20_poly1305_test.json")) {
689       params.push_back({/*test_name=*/"Xchacha20Poly1305",
690                         /*cipher_name=*/CipherType::kXchacha20Poly1305,
691                         /*nonce_size=*/24,
692                         /*tag_size=*/16,
693                         /*key_sizes=*/{32}, test_vector});
694     }
695   }
696   return params;
697 }
698 
699 INSTANTIATE_TEST_SUITE_P(
700     SslOneShotAeadWycheproofTests, SslOneShotAeadWycheproofTest,
701     ValuesIn(GetWycheproofTestParams()),
__anond5b904b60302(const TestParamInfo<SslOneShotAeadWycheproofTest::ParamType>& info) 702     [](const TestParamInfo<SslOneShotAeadWycheproofTest::ParamType>& info) {
703       return absl::StrCat(info.param.test_name, "Tid",
704                           info.param.test_vector.id);
705     });
706 
707 }  // namespace
708 }  // namespace internal
709 }  // namespace tink
710 }  // namespace crypto
711