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