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/signature/public_key_verify_wrapper.h"
18
19 #include <memory>
20 #include <string>
21 #include <utility>
22
23 #include "gtest/gtest.h"
24 #include "tink/primitive_set.h"
25 #include "tink/public_key_verify.h"
26 #include "tink/internal/registry_impl.h"
27 #include "tink/monitoring/monitoring.h"
28 #include "tink/monitoring/monitoring_client_mocks.h"
29 #include "tink/signature/failing_signature.h"
30 #include "tink/util/status.h"
31 #include "tink/util/test_matchers.h"
32 #include "tink/util/test_util.h"
33
34 namespace crypto {
35 namespace tink {
36 namespace {
37
38 using ::crypto::tink::test::DummyPublicKeySign;
39 using ::crypto::tink::test::DummyPublicKeyVerify;
40 using ::crypto::tink::test::IsOk;
41 using ::crypto::tink::test::IsOkAndHolds;
42 using ::crypto::tink::test::StatusIs;
43 using ::google::crypto::tink::KeysetInfo;
44 using ::google::crypto::tink::KeyStatusType;
45 using ::google::crypto::tink::OutputPrefixType;
46 using ::testing::_;
47 using ::testing::ByMove;
48 using ::testing::IsNull;
49 using ::testing::StrictMock;
50 using ::testing::Not;
51 using ::testing::NotNull;
52 using ::testing::Return;
53 using ::testing::Test;
54
55 class PublicKeyVerifySetWrapperTest : public ::testing::Test {
56 protected:
SetUp()57 void SetUp() override {
58 }
TearDown()59 void TearDown() override {
60 }
61 };
62
TEST_F(PublicKeyVerifySetWrapperTest,testBasic)63 TEST_F(PublicKeyVerifySetWrapperTest, testBasic) {
64 { // pk_verify_set is nullptr.
65 auto pk_verify_result = PublicKeyVerifyWrapper().Wrap(nullptr);
66 EXPECT_FALSE(pk_verify_result.ok());
67 EXPECT_EQ(absl::StatusCode::kInternal, pk_verify_result.status().code());
68 EXPECT_PRED_FORMAT2(testing::IsSubstring, "non-NULL",
69 std::string(pk_verify_result.status().message()));
70 }
71
72 { // pk_verify_set has no primary primitive.
73 std::unique_ptr<PrimitiveSet<PublicKeyVerify>>
74 pk_verify_set(new PrimitiveSet<PublicKeyVerify>());
75 auto pk_verify_result =
76 PublicKeyVerifyWrapper().Wrap(std::move(pk_verify_set));
77 EXPECT_FALSE(pk_verify_result.ok());
78 EXPECT_EQ(absl::StatusCode::kInvalidArgument,
79 pk_verify_result.status().code());
80 EXPECT_PRED_FORMAT2(testing::IsSubstring, "no primary",
81 std::string(pk_verify_result.status().message()));
82 }
83
84 { // Correct pk_verify_set;
85 KeysetInfo::KeyInfo* key_info;
86 KeysetInfo keyset_info;
87
88 uint32_t key_id_0 = 1234543;
89 key_info = keyset_info.add_key_info();
90 key_info->set_output_prefix_type(OutputPrefixType::RAW);
91 key_info->set_key_id(key_id_0);
92 key_info->set_status(KeyStatusType::ENABLED);
93
94 uint32_t key_id_1 = 726329;
95 key_info = keyset_info.add_key_info();
96 key_info->set_output_prefix_type(OutputPrefixType::LEGACY);
97 key_info->set_key_id(key_id_1);
98 key_info->set_status(KeyStatusType::ENABLED);
99
100 uint32_t key_id_2 = 7213743;
101 key_info = keyset_info.add_key_info();
102 key_info->set_output_prefix_type(OutputPrefixType::TINK);
103 key_info->set_key_id(key_id_2);
104 key_info->set_status(KeyStatusType::ENABLED);
105
106 std::string signature_name_0 = "signature_0";
107 std::string signature_name_1 = "signature_1";
108 std::string signature_name_2 = "signature_2";
109 std::unique_ptr<PrimitiveSet<PublicKeyVerify>> pk_verify_set(
110 new PrimitiveSet<PublicKeyVerify>());
111
112 std::unique_ptr<PublicKeyVerify> pk_verify(
113 new DummyPublicKeyVerify(signature_name_0));
114 auto entry_result = pk_verify_set->AddPrimitive(std::move(pk_verify),
115 keyset_info.key_info(0));
116 ASSERT_TRUE(entry_result.ok());
117
118 pk_verify = std::make_unique<DummyPublicKeyVerify>(signature_name_1);
119 entry_result = pk_verify_set->AddPrimitive(std::move(pk_verify),
120 keyset_info.key_info(1));
121 ASSERT_TRUE(entry_result.ok());
122
123 pk_verify = std::make_unique<DummyPublicKeyVerify>(signature_name_2);
124 entry_result = pk_verify_set->AddPrimitive(std::move(pk_verify),
125 keyset_info.key_info(2));
126 ASSERT_TRUE(entry_result.ok());
127
128 // The last key is the primary.
129 ASSERT_THAT(pk_verify_set->set_primary(entry_result.value()), IsOk());
130
131 // Wrap pk_verify_set and test the resulting PublicKeyVerify.
132 auto pk_verify_result =
133 PublicKeyVerifyWrapper().Wrap(std::move(pk_verify_set));
134 EXPECT_TRUE(pk_verify_result.ok()) << pk_verify_result.status();
135 pk_verify = std::move(pk_verify_result.value());
136 std::string data = "some data to sign";
137 std::unique_ptr<PublicKeySign> pk_sign(
138 new DummyPublicKeySign(signature_name_0));
139 std::string signature = pk_sign->Sign(data).value();
140 util::Status status = pk_verify->Verify(signature, data);
141 EXPECT_TRUE(status.ok()) << status;
142 }
143 }
144
PopulateKeyInfo(uint32_t key_id,OutputPrefixType out_prefix_type,KeyStatusType status)145 KeysetInfo::KeyInfo PopulateKeyInfo(uint32_t key_id,
146 OutputPrefixType out_prefix_type,
147 KeyStatusType status) {
148 KeysetInfo::KeyInfo key_info;
149 key_info.set_output_prefix_type(out_prefix_type);
150 key_info.set_key_id(key_id);
151 key_info.set_status(status);
152 return key_info;
153 }
154
155 // Creates a test keyset info object.
CreateTestKeysetInfo()156 KeysetInfo CreateTestKeysetInfo() {
157 KeysetInfo keyset_info;
158 *keyset_info.add_key_info() =
159 PopulateKeyInfo(/*key_id=*/1234543, OutputPrefixType::TINK,
160 /*status=*/KeyStatusType::ENABLED);
161 *keyset_info.add_key_info() =
162 PopulateKeyInfo(/*key_id=*/726329, OutputPrefixType::LEGACY,
163 /*status=*/KeyStatusType::ENABLED);
164 *keyset_info.add_key_info() =
165 PopulateKeyInfo(/*key_id=*/7213743, OutputPrefixType::TINK,
166 /*status=*/KeyStatusType::ENABLED);
167 return keyset_info;
168 }
169
170 // Tests for the monitoring behavior.
171 class PublicKeyVerifySetWrapperWithMonitoringTest : public Test {
172 protected:
173 // Perform some common initialization: reset the global registry, set expected
174 // calls for the mock monitoring factory and the returned clients.
SetUp()175 void SetUp() override {
176 Registry::Reset();
177
178 // Setup mocks for catching Monitoring calls.
179 auto monitoring_client_factory =
180 absl::make_unique<MockMonitoringClientFactory>();
181 auto verify_monitoring_client =
182 absl::make_unique<StrictMock<MockMonitoringClient>>();
183 verify_monitoring_client_ = verify_monitoring_client.get();
184
185 // Monitoring tests expect that the client factory will create the
186 // corresponding MockMonitoringClients.
187 EXPECT_CALL(*monitoring_client_factory, New(_))
188 .WillOnce(
189 Return(ByMove(util::StatusOr<std::unique_ptr<MonitoringClient>>(
190 std::move(verify_monitoring_client)))));
191
192 ASSERT_THAT(internal::RegistryImpl::GlobalInstance()
193 .RegisterMonitoringClientFactory(
194 std::move(monitoring_client_factory)),
195 IsOk());
196 ASSERT_THAT(
197 internal::RegistryImpl::GlobalInstance().GetMonitoringClientFactory(),
198 Not(IsNull()));
199 }
200
201 // Cleanup the registry to avoid mock leaks.
~PublicKeyVerifySetWrapperWithMonitoringTest()202 ~PublicKeyVerifySetWrapperWithMonitoringTest() override { Registry::Reset(); }
203
204 MockMonitoringClient* verify_monitoring_client_;
205 };
206
207 // Test that successful sign operations are logged.
TEST_F(PublicKeyVerifySetWrapperWithMonitoringTest,WrapKeysetWithMonitoringVerifySuccess)208 TEST_F(PublicKeyVerifySetWrapperWithMonitoringTest,
209 WrapKeysetWithMonitoringVerifySuccess) {
210 // Create a primitive set and fill it with some entries
211 KeysetInfo keyset_info = CreateTestKeysetInfo();
212 const absl::flat_hash_map<std::string, std::string> kAnnotations = {
213 {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}};
214 auto public_key_verify_primitive_set =
215 absl::make_unique<PrimitiveSet<PublicKeyVerify>>(kAnnotations);
216 ASSERT_THAT(
217 public_key_verify_primitive_set
218 ->AddPrimitive(absl::make_unique<DummyPublicKeyVerify>("verify0"),
219 keyset_info.key_info(0))
220 .status(),
221 IsOk());
222 ASSERT_THAT(
223 public_key_verify_primitive_set
224 ->AddPrimitive(absl::make_unique<DummyPublicKeyVerify>("sign1"),
225 keyset_info.key_info(1))
226 .status(),
227 IsOk());
228 // Set the last as primary.
229 util::StatusOr<PrimitiveSet<PublicKeyVerify>::Entry<PublicKeyVerify>*> last =
230 public_key_verify_primitive_set->AddPrimitive(
231 absl::make_unique<DummyPublicKeyVerify>("sign2"),
232 keyset_info.key_info(2));
233 ASSERT_THAT(last.status(), IsOk());
234 ASSERT_THAT(public_key_verify_primitive_set->set_primary(*last), IsOk());
235 // Record the ID of the primary key.
236 const uint32_t primary_key_id = keyset_info.key_info(2).key_id();
237
238 // Create a PublicKeyVerify primitive to verify a signature.
239 util::StatusOr<std::unique_ptr<PublicKeyVerify>> public_key_verify =
240 PublicKeyVerifyWrapper().Wrap(std::move(public_key_verify_primitive_set));
241 ASSERT_THAT(public_key_verify, IsOkAndHolds(NotNull()));
242
243 // Create a PublicKeySign primitive and sign some data we can verify.
244 constexpr absl::string_view message = "This is some message!";
245 std::string signature =
246 absl::StrCat((*last)->get_identifier(),
247 DummyPublicKeySign("sign2").Sign(message).value());
248
249 // Check that calling Verify triggers a Log() call.
250 EXPECT_CALL(*verify_monitoring_client_, Log(primary_key_id, message.size()));
251 EXPECT_THAT((*public_key_verify)->Verify(signature, message), IsOk());
252 }
253
TEST_F(PublicKeyVerifySetWrapperWithMonitoringTest,WrapKeysetWithMonitoringVerifyFailures)254 TEST_F(PublicKeyVerifySetWrapperWithMonitoringTest,
255 WrapKeysetWithMonitoringVerifyFailures) {
256 // Create a primitive set and fill it with some entries
257 KeysetInfo keyset_info = CreateTestKeysetInfo();
258 const absl::flat_hash_map<std::string, std::string> kAnnotations = {
259 {"key1", "value1"}, {"key2", "value2"}, {"key3", "value3"}};
260 auto public_key_verify_primitive_set =
261 absl::make_unique<PrimitiveSet<PublicKeyVerify>>(kAnnotations);
262 ASSERT_THAT(public_key_verify_primitive_set
263 ->AddPrimitive(CreateAlwaysFailingPublicKeyVerify("sign0"),
264 keyset_info.key_info(0))
265 .status(),
266 IsOk());
267 ASSERT_THAT(public_key_verify_primitive_set
268 ->AddPrimitive(CreateAlwaysFailingPublicKeyVerify("sign1"),
269 keyset_info.key_info(1))
270 .status(),
271 IsOk());
272 // Set the last as primary.
273 util::StatusOr<PrimitiveSet<PublicKeyVerify>::Entry<PublicKeyVerify>*> last =
274 public_key_verify_primitive_set->AddPrimitive(
275 CreateAlwaysFailingPublicKeyVerify("sign2"), keyset_info.key_info(2));
276 ASSERT_THAT(last.status(), IsOk());
277 ASSERT_THAT(public_key_verify_primitive_set->set_primary(*last), IsOk());
278
279 // Create a PublicKeySign and sign some data we can verify.
280 util::StatusOr<std::unique_ptr<PublicKeyVerify>> public_key_verify =
281 PublicKeyVerifyWrapper().Wrap(std::move(public_key_verify_primitive_set));
282 ASSERT_THAT(public_key_verify, IsOkAndHolds(NotNull()));
283
284 constexpr absl::string_view message = "This is some message!";
285 constexpr absl::string_view signature = "This is some invalid signature!";
286
287 // Check that calling Verify triggers a LogFailure() call.
288 EXPECT_CALL(*verify_monitoring_client_, LogFailure());
289 EXPECT_THAT((*public_key_verify)->Verify(signature, message),
290 StatusIs(absl::StatusCode::kInvalidArgument));
291 }
292
293 } // namespace
294 } // namespace tink
295 } // namespace crypto
296