Coverage Report

Created: 2026-06-10 06:57

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
131k
inline const uint8_t* castToUChar(const absl::string_view& str) {
36
131k
  return reinterpret_cast<const uint8_t*>(str.data());
37
131k
}
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.49k
                        size_t signed_data_len) {
42
5.49k
  if (key == nullptr || md == nullptr || signature == nullptr ||
43
5.49k
      signed_data == nullptr) {
44
0
    return false;
45
0
  }
46
5.49k
  bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
47
5.49k
  if (EVP_PKEY_set1_RSA(evp_pkey.get(), key) != 1) {
48
0
    return false;
49
0
  }
50
51
5.49k
  bssl::UniquePtr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_create());
52
5.49k
  if (EVP_DigestVerifyInit(md_ctx.get(), nullptr, md, nullptr,
53
5.49k
                           evp_pkey.get()) == 1) {
54
5.49k
    if (EVP_DigestVerifyUpdate(md_ctx.get(), signed_data, signed_data_len) ==
55
5.49k
        1) {
56
5.49k
      if (EVP_DigestVerifyFinal(md_ctx.get(), signature, signature_len) == 1) {
57
1
        return true;
58
1
      }
59
5.49k
    }
60
5.49k
  }
61
5.49k
  ERR_clear_error();
62
5.49k
  return false;
63
5.49k
}
64
65
bool verifySignatureRSA(RSA* key, const EVP_MD* md, absl::string_view signature,
66
5.49k
                        absl::string_view signed_data) {
67
5.49k
  return verifySignatureRSA(key, md, castToUChar(signature), signature.length(),
68
5.49k
                            castToUChar(signed_data), signed_data.length());
69
5.49k
}
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.62k
                           size_t signed_data_len) {
74
8.62k
  if (key == nullptr || md == nullptr || signature == nullptr ||
75
8.62k
      signed_data == nullptr) {
76
0
    return false;
77
0
  }
78
8.62k
  bssl::UniquePtr<EVP_PKEY> evp_pkey(EVP_PKEY_new());
79
8.62k
  if (EVP_PKEY_set1_RSA(evp_pkey.get(), key) != 1) {
80
0
    return false;
81
0
  }
82
83
8.62k
  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.62k
  EVP_PKEY_CTX* pctx;
86
8.62k
  if (EVP_DigestVerifyInit(md_ctx.get(), &pctx, md, nullptr, evp_pkey.get()) ==
87
8.62k
          1 &&
88
8.62k
      EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) == 1 &&
89
8.62k
      EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, md) == 1 &&
90
8.62k
      EVP_DigestVerify(md_ctx.get(), signature, signature_len, signed_data,
91
8.62k
                       signed_data_len) == 1) {
92
0
    return true;
93
0
  }
94
95
8.62k
  ERR_clear_error();
96
8.62k
  return false;
