xref: /aosp_15_r20/external/tink/cc/core/json_keyset_reader_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
1 // Copyright 2017 Google Inc.
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/json_keyset_reader.h"
18 
19 #include <ios>
20 #include <iostream>
21 #include <istream>
22 #include <memory>
23 #include <sstream>
24 #include <string>
25 #include <utility>
26 
27 #include "gtest/gtest.h"
28 #include "absl/strings/escaping.h"
29 #include "absl/strings/substitute.h"
30 #include "tink/util/test_matchers.h"
31 #include "tink/util/test_util.h"
32 #include "proto/aes_eax.pb.h"
33 #include "proto/aes_gcm.pb.h"
34 #include "proto/tink.pb.h"
35 
36 namespace crypto {
37 namespace tink {
38 
39 using ::crypto::tink::test::AddRawKey;
40 using ::crypto::tink::test::AddTinkKey;
41 using ::crypto::tink::test::IsOk;
42 
43 using ::google::crypto::tink::AesEaxKey;
44 using ::google::crypto::tink::AesGcmKey;
45 using ::google::crypto::tink::EncryptedKeyset;
46 using ::google::crypto::tink::KeyData;
47 using ::google::crypto::tink::Keyset;
48 using ::google::crypto::tink::KeyStatusType;
49 using ::google::crypto::tink::OutputPrefixType;
50 using ::testing::Eq;
51 using ::testing::Not;
52 
53 namespace {
54 
55 class JsonKeysetReaderTest : public ::testing::Test {
56  protected:
SetUp()57   void SetUp() override {
58     gcm_key_.set_key_value("some gcm key value");
59     gcm_key_.set_version(0);
60 
61     eax_key_.set_key_value("some eax key value");
62     eax_key_.set_version(0);
63     eax_key_.mutable_params()->set_iv_size(16);
64 
65     AddTinkKey("type.googleapis.com/google.crypto.tink.AesGcmKey", 42, gcm_key_,
66                KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset_);
67     AddRawKey("type.googleapis.com/google.crypto.tink.AesEaxKey", 711, eax_key_,
68               KeyStatusType::ENABLED, KeyData::SYMMETRIC, &keyset_);
69     keyset_.set_primary_key_id(42);
70     good_json_keyset_ = absl::Substitute(
71         R"(
72       {
73          "primaryKeyId":42,
74          "key":[
75             {
76                "keyData":{
77                   "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
78                   "keyMaterialType":"SYMMETRIC",
79                   "value": "$0"
80                },
81                "outputPrefixType":"TINK",
82                "keyId":42,
83                "status":"ENABLED"
84             },
85             {
86                "keyData":{
87                   "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey",
88                   "keyMaterialType":"SYMMETRIC",
89                   "value":"$1"
90                },
91                "outputPrefixType":"RAW",
92                "keyId":711,
93                "status":"ENABLED"
94             }
95          ]
96       })",
97         absl::Base64Escape(gcm_key_.SerializeAsString()),
98         absl::Base64Escape(eax_key_.SerializeAsString()));
99 
100     bad_json_keyset_ = "some weird string";
101 
102     std::string enc_keyset = "some ciphertext with keyset";
103     encrypted_keyset_.set_encrypted_keyset(enc_keyset);
104     std::string enc_keyset_base64;
105     absl::Base64Escape(enc_keyset, &enc_keyset_base64);
106     auto keyset_info = encrypted_keyset_.mutable_keyset_info();
107     keyset_info->set_primary_key_id(42);
108     auto key_info = keyset_info->add_key_info();
109     key_info->set_type_url("type.googleapis.com/google.crypto.tink.AesGcmKey");
110     key_info->set_key_id(42);
111     key_info->set_output_prefix_type(OutputPrefixType::TINK);
112     key_info->set_status(KeyStatusType::ENABLED);
113     good_json_encrypted_keyset_ =
114         "{"
115         "\"encryptedKeyset\": \"" +
116         enc_keyset_base64 +
117         "\", "
118         "\"keysetInfo\": {"
119         "  \"primaryKeyId\": 42,"
120         "  \"keyInfo\": ["
121         "    {"
122         "      \"typeUrl\":"
123         "        \"type.googleapis.com/google.crypto.tink.AesGcmKey\","
124         "      \"outputPrefixType\": \"TINK\","
125         "      \"keyId\": 42,"
126         "      \"status\": \"ENABLED\""
127         "    }"
128         "  ]"
129         "}}";
130   }
131 
132   EncryptedKeyset encrypted_keyset_;
133   Keyset keyset_;
134   std::string bad_json_keyset_;
135   std::string good_json_keyset_;
136   std::string good_json_encrypted_keyset_;
137 
138   // Some prepopulated keys.
139   AesGcmKey gcm_key_;
140   AesEaxKey eax_key_;
141 };
142 
TEST_F(JsonKeysetReaderTest,testReaderCreation)143 TEST_F(JsonKeysetReaderTest, testReaderCreation) {
144   {  // Input stream is null.
145     std::unique_ptr<std::istream> null_stream(nullptr);
146     auto reader_result = JsonKeysetReader::New(std::move(null_stream));
147     EXPECT_FALSE(reader_result.ok());
148     EXPECT_EQ(absl::StatusCode::kInvalidArgument,
149               reader_result.status().code());
150   }
151 
152   {  // Good serialized keyset.
153     auto reader_result = JsonKeysetReader::New(good_json_keyset_);
154     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
155   }
156 
157   {  // Stream with good keyset.
158     std::unique_ptr<std::istream> good_keyset_stream(new std::stringstream(
159         std::string(good_json_keyset_), std::ios_base::in));
160     auto reader_result = JsonKeysetReader::New(std::move(good_keyset_stream));
161     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
162   }
163 
164   {  // Bad serialized keyset.
165     auto reader_result = JsonKeysetReader::New(bad_json_keyset_);
166     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
167   }
168 
169   {  // Stream with bad keyset.
170     std::unique_ptr<std::istream> bad_keyset_stream(new std::stringstream(
171         std::string(bad_json_keyset_), std::ios_base::in));
172     auto reader_result = JsonKeysetReader::New(std::move(bad_keyset_stream));
173     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
174   }
175 }
176 
TEST_F(JsonKeysetReaderTest,testReadFromString)177 TEST_F(JsonKeysetReaderTest, testReadFromString) {
178   {  // Good string.
179     auto reader_result = JsonKeysetReader::New(good_json_keyset_);
180     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
181     auto reader = std::move(reader_result.value());
182     auto read_result = reader->Read();
183     EXPECT_TRUE(read_result.ok()) << read_result.status();
184     auto keyset = std::move(read_result.value());
185     EXPECT_EQ(keyset_.SerializeAsString(), keyset->SerializeAsString());
186   }
187 
188   {  // Bad string.
189     auto reader_result = JsonKeysetReader::New(bad_json_keyset_);
190     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
191     auto reader = std::move(reader_result.value());
192     auto read_result = reader->Read();
193     EXPECT_FALSE(read_result.ok());
194     EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_result.status().code());
195   }
196 }
197 
TEST_F(JsonKeysetReaderTest,testReadFromStream)198 TEST_F(JsonKeysetReaderTest, testReadFromStream) {
199   {  // Good stream.
200     std::unique_ptr<std::istream> good_keyset_stream(new std::stringstream(
201         std::string(good_json_keyset_), std::ios_base::in));
202     auto reader_result = JsonKeysetReader::New(std::move(good_keyset_stream));
203     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
204     auto reader = std::move(reader_result.value());
205     auto read_result = reader->Read();
206     EXPECT_TRUE(read_result.ok()) << read_result.status();
207     auto keyset = std::move(read_result.value());
208     EXPECT_EQ(keyset_.SerializeAsString(), keyset->SerializeAsString());
209   }
210 
211   {  // Bad stream.
212     std::unique_ptr<std::istream> bad_keyset_stream(new std::stringstream(
213         std::string(bad_json_keyset_), std::ios_base::in));
214     auto reader_result = JsonKeysetReader::New(std::move(bad_keyset_stream));
215     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
216     auto reader = std::move(reader_result.value());
217     auto read_result = reader->Read();
218     EXPECT_FALSE(read_result.ok());
219     EXPECT_EQ(absl::StatusCode::kInvalidArgument, read_result.status().code());
220   }
221 }
222 
TEST_F(JsonKeysetReaderTest,testReadEncryptedFromString)223 TEST_F(JsonKeysetReaderTest, testReadEncryptedFromString) {
224   {  // Good string.
225     auto reader_result = JsonKeysetReader::New(good_json_encrypted_keyset_);
226     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
227     auto reader = std::move(reader_result.value());
228     auto read_encrypted_result = reader->ReadEncrypted();
229     EXPECT_TRUE(read_encrypted_result.ok()) << read_encrypted_result.status();
230     auto encrypted_keyset = std::move(read_encrypted_result.value());
231     EXPECT_EQ(encrypted_keyset_.SerializeAsString(),
232               encrypted_keyset->SerializeAsString());
233   }
234 
235   {  // Bad string.
236     auto reader_result = JsonKeysetReader::New(bad_json_keyset_);
237     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
238     auto reader = std::move(reader_result.value());
239     auto read_encrypted_result = reader->ReadEncrypted();
240     EXPECT_FALSE(read_encrypted_result.ok());
241     EXPECT_EQ(absl::StatusCode::kInvalidArgument,
242               read_encrypted_result.status().code());
243   }
244 }
245 
TEST_F(JsonKeysetReaderTest,testReadEncryptedFromStream)246 TEST_F(JsonKeysetReaderTest, testReadEncryptedFromStream) {
247   {  // Good stream.
248     std::unique_ptr<std::istream> good_encrypted_keyset_stream(
249         new std::stringstream(std::string(good_json_encrypted_keyset_),
250                               std::ios_base::in));
251     auto reader_result =
252         JsonKeysetReader::New(std::move(good_encrypted_keyset_stream));
253     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
254     auto reader = std::move(reader_result.value());
255     auto read_encrypted_result = reader->ReadEncrypted();
256     EXPECT_TRUE(read_encrypted_result.ok()) << read_encrypted_result.status();
257     auto encrypted_keyset = std::move(read_encrypted_result.value());
258     EXPECT_EQ(encrypted_keyset_.SerializeAsString(),
259               encrypted_keyset->SerializeAsString());
260   }
261 
262   {  // Bad string.
263     std::unique_ptr<std::istream> bad_keyset_stream(new std::stringstream(
264         std::string(bad_json_keyset_), std::ios_base::in));
265     auto reader_result = JsonKeysetReader::New(std::move(bad_keyset_stream));
266     EXPECT_TRUE(reader_result.ok()) << reader_result.status();
267     auto reader = std::move(reader_result.value());
268     auto read_encrypted_result = reader->ReadEncrypted();
269     EXPECT_FALSE(read_encrypted_result.ok());
270     EXPECT_EQ(absl::StatusCode::kInvalidArgument,
271               read_encrypted_result.status().code());
272   }
273 }
274 
TEST_F(JsonKeysetReaderTest,ReadLargeKeyId)275 TEST_F(JsonKeysetReaderTest, ReadLargeKeyId) {
276   std::string json_serialization =
277       absl::Substitute(R"(
278       {
279          "primaryKeyId": 4294967275,
280          "key":[
281             {
282                "keyData":{
283                   "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
284                   "keyMaterialType":"SYMMETRIC",
285                   "value": "$0"
286                },
287                "outputPrefixType":"TINK",
288                "keyId": 4294967275,
289                "status":"ENABLED"
290             },
291             {
292                "keyData":{
293                   "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey",
294                   "keyMaterialType":"SYMMETRIC",
295                   "value":"$1"
296                },
297                "outputPrefixType":"RAW",
298                "keyId":711,
299                "status":"ENABLED"
300             }
301          ]
302       })",
303                        absl::Base64Escape(gcm_key_.SerializeAsString()),
304                        absl::Base64Escape(eax_key_.SerializeAsString()));
305   auto reader_result = JsonKeysetReader::New(json_serialization);
306   ASSERT_THAT(reader_result, IsOk());
307   auto reader = std::move(reader_result.value());
308   auto read_result = reader->Read();
309   ASSERT_THAT(read_result, IsOk());
310   auto keyset = std::move(read_result.value());
311   EXPECT_THAT(keyset->primary_key_id(), Eq(4294967275));
312 }
313 
TEST_F(JsonKeysetReaderTest,RejectsNegativeKeyIds)314 TEST_F(JsonKeysetReaderTest, RejectsNegativeKeyIds) {
315   std::string json_serialization =
316       absl::Substitute(R"(
317       {
318          "primaryKeyId": 711,
319          "key":[
320             {
321                "keyData":{
322                   "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
323                   "keyMaterialType":"SYMMETRIC",
324                   "value": "$0"
325                },
326                "outputPrefixType":"TINK",
327                "keyId": -21,
328                "status":"ENABLED"
329             },
330             {
331                "keyData":{
332                   "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey",
333                   "keyMaterialType":"SYMMETRIC",
334                   "value":"$1"
335                },
336                "outputPrefixType":"RAW",
337                "keyId":711,
338                "status":"ENABLED"
339             }
340          ]
341       })",
342                        absl::Base64Escape(gcm_key_.SerializeAsString()),
343                        absl::Base64Escape(eax_key_.SerializeAsString()));
344   auto reader_result = JsonKeysetReader::New(json_serialization);
345   ASSERT_THAT(reader_result, IsOk());
346   auto reader = std::move(reader_result.value());
347   auto read_result = reader->Read();
348   EXPECT_THAT(read_result, Not(IsOk()));
349 }
350 
TEST_F(JsonKeysetReaderTest,RejectsKeyIdLargerThanUint32)351 TEST_F(JsonKeysetReaderTest, RejectsKeyIdLargerThanUint32) {
352   // 4294967296 = 2^32, which is too large for uint32.
353   std::string json_serialization =
354       absl::Substitute(R"(
355       {
356          "primaryKeyId": 711,
357          "key":[
358             {
359                "keyData":{
360                   "typeUrl":"type.googleapis.com/google.crypto.tink.AesGcmKey",
361                   "keyMaterialType":"SYMMETRIC",
362                   "value": "$0"
363                },
364                "outputPrefixType":"TINK",
365                "keyId": 4294967296,
366                "status":"ENABLED"
367             },
368             {
369                "keyData":{
370                   "typeUrl":"type.googleapis.com/google.crypto.tink.AesEaxKey",
371                   "keyMaterialType":"SYMMETRIC",
372                   "value":"$1"
373                },
374                "outputPrefixType":"RAW",
375                "keyId":711,
376                "status":"ENABLED"
377             }
378          ]
379       })",
380                        absl::Base64Escape(gcm_key_.SerializeAsString()),
381                        absl::Base64Escape(eax_key_.SerializeAsString()));
382   auto reader_result = JsonKeysetReader::New(json_serialization);
383   ASSERT_THAT(reader_result, IsOk());
384   auto reader = std::move(reader_result.value());
385   auto read_result = reader->Read();
386   EXPECT_THAT(read_result, Not(IsOk()));
387 }
388 
389 }  // namespace
390 }  // namespace tink
391 }  // namespace crypto
392