blob: ea43b2aa50a72330a30d827ecb194753aa8cbdc1 [file] [log] [blame]
Adam Langley95c29f32014-06-20 12:00:00 -07001/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2 * All rights reserved.
3 *
4 * This package is an SSL implementation written
5 * by Eric Young (eay@cryptsoft.com).
6 * The implementation was written so as to conform with Netscapes SSL.
7 *
8 * This library is free for commercial and non-commercial use as long as
9 * the following conditions are aheared to. The following conditions
10 * apply to all code found in this distribution, be it the RC4, RSA,
11 * lhash, DES, etc., code; not just the SSL code. The SSL documentation
12 * included with this distribution is covered by the same copyright terms
13 * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14 *
15 * Copyright remains Eric Young's, and as such any Copyright notices in
16 * the code are not to be removed.
17 * If this package is used in a product, Eric Young should be given attribution
18 * as the author of the parts of the library used.
19 * This can be in the form of a textual message at program startup or
20 * in documentation (online or textual) provided with the package.
21 *
22 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions
24 * are met:
25 * 1. Redistributions of source code must retain the copyright
26 * notice, this list of conditions and the following disclaimer.
27 * 2. Redistributions in binary form must reproduce the above copyright
28 * notice, this list of conditions and the following disclaimer in the
29 * documentation and/or other materials provided with the distribution.
30 * 3. All advertising materials mentioning features or use of this software
31 * must display the following acknowledgement:
32 * "This product includes cryptographic software written by
33 * Eric Young (eay@cryptsoft.com)"
34 * The word 'cryptographic' can be left out if the rouines from the library
35 * being used are not cryptographic related :-).
36 * 4. If you include any Windows specific code (or a derivative thereof) from
37 * the apps directory (application code) you must include an acknowledgement:
38 * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39 *
40 * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50 * SUCH DAMAGE.
51 *
52 * The licence and distribution terms for any publically available version or
53 * derivative of this code cannot be changed. i.e. this code cannot simply be
54 * copied and put under another distribution licence
55 * [including the GNU Public Licence.] */
56
Jesse Seloverb4810de2018-06-18 17:31:39 -040057#include <ctype.h>
Adam Langley2b2d66d2015-01-30 17:08:37 -080058#include <string.h>
Adam Langley95c29f32014-06-20 12:00:00 -070059#include <time.h>
60
61#include <openssl/asn1.h>
Adam Langley95c29f32014-06-20 12:00:00 -070062#include <openssl/err.h>
63#include <openssl/evp.h>
Adam Langley95c29f32014-06-20 12:00:00 -070064#include <openssl/mem.h>
65#include <openssl/obj.h>
Brian Smith054e6822015-03-27 21:12:01 -100066#include <openssl/thread.h>
Adam Langley95c29f32014-06-20 12:00:00 -070067#include <openssl/x509.h>
Adam Langley95c29f32014-06-20 12:00:00 -070068
Brian Smitha039d702015-01-29 15:03:18 -080069#include "../internal.h"
David Benjamin260a10c2022-06-16 13:58:28 -040070#include "internal.h"
Brian Smitha039d702015-01-29 15:03:18 -080071
David Benjaminaa585132015-06-29 23:36:17 -040072static CRYPTO_EX_DATA_CLASS g_ex_data_class =
Adam Langley57707c72016-01-14 11:25:12 -080073 CRYPTO_EX_DATA_CLASS_INIT_WITH_APP_DATA;
David Benjamin9f33fc62015-04-15 17:29:53 -040074
David Benjamin46350482022-06-16 14:03:12 -040075// CRL score values
Adam Langley95c29f32014-06-20 12:00:00 -070076
David Benjamin46350482022-06-16 14:03:12 -040077// No unhandled critical extensions
David Benjamin260a10c2022-06-16 13:58:28 -040078#define CRL_SCORE_NOCRITICAL 0x100
Adam Langley95c29f32014-06-20 12:00:00 -070079
David Benjamin46350482022-06-16 14:03:12 -040080// certificate is within CRL scope
David Benjamin260a10c2022-06-16 13:58:28 -040081#define CRL_SCORE_SCOPE 0x080
Adam Langley95c29f32014-06-20 12:00:00 -070082
David Benjamin46350482022-06-16 14:03:12 -040083// CRL times valid
David Benjamin260a10c2022-06-16 13:58:28 -040084#define CRL_SCORE_TIME 0x040
Adam Langley95c29f32014-06-20 12:00:00 -070085
David Benjamin46350482022-06-16 14:03:12 -040086// Issuer name matches certificate
David Benjamin260a10c2022-06-16 13:58:28 -040087#define CRL_SCORE_ISSUER_NAME 0x020
Adam Langley95c29f32014-06-20 12:00:00 -070088
David Benjamin46350482022-06-16 14:03:12 -040089// If this score or above CRL is probably valid
David Benjamin260a10c2022-06-16 13:58:28 -040090#define CRL_SCORE_VALID \
91 (CRL_SCORE_NOCRITICAL | CRL_SCORE_TIME | CRL_SCORE_SCOPE)
Adam Langley95c29f32014-06-20 12:00:00 -070092
David Benjamin46350482022-06-16 14:03:12 -040093// CRL issuer is certificate issuer
David Benjamin260a10c2022-06-16 13:58:28 -040094#define CRL_SCORE_ISSUER_CERT 0x018
Adam Langley95c29f32014-06-20 12:00:00 -070095
David Benjamin46350482022-06-16 14:03:12 -040096// CRL issuer is on certificate path
David Benjamin260a10c2022-06-16 13:58:28 -040097#define CRL_SCORE_SAME_PATH 0x008
Adam Langley95c29f32014-06-20 12:00:00 -070098
David Benjamin46350482022-06-16 14:03:12 -040099// CRL issuer matches CRL AKID
David Benjamin260a10c2022-06-16 13:58:28 -0400100#define CRL_SCORE_AKID 0x004
Adam Langley95c29f32014-06-20 12:00:00 -0700101
Adam Langley57707c72016-01-14 11:25:12 -0800102static int null_callback(int ok, X509_STORE_CTX *e);
Adam Langley95c29f32014-06-20 12:00:00 -0700103static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x);
104static int check_chain_extensions(X509_STORE_CTX *ctx);
105static int check_name_constraints(X509_STORE_CTX *ctx);
106static int check_id(X509_STORE_CTX *ctx);
107static int check_trust(X509_STORE_CTX *ctx);
108static int check_revocation(X509_STORE_CTX *ctx);
109static int check_cert(X509_STORE_CTX *ctx);
110static int check_policy(X509_STORE_CTX *ctx);
111
David Benjamin580c0412023-11-12 14:28:51 -0500112static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, X509_CRL *crl,
113 X509 *x);
David Benjamind9a58a12023-11-12 14:04:00 -0500114static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x);
David Benjamina4851dd2023-11-12 15:51:49 -0500115static int crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer,
116 int *pcrl_score);
David Benjamin580c0412023-11-12 14:28:51 -0500117static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score);
David Benjamin998f5112023-11-19 10:04:06 -0500118static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x);
Adam Langley95c29f32014-06-20 12:00:00 -0700119
120static int internal_verify(X509_STORE_CTX *ctx);
Adam Langley95c29f32014-06-20 12:00:00 -0700121
David Benjamin260a10c2022-06-16 13:58:28 -0400122static int null_callback(int ok, X509_STORE_CTX *e) { return ok; }
Adam Langley95c29f32014-06-20 12:00:00 -0700123
David Benjamin46350482022-06-16 14:03:12 -0400124// cert_self_signed checks if |x| is self-signed. If |x| is valid, it returns
125// one and sets |*out_is_self_signed| to the result. If |x| is invalid, it
126// returns zero.
David Benjamin260a10c2022-06-16 13:58:28 -0400127static int cert_self_signed(X509 *x, int *out_is_self_signed) {
128 if (!x509v3_cache_extensions(x)) {
129 return 0;
130 }
131 *out_is_self_signed = (x->ex_flags & EXFLAG_SS) != 0;
132 return 1;
Adam Langley57707c72016-01-14 11:25:12 -0800133}
Adam Langley95c29f32014-06-20 12:00:00 -0700134
David Benjamin46350482022-06-16 14:03:12 -0400135// Given a certificate try and find an exact match in the store
Adam Langley95c29f32014-06-20 12:00:00 -0700136
David Benjamin260a10c2022-06-16 13:58:28 -0400137static X509 *lookup_cert_match(X509_STORE_CTX *ctx, X509 *x) {
138 STACK_OF(X509) *certs;
139 X509 *xtmp = NULL;
140 size_t i;
David Benjamin46350482022-06-16 14:03:12 -0400141 // Lookup all certs with matching subject name
David Benjamin998f5112023-11-19 10:04:06 -0500142 certs = X509_STORE_get1_certs(ctx, X509_get_subject_name(x));
David Benjaminc0b87a02022-06-16 14:02:15 -0400143 if (certs == NULL) {
David Benjamin260a10c2022-06-16 13:58:28 -0400144 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400145 }
David Benjamin46350482022-06-16 14:03:12 -0400146 // Look for exact match
David Benjamin260a10c2022-06-16 13:58:28 -0400147 for (i = 0; i < sk_X509_num(certs); i++) {
148 xtmp = sk_X509_value(certs, i);
David Benjaminc0b87a02022-06-16 14:02:15 -0400149 if (!X509_cmp(xtmp, x)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400150 break;
David Benjaminc0b87a02022-06-16 14:02:15 -0400151 }
David Benjamin260a10c2022-06-16 13:58:28 -0400152 }
David Benjaminc0b87a02022-06-16 14:02:15 -0400153 if (i < sk_X509_num(certs)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400154 X509_up_ref(xtmp);
David Benjaminc0b87a02022-06-16 14:02:15 -0400155 } else {
David Benjamin260a10c2022-06-16 13:58:28 -0400156 xtmp = NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400157 }
David Benjamin260a10c2022-06-16 13:58:28 -0400158 sk_X509_pop_free(certs, X509_free);
159 return xtmp;
Adam Langley57707c72016-01-14 11:25:12 -0800160}
Adam Langley95c29f32014-06-20 12:00:00 -0700161
David Benjamin260a10c2022-06-16 13:58:28 -0400162int X509_verify_cert(X509_STORE_CTX *ctx) {
163 X509 *x, *xtmp, *xtmp2, *chain_ss = NULL;
164 int bad_chain = 0;
165 X509_VERIFY_PARAM *param = ctx->param;
166 int depth, i, ok = 0;
167 int num, j, retry, trust;
168 STACK_OF(X509) *sktmp = NULL;
Bob Beck66863522022-04-21 09:37:41 -0600169
David Benjamin260a10c2022-06-16 13:58:28 -0400170 if (ctx->cert == NULL) {
171 OPENSSL_PUT_ERROR(X509, X509_R_NO_CERT_SET_FOR_US_TO_VERIFY);
172 ctx->error = X509_V_ERR_INVALID_CALL;
173 return -1;
174 }
David Benjaminf8614992023-11-12 13:43:33 -0500175
David Benjamin260a10c2022-06-16 13:58:28 -0400176 if (ctx->chain != NULL) {
David Benjamin46350482022-06-16 14:03:12 -0400177 // This X509_STORE_CTX has already been used to verify a cert. We
178 // cannot do another one.
David Benjamin260a10c2022-06-16 13:58:28 -0400179 OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
180 ctx->error = X509_V_ERR_INVALID_CALL;
181 return -1;
182 }
Adam Langley95c29f32014-06-20 12:00:00 -0700183
David Benjaminf8614992023-11-12 13:43:33 -0500184 if (ctx->param->flags &
185 (X509_V_FLAG_EXTENDED_CRL_SUPPORT | X509_V_FLAG_USE_DELTAS)) {
186 // We do not support indirect or delta CRLs. The flags still exist for
187 // compatibility with bindings libraries, but to ensure we do not
188 // inadvertently skip a CRL check that the caller expects, fail closed.
189 OPENSSL_PUT_ERROR(X509, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
190 ctx->error = X509_V_ERR_INVALID_CALL;
191 return -1;
192 }
193
David Benjamin46350482022-06-16 14:03:12 -0400194 // first we make sure the chain we are going to build is present and that
195 // the first entry is in place
David Benjamin260a10c2022-06-16 13:58:28 -0400196 ctx->chain = sk_X509_new_null();
197 if (ctx->chain == NULL || !sk_X509_push(ctx->chain, ctx->cert)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400198 ctx->error = X509_V_ERR_OUT_OF_MEM;
199 goto end;
200 }
201 X509_up_ref(ctx->cert);
202 ctx->last_untrusted = 1;
203
David Benjamin46350482022-06-16 14:03:12 -0400204 // We use a temporary STACK so we can chop and hack at it.
David Benjamin260a10c2022-06-16 13:58:28 -0400205 if (ctx->untrusted != NULL && (sktmp = sk_X509_dup(ctx->untrusted)) == NULL) {
David Benjamin260a10c2022-06-16 13:58:28 -0400206 ctx->error = X509_V_ERR_OUT_OF_MEM;
207 goto end;
208 }
209
David Benjamin89a62532023-05-23 11:45:10 -0400210 num = (int)sk_X509_num(ctx->chain);
David Benjamin260a10c2022-06-16 13:58:28 -0400211 x = sk_X509_value(ctx->chain, num - 1);
212 depth = param->depth;
213
214 for (;;) {
David Benjamin46350482022-06-16 14:03:12 -0400215 // If we have enough, we break
David Benjaminc0b87a02022-06-16 14:02:15 -0400216 if (depth < num) {
David Benjamin46350482022-06-16 14:03:12 -0400217 break; // FIXME: If this happens, we should take
218 // note of it and, if appropriate, use the
219 // X509_V_ERR_CERT_CHAIN_TOO_LONG error code
220 // later.
David Benjaminc0b87a02022-06-16 14:02:15 -0400221 }
David Benjamin260a10c2022-06-16 13:58:28 -0400222
223 int is_self_signed;
224 if (!cert_self_signed(x, &is_self_signed)) {
225 ctx->error = X509_V_ERR_INVALID_EXTENSION;
226 goto end;
Adam Langley57707c72016-01-14 11:25:12 -0800227 }
Adam Langley95c29f32014-06-20 12:00:00 -0700228
David Benjamin46350482022-06-16 14:03:12 -0400229 // If we are self signed, we break
David Benjaminc0b87a02022-06-16 14:02:15 -0400230 if (is_self_signed) {
David Benjamin260a10c2022-06-16 13:58:28 -0400231 break;
David Benjaminc0b87a02022-06-16 14:02:15 -0400232 }
David Benjamin46350482022-06-16 14:03:12 -0400233 // If asked see if we can find issuer in trusted store first
David Benjamin260a10c2022-06-16 13:58:28 -0400234 if (ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) {
235 ok = ctx->get_issuer(&xtmp, ctx, x);
236 if (ok < 0) {
237 ctx->error = X509_V_ERR_STORE_LOOKUP;
238 goto end;
239 }
David Benjamin46350482022-06-16 14:03:12 -0400240 // If successful for now free up cert so it will be picked up
241 // again later.
David Benjamin260a10c2022-06-16 13:58:28 -0400242 if (ok > 0) {
243 X509_free(xtmp);
Adam Langley57707c72016-01-14 11:25:12 -0800244 break;
David Benjamin260a10c2022-06-16 13:58:28 -0400245 }
Adam Langley57707c72016-01-14 11:25:12 -0800246 }
Adam Langley95c29f32014-06-20 12:00:00 -0700247
David Benjamin46350482022-06-16 14:03:12 -0400248 // If we were passed a cert chain, use it first
David Benjamin260a10c2022-06-16 13:58:28 -0400249 if (sktmp != NULL) {
250 xtmp = find_issuer(ctx, sktmp, x);
251 if (xtmp != NULL) {
252 if (!sk_X509_push(ctx->chain, xtmp)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400253 ctx->error = X509_V_ERR_OUT_OF_MEM;
254 ok = 0;
255 goto end;
256 }
257 X509_up_ref(xtmp);
258 (void)sk_X509_delete_ptr(sktmp, xtmp);
259 ctx->last_untrusted++;
260 x = xtmp;
261 num++;
David Benjamin46350482022-06-16 14:03:12 -0400262 // reparse the full chain for the next one
David Benjamin260a10c2022-06-16 13:58:28 -0400263 continue;
264 }
265 }
266 break;
267 }
David Benjaminfd86eaa2020-06-17 15:13:16 -0400268
David Benjamin46350482022-06-16 14:03:12 -0400269 // Remember how many untrusted certs we have
David Benjamin260a10c2022-06-16 13:58:28 -0400270 j = num;
David Benjamin46350482022-06-16 14:03:12 -0400271 // at this point, chain should contain a list of untrusted certificates.
272 // We now need to add at least one trusted one, if possible, otherwise we
273 // complain.
David Benjaminfd86eaa2020-06-17 15:13:16 -0400274
David Benjamin260a10c2022-06-16 13:58:28 -0400275 do {
David Benjamin46350482022-06-16 14:03:12 -0400276 // Examine last certificate in chain and see if it is self signed.
David Benjamin89a62532023-05-23 11:45:10 -0400277 i = (int)sk_X509_num(ctx->chain);
David Benjamin260a10c2022-06-16 13:58:28 -0400278 x = sk_X509_value(ctx->chain, i - 1);
279
280 int is_self_signed;
281 if (!cert_self_signed(x, &is_self_signed)) {
282 ctx->error = X509_V_ERR_INVALID_EXTENSION;
283 goto end;
284 }
285
286 if (is_self_signed) {
David Benjamin46350482022-06-16 14:03:12 -0400287 // we have a self signed certificate
David Benjamin260a10c2022-06-16 13:58:28 -0400288 if (sk_X509_num(ctx->chain) == 1) {
David Benjamin46350482022-06-16 14:03:12 -0400289 // We have a single self signed certificate: see if we can
290 // find it in the store. We must have an exact match to avoid
291 // possible impersonation.
David Benjamin260a10c2022-06-16 13:58:28 -0400292 ok = ctx->get_issuer(&xtmp, ctx, x);
293 if ((ok <= 0) || X509_cmp(x, xtmp)) {
294 ctx->error = X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT;
295 ctx->current_cert = x;
296 ctx->error_depth = i - 1;
David Benjaminc0b87a02022-06-16 14:02:15 -0400297 if (ok == 1) {
David Benjamin260a10c2022-06-16 13:58:28 -0400298 X509_free(xtmp);
David Benjaminc0b87a02022-06-16 14:02:15 -0400299 }
David Benjamin260a10c2022-06-16 13:58:28 -0400300 bad_chain = 1;
301 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400302 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400303 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400304 }
Adam Langley57707c72016-01-14 11:25:12 -0800305 } else {
David Benjamin46350482022-06-16 14:03:12 -0400306 // We have a match: replace certificate with store
307 // version so we get any trust settings.
David Benjamin260a10c2022-06-16 13:58:28 -0400308 X509_free(x);
309 x = xtmp;
310 (void)sk_X509_set(ctx->chain, i - 1, x);
311 ctx->last_untrusted = 0;
Adam Langley57707c72016-01-14 11:25:12 -0800312 }
David Benjamin260a10c2022-06-16 13:58:28 -0400313 } else {
David Benjamin46350482022-06-16 14:03:12 -0400314 // extract and save self signed certificate for later use
David Benjamin260a10c2022-06-16 13:58:28 -0400315 chain_ss = sk_X509_pop(ctx->chain);
316 ctx->last_untrusted--;
317 num--;
318 j--;
319 x = sk_X509_value(ctx->chain, num - 1);
320 }
321 }
David Benjamin46350482022-06-16 14:03:12 -0400322 // We now lookup certs from the certificate store
David Benjamin260a10c2022-06-16 13:58:28 -0400323 for (;;) {
David Benjamin46350482022-06-16 14:03:12 -0400324 // If we have enough, we break
David Benjaminc0b87a02022-06-16 14:02:15 -0400325 if (depth < num) {
David Benjamin260a10c2022-06-16 13:58:28 -0400326 break;
David Benjaminc0b87a02022-06-16 14:02:15 -0400327 }
David Benjamin260a10c2022-06-16 13:58:28 -0400328 if (!cert_self_signed(x, &is_self_signed)) {
329 ctx->error = X509_V_ERR_INVALID_EXTENSION;
330 goto end;
331 }
David Benjamin46350482022-06-16 14:03:12 -0400332 // If we are self signed, we break
David Benjaminc0b87a02022-06-16 14:02:15 -0400333 if (is_self_signed) {
David Benjamin260a10c2022-06-16 13:58:28 -0400334 break;
David Benjaminc0b87a02022-06-16 14:02:15 -0400335 }
David Benjamin260a10c2022-06-16 13:58:28 -0400336 ok = ctx->get_issuer(&xtmp, ctx, x);
Adam Langley95c29f32014-06-20 12:00:00 -0700337
David Benjamin260a10c2022-06-16 13:58:28 -0400338 if (ok < 0) {
339 ctx->error = X509_V_ERR_STORE_LOOKUP;
340 goto end;
341 }
David Benjaminc0b87a02022-06-16 14:02:15 -0400342 if (ok == 0) {
David Benjamin260a10c2022-06-16 13:58:28 -0400343 break;
David Benjaminc0b87a02022-06-16 14:02:15 -0400344 }
David Benjamin260a10c2022-06-16 13:58:28 -0400345 x = xtmp;
346 if (!sk_X509_push(ctx->chain, x)) {
347 X509_free(xtmp);
David Benjamin260a10c2022-06-16 13:58:28 -0400348 ctx->error = X509_V_ERR_OUT_OF_MEM;
349 ok = 0;
350 goto end;
351 }
352 num++;
Adam Langley57707c72016-01-14 11:25:12 -0800353 }
Adam Langley95c29f32014-06-20 12:00:00 -0700354
David Benjamin46350482022-06-16 14:03:12 -0400355 // we now have our chain, lets check it...
David Benjamin260a10c2022-06-16 13:58:28 -0400356 trust = check_trust(ctx);
Adam Langley95c29f32014-06-20 12:00:00 -0700357
David Benjamin46350482022-06-16 14:03:12 -0400358 // If explicitly rejected error
David Benjamin260a10c2022-06-16 13:58:28 -0400359 if (trust == X509_TRUST_REJECTED) {
360 ok = 0;
361 goto end;
362 }
David Benjamin46350482022-06-16 14:03:12 -0400363 // If it's not explicitly trusted then check if there is an alternative
364 // chain that could be used. We only do this if we haven't already
365 // checked via TRUSTED_FIRST and the user hasn't switched off alternate
366 // chain checking
David Benjamin260a10c2022-06-16 13:58:28 -0400367 retry = 0;
368 if (trust != X509_TRUST_TRUSTED &&
369 !(ctx->param->flags & X509_V_FLAG_TRUSTED_FIRST) &&
370 !(ctx->param->flags & X509_V_FLAG_NO_ALT_CHAINS)) {
371 while (j-- > 1) {
372 xtmp2 = sk_X509_value(ctx->chain, j - 1);
373 ok = ctx->get_issuer(&xtmp, ctx, xtmp2);
David Benjaminc0b87a02022-06-16 14:02:15 -0400374 if (ok < 0) {
David Benjamin260a10c2022-06-16 13:58:28 -0400375 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400376 }
David Benjamin46350482022-06-16 14:03:12 -0400377 // Check if we found an alternate chain
David Benjamin260a10c2022-06-16 13:58:28 -0400378 if (ok > 0) {
David Benjamin46350482022-06-16 14:03:12 -0400379 // Free up the found cert we'll add it again later
David Benjamin260a10c2022-06-16 13:58:28 -0400380 X509_free(xtmp);
Adam Langley95c29f32014-06-20 12:00:00 -0700381
David Benjamin46350482022-06-16 14:03:12 -0400382 // Dump all the certs above this point - we've found an
383 // alternate chain
David Benjamin260a10c2022-06-16 13:58:28 -0400384 while (num > j) {
385 xtmp = sk_X509_pop(ctx->chain);
386 X509_free(xtmp);
387 num--;
388 }
David Benjamin89a62532023-05-23 11:45:10 -0400389 ctx->last_untrusted = (int)sk_X509_num(ctx->chain);
David Benjamin260a10c2022-06-16 13:58:28 -0400390 retry = 1;
391 break;
392 }
393 }
394 }
395 } while (retry);
Adam Langley95c29f32014-06-20 12:00:00 -0700396
David Benjamin46350482022-06-16 14:03:12 -0400397 // If not explicitly trusted then indicate error unless it's a single
398 // self signed certificate in which case we've indicated an error already
399 // and set bad_chain == 1
David Benjamin260a10c2022-06-16 13:58:28 -0400400 if (trust != X509_TRUST_TRUSTED && !bad_chain) {
David Benjamin998f5112023-11-19 10:04:06 -0500401 if (chain_ss == NULL ||
402 !x509_check_issued_with_callback(ctx, x, chain_ss)) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400403 if (ctx->last_untrusted >= num) {
David Benjamin260a10c2022-06-16 13:58:28 -0400404 ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY;
David Benjaminc0b87a02022-06-16 14:02:15 -0400405 } else {
David Benjamin260a10c2022-06-16 13:58:28 -0400406 ctx->error = X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT;
David Benjaminc0b87a02022-06-16 14:02:15 -0400407 }
David Benjamin260a10c2022-06-16 13:58:28 -0400408 ctx->current_cert = x;
409 } else {
410 sk_X509_push(ctx->chain, chain_ss);
411 num++;
412 ctx->last_untrusted = num;
413 ctx->current_cert = chain_ss;
414 ctx->error = X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN;
415 chain_ss = NULL;
Adam Langley57707c72016-01-14 11:25:12 -0800416 }
Adam Langley95c29f32014-06-20 12:00:00 -0700417
David Benjamin260a10c2022-06-16 13:58:28 -0400418 ctx->error_depth = num - 1;
419 bad_chain = 1;
420 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400421 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400422 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400423 }
David Benjamin260a10c2022-06-16 13:58:28 -0400424 }
Adam Langley95c29f32014-06-20 12:00:00 -0700425
David Benjamin46350482022-06-16 14:03:12 -0400426 // We have the chain complete: now we need to check its purpose
David Benjamin260a10c2022-06-16 13:58:28 -0400427 ok = check_chain_extensions(ctx);
Martin Kreichgauerb86be362017-08-14 15:55:48 -0700428
David Benjaminc0b87a02022-06-16 14:02:15 -0400429 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400430 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400431 }
David Benjamin260a10c2022-06-16 13:58:28 -0400432
433 ok = check_id(ctx);
434
David Benjaminc0b87a02022-06-16 14:02:15 -0400435 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400436 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400437 }
David Benjamin260a10c2022-06-16 13:58:28 -0400438
David Benjamin46350482022-06-16 14:03:12 -0400439 // Check revocation status: we do this after copying parameters because
440 // they may be needed for CRL signature verification.
David Benjamin998f5112023-11-19 10:04:06 -0500441 ok = check_revocation(ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400442 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400443 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400444 }
David Benjamin260a10c2022-06-16 13:58:28 -0400445
David Benjamin46350482022-06-16 14:03:12 -0400446 // At this point, we have a chain and need to verify it
David Benjamin998f5112023-11-19 10:04:06 -0500447 ok = internal_verify(ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400448 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400449 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400450 }
David Benjamindd1ca992015-02-16 21:15:53 -0500451
David Benjamin46350482022-06-16 14:03:12 -0400452 // Check name constraints
David Benjamin260a10c2022-06-16 13:58:28 -0400453 ok = check_name_constraints(ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400454 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400455 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400456 }
David Benjamin260a10c2022-06-16 13:58:28 -0400457
David Benjamin28226f52023-03-29 14:04:44 +0900458 // If we get this far, evaluate policies.
459 if (!bad_chain) {
David Benjamin998f5112023-11-19 10:04:06 -0500460 ok = check_policy(ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400461 }
David Benjamin260a10c2022-06-16 13:58:28 -0400462
463end:
David Benjaminc0b87a02022-06-16 14:02:15 -0400464 if (sktmp != NULL) {
David Benjamin260a10c2022-06-16 13:58:28 -0400465 sk_X509_free(sktmp);
David Benjaminc0b87a02022-06-16 14:02:15 -0400466 }
467 if (chain_ss != NULL) {
David Benjamin260a10c2022-06-16 13:58:28 -0400468 X509_free(chain_ss);
David Benjaminc0b87a02022-06-16 14:02:15 -0400469 }
David Benjamin260a10c2022-06-16 13:58:28 -0400470
David Benjamin46350482022-06-16 14:03:12 -0400471 // Safety net, error returns must set ctx->error
David Benjaminc0b87a02022-06-16 14:02:15 -0400472 if (ok <= 0 && ctx->error == X509_V_OK) {
David Benjamin260a10c2022-06-16 13:58:28 -0400473 ctx->error = X509_V_ERR_UNSPECIFIED;
David Benjaminc0b87a02022-06-16 14:02:15 -0400474 }
David Benjamin260a10c2022-06-16 13:58:28 -0400475 return ok;
Adam Langley57707c72016-01-14 11:25:12 -0800476}
Adam Langley95c29f32014-06-20 12:00:00 -0700477
David Benjamin46350482022-06-16 14:03:12 -0400478// Given a STACK_OF(X509) find the issuer of cert (if any)
Adam Langley95c29f32014-06-20 12:00:00 -0700479
David Benjamin260a10c2022-06-16 13:58:28 -0400480static X509 *find_issuer(X509_STORE_CTX *ctx, STACK_OF(X509) *sk, X509 *x) {
481 size_t i;
482 X509 *issuer;
483 for (i = 0; i < sk_X509_num(sk); i++) {
484 issuer = sk_X509_value(sk, i);
David Benjamin998f5112023-11-19 10:04:06 -0500485 if (x509_check_issued_with_callback(ctx, x, issuer)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400486 return issuer;
David Benjaminc0b87a02022-06-16 14:02:15 -0400487 }
David Benjamin260a10c2022-06-16 13:58:28 -0400488 }
489 return NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700490}
491
David Benjamin46350482022-06-16 14:03:12 -0400492// Given a possible certificate and issuer check them
Adam Langley95c29f32014-06-20 12:00:00 -0700493
David Benjamin998f5112023-11-19 10:04:06 -0500494int x509_check_issued_with_callback(X509_STORE_CTX *ctx, X509 *x,
495 X509 *issuer) {
David Benjamin260a10c2022-06-16 13:58:28 -0400496 int ret;
497 ret = X509_check_issued(issuer, x);
David Benjaminc0b87a02022-06-16 14:02:15 -0400498 if (ret == X509_V_OK) {
David Benjamin260a10c2022-06-16 13:58:28 -0400499 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -0400500 }
David Benjamin46350482022-06-16 14:03:12 -0400501 // If we haven't asked for issuer errors don't set ctx
David Benjaminc0b87a02022-06-16 14:02:15 -0400502 if (!(ctx->param->flags & X509_V_FLAG_CB_ISSUER_CHECK)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400503 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400504 }
Adam Langley95c29f32014-06-20 12:00:00 -0700505
David Benjamin260a10c2022-06-16 13:58:28 -0400506 ctx->error = ret;
507 ctx->current_cert = x;
508 ctx->current_issuer = issuer;
509 return ctx->verify_cb(0, ctx);
Adam Langley95c29f32014-06-20 12:00:00 -0700510}
511
David Benjamin46350482022-06-16 14:03:12 -0400512// Alternative lookup method: look from a STACK stored in other_ctx
Adam Langley95c29f32014-06-20 12:00:00 -0700513
David Benjamin260a10c2022-06-16 13:58:28 -0400514static int get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) {
515 *issuer = find_issuer(ctx, ctx->other_ctx, x);
516 if (*issuer) {
517 X509_up_ref(*issuer);
518 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -0400519 } else {
David Benjamin260a10c2022-06-16 13:58:28 -0400520 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400521 }
Adam Langley95c29f32014-06-20 12:00:00 -0700522}
Adam Langley95c29f32014-06-20 12:00:00 -0700523
David Benjamin46350482022-06-16 14:03:12 -0400524// Check a certificate chains extensions for consistency with the supplied
525// purpose
Adam Langley95c29f32014-06-20 12:00:00 -0700526
David Benjamin260a10c2022-06-16 13:58:28 -0400527static int check_chain_extensions(X509_STORE_CTX *ctx) {
David Benjaminca1690e2023-02-14 16:07:45 -0500528 int ok = 0, plen = 0;
David Benjamina4851dd2023-11-12 15:51:49 -0500529 int purpose = ctx->param->purpose;
David Benjamin260a10c2022-06-16 13:58:28 -0400530
David Benjamin46350482022-06-16 14:03:12 -0400531 // Check all untrusted certificates
David Benjaminca1690e2023-02-14 16:07:45 -0500532 for (int i = 0; i < ctx->last_untrusted; i++) {
533 X509 *x = sk_X509_value(ctx->chain, i);
David Benjamin260a10c2022-06-16 13:58:28 -0400534 if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) &&
535 (x->ex_flags & EXFLAG_CRITICAL)) {
536 ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION;
537 ctx->error_depth = i;
538 ctx->current_cert = x;
539 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400540 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400541 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400542 }
David Benjamin260a10c2022-06-16 13:58:28 -0400543 }
Adam Langley95c29f32014-06-20 12:00:00 -0700544
David Benjaminca1690e2023-02-14 16:07:45 -0500545 int must_be_ca = i > 0;
546 if (must_be_ca && !X509_check_ca(x)) {
547 ctx->error = X509_V_ERR_INVALID_CA;
David Benjamin260a10c2022-06-16 13:58:28 -0400548 ctx->error_depth = i;
549 ctx->current_cert = x;
550 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400551 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400552 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400553 }
David Benjamin260a10c2022-06-16 13:58:28 -0400554 }
David Benjaminca1690e2023-02-14 16:07:45 -0500555 if (ctx->param->purpose > 0 &&
556 X509_check_purpose(x, purpose, must_be_ca) != 1) {
557 ctx->error = X509_V_ERR_INVALID_PURPOSE;
558 ctx->error_depth = i;
559 ctx->current_cert = x;
560 ok = ctx->verify_cb(0, ctx);
561 if (!ok) {
562 goto end;
David Benjamin260a10c2022-06-16 13:58:28 -0400563 }
564 }
David Benjamin46350482022-06-16 14:03:12 -0400565 // Check pathlen if not self issued
David Benjaminca1690e2023-02-14 16:07:45 -0500566 if (i > 1 && !(x->ex_flags & EXFLAG_SI) && x->ex_pathlen != -1 &&
567 plen > x->ex_pathlen + 1) {
David Benjamin260a10c2022-06-16 13:58:28 -0400568 ctx->error = X509_V_ERR_PATH_LENGTH_EXCEEDED;
569 ctx->error_depth = i;
570 ctx->current_cert = x;
571 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400572 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400573 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -0400574 }
David Benjamin260a10c2022-06-16 13:58:28 -0400575 }
David Benjamin46350482022-06-16 14:03:12 -0400576 // Increment path length if not self issued
David Benjaminc0b87a02022-06-16 14:02:15 -0400577 if (!(x->ex_flags & EXFLAG_SI)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400578 plen++;
David Benjaminc0b87a02022-06-16 14:02:15 -0400579 }
David Benjamin260a10c2022-06-16 13:58:28 -0400580 }
581 ok = 1;
582end:
583 return ok;
584}
585
586static int reject_dns_name_in_common_name(X509 *x509) {
David Benjaminb6f47e82022-07-09 00:57:54 -0400587 const X509_NAME *name = X509_get_subject_name(x509);
David Benjamin260a10c2022-06-16 13:58:28 -0400588 int i = -1;
589 for (;;) {
590 i = X509_NAME_get_index_by_NID(name, NID_commonName, i);
591 if (i == -1) {
592 return X509_V_OK;
593 }
594
David Benjaminb6f47e82022-07-09 00:57:54 -0400595 const X509_NAME_ENTRY *entry = X509_NAME_get_entry(name, i);
596 const ASN1_STRING *common_name = X509_NAME_ENTRY_get_data(entry);
David Benjamin260a10c2022-06-16 13:58:28 -0400597 unsigned char *idval;
598 int idlen = ASN1_STRING_to_UTF8(&idval, common_name);
599 if (idlen < 0) {
600 return X509_V_ERR_OUT_OF_MEM;
601 }
David Benjamin46350482022-06-16 14:03:12 -0400602 // Only process attributes that look like host names. Note it is
603 // important that this check be mirrored in |X509_check_host|.
David Benjamin260a10c2022-06-16 13:58:28 -0400604 int looks_like_dns = x509v3_looks_like_dns_name(idval, (size_t)idlen);
605 OPENSSL_free(idval);
606 if (looks_like_dns) {
607 return X509_V_ERR_NAME_CONSTRAINTS_WITHOUT_SANS;
608 }
609 }
610}
611
612static int check_name_constraints(X509_STORE_CTX *ctx) {
613 int i, j, rv;
614 int has_name_constraints = 0;
David Benjamin46350482022-06-16 14:03:12 -0400615 // Check name constraints for all certificates
David Benjamin89a62532023-05-23 11:45:10 -0400616 for (i = (int)sk_X509_num(ctx->chain) - 1; i >= 0; i--) {
David Benjamin260a10c2022-06-16 13:58:28 -0400617 X509 *x = sk_X509_value(ctx->chain, i);
David Benjamin46350482022-06-16 14:03:12 -0400618 // Ignore self issued certs unless last in chain
David Benjaminc0b87a02022-06-16 14:02:15 -0400619 if (i && (x->ex_flags & EXFLAG_SI)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400620 continue;
David Benjaminc0b87a02022-06-16 14:02:15 -0400621 }
David Benjamin46350482022-06-16 14:03:12 -0400622 // Check against constraints for all certificates higher in chain
623 // including trust anchor. Trust anchor not strictly speaking needed
624 // but if it includes constraints it is to be assumed it expects them
625 // to be obeyed.
David Benjamin89a62532023-05-23 11:45:10 -0400626 for (j = (int)sk_X509_num(ctx->chain) - 1; j > i; j--) {
David Benjamin260a10c2022-06-16 13:58:28 -0400627 NAME_CONSTRAINTS *nc = sk_X509_value(ctx->chain, j)->nc;
628 if (nc) {
629 has_name_constraints = 1;
630 rv = NAME_CONSTRAINTS_check(x, nc);
631 switch (rv) {
632 case X509_V_OK:
633 continue;
634 case X509_V_ERR_OUT_OF_MEM:
635 ctx->error = rv;
636 return 0;
637 default:
638 ctx->error = rv;
639 ctx->error_depth = i;
640 ctx->current_cert = x;
David Benjaminc0b87a02022-06-16 14:02:15 -0400641 if (!ctx->verify_cb(0, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400642 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400643 }
David Benjamin260a10c2022-06-16 13:58:28 -0400644 break;
645 }
646 }
647 }
648 }
649
David Benjamin46350482022-06-16 14:03:12 -0400650 // Name constraints do not match against the common name, but
651 // |X509_check_host| still implements the legacy behavior where, on
652 // certificates lacking a SAN list, DNS-like names in the common name are
653 // checked instead.
654 //
655 // While we could apply the name constraints to the common name, name
656 // constraints are rare enough that can hold such certificates to a higher
657 // standard. Note this does not make "DNS-like" heuristic failures any
658 // worse. A decorative common-name misidentified as a DNS name would fail
659 // the name constraint anyway.
David Benjamin260a10c2022-06-16 13:58:28 -0400660 X509 *leaf = sk_X509_value(ctx->chain, 0);
661 if (has_name_constraints && leaf->altname == NULL) {
662 rv = reject_dns_name_in_common_name(leaf);
663 switch (rv) {
664 case X509_V_OK:
665 break;
666 case X509_V_ERR_OUT_OF_MEM:
667 ctx->error = rv;
668 return 0;
669 default:
670 ctx->error = rv;
671 ctx->error_depth = i;
672 ctx->current_cert = leaf;
David Benjaminc0b87a02022-06-16 14:02:15 -0400673 if (!ctx->verify_cb(0, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400674 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400675 }
David Benjamin260a10c2022-06-16 13:58:28 -0400676 break;
677 }
678 }
679
680 return 1;
681}
682
683static int check_id_error(X509_STORE_CTX *ctx, int errcode) {
684 ctx->error = errcode;
685 ctx->current_cert = ctx->cert;
686 ctx->error_depth = 0;
687 return ctx->verify_cb(0, ctx);
688}
689
690static int check_hosts(X509 *x, X509_VERIFY_PARAM *param) {
691 size_t i;
692 size_t n = sk_OPENSSL_STRING_num(param->hosts);
693 char *name;
694
695 if (param->peername != NULL) {
696 OPENSSL_free(param->peername);
697 param->peername = NULL;
698 }
699 for (i = 0; i < n; ++i) {
700 name = sk_OPENSSL_STRING_value(param->hosts, i);
701 if (X509_check_host(x, name, strlen(name), param->hostflags,
David Benjaminc0b87a02022-06-16 14:02:15 -0400702 &param->peername) > 0) {
David Benjamin260a10c2022-06-16 13:58:28 -0400703 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -0400704 }
David Benjamin260a10c2022-06-16 13:58:28 -0400705 }
706 return n == 0;
707}
708
709static int check_id(X509_STORE_CTX *ctx) {
710 X509_VERIFY_PARAM *vpm = ctx->param;
711 X509 *x = ctx->cert;
712 if (vpm->poison) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400713 if (!check_id_error(ctx, X509_V_ERR_INVALID_CALL)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400714 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400715 }
David Benjamin260a10c2022-06-16 13:58:28 -0400716 }
717 if (vpm->hosts && check_hosts(x, vpm) <= 0) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400718 if (!check_id_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400719 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400720 }
David Benjamin260a10c2022-06-16 13:58:28 -0400721 }
722 if (vpm->email && X509_check_email(x, vpm->email, vpm->emaillen, 0) <= 0) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400723 if (!check_id_error(ctx, X509_V_ERR_EMAIL_MISMATCH)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400724 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400725 }
David Benjamin260a10c2022-06-16 13:58:28 -0400726 }
727 if (vpm->ip && X509_check_ip(x, vpm->ip, vpm->iplen, 0) <= 0) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400728 if (!check_id_error(ctx, X509_V_ERR_IP_ADDRESS_MISMATCH)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400729 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400730 }
David Benjamin260a10c2022-06-16 13:58:28 -0400731 }
732 return 1;
733}
734
735static int check_trust(X509_STORE_CTX *ctx) {
David Benjamin260a10c2022-06-16 13:58:28 -0400736 int ok;
737 X509 *x = NULL;
David Benjamin46350482022-06-16 14:03:12 -0400738 // Check all trusted certificates in chain
David Benjamin89a62532023-05-23 11:45:10 -0400739 for (size_t i = ctx->last_untrusted; i < sk_X509_num(ctx->chain); i++) {
David Benjamin260a10c2022-06-16 13:58:28 -0400740 x = sk_X509_value(ctx->chain, i);
741 ok = X509_check_trust(x, ctx->param->trust, 0);
David Benjamin46350482022-06-16 14:03:12 -0400742 // If explicitly trusted return trusted
David Benjaminc0b87a02022-06-16 14:02:15 -0400743 if (ok == X509_TRUST_TRUSTED) {
David Benjamin260a10c2022-06-16 13:58:28 -0400744 return X509_TRUST_TRUSTED;
David Benjaminc0b87a02022-06-16 14:02:15 -0400745 }
David Benjamin46350482022-06-16 14:03:12 -0400746 // If explicitly rejected notify callback and reject if not
747 // overridden.
David Benjamin260a10c2022-06-16 13:58:28 -0400748 if (ok == X509_TRUST_REJECTED) {
David Benjamin89a62532023-05-23 11:45:10 -0400749 ctx->error_depth = (int)i;
David Benjamin260a10c2022-06-16 13:58:28 -0400750 ctx->current_cert = x;
751 ctx->error = X509_V_ERR_CERT_REJECTED;
752 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400753 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400754 return X509_TRUST_REJECTED;
David Benjaminc0b87a02022-06-16 14:02:15 -0400755 }
David Benjamin260a10c2022-06-16 13:58:28 -0400756 }
757 }
David Benjamin46350482022-06-16 14:03:12 -0400758 // If we accept partial chains and have at least one trusted certificate
759 // return success.
David Benjamin260a10c2022-06-16 13:58:28 -0400760 if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
761 X509 *mx;
David Benjaminc0b87a02022-06-16 14:02:15 -0400762 if (ctx->last_untrusted < (int)sk_X509_num(ctx->chain)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400763 return X509_TRUST_TRUSTED;
David Benjaminc0b87a02022-06-16 14:02:15 -0400764 }
David Benjamin260a10c2022-06-16 13:58:28 -0400765 x = sk_X509_value(ctx->chain, 0);
766 mx = lookup_cert_match(ctx, x);
767 if (mx) {
768 (void)sk_X509_set(ctx->chain, 0, mx);
769 X509_free(x);
770 ctx->last_untrusted = 0;
771 return X509_TRUST_TRUSTED;
772 }
773 }
774
David Benjamin46350482022-06-16 14:03:12 -0400775 // If no trusted certs in chain at all return untrusted and allow
776 // standard (no issuer cert) etc errors to be indicated.
David Benjamin260a10c2022-06-16 13:58:28 -0400777 return X509_TRUST_UNTRUSTED;
778}
779
780static int check_revocation(X509_STORE_CTX *ctx) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400781 if (!(ctx->param->flags & X509_V_FLAG_CRL_CHECK)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400782 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -0400783 }
David Benjamin89a62532023-05-23 11:45:10 -0400784 int last;
David Benjaminc0b87a02022-06-16 14:02:15 -0400785 if (ctx->param->flags & X509_V_FLAG_CRL_CHECK_ALL) {
David Benjamin89a62532023-05-23 11:45:10 -0400786 last = (int)sk_X509_num(ctx->chain) - 1;
David Benjaminc0b87a02022-06-16 14:02:15 -0400787 } else {
David Benjamin260a10c2022-06-16 13:58:28 -0400788 last = 0;
789 }
David Benjamin89a62532023-05-23 11:45:10 -0400790 for (int i = 0; i <= last; i++) {
David Benjamin260a10c2022-06-16 13:58:28 -0400791 ctx->error_depth = i;
David Benjamin89a62532023-05-23 11:45:10 -0400792 int ok = check_cert(ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -0400793 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -0400794 return ok;
David Benjaminc0b87a02022-06-16 14:02:15 -0400795 }
David Benjamin260a10c2022-06-16 13:58:28 -0400796 }
797 return 1;
798}
799
800static int check_cert(X509_STORE_CTX *ctx) {
David Benjamind9a58a12023-11-12 14:04:00 -0500801 X509_CRL *crl = NULL;
David Benjamin8cae3d02023-11-12 14:42:35 -0500802 int ok = 0, cnum = ctx->error_depth;
803 X509 *x = sk_X509_value(ctx->chain, cnum);
David Benjamin260a10c2022-06-16 13:58:28 -0400804 ctx->current_cert = x;
805 ctx->current_issuer = NULL;
806 ctx->current_crl_score = 0;
David Benjamin260a10c2022-06-16 13:58:28 -0400807
David Benjamin8cae3d02023-11-12 14:42:35 -0500808 // Try to retrieve relevant CRL
809 if (ctx->get_crl) {
810 ok = ctx->get_crl(ctx, &crl, x);
811 } else {
812 ok = get_crl(ctx, &crl, x);
813 }
814 // If error looking up CRL, nothing we can do except notify callback
815 if (!ok) {
816 ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL;
817 ok = ctx->verify_cb(0, ctx);
818 goto err;
819 }
820 ctx->current_crl = crl;
821 ok = ctx->check_crl(ctx, crl);
822 if (!ok) {
823 goto err;
824 }
David Benjamin260a10c2022-06-16 13:58:28 -0400825
David Benjamin998f5112023-11-19 10:04:06 -0500826 ok = cert_crl(ctx, crl, x);
David Benjamin8cae3d02023-11-12 14:42:35 -0500827 if (!ok) {
828 goto err;
David Benjamin260a10c2022-06-16 13:58:28 -0400829 }
David Benjamind9a58a12023-11-12 14:04:00 -0500830
David Benjamin260a10c2022-06-16 13:58:28 -0400831err:
832 X509_CRL_free(crl);
David Benjamin260a10c2022-06-16 13:58:28 -0400833 ctx->current_crl = NULL;
834 return ok;
Adam Langley57707c72016-01-14 11:25:12 -0800835}
Adam Langley95c29f32014-06-20 12:00:00 -0700836
David Benjamin46350482022-06-16 14:03:12 -0400837// Check CRL times against values in X509_STORE_CTX
David Benjamin260a10c2022-06-16 13:58:28 -0400838static int check_crl_time(X509_STORE_CTX *ctx, X509_CRL *crl, int notify) {
David Benjamineccd1032022-08-12 15:12:29 -0400839 if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) {
840 return 1;
841 }
842
David Benjaminc0b87a02022-06-16 14:02:15 -0400843 if (notify) {
David Benjamin260a10c2022-06-16 13:58:28 -0400844 ctx->current_crl = crl;
David Benjaminc0b87a02022-06-16 14:02:15 -0400845 }
Bob Beck6e20b772023-02-08 11:32:19 -0700846 int64_t ptime;
David Benjaminc0b87a02022-06-16 14:02:15 -0400847 if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) {
Bob Beck6e20b772023-02-08 11:32:19 -0700848 ptime = ctx->param->check_time;
David Benjaminc0b87a02022-06-16 14:02:15 -0400849 } else {
Bob Beck6e20b772023-02-08 11:32:19 -0700850 ptime = time(NULL);
David Benjaminc0b87a02022-06-16 14:02:15 -0400851 }
Adam Langley95c29f32014-06-20 12:00:00 -0700852
Bob Beck6e20b772023-02-08 11:32:19 -0700853 int i = X509_cmp_time_posix(X509_CRL_get0_lastUpdate(crl), ptime);
David Benjamin260a10c2022-06-16 13:58:28 -0400854 if (i == 0) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400855 if (!notify) {
David Benjamin260a10c2022-06-16 13:58:28 -0400856 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400857 }
David Benjamin260a10c2022-06-16 13:58:28 -0400858 ctx->error = X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD;
David Benjaminc0b87a02022-06-16 14:02:15 -0400859 if (!ctx->verify_cb(0, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400860 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400861 }
David Benjamin260a10c2022-06-16 13:58:28 -0400862 }
863
864 if (i > 0) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400865 if (!notify) {
David Benjamin260a10c2022-06-16 13:58:28 -0400866 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400867 }
David Benjamin260a10c2022-06-16 13:58:28 -0400868 ctx->error = X509_V_ERR_CRL_NOT_YET_VALID;
David Benjaminc0b87a02022-06-16 14:02:15 -0400869 if (!ctx->verify_cb(0, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400870 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400871 }
David Benjamin260a10c2022-06-16 13:58:28 -0400872 }
873
874 if (X509_CRL_get0_nextUpdate(crl)) {
Bob Beck6e20b772023-02-08 11:32:19 -0700875 i = X509_cmp_time_posix(X509_CRL_get0_nextUpdate(crl), ptime);
David Benjamin260a10c2022-06-16 13:58:28 -0400876
Adam Langley57707c72016-01-14 11:25:12 -0800877 if (i == 0) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400878 if (!notify) {
David Benjamin260a10c2022-06-16 13:58:28 -0400879 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400880 }
David Benjamin260a10c2022-06-16 13:58:28 -0400881 ctx->error = X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD;
David Benjaminc0b87a02022-06-16 14:02:15 -0400882 if (!ctx->verify_cb(0, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400883 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400884 }
Adam Langley57707c72016-01-14 11:25:12 -0800885 }
David Benjamin9bed3732023-11-12 14:51:23 -0500886 if (i < 0) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400887 if (!notify) {
David Benjamin260a10c2022-06-16 13:58:28 -0400888 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400889 }
David Benjamin260a10c2022-06-16 13:58:28 -0400890 ctx->error = X509_V_ERR_CRL_HAS_EXPIRED;
David Benjaminc0b87a02022-06-16 14:02:15 -0400891 if (!ctx->verify_cb(0, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400892 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400893 }
Adam Langley57707c72016-01-14 11:25:12 -0800894 }
David Benjamin260a10c2022-06-16 13:58:28 -0400895 }
Adam Langley95c29f32014-06-20 12:00:00 -0700896
David Benjaminc0b87a02022-06-16 14:02:15 -0400897 if (notify) {
David Benjamin260a10c2022-06-16 13:58:28 -0400898 ctx->current_crl = NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400899 }
Adam Langley95c29f32014-06-20 12:00:00 -0700900
David Benjamin260a10c2022-06-16 13:58:28 -0400901 return 1;
Adam Langley57707c72016-01-14 11:25:12 -0800902}
Adam Langley95c29f32014-06-20 12:00:00 -0700903
David Benjamind9a58a12023-11-12 14:04:00 -0500904static int get_crl_sk(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 **pissuer,
David Benjamin580c0412023-11-12 14:28:51 -0500905 int *pscore, STACK_OF(X509_CRL) *crls) {
David Benjamin260a10c2022-06-16 13:58:28 -0400906 int crl_score, best_score = *pscore;
David Benjamin260a10c2022-06-16 13:58:28 -0400907 X509 *x = ctx->current_cert;
David Benjamind9a58a12023-11-12 14:04:00 -0500908 X509_CRL *best_crl = NULL;
David Benjamin260a10c2022-06-16 13:58:28 -0400909 X509 *crl_issuer = NULL, *best_crl_issuer = NULL;
Adam Langley95c29f32014-06-20 12:00:00 -0700910
David Benjamind9a58a12023-11-12 14:04:00 -0500911 for (size_t i = 0; i < sk_X509_CRL_num(crls); i++) {
912 X509_CRL *crl = sk_X509_CRL_value(crls, i);
David Benjamin580c0412023-11-12 14:28:51 -0500913 crl_score = get_crl_score(ctx, &crl_issuer, crl, x);
David Benjaminc0b87a02022-06-16 14:02:15 -0400914 if (crl_score < best_score || crl_score == 0) {
David Benjamin260a10c2022-06-16 13:58:28 -0400915 continue;
David Benjaminc0b87a02022-06-16 14:02:15 -0400916 }
David Benjamin46350482022-06-16 14:03:12 -0400917 // If current CRL is equivalent use it if it is newer
David Benjamin260a10c2022-06-16 13:58:28 -0400918 if (crl_score == best_score && best_crl != NULL) {
919 int day, sec;
920 if (ASN1_TIME_diff(&day, &sec, X509_CRL_get0_lastUpdate(best_crl),
David Benjaminc0b87a02022-06-16 14:02:15 -0400921 X509_CRL_get0_lastUpdate(crl)) == 0) {
David Benjamin260a10c2022-06-16 13:58:28 -0400922 continue;
David Benjaminc0b87a02022-06-16 14:02:15 -0400923 }
David Benjamin46350482022-06-16 14:03:12 -0400924 // ASN1_TIME_diff never returns inconsistent signs for |day|
925 // and |sec|.
David Benjaminc0b87a02022-06-16 14:02:15 -0400926 if (day <= 0 && sec <= 0) {
David Benjamin260a10c2022-06-16 13:58:28 -0400927 continue;
David Benjaminc0b87a02022-06-16 14:02:15 -0400928 }
Adam Langley57707c72016-01-14 11:25:12 -0800929 }
David Benjamin260a10c2022-06-16 13:58:28 -0400930 best_crl = crl;
931 best_crl_issuer = crl_issuer;
932 best_score = crl_score;
David Benjamin260a10c2022-06-16 13:58:28 -0400933 }
Adam Langley95c29f32014-06-20 12:00:00 -0700934
David Benjamin260a10c2022-06-16 13:58:28 -0400935 if (best_crl) {
David Benjaminc0b87a02022-06-16 14:02:15 -0400936 if (*pcrl) {
David Benjamin260a10c2022-06-16 13:58:28 -0400937 X509_CRL_free(*pcrl);
David Benjaminc0b87a02022-06-16 14:02:15 -0400938 }
David Benjamin260a10c2022-06-16 13:58:28 -0400939 *pcrl = best_crl;
940 *pissuer = best_crl_issuer;
941 *pscore = best_score;
David Benjamin260a10c2022-06-16 13:58:28 -0400942 X509_CRL_up_ref(best_crl);
David Benjamin260a10c2022-06-16 13:58:28 -0400943 }
Adam Langley95c29f32014-06-20 12:00:00 -0700944
David Benjaminc0b87a02022-06-16 14:02:15 -0400945 if (best_score >= CRL_SCORE_VALID) {
David Benjamin260a10c2022-06-16 13:58:28 -0400946 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -0400947 }
Adam Langley95c29f32014-06-20 12:00:00 -0700948
David Benjamin260a10c2022-06-16 13:58:28 -0400949 return 0;
Adam Langley57707c72016-01-14 11:25:12 -0800950}
Adam Langley95c29f32014-06-20 12:00:00 -0700951
David Benjamin46350482022-06-16 14:03:12 -0400952// For a given CRL return how suitable it is for the supplied certificate
953// 'x'. The return value is a mask of several criteria. If the issuer is not
David Benjamin580c0412023-11-12 14:28:51 -0500954// the certificate issuer this is returned in *pissuer.
955static int get_crl_score(X509_STORE_CTX *ctx, X509 **pissuer, X509_CRL *crl,
956 X509 *x) {
David Benjamin260a10c2022-06-16 13:58:28 -0400957 int crl_score = 0;
Adam Langley95c29f32014-06-20 12:00:00 -0700958
David Benjamin46350482022-06-16 14:03:12 -0400959 // First see if we can reject CRL straight away
Adam Langley95c29f32014-06-20 12:00:00 -0700960
David Benjamin46350482022-06-16 14:03:12 -0400961 // Invalid IDP cannot be processed
David Benjaminc0b87a02022-06-16 14:02:15 -0400962 if (crl->idp_flags & IDP_INVALID) {
David Benjamin260a10c2022-06-16 13:58:28 -0400963 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400964 }
David Benjaminf8614992023-11-12 13:43:33 -0500965 // Reason codes and indirect CRLs are not supported.
966 if (crl->idp_flags & (IDP_INDIRECT | IDP_REASONS)) {
967 return 0;
David Benjamin260a10c2022-06-16 13:58:28 -0400968 }
David Benjamin54eaf6b2023-11-12 15:00:31 -0500969 // We do not support indirect CRLs, so the issuer names must match.
David Benjamin260a10c2022-06-16 13:58:28 -0400970 if (X509_NAME_cmp(X509_get_issuer_name(x), X509_CRL_get_issuer(crl))) {
David Benjamin54eaf6b2023-11-12 15:00:31 -0500971 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400972 }
David Benjamin54eaf6b2023-11-12 15:00:31 -0500973 crl_score |= CRL_SCORE_ISSUER_NAME;
Adam Langley95c29f32014-06-20 12:00:00 -0700974
David Benjaminc0b87a02022-06-16 14:02:15 -0400975 if (!(crl->flags & EXFLAG_CRITICAL)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400976 crl_score |= CRL_SCORE_NOCRITICAL;
David Benjaminc0b87a02022-06-16 14:02:15 -0400977 }
Adam Langley95c29f32014-06-20 12:00:00 -0700978
David Benjamin46350482022-06-16 14:03:12 -0400979 // Check expiry
David Benjaminc0b87a02022-06-16 14:02:15 -0400980 if (check_crl_time(ctx, crl, 0)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400981 crl_score |= CRL_SCORE_TIME;
David Benjaminc0b87a02022-06-16 14:02:15 -0400982 }
Adam Langley95c29f32014-06-20 12:00:00 -0700983
David Benjamin46350482022-06-16 14:03:12 -0400984 // Check authority key ID and locate certificate issuer
David Benjamina4851dd2023-11-12 15:51:49 -0500985 if (!crl_akid_check(ctx, crl, pissuer, &crl_score)) {
986 // If we can't locate certificate issuer at this point forget it
David Benjamin260a10c2022-06-16 13:58:28 -0400987 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -0400988 }
Adam Langley95c29f32014-06-20 12:00:00 -0700989
David Benjamin46350482022-06-16 14:03:12 -0400990 // Check cert for matching CRL distribution points
David Benjamin580c0412023-11-12 14:28:51 -0500991 if (crl_crldp_check(x, crl, crl_score)) {
David Benjamin260a10c2022-06-16 13:58:28 -0400992 crl_score |= CRL_SCORE_SCOPE;
993 }
Adam Langley95c29f32014-06-20 12:00:00 -0700994
David Benjamin260a10c2022-06-16 13:58:28 -0400995 return crl_score;
Adam Langley57707c72016-01-14 11:25:12 -0800996}
Adam Langley95c29f32014-06-20 12:00:00 -0700997
David Benjamina4851dd2023-11-12 15:51:49 -0500998static int crl_akid_check(X509_STORE_CTX *ctx, X509_CRL *crl, X509 **pissuer,
999 int *pcrl_score) {
David Benjamin260a10c2022-06-16 13:58:28 -04001000 X509 *crl_issuer = NULL;
1001 X509_NAME *cnm = X509_CRL_get_issuer(crl);
1002 int cidx = ctx->error_depth;
Adam Langley95c29f32014-06-20 12:00:00 -07001003
David Benjaminc0b87a02022-06-16 14:02:15 -04001004 if ((size_t)cidx != sk_X509_num(ctx->chain) - 1) {
David Benjamin260a10c2022-06-16 13:58:28 -04001005 cidx++;
David Benjaminc0b87a02022-06-16 14:02:15 -04001006 }
Adam Langley95c29f32014-06-20 12:00:00 -07001007
David Benjamin260a10c2022-06-16 13:58:28 -04001008 crl_issuer = sk_X509_value(ctx->chain, cidx);
1009
1010 if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
David Benjamin54eaf6b2023-11-12 15:00:31 -05001011 *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_ISSUER_CERT;
1012 *pissuer = crl_issuer;
David Benjamina4851dd2023-11-12 15:51:49 -05001013 return 1;
David Benjamin260a10c2022-06-16 13:58:28 -04001014 }
1015
1016 for (cidx++; cidx < (int)sk_X509_num(ctx->chain); cidx++) {
Adam Langley57707c72016-01-14 11:25:12 -08001017 crl_issuer = sk_X509_value(ctx->chain, cidx);
David Benjaminc0b87a02022-06-16 14:02:15 -04001018 if (X509_NAME_cmp(X509_get_subject_name(crl_issuer), cnm)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001019 continue;
David Benjaminc0b87a02022-06-16 14:02:15 -04001020 }
Adam Langley57707c72016-01-14 11:25:12 -08001021 if (X509_check_akid(crl_issuer, crl->akid) == X509_V_OK) {
David Benjamin260a10c2022-06-16 13:58:28 -04001022 *pcrl_score |= CRL_SCORE_AKID | CRL_SCORE_SAME_PATH;
1023 *pissuer = crl_issuer;
David Benjamina4851dd2023-11-12 15:51:49 -05001024 return 1;
Adam Langley57707c72016-01-14 11:25:12 -08001025 }
David Benjamin260a10c2022-06-16 13:58:28 -04001026 }
Adam Langley95c29f32014-06-20 12:00:00 -07001027
David Benjamin260a10c2022-06-16 13:58:28 -04001028 return 0;
Adam Langley57707c72016-01-14 11:25:12 -08001029}
Adam Langley95c29f32014-06-20 12:00:00 -07001030
David Benjamin46350482022-06-16 14:03:12 -04001031// Check for match between two dist point names: three separate cases. 1.
1032// Both are relative names and compare X509_NAME types. 2. One full, one
1033// relative. Compare X509_NAME to GENERAL_NAMES. 3. Both are full names and
1034// compare two GENERAL_NAMES. 4. One is NULL: automatic match.
David Benjamin260a10c2022-06-16 13:58:28 -04001035static int idp_check_dp(DIST_POINT_NAME *a, DIST_POINT_NAME *b) {
1036 X509_NAME *nm = NULL;
1037 GENERAL_NAMES *gens = NULL;
1038 GENERAL_NAME *gena, *genb;
1039 size_t i, j;
David Benjaminc0b87a02022-06-16 14:02:15 -04001040 if (!a || !b) {
David Benjamin260a10c2022-06-16 13:58:28 -04001041 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -04001042 }
David Benjamin260a10c2022-06-16 13:58:28 -04001043 if (a->type == 1) {
David Benjaminc0b87a02022-06-16 14:02:15 -04001044 if (!a->dpname) {
David Benjamin260a10c2022-06-16 13:58:28 -04001045 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001046 }
David Benjamin46350482022-06-16 14:03:12 -04001047 // Case 1: two X509_NAME
David Benjamin260a10c2022-06-16 13:58:28 -04001048 if (b->type == 1) {
David Benjaminc0b87a02022-06-16 14:02:15 -04001049 if (!b->dpname) {
David Benjamin260a10c2022-06-16 13:58:28 -04001050 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001051 }
1052 if (!X509_NAME_cmp(a->dpname, b->dpname)) {
Adam Langley57707c72016-01-14 11:25:12 -08001053 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -04001054 } else {
Adam Langley57707c72016-01-14 11:25:12 -08001055 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001056 }
Adam Langley57707c72016-01-14 11:25:12 -08001057 }
David Benjamin46350482022-06-16 14:03:12 -04001058 // Case 2: set name and GENERAL_NAMES appropriately
David Benjamin260a10c2022-06-16 13:58:28 -04001059 nm = a->dpname;
1060 gens = b->name.fullname;
1061 } else if (b->type == 1) {
David Benjaminc0b87a02022-06-16 14:02:15 -04001062 if (!b->dpname) {
David Benjamin260a10c2022-06-16 13:58:28 -04001063 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001064 }
David Benjamin46350482022-06-16 14:03:12 -04001065 // Case 2: set name and GENERAL_NAMES appropriately
David Benjamin260a10c2022-06-16 13:58:28 -04001066 gens = a->name.fullname;
1067 nm = b->dpname;
1068 }
Adam Langley95c29f32014-06-20 12:00:00 -07001069
David Benjamin46350482022-06-16 14:03:12 -04001070 // Handle case 2 with one GENERAL_NAMES and one X509_NAME
David Benjamin260a10c2022-06-16 13:58:28 -04001071 if (nm) {
1072 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
1073 gena = sk_GENERAL_NAME_value(gens, i);
David Benjaminc0b87a02022-06-16 14:02:15 -04001074 if (gena->type != GEN_DIRNAME) {
David Benjamin260a10c2022-06-16 13:58:28 -04001075 continue;
David Benjaminc0b87a02022-06-16 14:02:15 -04001076 }
1077 if (!X509_NAME_cmp(nm, gena->d.directoryName)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001078 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -04001079 }
Adam Langley57707c72016-01-14 11:25:12 -08001080 }
Adam Langley57707c72016-01-14 11:25:12 -08001081 return 0;
David Benjamin260a10c2022-06-16 13:58:28 -04001082 }
Adam Langley95c29f32014-06-20 12:00:00 -07001083
David Benjamin46350482022-06-16 14:03:12 -04001084 // Else case 3: two GENERAL_NAMES
David Benjamin260a10c2022-06-16 13:58:28 -04001085
1086 for (i = 0; i < sk_GENERAL_NAME_num(a->name.fullname); i++) {
1087 gena = sk_GENERAL_NAME_value(a->name.fullname, i);
1088 for (j = 0; j < sk_GENERAL_NAME_num(b->name.fullname); j++) {
1089 genb = sk_GENERAL_NAME_value(b->name.fullname, j);
David Benjaminc0b87a02022-06-16 14:02:15 -04001090 if (!GENERAL_NAME_cmp(gena, genb)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001091 return 1;
David Benjaminc0b87a02022-06-16 14:02:15 -04001092 }
David Benjamin260a10c2022-06-16 13:58:28 -04001093 }
1094 }
1095
1096 return 0;
Adam Langley57707c72016-01-14 11:25:12 -08001097}
Adam Langley95c29f32014-06-20 12:00:00 -07001098
David Benjamin46350482022-06-16 14:03:12 -04001099// Check CRLDP and IDP
David Benjamin580c0412023-11-12 14:28:51 -05001100static int crl_crldp_check(X509 *x, X509_CRL *crl, int crl_score) {
David Benjaminc0b87a02022-06-16 14:02:15 -04001101 if (crl->idp_flags & IDP_ONLYATTR) {
Adam Langley57707c72016-01-14 11:25:12 -08001102 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001103 }
David Benjamin260a10c2022-06-16 13:58:28 -04001104 if (x->ex_flags & EXFLAG_CA) {
David Benjaminc0b87a02022-06-16 14:02:15 -04001105 if (crl->idp_flags & IDP_ONLYUSER) {
David Benjamin260a10c2022-06-16 13:58:28 -04001106 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001107 }
David Benjamin260a10c2022-06-16 13:58:28 -04001108 } else {
David Benjaminc0b87a02022-06-16 14:02:15 -04001109 if (crl->idp_flags & IDP_ONLYCA) {
David Benjamin260a10c2022-06-16 13:58:28 -04001110 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001111 }
David Benjamin260a10c2022-06-16 13:58:28 -04001112 }
David Benjamin580c0412023-11-12 14:28:51 -05001113 for (size_t i = 0; i < sk_DIST_POINT_num(x->crldp); i++) {
David Benjamin260a10c2022-06-16 13:58:28 -04001114 DIST_POINT *dp = sk_DIST_POINT_value(x->crldp, i);
David Benjamin54eaf6b2023-11-12 15:00:31 -05001115 // Skip distribution points with a reasons field or a CRL issuer:
1116 //
1117 // We do not support CRLs partitioned by reason code. RFC 5280 requires CAs
1118 // include at least one DistributionPoint that covers all reasons.
1119 //
1120 // We also do not support indirect CRLs, and a CRL issuer can only match
1121 // indirect CRLs (RFC 5280, section 6.3.3, step b.1).
1122 // support.
1123 if (dp->reasons != NULL && dp->CRLissuer != NULL &&
David Benjamin580c0412023-11-12 14:28:51 -05001124 (!crl->idp || idp_check_dp(dp->distpoint, crl->idp->distpoint))) {
1125 return 1;
David Benjamin260a10c2022-06-16 13:58:28 -04001126 }
1127 }
David Benjamin54eaf6b2023-11-12 15:00:31 -05001128
1129 // If the CRL does not specify an issuing distribution point, allow it to
1130 // match anything.
1131 //
1132 // TODO(davidben): Does this match RFC 5280? It's hard to follow because RFC
1133 // 5280 starts from distribution points, while this starts from CRLs.
1134 return !crl->idp || !crl->idp->distpoint;
Adam Langley57707c72016-01-14 11:25:12 -08001135}
Adam Langley95c29f32014-06-20 12:00:00 -07001136
David Benjamin0c448132023-11-12 19:33:53 -05001137// Retrieve CRL corresponding to current certificate.
David Benjamind9a58a12023-11-12 14:04:00 -05001138static int get_crl(X509_STORE_CTX *ctx, X509_CRL **pcrl, X509 *x) {
David Benjamin260a10c2022-06-16 13:58:28 -04001139 int ok;
1140 X509 *issuer = NULL;
1141 int crl_score = 0;
David Benjamind9a58a12023-11-12 14:04:00 -05001142 X509_CRL *crl = NULL;
David Benjamin260a10c2022-06-16 13:58:28 -04001143 STACK_OF(X509_CRL) *skcrl;
1144 X509_NAME *nm = X509_get_issuer_name(x);
David Benjamin580c0412023-11-12 14:28:51 -05001145 ok = get_crl_sk(ctx, &crl, &issuer, &crl_score, ctx->crls);
David Benjaminc0b87a02022-06-16 14:02:15 -04001146 if (ok) {
David Benjamin260a10c2022-06-16 13:58:28 -04001147 goto done;
David Benjaminc0b87a02022-06-16 14:02:15 -04001148 }
Adam Langley95c29f32014-06-20 12:00:00 -07001149
David Benjamin46350482022-06-16 14:03:12 -04001150 // Lookup CRLs from store
David Benjamin998f5112023-11-19 10:04:06 -05001151 skcrl = X509_STORE_get1_crls(ctx, nm);
Adam Langley95c29f32014-06-20 12:00:00 -07001152
David Benjamin46350482022-06-16 14:03:12 -04001153 // If no CRLs found and a near match from get_crl_sk use that
David Benjaminc0b87a02022-06-16 14:02:15 -04001154 if (!skcrl && crl) {
David Benjamin260a10c2022-06-16 13:58:28 -04001155 goto done;
David Benjaminc0b87a02022-06-16 14:02:15 -04001156 }
Adam Langley95c29f32014-06-20 12:00:00 -07001157
David Benjamin580c0412023-11-12 14:28:51 -05001158 get_crl_sk(ctx, &crl, &issuer, &crl_score, skcrl);
Adam Langley95c29f32014-06-20 12:00:00 -07001159
David Benjamin260a10c2022-06-16 13:58:28 -04001160 sk_X509_CRL_pop_free(skcrl, X509_CRL_free);
Adam Langley95c29f32014-06-20 12:00:00 -07001161
David Benjamin260a10c2022-06-16 13:58:28 -04001162done:
Adam Langley95c29f32014-06-20 12:00:00 -07001163
David Benjamin46350482022-06-16 14:03:12 -04001164 // If we got any kind of CRL use it and return success
David Benjamin260a10c2022-06-16 13:58:28 -04001165 if (crl) {
1166 ctx->current_issuer = issuer;
1167 ctx->current_crl_score = crl_score;
David Benjamin260a10c2022-06-16 13:58:28 -04001168 *pcrl = crl;
David Benjamin260a10c2022-06-16 13:58:28 -04001169 return 1;
1170 }
Adam Langley95c29f32014-06-20 12:00:00 -07001171
David Benjamin260a10c2022-06-16 13:58:28 -04001172 return 0;
Adam Langley57707c72016-01-14 11:25:12 -08001173}
Adam Langley95c29f32014-06-20 12:00:00 -07001174
David Benjamin46350482022-06-16 14:03:12 -04001175// Check CRL validity
David Benjamin260a10c2022-06-16 13:58:28 -04001176static int check_crl(X509_STORE_CTX *ctx, X509_CRL *crl) {
1177 X509 *issuer = NULL;
1178 EVP_PKEY *ikey = NULL;
David Benjamin89a62532023-05-23 11:45:10 -04001179 int ok = 0;
1180 int cnum = ctx->error_depth;
1181 int chnum = (int)sk_X509_num(ctx->chain) - 1;
David Benjamin46350482022-06-16 14:03:12 -04001182 // if we have an alternative CRL issuer cert use that
David Benjaminc0b87a02022-06-16 14:02:15 -04001183 if (ctx->current_issuer) {
David Benjamin260a10c2022-06-16 13:58:28 -04001184 issuer = ctx->current_issuer;
David Benjaminc0b87a02022-06-16 14:02:15 -04001185 }
Adam Langley95c29f32014-06-20 12:00:00 -07001186
David Benjamin46350482022-06-16 14:03:12 -04001187 // Else find CRL issuer: if not last certificate then issuer is next
1188 // certificate in chain.
David Benjaminc0b87a02022-06-16 14:02:15 -04001189 else if (cnum < chnum) {
David Benjamin260a10c2022-06-16 13:58:28 -04001190 issuer = sk_X509_value(ctx->chain, cnum + 1);
David Benjaminc0b87a02022-06-16 14:02:15 -04001191 } else {
David Benjamin260a10c2022-06-16 13:58:28 -04001192 issuer = sk_X509_value(ctx->chain, chnum);
David Benjamin46350482022-06-16 14:03:12 -04001193 // If not self signed, can't check signature
David Benjamin998f5112023-11-19 10:04:06 -05001194 if (!x509_check_issued_with_callback(ctx, issuer, issuer)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001195 ctx->error = X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER;
1196 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -04001197 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -04001198 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -04001199 }
David Benjamin260a10c2022-06-16 13:58:28 -04001200 }
1201 }
1202
1203 if (issuer) {
David Benjamin0c448132023-11-12 19:33:53 -05001204 // Check for cRLSign bit if keyUsage present
1205 if ((issuer->ex_flags & EXFLAG_KUSAGE) &&
1206 !(issuer->ex_kusage & KU_CRL_SIGN)) {
1207 ctx->error = X509_V_ERR_KEYUSAGE_NO_CRL_SIGN;
1208 ok = ctx->verify_cb(0, ctx);
1209 if (!ok) {
1210 goto err;
1211 }
1212 }
1213
1214 if (!(ctx->current_crl_score & CRL_SCORE_SCOPE)) {
1215 ctx->error = X509_V_ERR_DIFFERENT_CRL_SCOPE;
1216 ok = ctx->verify_cb(0, ctx);
1217 if (!ok) {
1218 goto err;
1219 }
1220 }
1221
David Benjamin0c448132023-11-12 19:33:53 -05001222 if (crl->idp_flags & IDP_INVALID) {
1223 ctx->error = X509_V_ERR_INVALID_EXTENSION;
1224 ok = ctx->verify_cb(0, ctx);
1225 if (!ok) {
1226 goto err;
David Benjamin260a10c2022-06-16 13:58:28 -04001227 }
Adam Langley57707c72016-01-14 11:25:12 -08001228 }
Adam Langley95c29f32014-06-20 12:00:00 -07001229
David Benjamin260a10c2022-06-16 13:58:28 -04001230 if (!(ctx->current_crl_score & CRL_SCORE_TIME)) {
1231 ok = check_crl_time(ctx, crl, 1);
David Benjaminc0b87a02022-06-16 14:02:15 -04001232 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -04001233 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -04001234 }
Adam Langley57707c72016-01-14 11:25:12 -08001235 }
Adam Langley95c29f32014-06-20 12:00:00 -07001236
David Benjamin46350482022-06-16 14:03:12 -04001237 // Attempt to get issuer certificate public key
David Benjamin260a10c2022-06-16 13:58:28 -04001238 ikey = X509_get_pubkey(issuer);
Adam Langley95c29f32014-06-20 12:00:00 -07001239
David Benjamin260a10c2022-06-16 13:58:28 -04001240 if (!ikey) {
1241 ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
1242 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -04001243 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -04001244 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -04001245 }
David Benjamin260a10c2022-06-16 13:58:28 -04001246 } else {
David Benjamin46350482022-06-16 14:03:12 -04001247 // Verify CRL signature
David Benjamin260a10c2022-06-16 13:58:28 -04001248 if (X509_CRL_verify(crl, ikey) <= 0) {
1249 ctx->error = X509_V_ERR_CRL_SIGNATURE_FAILURE;
1250 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -04001251 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -04001252 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -04001253 }
David Benjamin260a10c2022-06-16 13:58:28 -04001254 }
1255 }
1256 }
1257
1258 ok = 1;
1259
1260err:
1261 EVP_PKEY_free(ikey);
1262 return ok;
Adam Langley57707c72016-01-14 11:25:12 -08001263}
Adam Langley95c29f32014-06-20 12:00:00 -07001264
David Benjamin46350482022-06-16 14:03:12 -04001265// Check certificate against CRL
David Benjamin260a10c2022-06-16 13:58:28 -04001266static int cert_crl(X509_STORE_CTX *ctx, X509_CRL *crl, X509 *x) {
1267 int ok;
1268 X509_REVOKED *rev;
David Benjamin46350482022-06-16 14:03:12 -04001269 // The rules changed for this... previously if a CRL contained unhandled
1270 // critical extensions it could still be used to indicate a certificate
1271 // was revoked. This has since been changed since critical extension can
1272 // change the meaning of CRL entries.
David Benjamin260a10c2022-06-16 13:58:28 -04001273 if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) &&
1274 (crl->flags & EXFLAG_CRITICAL)) {
1275 ctx->error = X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION;
1276 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -04001277 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -04001278 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001279 }
David Benjamin260a10c2022-06-16 13:58:28 -04001280 }
David Benjamin9177d652023-11-12 14:05:24 -05001281 // Look for serial number of certificate in CRL.
David Benjamin260a10c2022-06-16 13:58:28 -04001282 if (X509_CRL_get0_by_cert(crl, &rev, x)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001283 ctx->error = X509_V_ERR_CERT_REVOKED;
1284 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -04001285 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -04001286 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001287 }
David Benjamin260a10c2022-06-16 13:58:28 -04001288 }
Adam Langley95c29f32014-06-20 12:00:00 -07001289
David Benjamin260a10c2022-06-16 13:58:28 -04001290 return 1;
Adam Langley57707c72016-01-14 11:25:12 -08001291}
Adam Langley95c29f32014-06-20 12:00:00 -07001292
David Benjamin260a10c2022-06-16 13:58:28 -04001293static int check_policy(X509_STORE_CTX *ctx) {
David Benjamin029d0e72022-12-26 19:38:40 -05001294 X509 *current_cert = NULL;
1295 int ret = X509_policy_check(ctx->chain, ctx->param->policies,
1296 ctx->param->flags, &current_cert);
1297 if (ret != X509_V_OK) {
1298 ctx->current_cert = current_cert;
1299 ctx->error = ret;
1300 if (ret == X509_V_ERR_OUT_OF_MEM) {
1301 return 0;
Adam Langley57707c72016-01-14 11:25:12 -08001302 }
David Benjamin260a10c2022-06-16 13:58:28 -04001303 return ctx->verify_cb(0, ctx);
1304 }
Adam Langley95c29f32014-06-20 12:00:00 -07001305
David Benjamin260a10c2022-06-16 13:58:28 -04001306 if (ctx->param->flags & X509_V_FLAG_NOTIFY_POLICY) {
1307 ctx->current_cert = NULL;
David Benjamin46350482022-06-16 14:03:12 -04001308 // Verification errors need to be "sticky", a callback may have allowed
1309 // an SSL handshake to continue despite an error, and we must then
1310 // remain in an error state. Therefore, we MUST NOT clear earlier
1311 // verification errors by setting the error to X509_V_OK.
David Benjaminc0b87a02022-06-16 14:02:15 -04001312 if (!ctx->verify_cb(2, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001313 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001314 }
David Benjamin260a10c2022-06-16 13:58:28 -04001315 }
1316
1317 return 1;
1318}
1319
1320static int check_cert_time(X509_STORE_CTX *ctx, X509 *x) {
David Benjamineccd1032022-08-12 15:12:29 -04001321 if (ctx->param->flags & X509_V_FLAG_NO_CHECK_TIME) {
1322 return 1;
1323 }
David Benjamin260a10c2022-06-16 13:58:28 -04001324
Bob Beck6e20b772023-02-08 11:32:19 -07001325 int64_t ptime;
David Benjaminc0b87a02022-06-16 14:02:15 -04001326 if (ctx->param->flags & X509_V_FLAG_USE_CHECK_TIME) {
Bob Beck6e20b772023-02-08 11:32:19 -07001327 ptime = ctx->param->check_time;
David Benjaminc0b87a02022-06-16 14:02:15 -04001328 } else {
Bob Beck6e20b772023-02-08 11:32:19 -07001329 ptime = time(NULL);
David Benjaminc0b87a02022-06-16 14:02:15 -04001330 }
David Benjamin260a10c2022-06-16 13:58:28 -04001331
Bob Beck6e20b772023-02-08 11:32:19 -07001332 int i = X509_cmp_time_posix(X509_get_notBefore(x), ptime);
David Benjamin260a10c2022-06-16 13:58:28 -04001333 if (i == 0) {
1334 ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD;
1335 ctx->current_cert = x;
David Benjaminc0b87a02022-06-16 14:02:15 -04001336 if (!ctx->verify_cb(0, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001337 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001338 }
David Benjamin260a10c2022-06-16 13:58:28 -04001339 }
1340
1341 if (i > 0) {
1342 ctx->error = X509_V_ERR_CERT_NOT_YET_VALID;
1343 ctx->current_cert = x;
David Benjaminc0b87a02022-06-16 14:02:15 -04001344 if (!ctx->verify_cb(0, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001345 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001346 }
David Benjamin260a10c2022-06-16 13:58:28 -04001347 }
1348
Bob Beck6e20b772023-02-08 11:32:19 -07001349 i = X509_cmp_time_posix(X509_get_notAfter(x), ptime);
David Benjamin260a10c2022-06-16 13:58:28 -04001350 if (i == 0) {
1351 ctx->error = X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD;
1352 ctx->current_cert = x;
David Benjaminc0b87a02022-06-16 14:02:15 -04001353 if (!ctx->verify_cb(0, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001354 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001355 }
David Benjamin260a10c2022-06-16 13:58:28 -04001356 }
1357
1358 if (i < 0) {
1359 ctx->error = X509_V_ERR_CERT_HAS_EXPIRED;
1360 ctx->current_cert = x;
David Benjaminc0b87a02022-06-16 14:02:15 -04001361 if (!ctx->verify_cb(0, ctx)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001362 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001363 }
David Benjamin260a10c2022-06-16 13:58:28 -04001364 }
1365
1366 return 1;
1367}
1368
1369static int internal_verify(X509_STORE_CTX *ctx) {
David Benjamin89a62532023-05-23 11:45:10 -04001370 int ok = 0;
David Benjamin260a10c2022-06-16 13:58:28 -04001371 X509 *xs, *xi;
1372 EVP_PKEY *pkey = NULL;
1373
David Benjamin89a62532023-05-23 11:45:10 -04001374 int n = (int)sk_X509_num(ctx->chain);
David Benjamin260a10c2022-06-16 13:58:28 -04001375 ctx->error_depth = n - 1;
1376 n--;
1377 xi = sk_X509_value(ctx->chain, n);
1378
David Benjamin998f5112023-11-19 10:04:06 -05001379 if (x509_check_issued_with_callback(ctx, xi, xi)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001380 xs = xi;
David Benjaminc0b87a02022-06-16 14:02:15 -04001381 } else {
David Benjamin260a10c2022-06-16 13:58:28 -04001382 if (ctx->param->flags & X509_V_FLAG_PARTIAL_CHAIN) {
1383 xs = xi;
1384 goto check_cert;
Adam Langley57707c72016-01-14 11:25:12 -08001385 }
David Benjamin260a10c2022-06-16 13:58:28 -04001386 if (n <= 0) {
1387 ctx->error = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE;
1388 ctx->current_cert = xi;
1389 ok = ctx->verify_cb(0, ctx);
1390 goto end;
David Benjamin046fc132021-08-01 15:20:53 -04001391 } else {
David Benjamin260a10c2022-06-16 13:58:28 -04001392 n--;
1393 ctx->error_depth = n;
1394 xs = sk_X509_value(ctx->chain, n);
1395 }
1396 }
1397
David Benjamin46350482022-06-16 14:03:12 -04001398 // ctx->error=0; not needed
David Benjamin260a10c2022-06-16 13:58:28 -04001399 while (n >= 0) {
1400 ctx->error_depth = n;
1401
David Benjamin46350482022-06-16 14:03:12 -04001402 // Skip signature check for self signed certificates unless
1403 // explicitly asked for. It doesn't add any security and just wastes
1404 // time.
David Benjamin260a10c2022-06-16 13:58:28 -04001405 if (xs != xi || (ctx->param->flags & X509_V_FLAG_CHECK_SS_SIGNATURE)) {
1406 if ((pkey = X509_get_pubkey(xi)) == NULL) {
1407 ctx->error = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
1408 ctx->current_cert = xi;
1409 ok = ctx->verify_cb(0, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -04001410 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -04001411 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -04001412 }
David Benjamin260a10c2022-06-16 13:58:28 -04001413 } else if (X509_verify(xs, pkey) <= 0) {
1414 ctx->error = X509_V_ERR_CERT_SIGNATURE_FAILURE;
1415 ctx->current_cert = xs;
1416 ok = ctx->verify_cb(0, ctx);
1417 if (!ok) {
1418 EVP_PKEY_free(pkey);
1419 goto end;
1420 }
1421 }
1422 EVP_PKEY_free(pkey);
1423 pkey = NULL;
Adam Langley57707c72016-01-14 11:25:12 -08001424 }
David Benjamin046fc132021-08-01 15:20:53 -04001425
David Benjamin260a10c2022-06-16 13:58:28 -04001426 check_cert:
1427 ok = check_cert_time(ctx, xs);
David Benjaminc0b87a02022-06-16 14:02:15 -04001428 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -04001429 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -04001430 }
David Benjamin260a10c2022-06-16 13:58:28 -04001431
David Benjamin46350482022-06-16 14:03:12 -04001432 // The last error (if any) is still in the error value
David Benjamin260a10c2022-06-16 13:58:28 -04001433 ctx->current_issuer = xi;
1434 ctx->current_cert = xs;
1435 ok = ctx->verify_cb(1, ctx);
David Benjaminc0b87a02022-06-16 14:02:15 -04001436 if (!ok) {
David Benjamin260a10c2022-06-16 13:58:28 -04001437 goto end;
David Benjaminc0b87a02022-06-16 14:02:15 -04001438 }
David Benjamin260a10c2022-06-16 13:58:28 -04001439
1440 n--;
1441 if (n >= 0) {
1442 xi = xs;
1443 xs = sk_X509_value(ctx->chain, n);
1444 }
1445 }
1446 ok = 1;
1447end:
1448 return ok;
1449}
1450
1451int X509_cmp_current_time(const ASN1_TIME *ctm) {
Bob Beck6e20b772023-02-08 11:32:19 -07001452 return X509_cmp_time_posix(ctm, time(NULL));
David Benjamin260a10c2022-06-16 13:58:28 -04001453}
1454
David Benjamin899c1a72023-07-05 21:56:55 -04001455int X509_cmp_time(const ASN1_TIME *ctm, const time_t *cmp_time) {
Bob Beck6e20b772023-02-08 11:32:19 -07001456 int64_t compare_time = (cmp_time == NULL) ? time(NULL) : *cmp_time;
1457 return X509_cmp_time_posix(ctm, compare_time);
1458}
1459
1460int X509_cmp_time_posix(const ASN1_TIME *ctm, int64_t cmp_time) {
Bob Beckccd665d2022-07-29 15:57:00 -06001461 int64_t ctm_time;
1462 if (!ASN1_TIME_to_posix(ctm, &ctm_time)) {
David Benjamin260a10c2022-06-16 13:58:28 -04001463 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001464 }
David Benjamin46350482022-06-16 14:03:12 -04001465 // The return value 0 is reserved for errors.
Bob Beck6e20b772023-02-08 11:32:19 -07001466 return (ctm_time - cmp_time <= 0) ? -1 : 1;
David Benjamin260a10c2022-06-16 13:58:28 -04001467}
1468
1469ASN1_TIME *X509_gmtime_adj(ASN1_TIME *s, long offset_sec) {
1470 return X509_time_adj(s, offset_sec, NULL);
1471}
1472
David Benjamin899c1a72023-07-05 21:56:55 -04001473ASN1_TIME *X509_time_adj(ASN1_TIME *s, long offset_sec, const time_t *in_tm) {
David Benjamin260a10c2022-06-16 13:58:28 -04001474 return X509_time_adj_ex(s, 0, offset_sec, in_tm);
1475}
1476
1477ASN1_TIME *X509_time_adj_ex(ASN1_TIME *s, int offset_day, long offset_sec,
David Benjamin899c1a72023-07-05 21:56:55 -04001478 const time_t *in_tm) {
Bob Beck6e20b772023-02-08 11:32:19 -07001479 int64_t t = 0;
David Benjamin260a10c2022-06-16 13:58:28 -04001480
1481 if (in_tm) {
1482 t = *in_tm;
1483 } else {
Bob Beck6e20b772023-02-08 11:32:19 -07001484 t = time(NULL);
David Benjamin260a10c2022-06-16 13:58:28 -04001485 }
1486
1487 return ASN1_TIME_adj(s, t, offset_day, offset_sec);
Adam Langley57707c72016-01-14 11:25:12 -08001488}
Adam Langley95c29f32014-06-20 12:00:00 -07001489
Adam Langley57707c72016-01-14 11:25:12 -08001490int X509_STORE_CTX_get_ex_new_index(long argl, void *argp,
David Benjamin260a10c2022-06-16 13:58:28 -04001491 CRYPTO_EX_unused *unused,
David Benjamind94682d2017-05-14 17:10:18 -04001492 CRYPTO_EX_dup *dup_unused,
David Benjamin260a10c2022-06-16 13:58:28 -04001493 CRYPTO_EX_free *free_func) {
David Benjamin46350482022-06-16 14:03:12 -04001494 // This function is (usually) called only once, by
1495 // SSL_get_ex_data_X509_STORE_CTX_idx (ssl/ssl_cert.c).
David Benjamin260a10c2022-06-16 13:58:28 -04001496 int index;
1497 if (!CRYPTO_get_ex_new_index(&g_ex_data_class, &index, argl, argp,
1498 free_func)) {
1499 return -1;
1500 }
1501 return index;
Adam Langley57707c72016-01-14 11:25:12 -08001502}
Adam Langley95c29f32014-06-20 12:00:00 -07001503
David Benjamin260a10c2022-06-16 13:58:28 -04001504int X509_STORE_CTX_set_ex_data(X509_STORE_CTX *ctx, int idx, void *data) {
1505 return CRYPTO_set_ex_data(&ctx->ex_data, idx, data);
Adam Langley57707c72016-01-14 11:25:12 -08001506}
Adam Langley95c29f32014-06-20 12:00:00 -07001507
David Benjamin260a10c2022-06-16 13:58:28 -04001508void *X509_STORE_CTX_get_ex_data(X509_STORE_CTX *ctx, int idx) {
1509 return CRYPTO_get_ex_data(&ctx->ex_data, idx);
Adam Langley57707c72016-01-14 11:25:12 -08001510}
Adam Langley95c29f32014-06-20 12:00:00 -07001511
David Benjamin260a10c2022-06-16 13:58:28 -04001512int X509_STORE_CTX_get_error(X509_STORE_CTX *ctx) { return ctx->error; }
1513
1514void X509_STORE_CTX_set_error(X509_STORE_CTX *ctx, int err) {
1515 ctx->error = err;
Adam Langley57707c72016-01-14 11:25:12 -08001516}
Adam Langley95c29f32014-06-20 12:00:00 -07001517
David Benjamin260a10c2022-06-16 13:58:28 -04001518int X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx) {
1519 return ctx->error_depth;
Adam Langley57707c72016-01-14 11:25:12 -08001520}
Adam Langley95c29f32014-06-20 12:00:00 -07001521
David Benjamin260a10c2022-06-16 13:58:28 -04001522X509 *X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx) {
1523 return ctx->current_cert;
Adam Langley57707c72016-01-14 11:25:12 -08001524}
Adam Langley95c29f32014-06-20 12:00:00 -07001525
David Benjamin260a10c2022-06-16 13:58:28 -04001526STACK_OF(X509) *X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx) {
1527 return ctx->chain;
Adam Langley57707c72016-01-14 11:25:12 -08001528}
Adam Langley95c29f32014-06-20 12:00:00 -07001529
David Benjamin260a10c2022-06-16 13:58:28 -04001530STACK_OF(X509) *X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx) {
1531 return ctx->chain;
Adam Langley57707c72016-01-14 11:25:12 -08001532}
Adam Langley95c29f32014-06-20 12:00:00 -07001533
David Benjamin260a10c2022-06-16 13:58:28 -04001534STACK_OF(X509) *X509_STORE_CTX_get1_chain(X509_STORE_CTX *ctx) {
David Benjaminc0b87a02022-06-16 14:02:15 -04001535 if (!ctx->chain) {
David Benjamin260a10c2022-06-16 13:58:28 -04001536 return NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -04001537 }
David Benjamin260a10c2022-06-16 13:58:28 -04001538 return X509_chain_up_ref(ctx->chain);
David Benjamin5cd07242020-03-23 21:28:27 -04001539}
1540
David Benjamin260a10c2022-06-16 13:58:28 -04001541X509 *X509_STORE_CTX_get0_current_issuer(X509_STORE_CTX *ctx) {
1542 return ctx->current_issuer;
Adam Langley57707c72016-01-14 11:25:12 -08001543}
Adam Langley95c29f32014-06-20 12:00:00 -07001544
David Benjamin260a10c2022-06-16 13:58:28 -04001545X509_CRL *X509_STORE_CTX_get0_current_crl(X509_STORE_CTX *ctx) {
1546 return ctx->current_crl;
Adam Langley57707c72016-01-14 11:25:12 -08001547}
Adam Langley95c29f32014-06-20 12:00:00 -07001548
David Benjamin260a10c2022-06-16 13:58:28 -04001549X509_STORE_CTX *X509_STORE_CTX_get0_parent_ctx(X509_STORE_CTX *ctx) {
David Benjamina4851dd2023-11-12 15:51:49 -05001550 // In OpenSSL, an |X509_STORE_CTX| sometimes has a parent context during CRL
1551 // path validation for indirect CRLs. We require the CRL to be issued
1552 // somewhere along the certificate path, so this is always NULL.
1553 return NULL;
Adam Langley57707c72016-01-14 11:25:12 -08001554}
Adam Langley95c29f32014-06-20 12:00:00 -07001555
David Benjamin260a10c2022-06-16 13:58:28 -04001556void X509_STORE_CTX_set_cert(X509_STORE_CTX *ctx, X509 *x) { ctx->cert = x; }
1557
1558void X509_STORE_CTX_set_chain(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) {
1559 ctx->untrusted = sk;
Adam Langley57707c72016-01-14 11:25:12 -08001560}
Adam Langley95c29f32014-06-20 12:00:00 -07001561
David Benjamin260a10c2022-06-16 13:58:28 -04001562STACK_OF(X509) *X509_STORE_CTX_get0_untrusted(X509_STORE_CTX *ctx) {
1563 return ctx->untrusted;
Adam Langley57707c72016-01-14 11:25:12 -08001564}
Adam Langley95c29f32014-06-20 12:00:00 -07001565
David Benjamin260a10c2022-06-16 13:58:28 -04001566void X509_STORE_CTX_set0_crls(X509_STORE_CTX *ctx, STACK_OF(X509_CRL) *sk) {
1567 ctx->crls = sk;
Adam Langley57707c72016-01-14 11:25:12 -08001568}
Adam Langley95c29f32014-06-20 12:00:00 -07001569
David Benjamin260a10c2022-06-16 13:58:28 -04001570int X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose) {
1571 return X509_STORE_CTX_purpose_inherit(ctx, 0, purpose, 0);
David Benjamin81f030b2016-08-12 14:48:19 -04001572}
1573
David Benjamin260a10c2022-06-16 13:58:28 -04001574int X509_STORE_CTX_set_trust(X509_STORE_CTX *ctx, int trust) {
1575 return X509_STORE_CTX_purpose_inherit(ctx, 0, 0, trust);
Adam Langley57707c72016-01-14 11:25:12 -08001576}
Adam Langley95c29f32014-06-20 12:00:00 -07001577
David Benjamin46350482022-06-16 14:03:12 -04001578// This function is used to set the X509_STORE_CTX purpose and trust values.
1579// This is intended to be used when another structure has its own trust and
1580// purpose values which (if set) will be inherited by the ctx. If they aren't
1581// set then we will usually have a default purpose in mind which should then
1582// be used to set the trust value. An example of this is SSL use: an SSL
1583// structure will have its own purpose and trust settings which the
1584// application can set: if they aren't set then we use the default of SSL
1585// client/server.
Adam Langley95c29f32014-06-20 12:00:00 -07001586
1587int X509_STORE_CTX_purpose_inherit(X509_STORE_CTX *ctx, int def_purpose,
David Benjamin260a10c2022-06-16 13:58:28 -04001588 int purpose, int trust) {
1589 int idx;
David Benjamin46350482022-06-16 14:03:12 -04001590 // If purpose not set use default
David Benjaminc0b87a02022-06-16 14:02:15 -04001591 if (!purpose) {
David Benjamin260a10c2022-06-16 13:58:28 -04001592 purpose = def_purpose;
David Benjaminc0b87a02022-06-16 14:02:15 -04001593 }
David Benjamin46350482022-06-16 14:03:12 -04001594 // If we have a purpose then check it is valid
David Benjamin260a10c2022-06-16 13:58:28 -04001595 if (purpose) {
1596 X509_PURPOSE *ptmp;
1597 idx = X509_PURPOSE_get_by_id(purpose);
1598 if (idx == -1) {
1599 OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID);
1600 return 0;
Adam Langley57707c72016-01-14 11:25:12 -08001601 }
David Benjamin260a10c2022-06-16 13:58:28 -04001602 ptmp = X509_PURPOSE_get0(idx);
1603 if (ptmp->trust == X509_TRUST_DEFAULT) {
1604 idx = X509_PURPOSE_get_by_id(def_purpose);
1605 if (idx == -1) {
1606 OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_PURPOSE_ID);
1607 return 0;
1608 }
1609 ptmp = X509_PURPOSE_get0(idx);
Adam Langley57707c72016-01-14 11:25:12 -08001610 }
David Benjamin46350482022-06-16 14:03:12 -04001611 // If trust not set then get from purpose default
David Benjaminc0b87a02022-06-16 14:02:15 -04001612 if (!trust) {
David Benjamin260a10c2022-06-16 13:58:28 -04001613 trust = ptmp->trust;
David Benjaminc0b87a02022-06-16 14:02:15 -04001614 }
David Benjamin260a10c2022-06-16 13:58:28 -04001615 }
1616 if (trust) {
1617 idx = X509_TRUST_get_by_id(trust);
1618 if (idx == -1) {
1619 OPENSSL_PUT_ERROR(X509, X509_R_UNKNOWN_TRUST_ID);
1620 return 0;
1621 }
1622 }
Adam Langley95c29f32014-06-20 12:00:00 -07001623
David Benjaminc0b87a02022-06-16 14:02:15 -04001624 if (purpose && !ctx->param->purpose) {
David Benjamin260a10c2022-06-16 13:58:28 -04001625 ctx->param->purpose = purpose;
David Benjaminc0b87a02022-06-16 14:02:15 -04001626 }
1627 if (trust && !ctx->param->trust) {
David Benjamin260a10c2022-06-16 13:58:28 -04001628 ctx->param->trust = trust;
David Benjaminc0b87a02022-06-16 14:02:15 -04001629 }
David Benjamin260a10c2022-06-16 13:58:28 -04001630 return 1;
Adam Langley95c29f32014-06-20 12:00:00 -07001631}
1632
David Benjamin260a10c2022-06-16 13:58:28 -04001633X509_STORE_CTX *X509_STORE_CTX_new(void) {
David Benjamin698aa892023-11-18 17:57:01 -05001634 return OPENSSL_zalloc(sizeof(X509_STORE_CTX));
David Benjamin4492a612017-08-02 17:16:31 -04001635}
1636
David Benjamin260a10c2022-06-16 13:58:28 -04001637void X509_STORE_CTX_free(X509_STORE_CTX *ctx) {
1638 if (ctx == NULL) {
1639 return;
1640 }
1641 X509_STORE_CTX_cleanup(ctx);
1642 OPENSSL_free(ctx);
Adam Langley95c29f32014-06-20 12:00:00 -07001643}
1644
1645int X509_STORE_CTX_init(X509_STORE_CTX *ctx, X509_STORE *store, X509 *x509,
David Benjamin260a10c2022-06-16 13:58:28 -04001646 STACK_OF(X509) *chain) {
David Benjamin1685bd12023-11-21 12:01:38 -05001647 X509_STORE_CTX_cleanup(ctx);
1648
David Benjamin260a10c2022-06-16 13:58:28 -04001649 ctx->ctx = store;
1650 ctx->cert = x509;
1651 ctx->untrusted = chain;
Adam Langley69a01602014-11-17 17:26:55 -08001652
David Benjamin260a10c2022-06-16 13:58:28 -04001653 CRYPTO_new_ex_data(&ctx->ex_data);
Adam Langley95c29f32014-06-20 12:00:00 -07001654
David Benjamin260a10c2022-06-16 13:58:28 -04001655 if (store == NULL) {
1656 OPENSSL_PUT_ERROR(X509, ERR_R_PASSED_NULL_PARAMETER);
1657 goto err;
1658 }
David Benjaminca3f2432020-08-31 14:47:49 -04001659
David Benjamin260a10c2022-06-16 13:58:28 -04001660 ctx->param = X509_VERIFY_PARAM_new();
David Benjaminc0b87a02022-06-16 14:02:15 -04001661 if (!ctx->param) {
David Benjamin260a10c2022-06-16 13:58:28 -04001662 goto err;
David Benjaminc0b87a02022-06-16 14:02:15 -04001663 }
Adam Langley95c29f32014-06-20 12:00:00 -07001664
David Benjamin46350482022-06-16 14:03:12 -04001665 // Inherit callbacks and flags from X509_STORE.
Adam Langley95c29f32014-06-20 12:00:00 -07001666
David Benjamin260a10c2022-06-16 13:58:28 -04001667 ctx->verify_cb = store->verify_cb;
David Benjamin260a10c2022-06-16 13:58:28 -04001668
1669 if (!X509_VERIFY_PARAM_inherit(ctx->param, store->param) ||
1670 !X509_VERIFY_PARAM_inherit(ctx->param,
1671 X509_VERIFY_PARAM_lookup("default"))) {
1672 goto err;
1673 }
1674
David Benjaminc0b87a02022-06-16 14:02:15 -04001675 if (store->get_issuer) {
David Benjamin260a10c2022-06-16 13:58:28 -04001676 ctx->get_issuer = store->get_issuer;
David Benjaminc0b87a02022-06-16 14:02:15 -04001677 } else {
David Benjamin260a10c2022-06-16 13:58:28 -04001678 ctx->get_issuer = X509_STORE_CTX_get1_issuer;
David Benjaminc0b87a02022-06-16 14:02:15 -04001679 }
David Benjamin260a10c2022-06-16 13:58:28 -04001680
David Benjaminc0b87a02022-06-16 14:02:15 -04001681 if (store->verify_cb) {
David Benjaminca3f2432020-08-31 14:47:49 -04001682 ctx->verify_cb = store->verify_cb;
David Benjaminc0b87a02022-06-16 14:02:15 -04001683 } else {
David Benjamin260a10c2022-06-16 13:58:28 -04001684 ctx->verify_cb = null_callback;
David Benjaminc0b87a02022-06-16 14:02:15 -04001685 }
Adam Langley95c29f32014-06-20 12:00:00 -07001686
David Benjaminc0b87a02022-06-16 14:02:15 -04001687 if (store->get_crl) {
David Benjamin260a10c2022-06-16 13:58:28 -04001688 ctx->get_crl = store->get_crl;
David Benjaminc0b87a02022-06-16 14:02:15 -04001689 } else {
David Benjamin260a10c2022-06-16 13:58:28 -04001690 ctx->get_crl = NULL;
David Benjaminc0b87a02022-06-16 14:02:15 -04001691 }
Adam Langley95c29f32014-06-20 12:00:00 -07001692
David Benjaminc0b87a02022-06-16 14:02:15 -04001693 if (store->check_crl) {
David Benjamin260a10c2022-06-16 13:58:28 -04001694 ctx->check_crl = store->check_crl;
David Benjaminc0b87a02022-06-16 14:02:15 -04001695 } else {
David Benjamin260a10c2022-06-16 13:58:28 -04001696 ctx->check_crl = check_crl;
David Benjaminc0b87a02022-06-16 14:02:15 -04001697 }
Adam Langley95c29f32014-06-20 12:00:00 -07001698
David Benjamin260a10c2022-06-16 13:58:28 -04001699 return 1;
Adam Langley95c29f32014-06-20 12:00:00 -07001700
David Benjamin260a10c2022-06-16 13:58:28 -04001701err:
1702 CRYPTO_free_ex_data(&g_ex_data_class, ctx, &ctx->ex_data);
1703 if (ctx->param != NULL) {
1704 X509_VERIFY_PARAM_free(ctx->param);
1705 }
Adam Langley95c29f32014-06-20 12:00:00 -07001706
David Benjamin260a10c2022-06-16 13:58:28 -04001707 OPENSSL_memset(ctx, 0, sizeof(X509_STORE_CTX));
David Benjamin260a10c2022-06-16 13:58:28 -04001708 return 0;
Adam Langley57707c72016-01-14 11:25:12 -08001709}
Adam Langley95c29f32014-06-20 12:00:00 -07001710
David Benjamin46350482022-06-16 14:03:12 -04001711// Set alternative lookup method: just a STACK of trusted certificates. This
1712// avoids X509_STORE nastiness where it isn't needed.
Adam Langley95c29f32014-06-20 12:00:00 -07001713
David Benjamin2135ac62022-08-12 15:33:43 -04001714void X509_STORE_CTX_set0_trusted_stack(X509_STORE_CTX *ctx,
1715 STACK_OF(X509) *sk) {
David Benjamin260a10c2022-06-16 13:58:28 -04001716 ctx->other_ctx = sk;
1717 ctx->get_issuer = get_issuer_sk;
Adam Langley95c29f32014-06-20 12:00:00 -07001718}
1719
David Benjamin2135ac62022-08-12 15:33:43 -04001720void X509_STORE_CTX_trusted_stack(X509_STORE_CTX *ctx, STACK_OF(X509) *sk) {
1721 X509_STORE_CTX_set0_trusted_stack(ctx, sk);
1722}
1723
David Benjamin260a10c2022-06-16 13:58:28 -04001724void X509_STORE_CTX_cleanup(X509_STORE_CTX *ctx) {
David Benjamina4851dd2023-11-12 15:51:49 -05001725 X509_VERIFY_PARAM_free(ctx->param);
1726 ctx->param = NULL;
1727 sk_X509_pop_free(ctx->chain, X509_free);
1728 ctx->chain = NULL;
David Benjamin260a10c2022-06-16 13:58:28 -04001729 CRYPTO_free_ex_data(&g_ex_data_class, ctx, &(ctx->ex_data));
David Benjamin1685bd12023-11-21 12:01:38 -05001730 OPENSSL_memset(ctx, 0, sizeof(X509_STORE_CTX));
Adam Langley57707c72016-01-14 11:25:12 -08001731}
Adam Langley95c29f32014-06-20 12:00:00 -07001732
David Benjamin260a10c2022-06-16 13:58:28 -04001733void X509_STORE_CTX_set_depth(X509_STORE_CTX *ctx, int depth) {
1734 X509_VERIFY_PARAM_set_depth(ctx->param, depth);
Adam Langley57707c72016-01-14 11:25:12 -08001735}
Adam Langley95c29f32014-06-20 12:00:00 -07001736
David Benjamin260a10c2022-06-16 13:58:28 -04001737void X509_STORE_CTX_set_flags(X509_STORE_CTX *ctx, unsigned long flags) {
1738 X509_VERIFY_PARAM_set_flags(ctx->param, flags);
Adam Langley57707c72016-01-14 11:25:12 -08001739}
Adam Langley95c29f32014-06-20 12:00:00 -07001740
Bob Beck6e20b772023-02-08 11:32:19 -07001741void X509_STORE_CTX_set_time_posix(X509_STORE_CTX *ctx, unsigned long flags,
David Benjamin2ba76342023-11-19 10:20:04 -05001742 int64_t t) {
Bob Beck6e20b772023-02-08 11:32:19 -07001743 X509_VERIFY_PARAM_set_time_posix(ctx->param, t);
Adam Langley57707c72016-01-14 11:25:12 -08001744}
Adam Langley95c29f32014-06-20 12:00:00 -07001745
Bob Beck6e20b772023-02-08 11:32:19 -07001746void X509_STORE_CTX_set_time(X509_STORE_CTX *ctx, unsigned long flags,
1747 time_t t) {
1748 X509_STORE_CTX_set_time_posix(ctx, flags, t);
1749}
1750
1751X509 *X509_STORE_CTX_get0_cert(X509_STORE_CTX *ctx) {
1752 return ctx->cert;
1753}
David Benjaminf05e3ea2018-05-10 17:35:11 -04001754
Adam Langley95c29f32014-06-20 12:00:00 -07001755void X509_STORE_CTX_set_verify_cb(X509_STORE_CTX *ctx,
David Benjamin260a10c2022-06-16 13:58:28 -04001756 int (*verify_cb)(int, X509_STORE_CTX *)) {
1757 ctx->verify_cb = verify_cb;
Adam Langley57707c72016-01-14 11:25:12 -08001758}
Adam Langley95c29f32014-06-20 12:00:00 -07001759
David Benjamin260a10c2022-06-16 13:58:28 -04001760int X509_STORE_CTX_set_default(X509_STORE_CTX *ctx, const char *name) {
1761 const X509_VERIFY_PARAM *param;
1762 param = X509_VERIFY_PARAM_lookup(name);
David Benjaminc0b87a02022-06-16 14:02:15 -04001763 if (!param) {
David Benjamin260a10c2022-06-16 13:58:28 -04001764 return 0;
David Benjaminc0b87a02022-06-16 14:02:15 -04001765 }
David Benjamin260a10c2022-06-16 13:58:28 -04001766 return X509_VERIFY_PARAM_inherit(ctx->param, param);
Adam Langley57707c72016-01-14 11:25:12 -08001767}
Adam Langley95c29f32014-06-20 12:00:00 -07001768
David Benjamin260a10c2022-06-16 13:58:28 -04001769X509_VERIFY_PARAM *X509_STORE_CTX_get0_param(X509_STORE_CTX *ctx) {
1770 return ctx->param;
Adam Langley57707c72016-01-14 11:25:12 -08001771}
Adam Langley95c29f32014-06-20 12:00:00 -07001772
David Benjamin260a10c2022-06-16 13:58:28 -04001773void X509_STORE_CTX_set0_param(X509_STORE_CTX *ctx, X509_VERIFY_PARAM *param) {
David Benjaminc0b87a02022-06-16 14:02:15 -04001774 if (ctx->param) {
David Benjamin260a10c2022-06-16 13:58:28 -04001775 X509_VERIFY_PARAM_free(ctx->param);
David Benjaminc0b87a02022-06-16 14:02:15 -04001776 }
David Benjamin260a10c2022-06-16 13:58:28 -04001777 ctx->param = param;
Adam Langley57707c72016-01-14 11:25:12 -08001778}