Coverage Report

Created: 2026-08-13 06:54

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/proc/self/cwd/src/verify.cc
Line
Count
Source
1
// Copyright 2018 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
//    https://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
#include "jwt_verify_lib/verify.h"
16
17
#include "absl/strings/string_view.h"
18
#include "absl/time/clock.h"
19
#include "jwt_verify_lib/check_audience.h"
20
#include "openssl/bn.h"
21
#include "openssl/curve25519.h"
22
#include "openssl/ecdsa.h"
23
#include "openssl/err.h"
24
#include "openssl/evp.h"
25
#include "openssl/hmac.h"
26
#include "openssl/mem.h"
27
#include "openssl/rsa.h"
28
#include "openssl/sha.h"
29
30
namespace google {
31
namespace jwt_verify {
32
namespace {
33
34
// A convenience inline cast function.
35
103k
inline const uint8_t* castToUChar(const absl::string_view& str) {
36
103k
  return reinterpret_cast<const uint8_t*>(str.data());
37
103k
}
38
39
bool verifySignatureRSA(RSA* key, const EVP_MD* md, const uint8_t* signature,
40
                        size_t signature_len, const uint8_t* signed_data,
41
5.45k
                        size_t signed_data_len) {
42
5.45k
  if (key == nullptr || md == nullptr || signature == nullptr ||
43
5.45k
      signed_data == nullptr) {
44
0
    return false;
45
0
  }
46
5.45k
  bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
47
5.45k
  if (EVP_PKEY_set1_RSA(evp_pkey.get(), key) != 1) {
48
0
    return false;
49
0
  }
50
51
5.45k
  bssl::UniquePtr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_create());
52
5.45k
  if (EVP_DigestVerifyInit(md_ctx.get(), nullptr, md, nullptr,
53
5.45k
                           evp_pkey.get()) == 1) {
54
5.45k
    if (EVP_DigestVerifyUpdate(md_ctx.get(), signed_data, signed_data_len) ==
55
5.45k
        1) {
56
5.45k
      if (EVP_DigestVerifyFinal(md_ctx.get(), signature, signature_len) == 1) {
57
2
        return true;
58
2
      }
59
5.45k
    }
60
5.45k
  }
61
5.45k
  ERR_clear_error();
62
5.45k
  return false;
63
5.45k
}
64
65
bool verifySignatureRSA(RSA* key, const EVP_MD* md, absl::string_view signature,
66
5.45k
                        absl::string_view signed_data) {
67
5.45k
  return verifySignatureRSA(key, md, castToUChar(signature), signature.length(),
68
5.45k
                            castToUChar(signed_data), signed_data.length());
69
5.45k
}
70
71
bool verifySignatureRSAPSS(RSA* key, const EVP_MD* md, const uint8_t* signature,
72
                           size_t signature_len, const uint8_t* signed_data,
73
8.51k
                           size_t signed_data_len) {
74
8.51k
  if (key == nullptr || md == nullptr || signature == nullptr ||
75
8.51k
      signed_data == nullptr) {
76
0
    return false;
77
0
  }
78
8.51k
  bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
79
8.51k
  if (EVP_PKEY_set1_RSA(evp_pkey.get(), key) != 1) {
80
0
    return false;
81
0
  }
82
83
8.51k
  bssl::UniquePtr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_create());
84
  // pctx is owned by md_ctx, no need to free it separately.
85
8.51k
  EVP_PKEY_CTX* pctx;
86
8.51k
  if (EVP_DigestVerifyInit(md_ctx.get(), &pctx, md, nullptr, evp_pkey.get()) ==
87
8.51k
          1 &&
88
8.51k
      EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) == 1 &&
89
8.51k
      EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, md) == 1 &&
90
8.51k
      EVP_DigestVerify(md_ctx.get(), signature, signature_len, signed_data,
91
8.51k
                       signed_data_len) == 1) {
92
0
    return true;
93
0
  }
94
95
8.51k
  ERR_clear_error();
96
8.51k
  return false;
97
8.51k
}
98
99
bool verifySignatureRSAPSS(RSA* key, const EVP_MD* md,
100
                           absl::string_view signature,
101
8.51k
                           absl::string_view signed_data) {
102
8.51k
  return verifySignatureRSAPSS(key, md, castToUChar(signature),
103
8.51k
                               signature.length(), castToUChar(signed_data),
104
8.51k
                               signed_data.length());
105
8.51k
}
106
107
bool verifySignatureEC(EC_KEY* key, const EVP_MD* md, const uint8_t* signature,
108
                       size_t signature_len, const uint8_t* signed_data,
109
8.33k
                       size_t signed_data_len) {
110
8.33k
  if (key == nullptr || md == nullptr || signature == nullptr ||
111
8.33k
      signed_data == nullptr) {
112
0
    return false;
113
0
  }
114
8.33k
  bssl::UniquePtr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_create());
115
8.33k
  std::vector<uint8_t> digest(EVP_MAX_MD_SIZE);
