summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/x509/x509_internal.h3
-rw-r--r--src/lib/libcrypto/x509/x509_verify.c88
2 files changed, 79 insertions, 12 deletions
diff --git a/src/lib/libcrypto/x509/x509_internal.h b/src/lib/libcrypto/x509/x509_internal.h
index 9d69055afa..f6887be5fb 100644
--- a/src/lib/libcrypto/x509/x509_internal.h
+++ b/src/lib/libcrypto/x509/x509_internal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_internal.h,v 1.3 2020/09/15 11:55:14 beck Exp $ */ 1/* $OpenBSD: x509_internal.h,v 1.4 2020/11/11 18:49:34 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -57,6 +57,7 @@ struct x509_constraints_names {
57 57
58struct x509_verify_chain { 58struct x509_verify_chain {
59 STACK_OF(X509) *certs; /* Kept in chain order, includes leaf */ 59 STACK_OF(X509) *certs; /* Kept in chain order, includes leaf */
60 int *cert_errors; /* Verify error for each cert in chain. */
60 struct x509_constraints_names *names; /* All names from all certs */ 61 struct x509_constraints_names *names; /* All names from all certs */
61}; 62};
62 63
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c
index c3923a88d5..c76a5e103e 100644
--- a/src/lib/libcrypto/x509/x509_verify.c
+++ b/src/lib/libcrypto/x509/x509_verify.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_verify.c,v 1.18 2020/11/03 17:43:01 jsing Exp $ */ 1/* $OpenBSD: x509_verify.c,v 1.19 2020/11/11 18:49:34 jsing Exp $ */
2/* 2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -15,7 +15,7 @@
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */ 16 */
17 17
18/* x509_verify - inspired by golang's crypto/x509/Verify */ 18/* x509_verify - inspired by golang's crypto/x509.Verify */
19 19
20#include <errno.h> 20#include <errno.h>
21#include <stdio.h> 21#include <stdio.h>
@@ -49,6 +49,9 @@ x509_verify_chain_new(void)
49 goto err; 49 goto err;
50 if ((chain->certs = sk_X509_new_null()) == NULL) 50 if ((chain->certs = sk_X509_new_null()) == NULL)
51 goto err; 51 goto err;
52 if ((chain->cert_errors = calloc(X509_VERIFY_MAX_CHAIN_CERTS,
53 sizeof(int))) == NULL)
54 goto err;
52 if ((chain->names = x509_constraints_names_new()) == NULL) 55 if ((chain->names = x509_constraints_names_new()) == NULL)
53 goto err; 56 goto err;
54 57
@@ -63,6 +66,8 @@ x509_verify_chain_clear(struct x509_verify_chain *chain)
63{ 66{
64 sk_X509_pop_free(chain->certs, X509_free); 67 sk_X509_pop_free(chain->certs, X509_free);
65 chain->certs = NULL; 68 chain->certs = NULL;
69 free(chain->cert_errors);
70 chain->cert_errors = NULL;
66 x509_constraints_names_free(chain->names); 71 x509_constraints_names_free(chain->names);
67 chain->names = NULL; 72 chain->names = NULL;
68} 73}
@@ -85,6 +90,11 @@ x509_verify_chain_dup(struct x509_verify_chain *chain)
85 goto err; 90 goto err;
86 if ((new_chain->certs = X509_chain_up_ref(chain->certs)) == NULL) 91 if ((new_chain->certs = X509_chain_up_ref(chain->certs)) == NULL)
87 goto err; 92 goto err;
93 if ((new_chain->cert_errors = calloc(X509_VERIFY_MAX_CHAIN_CERTS,
94 sizeof(int))) == NULL)
95 goto err;
96 memcpy(new_chain->cert_errors, chain->cert_errors,
97 X509_VERIFY_MAX_CHAIN_CERTS * sizeof(int));
88 if ((new_chain->names = 98 if ((new_chain->names =
89 x509_constraints_names_dup(chain->names)) == NULL) 99 x509_constraints_names_dup(chain->names)) == NULL)
90 goto err; 100 goto err;
@@ -99,18 +109,32 @@ x509_verify_chain_append(struct x509_verify_chain *chain, X509 *cert,
99 int *error) 109 int *error)
100{ 110{
101 int verify_err = X509_V_ERR_UNSPECIFIED; 111 int verify_err = X509_V_ERR_UNSPECIFIED;
112 size_t idx;
102 113
103 if (!x509_constraints_extract_names(chain->names, cert, 114 if (!x509_constraints_extract_names(chain->names, cert,
104 sk_X509_num(chain->certs) == 0, &verify_err)) { 115 sk_X509_num(chain->certs) == 0, &verify_err)) {
105 *error = verify_err; 116 *error = verify_err;
106 return 0; 117 return 0;
107 } 118 }
119
108 X509_up_ref(cert); 120 X509_up_ref(cert);
109 if (!sk_X509_push(chain->certs, cert)) { 121 if (!sk_X509_push(chain->certs, cert)) {
110 X509_free(cert); 122 X509_free(cert);
111 *error = X509_V_ERR_OUT_OF_MEM; 123 *error = X509_V_ERR_OUT_OF_MEM;
112 return 0; 124 return 0;
113 } 125 }
126
127 idx = sk_X509_num(chain->certs) - 1;
128 chain->cert_errors[idx] = *error;
129
130 /*
131 * We've just added the issuer for the previous certificate,
132 * clear its error if appropriate.
133 */
134 if (idx > 1 && chain->cert_errors[idx - 1] ==
135 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
136 chain->cert_errors[idx - 1] = X509_V_OK;
137
114 return 1; 138 return 1;
115} 139}
116 140
@@ -171,10 +195,11 @@ x509_verify_ctx_cert_is_root(struct x509_verify_ctx *ctx, X509 *cert)
171 195
172static int 196static int
173x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx, 197x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx,
174 struct x509_verify_chain *chain) 198 struct x509_verify_chain *chain, int set_error)
175{ 199{
176 size_t depth;
177 X509 *last = x509_verify_chain_last(chain); 200 X509 *last = x509_verify_chain_last(chain);
201 size_t depth;
202 int i;
178 203
179 if (ctx->xsc == NULL) 204 if (ctx->xsc == NULL)
180 return 1; 205 return 1;
@@ -189,6 +214,19 @@ x509_verify_ctx_set_xsc_chain(struct x509_verify_ctx *ctx,
189 if (ctx->xsc->chain == NULL) 214 if (ctx->xsc->chain == NULL)
190 return x509_verify_cert_error(ctx, last, depth, 215 return x509_verify_cert_error(ctx, last, depth,
191 X509_V_ERR_OUT_OF_MEM, 0); 216 X509_V_ERR_OUT_OF_MEM, 0);
217
218 if (set_error) {
219 ctx->xsc->error = X509_V_OK;
220 ctx->xsc->error_depth = 0;
221 for (i = 0; i < sk_X509_num(chain->certs); i++) {
222 if (chain->cert_errors[i] != X509_V_OK) {
223 ctx->xsc->error = chain->cert_errors[i];
224 ctx->xsc->error_depth = i;
225 break;
226 }
227 }
228 }
229
192 return 1; 230 return 1;
193} 231}
194 232
@@ -208,6 +246,11 @@ x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx,
208 return x509_verify_cert_error(ctx, last, depth, 246 return x509_verify_cert_error(ctx, last, depth,
209 X509_V_ERR_CERT_CHAIN_TOO_LONG, 0); 247 X509_V_ERR_CERT_CHAIN_TOO_LONG, 0);
210 248
249 /* Clear a get issuer failure for a root certificate. */
250 if (chain->cert_errors[depth] ==
251 X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)
252 chain->cert_errors[depth] = X509_V_OK;
253
211 /* 254 /*
212 * If we have a legacy xsc, choose a validated chain, 255 * If we have a legacy xsc, choose a validated chain,
213 * and apply the extensions, revocation, and policy checks 256 * and apply the extensions, revocation, and policy checks
@@ -217,7 +260,11 @@ x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx,
217 * knobs that are there for the fiddling. 260 * knobs that are there for the fiddling.
218 */ 261 */
219 if (ctx->xsc != NULL) { 262 if (ctx->xsc != NULL) {
220 if (!x509_verify_ctx_set_xsc_chain(ctx, chain)) 263 /* These may be set in one of the following calls. */
264 ctx->xsc->error = X509_V_OK;
265 ctx->xsc->error_depth = 0;
266
267 if (!x509_verify_ctx_set_xsc_chain(ctx, chain, 0))
221 return 0; 268 return 0;
222 269
223 /* 270 /*
@@ -241,6 +288,18 @@ x509_verify_ctx_add_chain(struct x509_verify_ctx *ctx,
241 288
242 if (!x509_vfy_check_policy(ctx->xsc)) 289 if (!x509_vfy_check_policy(ctx->xsc))
243 return 0; 290 return 0;
291
292 /*
293 * The above checks may have set ctx->xsc->error and
294 * ctx->xsc->error_depth - save these for later on.
295 */
296 if (ctx->xsc->error != X509_V_OK) {
297 if (ctx->xsc->error_depth < 0 ||
298 ctx->xsc->error_depth >= X509_VERIFY_MAX_CHAIN_CERTS)
299 return 0;
300 chain->cert_errors[ctx->xsc->error_depth] =
301 ctx->xsc->error;
302 }
244 } 303 }
245 /* 304 /*
246 * no xsc means we are being called from the non-legacy API, 305 * no xsc means we are being called from the non-legacy API,
@@ -350,8 +409,7 @@ x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert,
350 return 0; 409 return 0;
351 } 410 }
352 if (!x509_verify_chain_append(new_chain, candidate, &ctx->error)) { 411 if (!x509_verify_chain_append(new_chain, candidate, &ctx->error)) {
353 x509_verify_cert_error(ctx, candidate, depth, 412 x509_verify_cert_error(ctx, candidate, depth, ctx->error, 0);
354 ctx->error, 0);
355 x509_verify_chain_free(new_chain); 413 x509_verify_chain_free(new_chain);
356 return 0; 414 return 0;
357 } 415 }
@@ -362,7 +420,7 @@ x509_verify_consider_candidate(struct x509_verify_ctx *ctx, X509 *cert,
362 * give up. 420 * give up.
363 */ 421 */
364 if (is_root_cert) { 422 if (is_root_cert) {
365 if (!x509_verify_ctx_set_xsc_chain(ctx, new_chain)) { 423 if (!x509_verify_ctx_set_xsc_chain(ctx, new_chain, 0)) {
366 x509_verify_chain_free(new_chain); 424 x509_verify_chain_free(new_chain);
367 return 0; 425 return 0;
368 } 426 }
@@ -931,16 +989,24 @@ x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name)
931 * We could not find a validated chain, and for some reason do not 989 * We could not find a validated chain, and for some reason do not
932 * have an error set. 990 * have an error set.
933 */ 991 */
934 if (ctx->chains_count == 0 && ctx->error == 0) 992 if (ctx->chains_count == 0 && ctx->error == 0) {
935 ctx->error = X509_V_ERR_UNSPECIFIED; 993 ctx->error = X509_V_ERR_UNSPECIFIED;
994 if (ctx->xsc != NULL && ctx->xsc->error != 0)
995 ctx->error = ctx->xsc->error;
996
997 }
936 998
937 /* Clear whatever errors happened if we have any validated chain */ 999 /* Clear whatever errors happened if we have any validated chain */
938 if (ctx->chains_count > 0) 1000 if (ctx->chains_count > 0)
939 ctx->error = X509_V_OK; 1001 ctx->error = X509_V_OK;
940 1002
941 if (ctx->xsc != NULL) { 1003 if (ctx->xsc != NULL) {
942 ctx->xsc->error = ctx->error; 1004 /* Take the first chain we found. */
943 return ctx->xsc->verify_cb(ctx->chains_count, ctx->xsc); 1005 if (ctx->chains_count > 0) {
1006 if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0], 1))
1007 goto err;
1008 }
1009 return ctx->xsc->verify_cb(ctx->chains_count > 0, ctx->xsc);
944 } 1010 }
945 return (ctx->chains_count); 1011 return (ctx->chains_count);
946 1012