xref: /aosp_15_r20/external/tink/cc/util/test_util_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2019 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/util/test_util.h"
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <memory>
21 #include <sstream>
22 #include <string>
23 #include <utility>
24 
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 #include "absl/strings/string_view.h"
28 #include "tink/internal/test_random_access_stream.h"
29 #include "tink/output_stream.h"
30 #include "tink/random_access_stream.h"
31 #include "tink/subtle/random.h"
32 #include "tink/subtle/test_util.h"
33 #include "tink/util/buffer.h"
34 #include "tink/util/ostream_output_stream.h"
35 #include "tink/util/statusor.h"
36 #include "tink/util/test_matchers.h"
37 #include "proto/aes_gcm.pb.h"
38 #include "proto/tink.pb.h"
39 
40 namespace crypto {
41 namespace tink {
42 namespace test {
43 namespace {
44 
45 using ::crypto::tink::internal::TestRandomAccessStream;
46 using ::crypto::tink::test::StatusIs;
47 using ::google::crypto::tink::AesGcmKey;
48 using ::google::crypto::tink::KeyData;
49 using ::testing::Eq;
50 using ::testing::Not;
51 
TEST(AsKeyDataTest,Basic)52 TEST(AsKeyDataTest, Basic) {
53   AesGcmKey key;
54   key.set_key_value(crypto::tink::subtle::Random::GetRandomBytes(11));
55 
56   KeyData key_data = AsKeyData(key, KeyData::SYMMETRIC);
57 
58   EXPECT_THAT(key_data.type_url(),
59               Eq("type.googleapis.com/google.crypto.tink.AesGcmKey"));
60   EXPECT_THAT(key_data.key_material_type(), Eq(KeyData::SYMMETRIC));
61   AesGcmKey deserialized_key;
62   EXPECT_TRUE(deserialized_key.ParseFromString(key_data.value()));
63   EXPECT_THAT(deserialized_key.key_value(), Eq(key.key_value()));
64 }
65 
TEST(DummyTests,Aead)66 TEST(DummyTests, Aead) {
67   EXPECT_THAT(DummyAead("dummy").Encrypt("foo", "bar").value(),
68               Eq("5:3:dummybarfoo"));
69 }
70 
TEST(DummyTests,AeadCord)71 TEST(DummyTests, AeadCord) {
72   absl::Cord plaintext;
73   plaintext.Append("foo");
74   absl::Cord aad;
75   aad.Append("bar");
76 
77   EXPECT_THAT(DummyCordAead("dummy").Encrypt(plaintext, aad).value(),
78               Eq("5:3:dummybarfoo"));
79 }
80 
TEST(DummyTests,AeadCordMultipleChunks)81 TEST(DummyTests, AeadCordMultipleChunks) {
82   absl::Cord plaintext;
83   plaintext.Append("f");
84   plaintext.Append("o");
85   plaintext.Append("o");
86   absl::Cord aad;
87   aad.Append("b");
88   aad.Append("a");
89   aad.Append("r");
90 
91   EXPECT_THAT(DummyCordAead("dummy").Encrypt(plaintext, aad).value(),
92               Eq("5:3:dummybarfoo"));
93 }
94 
TEST(ZTests,UniformString)95 TEST(ZTests, UniformString) {
96   EXPECT_THAT(ZTestUniformString(std::string(32, 0xaa)), IsOk());
97   EXPECT_THAT(ZTestUniformString(std::string(32, 0x00)), Not(IsOk()));
98   EXPECT_THAT(ZTestUniformString(subtle::Random::GetRandomBytes(32)), IsOk());
99 }
100 
TEST(ZTests,CrossCorrelationUniformString)101 TEST(ZTests, CrossCorrelationUniformString) {
102   EXPECT_THAT(ZTestCrosscorrelationUniformStrings(std::string(32, 0xaa),
103                                                   std::string(32, 0x99)),
104               IsOk());
105   EXPECT_THAT(ZTestCrosscorrelationUniformStrings(std::string(32, 0xaa),
106                                                   std::string(32, 0xaa)),
107               Not(IsOk()));
108   EXPECT_THAT(
109       ZTestCrosscorrelationUniformStrings(subtle::Random::GetRandomBytes(32),
110                                           subtle::Random::GetRandomBytes(32)),
111       IsOk());
112 }
113 
TEST(ZTests,AutocorrelationUniformString)114 TEST(ZTests, AutocorrelationUniformString) {
115   EXPECT_THAT(ZTestAutocorrelationUniformString(std::string(32, 0xaa)),
116               Not(IsOk()));
117   EXPECT_THAT(ZTestAutocorrelationUniformString(std::string(
118                   "This is a text that is only ascii characters and therefore "
119                   "not random. It needs quite a few characters before it has "
120                   "enough to find a pattern, though, as it is text.")),
121               Not(IsOk()));
122   EXPECT_THAT(
123       ZTestAutocorrelationUniformString(subtle::Random::GetRandomBytes(32)),
124       IsOk());
125 }
126 
TEST(DummyStreamingAead,DummyDecryptingStreamPreadAllAtOnceSucceeds)127 TEST(DummyStreamingAead, DummyDecryptingStreamPreadAllAtOnceSucceeds) {
128   const int stream_size = 1024;
129   std::string stream_content = subtle::Random::GetRandomBytes(stream_size);
130 
131   auto ostream = std::make_unique<std::ostringstream>();
132   auto string_stream_buffer = ostream->rdbuf();
133   auto output_stream =
134       std::make_unique<util::OstreamOutputStream>(std::move(ostream));
135 
136   DummyStreamingAead streaming_aead("Some AEAD");
137   util::StatusOr<std::unique_ptr<OutputStream>> encrypting_output_stream =
138       streaming_aead.NewEncryptingStream(std::move(output_stream), "Some AAD");
139   ASSERT_THAT(encrypting_output_stream.status(), IsOk());
140   ASSERT_THAT(subtle::test::WriteToStream(
141                   encrypting_output_stream.value().get(), stream_content),
142               IsOk());
143 
144   std::string ciphertext = string_stream_buffer->str();
145   auto test_random_access_stream =
146       std::make_unique<TestRandomAccessStream>(ciphertext);
147   util::StatusOr<std::unique_ptr<RandomAccessStream>>
148       decrypting_random_access_stream =
149           streaming_aead.NewDecryptingRandomAccessStream(
150               std::move(test_random_access_stream), "Some AAD");
151   ASSERT_THAT(decrypting_random_access_stream.status(), IsOk());
152 
153   auto buffer = util::Buffer::New(ciphertext.size());
154   EXPECT_THAT((*decrypting_random_access_stream)
155                   ->PRead(/*position=*/0, ciphertext.size(), buffer->get()),
156               StatusIs(absl::StatusCode::kOutOfRange));
157   EXPECT_EQ(stream_content,
158             std::string((*buffer)->get_mem_block(), (*buffer)->size()));
159 }
160 
TEST(DummyStreamingAead,DummyDecryptingStreamPreadInChunksSucceeds)161 TEST(DummyStreamingAead, DummyDecryptingStreamPreadInChunksSucceeds) {
162   const int stream_size = 1024;
163   std::string stream_content = subtle::Random::GetRandomBytes(stream_size);
164 
165   auto ostream = std::make_unique<std::ostringstream>();
166   auto string_stream_buffer = ostream->rdbuf();
167   auto output_stream =
168       std::make_unique<util::OstreamOutputStream>(std::move(ostream));
169 
170   DummyStreamingAead streaming_aead("Some AEAD");
171   util::StatusOr<std::unique_ptr<OutputStream>> encrypting_output_stream =
172       streaming_aead.NewEncryptingStream(std::move(output_stream), "Some AAD");
173   ASSERT_THAT(encrypting_output_stream.status(), IsOk());
174   ASSERT_THAT(subtle::test::WriteToStream(
175                   encrypting_output_stream.value().get(), stream_content),
176               IsOk());
177 
178   std::string ciphertext = string_stream_buffer->str();
179   auto test_random_access_stream =
180       std::make_unique<TestRandomAccessStream>(ciphertext);
181   util::StatusOr<std::unique_ptr<RandomAccessStream>>
182       decrypting_random_access_stream =
183           streaming_aead.NewDecryptingRandomAccessStream(
184               std::move(test_random_access_stream), "Some AAD");
185   ASSERT_THAT(decrypting_random_access_stream.status(), IsOk());
186 
187   int chunk_size = 10;
188   auto buffer = util::Buffer::New(chunk_size);
189   std::string plaintext;
190   int64_t position = 0;
191   util::Status status = (*decrypting_random_access_stream)
192                             ->PRead(position, chunk_size, buffer->get());
193   while (status.ok()) {
194     plaintext.append((*buffer)->get_mem_block(), (*buffer)->size());
195     position += (*buffer)->size();
196     status = (*decrypting_random_access_stream)
197                  ->PRead(position, chunk_size, buffer->get());
198   }
199   EXPECT_THAT(status, StatusIs(absl::StatusCode::kOutOfRange));
200   plaintext.append((*buffer)->get_mem_block(), (*buffer)->size());
201   EXPECT_EQ(stream_content, plaintext);
202 }
203 
TEST(DummyStreamingAead,DummyDecryptingStreamPreadWithSmallerHeaderFails)204 TEST(DummyStreamingAead, DummyDecryptingStreamPreadWithSmallerHeaderFails) {
205   const int stream_size = 1024;
206   std::string stream_content = subtle::Random::GetRandomBytes(stream_size);
207 
208   auto ostream = std::make_unique<std::ostringstream>();
209   auto output_stream =
210       std::make_unique<util::OstreamOutputStream>(std::move(ostream));
211 
212   constexpr absl::string_view kStreamingAeadName = "Some AEAD";
213   constexpr absl::string_view kStreamingAeadAad = "Some associated data";
214 
215   DummyStreamingAead streaming_aead(kStreamingAeadName);
216   util::StatusOr<std::unique_ptr<OutputStream>> encrypting_output_stream =
217       streaming_aead.NewEncryptingStream(std::move(output_stream),
218                                          kStreamingAeadAad);
219   ASSERT_THAT(encrypting_output_stream.status(), IsOk());
220   ASSERT_THAT(subtle::test::WriteToStream(
221                   encrypting_output_stream.value().get(), stream_content),
222               IsOk());
223   // Stream content size is too small; DummyDecryptingStream expects
224   // absl::StrCat(kStreamingAeadName, kStreamingAeadAad).
225   std::string ciphertext = "Invalid header";
226   auto test_random_access_stream =
227       std::make_unique<TestRandomAccessStream>(ciphertext);
228   util::StatusOr<std::unique_ptr<RandomAccessStream>>
229       decrypting_random_access_stream =
230           streaming_aead.NewDecryptingRandomAccessStream(
231               std::move(test_random_access_stream), kStreamingAeadAad);
232   ASSERT_THAT(decrypting_random_access_stream.status(), IsOk());
233 
234   int chunk_size = 10;
235   auto buffer = util::Buffer::New(chunk_size);
236   EXPECT_THAT(
237       (*decrypting_random_access_stream)
238           ->PRead(/*position=*/0, chunk_size, buffer->get()),
239       StatusIs(absl::StatusCode::kInvalidArgument, "Could not read header"));
240   EXPECT_THAT(
241       (*decrypting_random_access_stream)
242           ->PRead(/*position=*/0, chunk_size, buffer->get()),
243       StatusIs(absl::StatusCode::kInvalidArgument, "Could not read header"));
244   EXPECT_THAT(
245       (*decrypting_random_access_stream)->size().status(),
246       StatusIs(absl::StatusCode::kInvalidArgument, "Could not read header"));
247 }
248 
TEST(DummyStreamingAead,DummyDecryptingStreamPreadWithCorruptedAadFails)249 TEST(DummyStreamingAead, DummyDecryptingStreamPreadWithCorruptedAadFails) {
250   const int stream_size = 1024;
251   std::string stream_content = subtle::Random::GetRandomBytes(stream_size);
252 
253   auto ostream = std::make_unique<std::ostringstream>();
254   auto string_stream_buffer = ostream->rdbuf();
255   auto output_stream =
256       std::make_unique<util::OstreamOutputStream>(std::move(ostream));
257 
258   constexpr absl::string_view kStreamingAeadName = "Some AEAD";
259   constexpr absl::string_view kStreamingAeadAad = "Some associated data";
260 
261   DummyStreamingAead streaming_aead(kStreamingAeadName);
262   util::StatusOr<std::unique_ptr<OutputStream>> encrypting_output_stream =
263       streaming_aead.NewEncryptingStream(std::move(output_stream),
264                                          kStreamingAeadAad);
265   ASSERT_THAT(encrypting_output_stream.status(), IsOk());
266   ASSERT_THAT(subtle::test::WriteToStream(
267                   encrypting_output_stream.value().get(), stream_content),
268               IsOk());
269   // Invalid associated data.
270   std::string ciphertext = string_stream_buffer->str();
271   auto test_random_access_stream =
272       std::make_unique<TestRandomAccessStream>(ciphertext);
273   util::StatusOr<std::unique_ptr<RandomAccessStream>>
274       decrypting_random_access_stream =
275           streaming_aead.NewDecryptingRandomAccessStream(
276               std::move(test_random_access_stream), "Some wrong AAD");
277   ASSERT_THAT(decrypting_random_access_stream.status(), IsOk());
278 
279   int chunk_size = 10;
280   auto buffer = util::Buffer::New(chunk_size);
281   EXPECT_THAT((*decrypting_random_access_stream)
282                   ->PRead(/*position=*/0, chunk_size, buffer->get()),
283               StatusIs(absl::StatusCode::kInvalidArgument, "Corrupted header"));
284   EXPECT_THAT((*decrypting_random_access_stream)
285                   ->PRead(/*position=*/0, chunk_size, buffer->get()),
286               StatusIs(absl::StatusCode::kInvalidArgument, "Corrupted header"));
287   EXPECT_THAT((*decrypting_random_access_stream)->size().status(),
288               StatusIs(absl::StatusCode::kInvalidArgument, "Corrupted header"));
289 }
290 
291 }  // namespace
292 }  // namespace test
293 }  // namespace tink
294 }  // namespace crypto
295