116
8.33k
  unsigned int digest_len = 0;
117
118
8.33k
  if (EVP_DigestInit(md_ctx.get(), md) == 0) {
119
0
    return false;
120
0
  }
121
122
8.33k
  if (EVP_DigestUpdate(md_ctx.get(), signed_data, signed_data_len) == 0) {
123
0
    return false;
124
0
  }
125
126
8.33k
  if (EVP_DigestFinal(md_ctx.get(), digest.data(), &digest_len) == 0) {
127
0
    return false;
128
0
  }
129
130
8.33k
  bssl::UniquePtr<ECDSA_SIG> ecdsa_sig(ECDSA_SIG_new());
131
8.33k
  if (!ecdsa_sig) {
132
0
    return false;
133
0
  }
134
135
8.33k
  if (BN_bin2bn(signature, signature_len / 2, ecdsa_sig->r) == nullptr ||
136
8.33k
      BN_bin2bn(signature + (signature_len / 2), signature_len / 2,
137
8.33k
                ecdsa_sig->s) == nullptr) {
138
0
    return false;
139
0
  }
140
141
8.33k
  if (ECDSA_do_verify(digest.data(), digest_len, ecdsa_sig.get(), key) == 1) {
142
3
    return true;
143
3
  }
144
145
8.33k
  ERR_clear_error();
146
8.33k
  return false;
