1 // Copyright 2020 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
17 #include "keyset_impl.h"
18
19 #include <memory>
20 #include <ostream>
21 #include <sstream>
22 #include <string>
23 #include <utility>
24
25 #include "gmock/gmock.h"
26 #include "gtest/gtest.h"
27 #include "tink/aead/aead_key_templates.h"
28 #include "tink/binary_keyset_reader.h"
29 #include "tink/binary_keyset_writer.h"
30 #include "tink/cleartext_keyset_handle.h"
31 #include "tink/config/tink_config.h"
32 #include "tink/hybrid/hybrid_key_templates.h"
33 #include "tink/util/test_matchers.h"
34 #include "proto/testing_api.grpc.pb.h"
35
36 namespace crypto {
37 namespace tink {
38 namespace {
39
40 using ::crypto::tink::AeadKeyTemplates;
41 using ::crypto::tink::BinaryKeysetReader;
42 using ::crypto::tink::BinaryKeysetWriter;
43 using ::crypto::tink::CleartextKeysetHandle;
44 using ::crypto::tink::HybridKeyTemplates;
45 using ::google::crypto::tink::KeyTemplate;
46 using ::testing::Eq;
47 using ::testing::IsEmpty;
48 using ::crypto::tink::test::IsOk;
49 using ::tink_testing_api::KeysetFromJsonRequest;
50 using ::tink_testing_api::KeysetFromJsonResponse;
51 using ::tink_testing_api::KeysetGenerateRequest;
52 using ::tink_testing_api::KeysetGenerateResponse;
53 using ::tink_testing_api::KeysetPublicRequest;
54 using ::tink_testing_api::KeysetPublicResponse;
55 using ::tink_testing_api::KeysetReadEncryptedRequest;
56 using ::tink_testing_api::KeysetReadEncryptedResponse;
57 using ::tink_testing_api::KeysetToJsonRequest;
58 using ::tink_testing_api::KeysetToJsonResponse;
59 using ::tink_testing_api::KeysetWriteEncryptedRequest;
60 using ::tink_testing_api::KeysetWriteEncryptedResponse;
61
62 class KeysetImplTest : public ::testing::Test {
63 protected:
SetUpTestSuite()64 static void SetUpTestSuite() { ASSERT_TRUE(TinkConfig::Register().ok()); }
65 };
66
TEST_F(KeysetImplTest,GenerateSuccess)67 TEST_F(KeysetImplTest, GenerateSuccess) {
68 tink_testing_api::KeysetImpl keyset;
69 const KeyTemplate& key_template = AeadKeyTemplates::Aes128Eax();
70 KeysetGenerateRequest request;
71 std::string templ;
72 EXPECT_TRUE(key_template.SerializeToString(&templ));
73 request.set_template_(templ);
74 KeysetGenerateResponse response;
75
76 EXPECT_TRUE(keyset.Generate(nullptr, &request, &response).ok());
77 EXPECT_THAT(response.err(), IsEmpty());
78
79 auto reader_result = BinaryKeysetReader::New(response.keyset());
80 ASSERT_TRUE(reader_result.ok());
81 auto handle_result =
82 CleartextKeysetHandle::Read(std::move(reader_result.value()));
83 EXPECT_TRUE(handle_result.ok());
84 }
85
TEST_F(KeysetImplTest,GenerateFail)86 TEST_F(KeysetImplTest, GenerateFail) {
87 tink_testing_api::KeysetImpl keyset;
88
89 KeysetGenerateRequest request;
90 request.set_template_("bad template");
91 KeysetGenerateResponse response;
92 EXPECT_TRUE(keyset.Generate(nullptr, &request, &response).ok());
93 EXPECT_THAT(response.err(), Not(IsEmpty()));
94 }
95
AeadKeyset()96 util::StatusOr<std::string> AeadKeyset() {
97 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
98 KeysetHandle::GenerateNew(AeadKeyTemplates::Aes128Gcm());
99 if (!handle.ok()) {
100 return handle.status();
101 }
102 std::stringbuf keyset;
103 util::StatusOr<std::unique_ptr<BinaryKeysetWriter>> writer =
104 BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&keyset));
105 if (!handle.ok()) {
106 return handle.status();
107 }
108 util::Status status = CleartextKeysetHandle::Write(writer->get(), **handle);
109 if (!status.ok()) {
110 return status;
111 }
112 return keyset.str();
113 }
114
ValidPrivateKeyset()115 util::StatusOr<std::string> ValidPrivateKeyset() {
116 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
117 KeysetHandle::GenerateNew(
118 HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm());
119 if (!handle.ok()) {
120 return handle.status();
121 }
122 std::stringbuf keyset;
123 util::StatusOr<std::unique_ptr<BinaryKeysetWriter>> writer =
124 BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&keyset));
125 if (!writer.ok()) {
126 return writer.status();
127 }
128 util::Status status = CleartextKeysetHandle::Write(writer->get(), **handle);
129 if (!status.ok()) {
130 return status;
131 }
132 return keyset.str();
133 }
134
TEST_F(KeysetImplTest,PublicSuccess)135 TEST_F(KeysetImplTest, PublicSuccess) {
136 tink_testing_api::KeysetImpl keyset;
137
138 util::StatusOr<std::string> private_keyset = ValidPrivateKeyset();
139 ASSERT_THAT(private_keyset.status(), IsOk());
140
141 KeysetPublicRequest request;
142 request.set_private_keyset(*private_keyset);
143 KeysetPublicResponse response;
144
145 EXPECT_TRUE(keyset.Public(nullptr, &request, &response).ok());
146 EXPECT_THAT(response.err(), IsEmpty());
147
148 auto reader_result = BinaryKeysetReader::New(response.public_keyset());
149 ASSERT_TRUE(reader_result.ok());
150 auto public_handle_result =
151 CleartextKeysetHandle::Read(std::move(reader_result.value()));
152 EXPECT_TRUE(public_handle_result.ok());
153 }
154
TEST_F(KeysetImplTest,PublicFail)155 TEST_F(KeysetImplTest, PublicFail) {
156 tink_testing_api::KeysetImpl keyset;
157
158 KeysetPublicRequest request;
159 request.set_private_keyset("bad keyset");
160 KeysetPublicResponse response;
161 EXPECT_TRUE(keyset.Public(nullptr, &request, &response).ok());
162 EXPECT_THAT(response.err(), Not(IsEmpty()));
163 }
164
TEST_F(KeysetImplTest,FromJsonSuccess)165 TEST_F(KeysetImplTest, FromJsonSuccess) {
166 tink_testing_api::KeysetImpl keyset;
167 std::string json_keyset = R""""(
168 {
169 "primaryKeyId": 42,
170 "key": [
171 {
172 "keyData": {
173 "typeUrl": "type.googleapis.com/google.crypto.tink.FakeKeyType",
174 "keyMaterialType": "SYMMETRIC",
175 "value": "AFakeTestKeyValue1234567"
176 },
177 "outputPrefixType": "TINK",
178 "keyId": 42,
179 "status": "ENABLED"
180 }
181 ]
182 })"""";
183 KeysetFromJsonRequest from_request;
184 from_request.set_json_keyset(json_keyset);
185 KeysetFromJsonResponse from_response;
186 EXPECT_TRUE(keyset.FromJson(nullptr, &from_request, &from_response).ok());
187 EXPECT_THAT(from_response.err(), IsEmpty());
188 std::string output = from_response.keyset();
189
190 auto reader_result = BinaryKeysetReader::New(from_response.keyset());
191 EXPECT_TRUE(reader_result.ok());
192 auto keyset_proto_result = reader_result.value()->Read();
193 EXPECT_TRUE(keyset_proto_result.ok());
194 EXPECT_THAT(keyset_proto_result.value()->primary_key_id(), Eq(42));
195 }
196
TEST_F(KeysetImplTest,ToFromJsonSuccess)197 TEST_F(KeysetImplTest, ToFromJsonSuccess) {
198 tink_testing_api::KeysetImpl keyset;
199 util::StatusOr<std::string> private_keyset = ValidPrivateKeyset();
200 EXPECT_THAT(private_keyset.status(), IsOk());
201
202 KeysetToJsonRequest to_request;
203 to_request.set_keyset(*private_keyset);
204 KeysetToJsonResponse to_response;
205 EXPECT_TRUE(keyset.ToJson(nullptr, &to_request, &to_response).ok());
206 EXPECT_THAT(to_response.err(), IsEmpty());
207 std::string json_keyset = to_response.json_keyset();
208
209 KeysetFromJsonRequest from_request;
210 from_request.set_json_keyset(json_keyset);
211 KeysetFromJsonResponse from_response;
212 EXPECT_TRUE(keyset.FromJson(nullptr, &from_request, &from_response).ok());
213 EXPECT_THAT(from_response.err(), IsEmpty());
214 std::string output = from_response.keyset();
215 EXPECT_THAT(from_response.keyset(), Eq(*private_keyset));
216 }
217
TEST_F(KeysetImplTest,ToJsonFail)218 TEST_F(KeysetImplTest, ToJsonFail) {
219 tink_testing_api::KeysetImpl keyset;
220
221 KeysetToJsonRequest request;
222 request.set_keyset("bad keyset");
223 KeysetToJsonResponse response;
224 EXPECT_TRUE(keyset.ToJson(nullptr, &request, &response).ok());
225 EXPECT_THAT(response.err(), Not(IsEmpty()));
226 }
227
TEST_F(KeysetImplTest,FromJsonFail)228 TEST_F(KeysetImplTest, FromJsonFail) {
229 tink_testing_api::KeysetImpl keyset;
230
231 KeysetFromJsonRequest request;
232 request.set_json_keyset("bad json keyset");
233 KeysetFromJsonResponse response;
234 EXPECT_TRUE(keyset.FromJson(nullptr, &request, &response).ok());
235 EXPECT_THAT(response.err(), Not(IsEmpty()));
236 }
237
TEST_F(KeysetImplTest,ReadWriteEncryptedKeysetSuccess)238 TEST_F(KeysetImplTest, ReadWriteEncryptedKeysetSuccess) {
239 tink_testing_api::KeysetImpl keyset_impl;
240
241 util::StatusOr<std::string> master_keyset = AeadKeyset();
242 ASSERT_THAT(master_keyset.status(), IsOk());
243 util::StatusOr<std::string> keyset = AeadKeyset();
244 ASSERT_THAT(master_keyset.status(), IsOk());
245
246 KeysetWriteEncryptedRequest write_request;
247 write_request.set_keyset(*keyset);
248 write_request.set_master_keyset(*master_keyset);
249 write_request.set_keyset_writer_type(tink_testing_api::KEYSET_WRITER_BINARY);
250 KeysetWriteEncryptedResponse write_response;
251
252 ASSERT_TRUE(
253 keyset_impl
254 .WriteEncrypted(/*context=*/nullptr, &write_request, &write_response)
255 .ok());
256 ASSERT_THAT(write_response.err(), IsEmpty());
257
258 KeysetReadEncryptedRequest read_request;
259 read_request.set_encrypted_keyset(write_response.encrypted_keyset());
260 read_request.set_master_keyset(*master_keyset);
261 read_request.set_keyset_reader_type(tink_testing_api::KEYSET_READER_BINARY);
262 KeysetReadEncryptedResponse read_response;
263
264 ASSERT_TRUE(
265 keyset_impl
266 .ReadEncrypted(/*context=*/nullptr, &read_request, &read_response)
267 .ok());
268 EXPECT_THAT(read_response.err(), IsEmpty());
269 EXPECT_EQ(read_response.keyset(), *keyset);
270 }
271
TEST_F(KeysetImplTest,ReadWriteEncryptedWithAssociatedDataKeysetSuccess)272 TEST_F(KeysetImplTest, ReadWriteEncryptedWithAssociatedDataKeysetSuccess) {
273 tink_testing_api::KeysetImpl keyset_impl;
274
275 util::StatusOr<std::string> master_keyset = AeadKeyset();
276 ASSERT_THAT(master_keyset.status(), IsOk());
277 util::StatusOr<std::string> keyset = AeadKeyset();
278 ASSERT_THAT(keyset.status(), IsOk());
279 std::string associated_data = "associated_data";
280
281 KeysetWriteEncryptedRequest write_request;
282 write_request.set_keyset(*keyset);
283 write_request.set_master_keyset(*master_keyset);
284 write_request.mutable_associated_data()->set_value(associated_data);
285 write_request.set_keyset_writer_type(tink_testing_api::KEYSET_WRITER_BINARY);
286 KeysetWriteEncryptedResponse write_response;
287
288 ASSERT_TRUE(
289 keyset_impl
290 .WriteEncrypted(/*context=*/nullptr, &write_request, &write_response)
291 .ok());
292 ASSERT_THAT(write_response.err(), IsEmpty());
293
294 KeysetReadEncryptedRequest read_request;
295 read_request.set_encrypted_keyset(write_response.encrypted_keyset());
296 read_request.set_master_keyset(*master_keyset);
297 read_request.mutable_associated_data()->set_value(associated_data);
298 read_request.set_keyset_reader_type(tink_testing_api::KEYSET_READER_BINARY);
299 KeysetReadEncryptedResponse read_response;
300
301 ASSERT_TRUE(
302 keyset_impl
303 .ReadEncrypted(/*context=*/nullptr, &read_request, &read_response)
304 .ok());
305 EXPECT_THAT(read_response.err(), IsEmpty());
306 EXPECT_EQ(read_response.keyset(), *keyset);
307 }
308
TEST_F(KeysetImplTest,WriteEncryptedKeysetFail)309 TEST_F(KeysetImplTest, WriteEncryptedKeysetFail) {
310 tink_testing_api::KeysetImpl keyset_impl;
311
312 util::StatusOr<std::string> master_keyset = AeadKeyset();
313 ASSERT_THAT(master_keyset.status(), IsOk());
314
315 KeysetWriteEncryptedRequest write_request;
316 write_request.set_keyset("invalid");
317 write_request.set_master_keyset(*master_keyset);
318 write_request.set_keyset_writer_type(tink_testing_api::KEYSET_WRITER_BINARY);
319 KeysetWriteEncryptedResponse write_response;
320
321 ASSERT_TRUE(
322 keyset_impl
323 .WriteEncrypted(/*context=*/nullptr, &write_request, &write_response)
324 .ok());
325 EXPECT_THAT(write_response.err(), Not(IsEmpty()));
326 }
327
TEST_F(KeysetImplTest,ReadEncryptedKeysetFail)328 TEST_F(KeysetImplTest, ReadEncryptedKeysetFail) {
329 tink_testing_api::KeysetImpl keyset_impl;
330
331 util::StatusOr<std::string> master_keyset = AeadKeyset();
332 ASSERT_THAT(master_keyset.status(), IsOk());
333
334 KeysetReadEncryptedRequest read_request;
335 read_request.set_encrypted_keyset("invalid");
336 read_request.set_master_keyset(*master_keyset);
337 read_request.set_keyset_reader_type(tink_testing_api::KEYSET_READER_BINARY);
338 KeysetReadEncryptedResponse read_response;
339
340 ASSERT_TRUE(
341 keyset_impl
342 .ReadEncrypted(/*context=*/nullptr, &read_request, &read_response)
343 .ok());
344 EXPECT_THAT(read_response.err(), Not(IsEmpty()));
345 }
346
347 } // namespace
348 } // namespace tink
349 } // namespace crypto
350