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 "hybrid_impl.h"
18
19 #include <memory>
20 #include <ostream>
21 #include <sstream>
22 #include <string>
23
24 #include "gmock/gmock.h"
25 #include "gtest/gtest.h"
26 #include "tink/binary_keyset_writer.h"
27 #include "tink/cleartext_keyset_handle.h"
28 #include "tink/hybrid/hybrid_config.h"
29 #include "tink/hybrid/hybrid_key_templates.h"
30 #include "proto/testing_api.grpc.pb.h"
31
32 namespace crypto {
33 namespace tink {
34 namespace {
35
36 using ::crypto::tink::BinaryKeysetWriter;
37 using ::crypto::tink::CleartextKeysetHandle;
38 using ::crypto::tink::HybridKeyTemplates;
39
40 using ::testing::Eq;
41 using ::testing::IsEmpty;
42 using ::tink_testing_api::CreationRequest;
43 using ::tink_testing_api::CreationResponse;
44 using ::tink_testing_api::HybridDecryptRequest;
45 using ::tink_testing_api::HybridDecryptResponse;
46 using ::tink_testing_api::HybridEncryptRequest;
47 using ::tink_testing_api::HybridEncryptResponse;
48
49 using crypto::tink::KeysetHandle;
50 using google::crypto::tink::KeyTemplate;
51
KeysetBytes(const KeysetHandle & keyset_handle)52 std::string KeysetBytes(const KeysetHandle& keyset_handle) {
53 std::stringbuf keyset;
54 auto writer_result =
55 BinaryKeysetWriter::New(absl::make_unique<std::ostream>(&keyset));
56 EXPECT_TRUE(writer_result.ok());
57 auto status =
58 CleartextKeysetHandle::Write(writer_result.value().get(), keyset_handle);
59 EXPECT_TRUE(status.ok());
60 return keyset.str();
61 }
62
63 class HybridImplTest : public ::testing::Test {
64 protected:
SetUpTestSuite()65 static void SetUpTestSuite() { ASSERT_TRUE(HybridConfig::Register().ok()); }
66 };
67
TEST_F(HybridImplTest,CreateHybridDecryptSuccess)68 TEST_F(HybridImplTest, CreateHybridDecryptSuccess) {
69 tink_testing_api::HybridImpl hybrid;
70 const KeyTemplate& key_template =
71 HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm();
72 ::crypto::tink::util::StatusOr<std::unique_ptr<KeysetHandle>>
73 private_keyset_handle = KeysetHandle::GenerateNew(key_template);
74 ASSERT_TRUE(private_keyset_handle.status().ok())
75 << private_keyset_handle.status();
76
77 CreationRequest request;
78 request.mutable_annotated_keyset()->set_serialized_keyset(
79 KeysetBytes(**private_keyset_handle));
80 CreationResponse response;
81
82 EXPECT_TRUE(hybrid.CreateHybridDecrypt(nullptr, &request, &response).ok());
83 EXPECT_THAT(response.err(), IsEmpty());
84 }
85
TEST_F(HybridImplTest,CreateHybridDecryptFailure)86 TEST_F(HybridImplTest, CreateHybridDecryptFailure) {
87 tink_testing_api::HybridImpl hybrid;
88
89 CreationRequest request;
90 request.mutable_annotated_keyset()->set_serialized_keyset("\x80");
91 CreationResponse response;
92
93 EXPECT_TRUE(hybrid.CreateHybridDecrypt(nullptr, &request, &response).ok());
94 EXPECT_THAT(response.err(), Not(IsEmpty()));
95 }
96
TEST_F(HybridImplTest,CreateHybridEncryptSuccess)97 TEST_F(HybridImplTest, CreateHybridEncryptSuccess) {
98 tink_testing_api::HybridImpl hybrid;
99 const KeyTemplate& key_template =
100 HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm();
101 ::crypto::tink::util::StatusOr<std::unique_ptr<KeysetHandle>>
102 private_keyset_handle = KeysetHandle::GenerateNew(key_template);
103 ASSERT_TRUE(private_keyset_handle.status().ok())
104 << private_keyset_handle.status();
105 ::crypto::tink::util::StatusOr<std::unique_ptr<KeysetHandle>>
106 public_keyset_handle = (*private_keyset_handle)->GetPublicKeysetHandle();
107 ASSERT_TRUE(public_keyset_handle.status().ok())
108 << public_keyset_handle.status();
109
110 CreationRequest request;
111 request.mutable_annotated_keyset()->set_serialized_keyset(
112 KeysetBytes(**public_keyset_handle));
113 CreationResponse response;
114
115 EXPECT_TRUE(hybrid.CreateHybridEncrypt(nullptr, &request, &response).ok());
116 EXPECT_THAT(response.err(), IsEmpty());
117 }
118
TEST_F(HybridImplTest,CreateHybridEncryptFailure)119 TEST_F(HybridImplTest, CreateHybridEncryptFailure) {
120 tink_testing_api::HybridImpl hybrid;
121
122 CreationRequest request;
123 request.mutable_annotated_keyset()->set_serialized_keyset("\x80");
124 CreationResponse response;
125
126 EXPECT_TRUE(hybrid.CreateHybridEncrypt(nullptr, &request, &response).ok());
127 EXPECT_THAT(response.err(), Not(IsEmpty()));
128 }
129
TEST_F(HybridImplTest,EncryptDecryptSuccess)130 TEST_F(HybridImplTest, EncryptDecryptSuccess) {
131 tink_testing_api::HybridImpl hybrid;
132 const KeyTemplate& key_template =
133 HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm();
134 auto private_handle_result = KeysetHandle::GenerateNew(key_template);
135 EXPECT_TRUE(private_handle_result.ok());
136 auto public_handle_result =
137 private_handle_result.value()->GetPublicKeysetHandle();
138 EXPECT_TRUE(public_handle_result.ok());
139
140 HybridEncryptRequest enc_request;
141 enc_request.mutable_public_annotated_keyset()->set_serialized_keyset(
142 KeysetBytes(*public_handle_result.value()));
143 enc_request.set_plaintext("Plain text");
144 enc_request.set_context_info("context");
145 HybridEncryptResponse enc_response;
146
147 EXPECT_TRUE(hybrid.Encrypt(nullptr, &enc_request, &enc_response).ok());
148 EXPECT_THAT(enc_response.err(), IsEmpty());
149
150 HybridDecryptRequest dec_request;
151 dec_request.mutable_private_annotated_keyset()->set_serialized_keyset(
152 KeysetBytes(*private_handle_result.value()));
153 dec_request.set_ciphertext(enc_response.ciphertext());
154 dec_request.set_context_info("context");
155 HybridDecryptResponse dec_response;
156
157 EXPECT_TRUE(hybrid.Decrypt(nullptr, &dec_request, &dec_response).ok());
158 EXPECT_THAT(dec_response.err(), IsEmpty());
159 EXPECT_THAT(dec_response.plaintext(), Eq("Plain text"));
160 }
161
TEST_F(HybridImplTest,EncryptBadKeysetFail)162 TEST_F(HybridImplTest, EncryptBadKeysetFail) {
163 tink_testing_api::HybridImpl hybrid;
164 HybridEncryptRequest enc_request;
165 enc_request.mutable_public_annotated_keyset()->set_serialized_keyset(
166 "bad keyset");
167 enc_request.set_plaintext("Plain text");
168 enc_request.set_context_info("context");
169 HybridEncryptResponse enc_response;
170
171 EXPECT_TRUE(hybrid.Encrypt(nullptr, &enc_request, &enc_response).ok());
172 EXPECT_THAT(enc_response.err(), Not(IsEmpty()));
173 }
174
TEST_F(HybridImplTest,DecryptBadCiphertextFail)175 TEST_F(HybridImplTest, DecryptBadCiphertextFail) {
176 tink_testing_api::HybridImpl hybrid;
177 const KeyTemplate& key_template =
178 HybridKeyTemplates::EciesP256HkdfHmacSha256Aes128Gcm();
179 auto private_handle_result = KeysetHandle::GenerateNew(key_template);
180 EXPECT_TRUE(private_handle_result.ok());
181
182 HybridDecryptRequest dec_request;
183 dec_request.mutable_private_annotated_keyset()->set_serialized_keyset(
184 KeysetBytes(*private_handle_result.value()));
185 dec_request.set_ciphertext("bad ciphertext");
186 dec_request.set_context_info("context");
187 HybridDecryptResponse dec_response;
188
189 EXPECT_TRUE(hybrid.Decrypt(nullptr, &dec_request, &dec_response).ok());
190 EXPECT_THAT(dec_response.err(), Not(IsEmpty()));
191 }
192
193 } // namespace
194 } // namespace tink
195 } // namespace crypto
196