147
8.33k
}
148
149
bool verifySignatureEC(EC_KEY* key, const EVP_MD* md,
150
                       absl::string_view signature,
151
8.33k
                       absl::string_view signed_data) {
152
8.33k
  return verifySignatureEC(key, md, castToUChar(signature), signature.length(),
153
8.33k
                           castToUChar(signed_data), signed_data.length());
154
8.33k
}
155
156
bool verifySignatureOct(const uint8_t* key, size_t key_len, const EVP_MD* md,
157
                        const uint8_t* signature, size_t signature_len,
158
11.3k
                        const uint8_t* signed_data, size_t signed_data_len) {
159
11.3k
  if (key == nullptr || md == nullptr || signature == nullptr ||
160
11.3k
      signed_data == nullptr) {
161
0
    return false;
162
0
  }
163
164
11.3k
  std::vector<uint8_t> out(EVP_MAX_MD_SIZE);
165
11.3k
  unsigned int out_len = 0;
166
11.3k
  if (HMAC(md, key, key_len, signed_data, signed_data_len, out.data(),
167
11.3k
           &out_len) == nullptr) {
168
0
    ERR_clear_error();
169
0
    return false;
170
0
  }
171
172
11.3k
  if (out_len != signature_len) {
173
10.4k
    return false;
174
10.4k
  }
175
176
931
  if (CRYPTO_memcmp(out.data(), signature, signature_len) == 0) {
177
2
    return true;
178
2
  }
179
180
929
  ERR_clear_error();
181
929
  return false;
182
931
}
183
184
bool verifySignatureOct(absl::string_view key, const EVP_MD* md,
185
                        absl::string_view signature,
186
11.3k
                        absl::string_view signed_data) {
187
11.3k
  return verifySignatureOct(castToUChar(key), key.length(), md,
188
11.3k
                            castToUChar(signature), signature.length(),
189
11.3k
                            castToUChar(signed_data), signed_data.length());
190
11.3k
}
191
192
Status verifySignatureEd25519(absl::string_view key,
193
                              absl::string_view signature,
194
8.33k
                              absl::string_view signed_data) {
195
8.33k
  if (signature.length() != ED25519_SIGNATURE_LEN) {
196
11
    return Status::JwtEd25519SignatureWrongLength;
197
11
  }
198
199
8.31k
  if (ED25519_verify(castToUChar(signed_data), signed_data.length(),
200
8.31k
                     castToUChar(signature), castToUChar(key.data())) == 1) {
201
2
    return Status::Ok;
202
2
  }
203
204
8.31k
  ERR_clear_error();
205
8.31k
  return Status::JwtVerificationFail;
206
8.31k
}
207
208
}  // namespace
209
210
2.43k
Status verifyJwtWithoutTimeChecking(const Jwt& jwt, const Jwks& jwks) {
211
  // Verify signature
212
2.43k
  std::string signed_data =
213
2.43k
      jwt.header_str_base64url_ + '.' + jwt.payload_str_base64url_;
214
2.43k
  bool kid_alg_matched = false;
215
46.0k
  for (const auto& jwk : jwks.keys()) {
216
    // If kid is specified in JWT, JWK with the same kid is used for
217
    // verification.
218
    // If kid is not specified in JWT, try all JWK.
219
46.0k
    if (!jwt.kid_.empty() && !jwk->kid_.empty() && jwk->kid_ != jwt.kid_) {
220
1.97k
      continue;
221
1.97k
    }
222
223
    // The same alg must be used.
224
44.1k
    if (!jwk->alg_.empty() && jwk->alg_ != jwt.alg_) {
225
971
      continue;
226
971
    }
227
43.1k
    kid_alg_matched = true;
228
229
43.1k
    if (jwk->kty_ == "EC") {
230
8.33k
      const EVP_MD* md;
231
8.33k
      if (jwt.alg_ == "ES384") {
232
0
        md = EVP_sha384();
233
8.33k
      } else if (jwt.alg_ == "ES512") {
234
1.46k
        md = EVP_sha512();
235
6.87k
      } else {
236
        // default to SHA256
237
6.87k
        md = EVP_sha256();
238
6.87k
      }
239
240
8.33k
      if (verifySignatureEC(jwk->ec_key_.get(), md, jwt.signature_,
241
8.33k
                            signed_data)) {
242
        // Verification succeeded.
243
3
        return Status::Ok;
244
3
      }
245
34.8k
    } else if (jwk->kty_ == "RSA") {
246
15.1k
      const EVP_MD* md;
247
15.1k
      if (jwt.alg_ == "RS384" || jwt.alg_ == "PS384") {
248
0
        md = EVP_sha384();
249
15.1k
      } else if (jwt.alg_ == "RS512" || jwt.alg_ == "PS512") {
250
1.34k
        md = EVP_sha512();
251
13.8k
      } else {
252
        // default to SHA256
253
13.8k
        md = EVP_sha256();
254
13.8k
      }
255
256
15.1k
      if (jwt.alg_.compare(0, 2, "RS") == 0) {
257
5.45k
        if (verifySignatureRSA(jwk->rsa_.get(), md, jwt.signature_,
258
5.45k
                               signed_data)) {
259
          // Verification succeeded.
260
2
          return Status::Ok;
261
2
        }
262
9.70k
      } else if (jwt.alg_.compare(0, 2, "PS") == 0) {
263
8.51k
        if (verifySignatureRSAPSS(jwk->rsa_.get(), md, jwt.signature_,
264
8.51k
                                  signed_data)) {
265
          // Verification succeeded.
266
0
          return Status::Ok;
267
0
        }
268
8.51k
      }
269
19.6k
    } else if (jwk->kty_ == "oct") {
270
11.3k
      const EVP_MD* md;
271
11.3k
      if (jwt.alg_ == "HS384") {
272
0
        md = EVP_sha384();
273
11.3k
      } else if (jwt.alg_ == "HS512") {
274
1.61k
        md = EVP_sha512();
275
9.72k
      } else {
276
        // default to SHA256
277
9.72k
        md = EVP_sha256();
278
9.72k
      }
279
280
11.3k
      if (verifySignatureOct(jwk->hmac_key_, md, jwt.signature_, signed_data)) {
281
        // Verification succeeded.
282
2
        return Status::Ok;
283
2
      }
284
11.3k
    } else if (jwk->kty_ == "OKP" && jwk->crv_ == "Ed25519") {
285
8.33k
      Status status = verifySignatureEd25519(jwk->okp_key_raw_, jwt.signature_,
286
8.33k
                                             signed_data);
287
      // For verification failures keep going and try the rest of the keys in
288
      // the JWKS. Otherwise status is either OK or an error with the JWT and we
289
      // can return immediately.
290
8.33k
      if (status == Status::Ok ||
291
8.32k
          status == Status::JwtEd25519SignatureWrongLength) {
292
13
        return status;
293
13
      }
294
8.33k
    }
295
43.1k
  }
296
297
  // Verification failed.
298
2.41k
  return kid_alg_matched ? Status::JwtVerificationFail
299
2.41k
                         : Status::JwksKidAlgMismatch;
300
2.43k
}
301
302
2.44k
Status verifyJwt(const Jwt& jwt, const Jwks& jwks) {
303
2.44k
  return verifyJwt(jwt, jwks, absl::ToUnixSeconds(absl::Now()));
304
2.44k
}
305
306
Status verifyJwt(const Jwt& jwt, const Jwks& jwks, uint64_t now,
307
2.44k
                 uint64_t clock_skew) {
308
2.44k
  Status time_status = jwt.verifyTimeConstraint(now, clock_skew);
309
2.44k
  if (time_status != Status::Ok) {
310
8
    return time_status;
311
8
  }
312
313
2.43k
  return verifyJwtWithoutTimeChecking(jwt, jwks);
314
2.44k
}
315
316
Status verifyJwt(const Jwt& jwt, const Jwks& jwks,
317
0
                 const std::vector<std::string>& audiences) {
318
0
  return verifyJwt(jwt, jwks, audiences, absl::ToUnixSeconds(absl::Now()));
319
0
}
320
321
Status verifyJwt(const Jwt& jwt, const Jwks& jwks,
322
0
                 const std::vector<std::string>& audiences, uint64_t now) {
323
0
  CheckAudience checker(audiences);
324
0
  if (!checker.areAudiencesAllowed(jwt.audiences_)) {
325
0
    return Status::JwtAudienceNotAllowed;
326
0
  }
327
0
  return verifyJwt(jwt, jwks, now);
328
0
}
329
330
}  // namespace jwt_verify
331
}  // namespace google