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 <algorithm>
17 #include <cstdint>
18 #include <iterator>
19 #include <limits>
20 #include <memory>
21 #include <string>
22 #include <unordered_set>
23 #include <vector>
24
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 #include "absl/container/flat_hash_set.h"
28 #include "absl/memory/memory.h"
29 #include "absl/status/status.h"
30 #include "absl/strings/escaping.h"
31 #include "absl/strings/string_view.h"
32 #include "absl/types/span.h"
33 #include "tink/aead/internal/ssl_aead.h"
34 #include "tink/config/tink_fips.h"
35 #include "tink/internal/ssl_util.h"
36 #include "tink/internal/util.h"
37 #include "tink/subtle/subtle_util.h"
38 #include "tink/util/secret_data.h"
39 #include "tink/util/statusor.h"
40 #include "tink/util/test_matchers.h"
41
42 // We test SslOneShotAead implementations against a very large input.
43 namespace crypto {
44 namespace tink {
45 namespace internal {
46 namespace {
47
48 using ::crypto::tink::test::IsOk;
49 using ::testing::TestWithParam;
50
51 constexpr absl::string_view kAad = "Some data to authenticate.";
52 // 128 bits key.
53 constexpr absl::string_view k128Key = "000102030405060708090a0b0c0d0e0f";
54 // 256 bits key.
55 constexpr absl::string_view k256Key =
56 "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f";
57 // 12 bytes IV.
58 constexpr absl::string_view kAesGcmIvHex = "0123456789012345678901234";
59 // 24 bytes IV.
60 constexpr absl::string_view kXchacha20Poly1305IvHex =
61 "012345678901234567890123456789012345678901234567";
62
63 struct TestParams {
64 std::string test_name;
65 std::string cipher;
66 int tag_size;
67 absl::string_view iv_hex;
68 absl::string_view key_hex;
69 };
70
71 // Returns a SslOneShotAead from `cipher_name` and `key`.
CipherFromName(absl::string_view cipher,const util::SecretData & key)72 util::StatusOr<std::unique_ptr<SslOneShotAead>> CipherFromName(
73 absl::string_view cipher, const util::SecretData& key) {
74 if (cipher == "aes_gcm") {
75 return CreateAesGcmOneShotCrypter(key);
76 }
77 if (cipher == "aes_gcm_siv") {
78 return CreateAesGcmSivOneShotCrypter(key);
79 }
80 if (cipher == "xchacha20_poly1305") {
81 return CreateXchacha20Poly1305OneShotCrypter(key);
82 }
83 return util::Status(absl::StatusCode::kInvalidArgument,
84 absl::StrCat("Invalid cipher ", cipher));
85 }
86
87 using SslOneShotAeadLargeInputsTest = TestWithParam<TestParams>;
88
89 // Encrypt/decrypt with an input larger than a MAX int.
TEST_P(SslOneShotAeadLargeInputsTest,EncryptDecryptLargeInput)90 TEST_P(SslOneShotAeadLargeInputsTest, EncryptDecryptLargeInput) {
91 if (IsWindows()) {
92 GTEST_SKIP() << "Skipping on Windows: this currently times out";
93 }
94 const int64_t buff_size =
95 static_cast<int64_t>(std::numeric_limits<int>::max()) + 1024;
96 std::string large_input(buff_size, '0');
97
98 TestParams test_param = GetParam();
99 util::StatusOr<std::unique_ptr<SslOneShotAead>> aead = CipherFromName(
100 test_param.cipher, util::SecretDataFromStringView(
101 absl::HexStringToBytes(test_param.key_hex)));
102 ASSERT_THAT(aead, IsOk());
103
104 std::string iv = absl::HexStringToBytes(test_param.iv_hex);
105 std::string ciphertext_buffer;
106 // Length of the message + tag.
107 subtle::ResizeStringUninitialized(
108 &ciphertext_buffer, (*aead)->CiphertextSize(large_input.size()));
109
110 // Encrypt.
111 ASSERT_GE(ciphertext_buffer.size(), large_input.size() + test_param.tag_size);
112 util::StatusOr<int64_t> res = (*aead)->Encrypt(
113 large_input, kAad, iv, absl::MakeSpan(ciphertext_buffer));
114 ASSERT_THAT(res, IsOk());
115 EXPECT_EQ(*res, large_input.size() + test_param.tag_size);
116
117 // Decrypt.
118 std::string plaintext_buff;
119 subtle::ResizeStringUninitialized(&plaintext_buff, large_input.size());
120 util::StatusOr<int64_t> written_bytes = (*aead)->Decrypt(
121 ciphertext_buffer, kAad, iv, absl::MakeSpan(plaintext_buff));
122 ASSERT_THAT(written_bytes, IsOk());
123 EXPECT_EQ(*written_bytes, large_input.size());
124 EXPECT_EQ(plaintext_buff, large_input);
125 }
126
GetTestParams()127 std::vector<TestParams> GetTestParams() {
128 std::vector<TestParams> params = {
129 {/*test_name=*/"AesGcm256", /*cipher=*/"aes_gcm",
130 /*tag_size=*/kAesGcmTagSizeInBytes,
131 /*iv_hex=*/kAesGcmIvHex,
132 /*key_hex=*/k256Key},
133 {/*test_name=*/"AesGcm128", /*cipher=*/"aes_gcm",
134 /*tag_size=*/kAesGcmTagSizeInBytes,
135 /*iv_hex=*/kAesGcmIvHex,
136 /*key_hex=*/k128Key}};
137 if (IsBoringSsl()) {
138 params.push_back({/*test_name=*/"AesGcmSiv256", /*cipher=*/"aes_gcm_siv",
139 /*tag_size=*/kAesGcmTagSizeInBytes,
140 /*iv_hex=*/kAesGcmIvHex,
141 /*key_hex=*/k256Key});
142 params.push_back({/*test_name=*/"AesGcmSiv128", /*cipher=*/"aes_gcm_siv",
143 /*tag_size=*/kAesGcmTagSizeInBytes,
144 /*iv_hex=*/kAesGcmIvHex,
145 /*key_hex=*/k128Key});
146 params.push_back({/*test_name=*/"Xchacha20Poly1305",
147 /*cipher=*/"xchacha20_poly1305",
148 /*tag_size=*/kXchacha20Poly1305TagSizeInBytes,
149 /*iv_hex=*/kXchacha20Poly1305IvHex,
150 /*key_hex=*/k256Key});
151 }
152 return params;
153 }
154
155 INSTANTIATE_TEST_SUITE_P(
156 SslOneShotAeadLargeInputsTests, SslOneShotAeadLargeInputsTest,
157 testing::ValuesIn(GetTestParams()),
158 [](const testing::TestParamInfo<SslOneShotAeadLargeInputsTest::ParamType>&
__anoncc17e4820202(const testing::TestParamInfo<SslOneShotAeadLargeInputsTest::ParamType>& info) 159 info) { return info.param.test_name; });
160
161 } // namespace
162 } // namespace internal
163 } // namespace tink
164 } // namespace crypto
165