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