xref: /aosp_15_r20/external/tink/cc/signature/public_key_sign_wrapper_test.cc (revision e7b1675dde1b92d52ec075b0a92829627f2c52a5)
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