97
8.62k
}
98
99
bool verifySignatureRSAPSS(RSA* key, const EVP_MD* md,
100
                           absl::string_view signature,
101
8.62k
                           absl::string_view signed_data) {
102
8.62k
  return verifySignatureRSAPSS(key, md, castToUChar(signature),
103
8.62k
                               signature.length(), castToUChar(signed_data),
104
8.62k
                               signed_data.length());
105
8.62k
}
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
9.85k
                       size_t signed_data_len) {
110
9.85k
  if (key == nullptr || md == nullptr || signature == nullptr ||
111
9.85k
      signed_data == nullptr) {
112
0
    return false;
113
0
  }
114
9.85k
  bssl::UniquePtr<EVP_MD_CTX> md_ctx(EVP_MD_CTX_create());
115
9.85k
  std::vector<uint8_t> digest(EVP_MAX_MD_SIZE);
116
9.85k
  unsigned int digest_len = 0;
117
118
9.85k
  if (EVP_DigestInit(md_ctx.get(), md) == 0) {
119
0
    return false;
120
0
  }
121
122
9.85k
  if (EVP_DigestUpdate(md_ctx.get(), signed_data, signed_data_len) == 0) {
123
0
    return false;
124
0
  }
125
126
9.85k
  if (EVP_DigestFinal(md_ctx.get(), digest.data(), &digest_len) == 0) {
127
0
    return false;
128
0
  }
129
130
9.85k
  bssl::UniquePtr<ECDSA_SIG> ecdsa_sig(ECDSA_SIG_new());
131
9.85k
  if (!ecdsa_sig) {
132
0
    return false;
133
0
  }
134
135
9.85k
  if (BN_bin2bn(signature, signature_len / 2, ecdsa_sig->r) == nullptr ||
136
9.85k
      BN_bin2bn(signature + (signature_len / 2), signature_len / 2,
137
9.85k
                ecdsa_sig->s) == nullptr) {
138
0
    return false;
139
0
  }
140
141
9.85k
  if (ECDSA_do_verify(digest.data(), digest_len, ecdsa_sig.get(), key) == 1) {
142
3
    return true;
143
3
  }
144
145
9.85k
  ERR_clear_error();
146
9.85k
  return false;
147
9.85k
}
148
149
bool verifySignatureEC(EC_KEY* key, const EVP_MD* md,
150
                       absl::string_view signature,
151
9.85k
                       absl::string_view signed_data) {
152
9.85k
  return verifySignatureEC(key, md, castToUChar(signature), signature.length(),
153
9.85k
                           castToUChar(signed_data), signed_data.length());
154
9.85k
}
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
21.5k
                        const uint8_t* signed_data, size_t signed_data_len) {
159
21.5k
  if (key == nullptr || md == nullptr || signature == nullptr ||
160
21.5k
      signed_data == nullptr) {
161
0
    return false;
162
0
  }
163
164
21.5k
  std::vector<uint8_t> out(EVP_MAX_MD_SIZE);
165
21.5k
  unsigned int out_len = 0;
166
21.5k
  if (HMAC(md, key, key_len, signed_data, signed_data_len, out.data(),
167
21.5k
           &out_len) == nullptr) {
168
0
    ERR_clear_error();
169
0
    return false;
170
0
  }
171
172
21.5k
  if (out_len != signature_len) {
173
20.6k
    return false;
174
20.6k
  }
175
176
950
  if (CRYPTO_memcmp(out.data(), signature, signature_len) == 0) {
177
1
    return true;
178
1
  }
179
180
949
  ERR_clear_error();
181
949
  return false;
182
950
}
183
184
bool verifySignatureOct(absl::string_view key, const EVP_MD* md,
185
                        absl::string_view signature,
186
21.5k
                        absl::string_view signed_data) {
187
21.5k
  return verifySignatureOct(castToUChar(key), key.length(), md,
188
21.5k
                            castToUChar(signature), signature.length(),
189
21.5k
                            castToUChar(signed_data), signed_data.length());
190
21.5k
}
191
192
Status verifySignatureEd25519(absl::string_view key,
193
                              absl::string_view signature,
194
6.45k
                              absl::string_view signed_data) {
195
6.45k
  if (signature.length() != ED25519_SIGNATURE_LEN) {
196
16
    return Status::JwtEd25519SignatureWrongLength;
197
16
  }
198
199
6.43k
  if (ED25519_verify(castToUChar(signed_data), signed_data.length(),
200
6.43k
                     castToUChar(signature), castToUChar(key.data())) == 1) {
201
1
    return Status::Ok;
202
1
  }
203
204
6.43k
  ERR_clear_error();
205
6.43k
  return Status::JwtVerificationFail;
206
6.43k
}
207
208
}  // namespace
209
210
2.57k
Status verifyJwtWithoutTimeChecking(const Jwt& jwt, const Jwks& jwks) {
211
  // Verify signature
212
2.57k
  std::string signed_data =
213
2.57k
      jwt.header_str_base64url_ + '.' + jwt.payload_str_base64url_;
214
2.57k
  bool kid_alg_matched = false;
215
55.4k
  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
55.4k
    if (!jwt.kid_.empty() && !jwk->kid_.empty() && jwk->kid_ != jwt.kid_) {
220
1.56k
      continue;
221
1.56k
    }
222
223
    // The same alg must be used.
224
53.8k
    if (!jwk->alg_.empty() && jwk->alg_ != jwt.alg_) {
225
1.07k
      continue;
226
1.07k
    }
227
52.8k
    kid_alg_matched = true;
228
229
52.8k
    if (jwk->kty_ == "EC") {
230
9.85k
      const EVP_MD* md;
231
9.85k
      if (jwt.alg_ == "ES384") {
232
0
        md = EVP_sha384();
233
9.85k
      } else if (jwt.alg_ == "ES512") {
234
1.36k
        md = EVP_sha512();
235
8.49k
      } else {
236
        // default to SHA256
237
8.49k
        md = EVP_sha256();
238
8.49k
      }
239
240
9.85k
      if (verifySignatureEC(jwk->ec_key_.get(), md, jwt.signature_,
241
9.85k
                            signed_data)) {
242
        // Verification succeeded.
243
3
        return Status::Ok;
244
3
      }
245
42.9k
    } else if (jwk->kty_ == "RSA") {
246
14.9k
      const EVP_MD* md;
247
14.9k
      if (jwt.alg_ == "RS384" || jwt.alg_ == "PS384") {
248
0
        md = EVP_sha384();
249
14.9k
      } else if (jwt.alg_ == "RS512" || jwt.alg_ == "PS512") {
250
849
        md = EVP_sha512();
251
14.0k
      } else {
252
        // default to SHA256
253
14.0k
        md = EVP_sha256();
254
14.0k
      }
255
256
14.9k
      if (jwt.alg_.compare(0, 2, "RS") == 0) {
257
5.49k
        if (verifySignatureRSA(jwk->rsa_.get(), md, jwt.signature_,
258
5.49k
                               signed_data)) {
259
          // Verification succeeded.
260
1
          return Status::Ok;
261
1
        }
262
9.45k
      } else if (jwt.alg_.compare(0, 2, "PS") == 0) {
263
8.62k
        if (verifySignatureRSAPSS(jwk->rsa_.get(), md, jwt.signature_,
264
8.62k
                                  signed_data)) {
265
          // Verification succeeded.
266
0
          return Status::Ok;
267
0
        }
268
8.62k
      }
269
28.0k
    } else if (jwk->kty_ == "oct") {
270
21.5k
      const EVP_MD* md;
271
21.5k
      if (jwt.alg_ == "HS384") {
272
0
        md = EVP_sha384();
273
21.5k
      } else if (jwt.alg_ == "HS512") {
274
2.08k
        md = EVP_sha512();
275
19.4k
      } else {
276
        // default to SHA256
277
19.4k
        md = EVP_sha256();
278
19.4k
      }
279
280
21.5k
      if (verifySignatureOct(jwk->hmac_key_, md, jwt.signature_, signed_data)) {
281
        // Verification succeeded.
282
1
        return Status::Ok;
283
1
      }
284
21.5k
    } else if (jwk->kty_ == "OKP" && jwk->crv_ == "Ed25519") {
285
6.45k
      Status status = verifySignatureEd25519(jwk->okp_key_raw_, jwt.signature_,
286
6.45k
                                             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
6.45k
      if (status == Status::Ok ||
291
6.45k
          status == Status::JwtEd25519SignatureWrongLength) {
292
17
        return status;
293
17
      }
294
6.45k
    }
295
52.8k
  }
296
297
  // Verification failed.
298
2.55k
  return kid_alg_matched ? Status::JwtVerificationFail
299
2.55k
                         : Status::JwksKidAlgMismatch;
300
2.57k
}
301
302
2.59k
Status verifyJwt(const Jwt& jwt, const Jwks& jwks) {
303
2.59k
  return verifyJwt(jwt, jwks, absl::ToUnixSeconds(absl::Now()));
304
2.59k
}
305
306
Status verifyJwt(const Jwt& jwt, const Jwks& jwks, uint64_t now,
307
2.59k
                 uint64_t clock_skew) {
308
2.59k
  Status time_status = jwt.verifyTimeConstraint(now, clock_skew);
309
2.59k
  if (time_status != Status::Ok) {
310
22
    return time_status;
311
22
  }
312
313
2.57k
  return verifyJwtWithoutTimeChecking(jwt, jwks);
314
2.59k
}
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