1 // Copyright 2022 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 "tink/proto_keyset_format.h"
18
19 #include <memory>
20 #include <string>
21
22 #include "gmock/gmock.h"
23 #include "gtest/gtest.h"
24 #include "absl/strings/escaping.h"
25 #include "tink/config/tink_config.h"
26 #include "tink/insecure_secret_key_access.h"
27 #include "tink/internal/legacy_proto_parameters.h"
28 #include "tink/internal/proto_parameters_serialization.h"
29 #include "tink/keyset_handle_builder.h"
30 #include "tink/mac.h"
31 #include "tink/mac/mac_key_templates.h"
32 #include "tink/signature/signature_key_templates.h"
33 #include "tink/util/secret_data.h"
34 #include "tink/util/test_matchers.h"
35
36 namespace crypto {
37 namespace tink {
38
39 namespace {
40
41 using ::crypto::tink::internal::LegacyProtoParameters;
42 using ::crypto::tink::internal::ProtoParametersSerialization;
43 using ::crypto::tink::test::IsOk;
44 using ::crypto::tink::util::SecretData;
45 using ::crypto::tink::util::SecretDataAsStringView;
46 using ::testing::Eq;
47 using ::testing::Not;
48
49 class SerializeKeysetToProtoKeysetFormatTest : public ::testing::Test {
50 protected:
SetUp()51 void SetUp() override {
52 auto status = TinkConfig::Register();
53 ASSERT_THAT(status, IsOk());
54 }
55 };
56
CmacParameters()57 util::StatusOr<LegacyProtoParameters> CmacParameters() {
58 util::StatusOr<ProtoParametersSerialization> serialization =
59 ProtoParametersSerialization::Create(MacKeyTemplates::AesCmac());
60 if (!serialization.ok()) return serialization.status();
61
62 return LegacyProtoParameters(*serialization);
63 }
64
EcdsaParameters()65 util::StatusOr<LegacyProtoParameters> EcdsaParameters() {
66 util::StatusOr<ProtoParametersSerialization> serialization =
67 ProtoParametersSerialization::Create(SignatureKeyTemplates::EcdsaP256());
68 if (!serialization.ok()) return serialization.status();
69
70 return LegacyProtoParameters(*serialization);
71 }
72
TEST_F(SerializeKeysetToProtoKeysetFormatTest,SerializeAndParseSingleKey)73 TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeAndParseSingleKey) {
74 util::StatusOr<internal::LegacyProtoParameters> parameters =
75 CmacParameters();
76 ASSERT_THAT(parameters, IsOk());
77
78 util::StatusOr<KeysetHandle> handle =
79 KeysetHandleBuilder()
80 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
81 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
82 /*id=*/123))
83 .Build();
84 ASSERT_THAT(handle, IsOk());
85
86 crypto::tink::util::StatusOr<SecretData> serialization =
87 SerializeKeysetToProtoKeysetFormat(*handle,
88 InsecureSecretKeyAccess::Get());
89 ASSERT_THAT(serialization, IsOk());
90
91 util::StatusOr<KeysetHandle> parsed_handle = ParseKeysetFromProtoKeysetFormat(
92 SecretDataAsStringView(*serialization), InsecureSecretKeyAccess::Get());
93 ASSERT_THAT(parsed_handle, IsOk());
94 ASSERT_THAT(handle->size(), Eq(1));
95 ASSERT_THAT(parsed_handle->size(), Eq(1));
96
97 EXPECT_TRUE(*(*handle)[0].GetKey() == *(*parsed_handle)[0].GetKey());
98 EXPECT_TRUE((*handle)[0].GetId() == (*parsed_handle)[0].GetId());
99 EXPECT_TRUE((*handle)[0].GetStatus() == (*parsed_handle)[0].GetStatus());
100 }
101
TEST_F(SerializeKeysetToProtoKeysetFormatTest,SerializeAndParseMultipleKeys)102 TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeAndParseMultipleKeys) {
103 util::StatusOr<internal::LegacyProtoParameters> parameters =
104 CmacParameters();
105 ASSERT_THAT(parameters, IsOk());
106
107 util::StatusOr<KeysetHandle> handle =
108 KeysetHandleBuilder()
109 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
110 *parameters, KeyStatus::kEnabled, /*is_primary=*/false,
111 /*id=*/123))
112 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
113 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
114 /*id=*/125))
115 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
116 *parameters, KeyStatus::kDisabled, /*is_primary=*/true,
117 /*id=*/127))
118 .Build();
119 ASSERT_THAT(handle, IsOk());
120
121 crypto::tink::util::StatusOr<SecretData> serialization =
122 SerializeKeysetToProtoKeysetFormat(*handle,
123 InsecureSecretKeyAccess::Get());
124 ASSERT_THAT(serialization, IsOk());
125
126 util::StatusOr<KeysetHandle> parsed_handle = ParseKeysetFromProtoKeysetFormat(
127 SecretDataAsStringView(*serialization), InsecureSecretKeyAccess::Get());
128 ASSERT_THAT(parsed_handle, IsOk());
129 ASSERT_THAT(handle->size(), Eq(3));
130 ASSERT_THAT(parsed_handle->size(), Eq(3));
131
132 EXPECT_TRUE(*(*handle)[0].GetKey() == *(*parsed_handle)[0].GetKey());
133 EXPECT_TRUE((*handle)[0].GetId() == (*parsed_handle)[0].GetId());
134 EXPECT_TRUE((*handle)[0].GetStatus() == (*parsed_handle)[0].GetStatus());
135
136 EXPECT_TRUE(*(*handle)[1].GetKey() == *(*parsed_handle)[1].GetKey());
137 EXPECT_TRUE((*handle)[1].GetId() == (*parsed_handle)[1].GetId());
138 EXPECT_TRUE((*handle)[1].GetStatus() == (*parsed_handle)[1].GetStatus());
139
140 EXPECT_TRUE(*(*handle)[2].GetKey() == *(*parsed_handle)[2].GetKey());
141 EXPECT_TRUE((*handle)[2].GetId() == (*parsed_handle)[2].GetId());
142 EXPECT_TRUE((*handle)[2].GetStatus() == (*parsed_handle)[2].GetStatus());
143 }
144
TEST_F(SerializeKeysetToProtoKeysetFormatTest,SerializeNoAccessFails)145 TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeNoAccessFails) {
146 util::StatusOr<internal::LegacyProtoParameters> parameters =
147 CmacParameters();
148 ASSERT_THAT(parameters, IsOk());
149
150 util::StatusOr<KeysetHandle> handle =
151 KeysetHandleBuilder()
152 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
153 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
154 /*id=*/123))
155 .Build();
156 ASSERT_THAT(handle, IsOk());
157
158 crypto::tink::util::StatusOr<std::string> serialization =
159 SerializeKeysetWithoutSecretToProtoKeysetFormat(*handle);
160 ASSERT_THAT(serialization, Not(IsOk()));
161 }
162
TEST_F(SerializeKeysetToProtoKeysetFormatTest,ParseNoAccessFails)163 TEST_F(SerializeKeysetToProtoKeysetFormatTest, ParseNoAccessFails) {
164 util::StatusOr<internal::LegacyProtoParameters> parameters =
165 CmacParameters();
166 ASSERT_THAT(parameters, IsOk());
167
168 util::StatusOr<KeysetHandle> handle =
169 KeysetHandleBuilder()
170 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
171 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
172 /*id=*/123))
173 .Build();
174 ASSERT_THAT(handle, IsOk());
175
176 crypto::tink::util::StatusOr<SecretData> serialization =
177 SerializeKeysetToProtoKeysetFormat(*handle,
178 InsecureSecretKeyAccess::Get());
179 ASSERT_THAT(serialization, IsOk());
180
181 util::StatusOr<KeysetHandle> parsed_handle =
182 ParseKeysetWithoutSecretFromProtoKeysetFormat(
183 SecretDataAsStringView(*serialization));
184 ASSERT_THAT(parsed_handle, Not(IsOk()));
185 }
186
TEST_F(SerializeKeysetToProtoKeysetFormatTest,TestVector)187 TEST_F(SerializeKeysetToProtoKeysetFormatTest, TestVector) {
188 std::string serialized_keyset = absl::HexStringToBytes(
189 "0895e59bcc0612680a5c0a2e747970652e676f6f676c65617069732e636f6d2f676f6f67"
190 "6c652e63727970746f2e74696e6b2e486d61634b657912281a20cca20f02278003b3513f"
191 "5d01759ac1302f7d883f2f4a40025532ee1b11f9e587120410100803180110011895e59b"
192 "cc062001");
193 crypto::tink::util::StatusOr<KeysetHandle> keyset_handle =
194 ParseKeysetFromProtoKeysetFormat(serialized_keyset,
195 InsecureSecretKeyAccess::Get());
196 ASSERT_THAT(keyset_handle.status(), IsOk());
197 crypto::tink::util::StatusOr<std::unique_ptr<Mac>> mac =
198 (*keyset_handle).GetPrimitive<Mac>();
199 ASSERT_THAT(mac.status(), IsOk());
200 ASSERT_THAT(
201 (*mac)->VerifyMac(
202 absl::HexStringToBytes("016986f2956092d259136923c6f4323557714ec499"),
203 "data"),
204 IsOk());
205 }
206
TEST_F(SerializeKeysetToProtoKeysetFormatTest,SerializeAndParsePublicKey)207 TEST_F(SerializeKeysetToProtoKeysetFormatTest, SerializeAndParsePublicKey) {
208 util::StatusOr<internal::LegacyProtoParameters> parameters =
209 EcdsaParameters();
210 ASSERT_THAT(parameters, IsOk());
211
212 util::StatusOr<KeysetHandle> handle =
213 KeysetHandleBuilder()
214 .AddEntry(KeysetHandleBuilder::Entry::CreateFromCopyableParams(
215 *parameters, KeyStatus::kEnabled, /*is_primary=*/true,
216 /*id=*/123))
217 .Build();
218 ASSERT_THAT(handle, IsOk());
219 util::StatusOr<std::unique_ptr<KeysetHandle>> public_handle =
220 handle->GetPublicKeysetHandle();
221 ASSERT_THAT(public_handle, IsOk());
222
223
224 crypto::tink::util::StatusOr<SecretData> serialization1 =
225 SerializeKeysetToProtoKeysetFormat(**public_handle,
226 InsecureSecretKeyAccess::Get());
227 ASSERT_THAT(serialization1, IsOk());
228 crypto::tink::util::StatusOr<std::string> serialization2 =
229 SerializeKeysetWithoutSecretToProtoKeysetFormat(**public_handle);
230 ASSERT_THAT(serialization2, IsOk());
231
232 util::StatusOr<KeysetHandle> parsed_handle1 =
233 ParseKeysetFromProtoKeysetFormat(SecretDataAsStringView(*serialization1),
234 InsecureSecretKeyAccess::Get());
235 ASSERT_THAT(parsed_handle1, IsOk());
236 util::StatusOr<KeysetHandle> parsed_handle2 =
237 ParseKeysetWithoutSecretFromProtoKeysetFormat(
238 SecretDataAsStringView(*serialization1));
239 ASSERT_THAT(parsed_handle2, IsOk());
240 util::StatusOr<KeysetHandle> parsed_handle3 =
241 ParseKeysetFromProtoKeysetFormat(*serialization2,
242 InsecureSecretKeyAccess::Get());
243 ASSERT_THAT(parsed_handle3, IsOk());
244 util::StatusOr<KeysetHandle> parsed_handle4 =
245 ParseKeysetWithoutSecretFromProtoKeysetFormat(*serialization2);
246 ASSERT_THAT(parsed_handle4, IsOk());
247
248 ASSERT_THAT((*public_handle)->size(), Eq(1));
249 ASSERT_THAT(parsed_handle1->size(), Eq(1));
250 ASSERT_THAT(parsed_handle2->size(), Eq(1));
251 ASSERT_THAT(parsed_handle3->size(), Eq(1));
252 ASSERT_THAT(parsed_handle4->size(), Eq(1));
253
254 // TODO(b/277791403): Replace with KeysetHandle::Entry equality checks.
255 EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle1)[0].GetKey());
256 EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle2)[0].GetKey());
257 EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle3)[0].GetKey());
258 EXPECT_TRUE(*(**public_handle)[0].GetKey() == *(*parsed_handle4)[0].GetKey());
259
260 EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle1)[0].GetId());
261 EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle2)[0].GetId());
262 EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle3)[0].GetId());
263 EXPECT_TRUE((**public_handle)[0].GetId() == (*parsed_handle4)[0].GetId());
264
265 EXPECT_TRUE((**public_handle)[0].GetStatus() ==
266 (*parsed_handle1)[0].GetStatus());
267 EXPECT_TRUE((**public_handle)[0].GetStatus() ==
268 (*parsed_handle2)[0].GetStatus());
269 EXPECT_TRUE((**public_handle)[0].GetStatus() ==
270 (*parsed_handle3)[0].GetStatus());
271 EXPECT_TRUE((**public_handle)[0].GetStatus() ==
272 (*parsed_handle4)[0].GetStatus());
273 }
274
275
276 } // namespace
277
278 } // namespace tink
279 } // namespace crypto
280