1 // Copyright 2021 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 <memory>
18 #include <string>
19 #include <utility>
20 #include <vector>
21
22 #include "gtest/gtest.h"
23 #include "absl/strings/str_split.h"
24 #include "tink/cleartext_keyset_handle.h"
25 #include "tink/jwt/internal/json_util.h"
26 #include "tink/jwt/internal/jwt_ecdsa_sign_key_manager.h"
27 #include "tink/jwt/internal/jwt_ecdsa_verify_key_manager.h"
28 #include "tink/jwt/internal/jwt_format.h"
29 #include "tink/jwt/internal/jwt_public_key_sign_wrapper.h"
30 #include "tink/jwt/internal/jwt_public_key_verify_wrapper.h"
31 #include "tink/keyset_manager.h"
32 #include "tink/primitive_set.h"
33 #include "tink/util/status.h"
34 #include "tink/util/test_matchers.h"
35 #include "tink/util/test_util.h"
36 #include "proto/jwt_ecdsa.pb.h"
37 #include "proto/tink.pb.h"
38
39 using ::crypto::tink::test::IsOk;
40 using ::google::crypto::tink::JwtEcdsaAlgorithm;
41 using ::google::crypto::tink::JwtEcdsaKeyFormat;
42 using ::google::crypto::tink::Keyset;
43 using ::google::crypto::tink::KeyTemplate;
44 using ::google::crypto::tink::OutputPrefixType;
45 using ::testing::Eq;
46 using ::testing::Not;
47 using ::testing::SizeIs;
48
49 namespace crypto {
50 namespace tink {
51 namespace jwt_internal {
52 namespace {
53
54 using ::crypto::tink::test::IsOk;
55 using ::testing::Eq;
56
CreateTemplate(OutputPrefixType output_prefix)57 KeyTemplate CreateTemplate(OutputPrefixType output_prefix) {
58 KeyTemplate key_template;
59 key_template.set_type_url(
60 "type.googleapis.com/google.crypto.tink.JwtEcdsaPrivateKey");
61 key_template.set_output_prefix_type(output_prefix);
62 JwtEcdsaKeyFormat key_format;
63 key_format.set_algorithm(JwtEcdsaAlgorithm::ES256);
64 key_format.SerializeToString(key_template.mutable_value());
65 return key_template;
66 }
67
68 // KeysetHandleWithNewKeyId generates a new keyset handle with the exact same
69 // keyset, except that the key ID of the first key is different.
KeysetHandleWithNewKeyId(const KeysetHandle & keyset_handle)70 std::unique_ptr<KeysetHandle> KeysetHandleWithNewKeyId(
71 const KeysetHandle& keyset_handle) {
72 Keyset keyset(CleartextKeysetHandle::GetKeyset(keyset_handle));
73 // Modify the key ID by XORing it with a arbitrary constant value.
74 uint32_t new_key_id = keyset.mutable_key(0)->key_id() ^ 0xdeadbeef;
75 keyset.mutable_key(0)->set_key_id(new_key_id);
76 keyset.set_primary_key_id(new_key_id);
77 return CleartextKeysetHandle::GetKeysetHandle(keyset);
78 }
79
80 // KeysetHandleWithTinkPrefix generates a new keyset handle with the exact same
81 // keyset, except that the output prefix type of the first key is set to TINK.
KeysetHandleWithTinkPrefix(const KeysetHandle & keyset_handle)82 std::unique_ptr<KeysetHandle> KeysetHandleWithTinkPrefix(
83 const KeysetHandle& keyset_handle) {
84 Keyset keyset(CleartextKeysetHandle::GetKeyset(keyset_handle));
85 keyset.mutable_key(0)->set_output_prefix_type(OutputPrefixType::TINK);
86 return CleartextKeysetHandle::GetKeysetHandle(keyset);
87 }
88
89 class JwtPublicKeyWrappersTest : public ::testing::Test {
90 protected:
SetUp()91 void SetUp() override {
92 ASSERT_THAT(Registry::RegisterPrimitiveWrapper(
93 absl::make_unique<JwtPublicKeySignWrapper>()), IsOk());
94 ASSERT_THAT(Registry::RegisterPrimitiveWrapper(
95 absl::make_unique<JwtPublicKeyVerifyWrapper>()), IsOk());
96 ASSERT_THAT(Registry::RegisterAsymmetricKeyManagers(
97 absl::make_unique<JwtEcdsaSignKeyManager>(),
98 absl::make_unique<JwtEcdsaVerifyKeyManager>(), true),
99 IsOk());
100 }
101 };
102
TEST_F(JwtPublicKeyWrappersTest,WrapNullptrSign)103 TEST_F(JwtPublicKeyWrappersTest, WrapNullptrSign) {
104 EXPECT_FALSE(JwtPublicKeySignWrapper().Wrap(nullptr).ok());
105 }
106
TEST_F(JwtPublicKeyWrappersTest,WrapNullptrVerify)107 TEST_F(JwtPublicKeyWrappersTest, WrapNullptrVerify) {
108 EXPECT_FALSE(JwtPublicKeyVerifyWrapper().Wrap(nullptr).ok());
109 }
110
TEST_F(JwtPublicKeyWrappersTest,WrapEmptySign)111 TEST_F(JwtPublicKeyWrappersTest, WrapEmptySign) {
112 auto jwt_sign_set =
113 absl::make_unique<PrimitiveSet<JwtPublicKeySignInternal>>();
114 auto result = JwtPublicKeySignWrapper().Wrap(std::move(jwt_sign_set));
115 EXPECT_FALSE(result.ok());
116 }
117
TEST_F(JwtPublicKeyWrappersTest,CannotWrapPrimitivesFromNonRawOrTinkKeys)118 TEST_F(JwtPublicKeyWrappersTest, CannotWrapPrimitivesFromNonRawOrTinkKeys) {
119 KeyTemplate tink_key_template = CreateTemplate(OutputPrefixType::LEGACY);
120
121 util::StatusOr<std::unique_ptr<KeysetHandle>> keyset_handle =
122 KeysetHandle::GenerateNew(tink_key_template);
123 ASSERT_THAT(keyset_handle, IsOk());
124 EXPECT_FALSE(
125 (*keyset_handle)->GetPrimitive<JwtPublicKeySign>().status().ok());
126
127 util::StatusOr<std::unique_ptr<KeysetHandle>> public_handle =
128 (*keyset_handle)->GetPublicKeysetHandle();
129 ASSERT_THAT(public_handle, IsOk());
130 EXPECT_FALSE(
131 (*public_handle)->GetPrimitive<JwtPublicKeyVerify>().status().ok());
132 }
133
TEST_F(JwtPublicKeyWrappersTest,GenerateRawSignVerifySuccess)134 TEST_F(JwtPublicKeyWrappersTest, GenerateRawSignVerifySuccess) {
135 KeyTemplate key_template = CreateTemplate(OutputPrefixType::RAW);
136 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
137 KeysetHandle::GenerateNew(key_template);
138 ASSERT_THAT(handle, IsOk());
139 util::StatusOr<std::unique_ptr<JwtPublicKeySign>> jwt_sign =
140 (*handle)->GetPrimitive<JwtPublicKeySign>();
141 EXPECT_THAT(jwt_sign, IsOk());
142
143 util::StatusOr<std::unique_ptr<KeysetHandle>> public_handle =
144 (*handle)->GetPublicKeysetHandle();
145 EXPECT_THAT(public_handle, IsOk());
146 util::StatusOr<std::unique_ptr<JwtPublicKeyVerify>> jwt_verify =
147 (*public_handle)->GetPrimitive<JwtPublicKeyVerify>();
148 EXPECT_THAT(jwt_verify, IsOk());
149
150 util::StatusOr<RawJwt> raw_jwt =
151 RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build();
152 ASSERT_THAT(raw_jwt, IsOk());
153
154 util::StatusOr<std::string> compact = (*jwt_sign)->SignAndEncode(*raw_jwt);
155 ASSERT_THAT(compact, IsOk());
156
157 util::StatusOr<JwtValidator> validator = JwtValidatorBuilder()
158 .ExpectIssuer("issuer")
159 .AllowMissingExpiration()
160 .Build();
161 ASSERT_THAT(validator, IsOk());
162 util::StatusOr<VerifiedJwt> verified_jwt =
163 (*jwt_verify)->VerifyAndDecode(*compact, *validator);
164 ASSERT_THAT(verified_jwt, IsOk());
165 EXPECT_THAT(verified_jwt->GetIssuer(), test::IsOkAndHolds("issuer"));
166
167 util::StatusOr<JwtValidator> validator2 = JwtValidatorBuilder()
168 .ExpectIssuer("unknown")
169 .AllowMissingExpiration()
170 .Build();
171 ASSERT_THAT(validator2, IsOk());
172 util::StatusOr<VerifiedJwt> verified_jwt2 =
173 (*jwt_verify)->VerifyAndDecode(*compact, *validator2);
174 EXPECT_FALSE(verified_jwt2.ok());
175 // Make sure the error message is interesting
176 EXPECT_THAT(verified_jwt2.status().message(), Eq("wrong issuer"));
177
178 // Raw primitives don't add a kid header, Tink primitives require a kid
179 // header to be set. Thefore, changing the output prefix to TINK makes the
180 // validation fail.
181 std::unique_ptr<KeysetHandle> tink_public_handle =
182 KeysetHandleWithTinkPrefix(**public_handle);
183 util::StatusOr<std::unique_ptr<JwtPublicKeyVerify>> tink_verify =
184 tink_public_handle->GetPrimitive<JwtPublicKeyVerify>();
185 ASSERT_THAT(tink_verify, IsOk());
186
187 EXPECT_THAT((*tink_verify)->VerifyAndDecode(*compact, *validator).status(),
188 Not(IsOk()));
189 }
190
TEST_F(JwtPublicKeyWrappersTest,GenerateTinkSignVerifySuccess)191 TEST_F(JwtPublicKeyWrappersTest, GenerateTinkSignVerifySuccess) {
192 KeyTemplate key_template = CreateTemplate(OutputPrefixType::TINK);
193 util::StatusOr<std::unique_ptr<KeysetHandle>> handle =
194 KeysetHandle::GenerateNew(key_template);
195 ASSERT_THAT(handle, IsOk());
196 util::StatusOr<std::unique_ptr<JwtPublicKeySign>> jwt_sign =
197 (*handle)->GetPrimitive<JwtPublicKeySign>();
198 EXPECT_THAT(jwt_sign, IsOk());
199
200 util::StatusOr<std::unique_ptr<KeysetHandle>> public_handle =
201 (*handle)->GetPublicKeysetHandle();
202 EXPECT_THAT(public_handle, IsOk());
203 util::StatusOr<std::unique_ptr<JwtPublicKeyVerify>> jwt_verify =
204 (*public_handle)->GetPrimitive<JwtPublicKeyVerify>();
205 EXPECT_THAT(jwt_verify, IsOk());
206
207 util::StatusOr<RawJwt> raw_jwt =
208 RawJwtBuilder().SetIssuer("issuer").WithoutExpiration().Build();
209 ASSERT_THAT(raw_jwt, IsOk());
210
211 util::StatusOr<std::string> compact = (*jwt_sign)->SignAndEncode(*raw_jwt);
212 ASSERT_THAT(compact, IsOk());
213
214 util::StatusOr<JwtValidator> validator = JwtValidatorBuilder()
215 .ExpectIssuer("issuer")
216 .AllowMissingExpiration()
217 .Build();
218 ASSERT_THAT(validator, IsOk());
219 util::StatusOr<VerifiedJwt> verified_jwt =
220 (*jwt_verify)->VerifyAndDecode(*compact, *validator);
221 ASSERT_THAT(verified_jwt, IsOk());
222 EXPECT_THAT(verified_jwt->GetIssuer(), test::IsOkAndHolds("issuer"));
223
224 // Parse header to make sure that key ID is correctly encoded.
225 google::crypto::tink::KeysetInfo keyset_info =
226 (*public_handle)->GetKeysetInfo();
227 uint32_t key_id = keyset_info.key_info(0).key_id();
228 std::vector<absl::string_view> parts = absl::StrSplit(*compact, '.');
229 ASSERT_THAT(parts, SizeIs(3));
230 std::string json_header;
231 ASSERT_TRUE(DecodeHeader(parts[0], &json_header));
232 util::StatusOr<google::protobuf::Struct> header =
233 JsonStringToProtoStruct(json_header);
234 ASSERT_THAT(header, IsOk());
235 google::protobuf::Value value = (*header).fields().find("kid")->second;
236 EXPECT_THAT(GetKeyId(value.string_value()), Eq(key_id));
237
238 // For Tink primitives, the kid must be correctly set and verified.
239 // Therefore, changing the key_id makes the validation fail.
240 std::unique_ptr<KeysetHandle> public_handle_with_new_key_id =
241 KeysetHandleWithNewKeyId(**public_handle);
242 util::StatusOr<std::unique_ptr<JwtPublicKeyVerify>> verify_with_new_key_id =
243 public_handle_with_new_key_id->GetPrimitive<JwtPublicKeyVerify>();
244 ASSERT_THAT(verify_with_new_key_id, IsOk());
245
246 util::StatusOr<VerifiedJwt> verified_jwt_2 =
247 (*verify_with_new_key_id)->VerifyAndDecode(*compact, *validator);
248 EXPECT_FALSE(verified_jwt_2.ok());
249 }
250
TEST_F(JwtPublicKeyWrappersTest,KeyRotation)251 TEST_F(JwtPublicKeyWrappersTest, KeyRotation) {
252 std::vector<OutputPrefixType> prefixes = {OutputPrefixType::RAW,
253 OutputPrefixType::TINK};
254 for (OutputPrefixType prefix : prefixes) {
255 SCOPED_TRACE(absl::StrCat("Testing with prefix ", prefix));
256 KeyTemplate key_template = CreateTemplate(prefix);
257 KeysetManager manager;
258
259 util::StatusOr<uint32_t> old_id = manager.Add(key_template);
260 ASSERT_THAT(old_id, IsOk());
261 ASSERT_THAT(manager.SetPrimary(*old_id), IsOk());
262 std::unique_ptr<KeysetHandle> handle1 = manager.GetKeysetHandle();
263 util::StatusOr<std::unique_ptr<JwtPublicKeySign>> jwt_sign1 =
264 handle1->GetPrimitive<JwtPublicKeySign>();
265 ASSERT_THAT(jwt_sign1, IsOk());
266 util::StatusOr<std::unique_ptr<KeysetHandle>> public_handle1 =
267 handle1->GetPublicKeysetHandle();
268 EXPECT_THAT(public_handle1, IsOk());
269 util::StatusOr<std::unique_ptr<JwtPublicKeyVerify>> jwt_verify1 =
270 (*public_handle1)->GetPrimitive<JwtPublicKeyVerify>();
271 EXPECT_THAT(jwt_verify1, IsOk());
272
273 util::StatusOr<uint32_t> new_id = manager.Add(key_template);
274 ASSERT_THAT(new_id, IsOk());
275 std::unique_ptr<KeysetHandle> handle2 = manager.GetKeysetHandle();
276 util::StatusOr<std::unique_ptr<JwtPublicKeySign>> jwt_sign2 =
277 handle2->GetPrimitive<JwtPublicKeySign>();
278 ASSERT_THAT(jwt_sign2, IsOk());
279 util::StatusOr<std::unique_ptr<KeysetHandle>> public_handle2 =
280 handle2->GetPublicKeysetHandle();
281 EXPECT_THAT(public_handle2, IsOk());
282 util::StatusOr<std::unique_ptr<JwtPublicKeyVerify>> jwt_verify2 =
283 (*public_handle2)->GetPrimitive<JwtPublicKeyVerify>();
284 EXPECT_THAT(jwt_verify2, IsOk());
285
286 ASSERT_THAT(manager.SetPrimary(*new_id), IsOk());
287 std::unique_ptr<KeysetHandle> handle3 = manager.GetKeysetHandle();
288 util::StatusOr<std::unique_ptr<JwtPublicKeySign>> jwt_sign3 =
289 handle3->GetPrimitive<JwtPublicKeySign>();
290 ASSERT_THAT(jwt_sign3, IsOk());
291 util::StatusOr<std::unique_ptr<KeysetHandle>> public_handle3 =
292 handle3->GetPublicKeysetHandle();
293 EXPECT_THAT(public_handle3, IsOk());
294 util::StatusOr<std::unique_ptr<JwtPublicKeyVerify>> jwt_verify3 =
295 (*public_handle3)->GetPrimitive<JwtPublicKeyVerify>();
296 EXPECT_THAT(jwt_verify3, IsOk());
297
298 ASSERT_THAT(manager.Disable(*old_id), IsOk());
299 std::unique_ptr<KeysetHandle> handle4 = manager.GetKeysetHandle();
300 util::StatusOr<std::unique_ptr<JwtPublicKeySign>> jwt_sign4 =
301 handle4->GetPrimitive<JwtPublicKeySign>();
302 ASSERT_THAT(jwt_sign4, IsOk());
303 util::StatusOr<std::unique_ptr<KeysetHandle>> public_handle4 =
304 handle4->GetPublicKeysetHandle();
305 EXPECT_THAT(public_handle4, IsOk());
306 util::StatusOr<std::unique_ptr<JwtPublicKeyVerify>> jwt_verify4 =
307 (*public_handle4)->GetPrimitive<JwtPublicKeyVerify>();
308 EXPECT_THAT(jwt_verify4, IsOk());
309
310 util::StatusOr<RawJwt> raw_jwt =
311 RawJwtBuilder().SetJwtId("id123").WithoutExpiration().Build();
312 ASSERT_THAT(raw_jwt, IsOk());
313 util::StatusOr<JwtValidator> validator =
314 JwtValidatorBuilder().AllowMissingExpiration().Build();
315 ASSERT_THAT(raw_jwt, IsOk());
316
317 util::StatusOr<std::string> compact1 =
318 (*jwt_sign1)->SignAndEncode(*raw_jwt);
319 ASSERT_THAT(compact1, IsOk());
320
321 util::StatusOr<std::string> compact2 =
322 (*jwt_sign2)->SignAndEncode(*raw_jwt);
323 ASSERT_THAT(compact2, IsOk());
324
325 util::StatusOr<std::string> compact3 =
326 (*jwt_sign3)->SignAndEncode(*raw_jwt);
327 ASSERT_THAT(compact3, IsOk());
328
329 util::StatusOr<std::string> compact4 =
330 (*jwt_sign4)->SignAndEncode(*raw_jwt);
331 ASSERT_THAT(compact4, IsOk());
332
333 EXPECT_THAT((*jwt_verify1)->VerifyAndDecode(*compact1, *validator).status(),
334 IsOk());
335 EXPECT_THAT((*jwt_verify2)->VerifyAndDecode(*compact1, *validator).status(),
336 IsOk());
337 EXPECT_THAT((*jwt_verify3)->VerifyAndDecode(*compact1, *validator).status(),
338 IsOk());
339 EXPECT_FALSE((*jwt_verify4)->VerifyAndDecode(*compact1, *validator).ok());
340
341 EXPECT_THAT((*jwt_verify1)->VerifyAndDecode(*compact2, *validator).status(),
342 IsOk());
343 EXPECT_THAT((*jwt_verify2)->VerifyAndDecode(*compact2, *validator).status(),
344 IsOk());
345 EXPECT_THAT((*jwt_verify3)->VerifyAndDecode(*compact2, *validator).status(),
346 IsOk());
347 EXPECT_FALSE((*jwt_verify4)->VerifyAndDecode(*compact2, *validator).ok());
348
349 EXPECT_FALSE((*jwt_verify1)->VerifyAndDecode(*compact3, *validator).ok());
350 EXPECT_THAT((*jwt_verify2)->VerifyAndDecode(*compact3, *validator).status(),
351 IsOk());
352 EXPECT_THAT((*jwt_verify3)->VerifyAndDecode(*compact3, *validator).status(),
353 IsOk());
354 EXPECT_THAT((*jwt_verify4)->VerifyAndDecode(*compact3, *validator).status(),
355 IsOk());
356
357 EXPECT_FALSE((*jwt_verify1)->VerifyAndDecode(*compact4, *validator).ok());
358 EXPECT_THAT((*jwt_verify2)->VerifyAndDecode(*compact4, *validator).status(),
359 IsOk());
360 EXPECT_THAT((*jwt_verify3)->VerifyAndDecode(*compact4, *validator).status(),
361 IsOk());
362 EXPECT_THAT((*jwt_verify4)->VerifyAndDecode(*compact4, *validator).status(),
363 IsOk());
364 }
365 }
366
367 } // namespace
368 } // namespace jwt_internal
369 } // namespace tink
370 } // namespace crypto
371