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