summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorbeck <>2021-11-24 05:38:12 +0000
committerbeck <>2021-11-24 05:38:12 +0000
commit423c3bdfa824af138953ed7df2ece97a5f5fbcab (patch)
treeaa24e5059056bbf6faad312217d9a1a414b6b213 /src/lib
parent762fac1fce36c5a65717448f5452ff0495f51406 (diff)
downloadopenbsd-423c3bdfa824af138953ed7df2ece97a5f5fbcab.tar.gz
openbsd-423c3bdfa824af138953ed7df2ece97a5f5fbcab.tar.bz2
openbsd-423c3bdfa824af138953ed7df2ece97a5f5fbcab.zip
In some situations, the verifier would discard the error on an unvalidated
certificte chain. This would happen when the verification callback was in use, instructing the verifier to continue unconditionally. This could lead to incorrect decisions being made in software.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/libcrypto/x509/x509_internal.h4
-rw-r--r--src/lib/libcrypto/x509/x509_verify.c129
-rw-r--r--src/lib/libcrypto/x509/x509_vfy.c8
3 files changed, 91 insertions, 50 deletions
diff --git a/src/lib/libcrypto/x509/x509_internal.h b/src/lib/libcrypto/x509/x509_internal.h
index a9b584b13e..9ac0c2bbde 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.15 2021/11/04 23:52:34 beck Exp $ */ 1/* $OpenBSD: x509_internal.h,v 1.16 2021/11/24 05:38:12 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -92,7 +92,7 @@ int x509_vfy_check_revocation(X509_STORE_CTX *ctx);
92int x509_vfy_check_policy(X509_STORE_CTX *ctx); 92int x509_vfy_check_policy(X509_STORE_CTX *ctx);
93int x509_vfy_check_trust(X509_STORE_CTX *ctx); 93int x509_vfy_check_trust(X509_STORE_CTX *ctx);
94int x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx); 94int x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx);
95int x509_vfy_callback_indicate_success(X509_STORE_CTX *ctx); 95int x509_vfy_callback_indicate_completion(X509_STORE_CTX *ctx);
96void x509v3_cache_extensions(X509 *x); 96void x509v3_cache_extensions(X509 *x);
97X509 *x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x); 97X509 *x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x);
98 98
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c
index e7493fdbf0..6a73cb74e2 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.53 2021/11/14 08:21:47 jsing Exp $ */ 1/* $OpenBSD: x509_verify.c,v 1.54 2021/11/24 05:38:12 beck Exp $ */
2/* 2/*
3 * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org> 3 * Copyright (c) 2020-2021 Bob Beck <beck@openbsd.org>
4 * 4 *
@@ -1164,62 +1164,99 @@ x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name)
1164 x509_verify_chain_free(current_chain); 1164 x509_verify_chain_free(current_chain);
1165 1165
1166 /* 1166 /*
1167 * Bring back the failure case we wanted to the xsc if 1167 * Do the new verifier style return, where we don't have an xsc
1168 * we saved one. 1168 * that allows a crazy callback to turn invalid things into valid.
1169 */ 1169 */
1170 if (!x509_verify_ctx_restore_xsc_error(ctx)) 1170 if (ctx->xsc == NULL) {
1171 goto err; 1171 /*
1172 * Safety net:
1173 * We could not find a validated chain, and for some reason do not
1174 * have an error set.
1175 */
1176 if (ctx->chains_count == 0 && ctx->error == X509_V_OK)
1177 ctx->error = X509_V_ERR_UNSPECIFIED;
1178
1179 /*
1180 * If we are not using an xsc, and have no possibility for the
1181 * crazy OpenSSL callback API changing the results of
1182 * validation steps (because the callback can make validation
1183 * proceed in the presence of invalid certs), any chains we
1184 * have here are correctly built and verified.
1185 */
1186 if (ctx->chains_count > 0)
1187 ctx->error = X509_V_OK;
1188
1189 return ctx->chains_count;
1190 }
1172 1191
1173 /* 1192 /*
1174 * Safety net: 1193 * Otherwise we are doing compatibility with an xsc, which means that we
1175 * We could not find a validated chain, and for some reason do not 1194 * will have one chain, which might actually be a bogus chain because
1176 * have an error set. 1195 * the callback told us to ignore errors and proceed to build an invalid
1196 * chain. Possible return values from this include returning 1 with an
1197 * invalid chain and a value of xsc->error != X509_V_OK (It's tradition
1198 * that makes it ok).
1177 */ 1199 */
1178 if (ctx->chains_count == 0 && ctx->error == X509_V_OK) {
1179 ctx->error = X509_V_ERR_UNSPECIFIED;
1180 if (ctx->xsc != NULL && ctx->xsc->error != X509_V_OK)
1181 ctx->error = ctx->xsc->error;
1182 }
1183 1200
1184 /* Clear whatever errors happened if we have any validated chain */ 1201 if (ctx->chains_count > 0) {
1185 if (ctx->chains_count > 0) 1202 /*
1186 ctx->error = X509_V_OK; 1203 * The chain we have using an xsc might not be a verified chain
1204 * if the callback perverted things while we built it to ignore
1205 * failures and proceed with chain building. We put this chain
1206 * and the error associated with it on the xsc.
1207 */
1208 if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0], 1, 1))
1209 goto err;
1187 1210
1188 if (ctx->xsc != NULL) { 1211 /*
1189 ctx->xsc->error = ctx->error; 1212 * Call the callback for completion up our built
1190 if (ctx->chains_count > 0) { 1213 * chain. The callback could still tell us to
1191 /* Take the first chain we found. */ 1214 * fail. Since this chain might exist as the result of
1192 if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0], 1215 * callback doing perversions, we could still return
1193 1, 1)) 1216 * "success" with something other than X509_V_OK set
1194 goto err; 1217 * as the error.
1195 ctx->xsc->error = X509_V_OK; 1218 */
1196 /* 1219 if (!x509_vfy_callback_indicate_completion(ctx->xsc))
1197 * Call the callback indicating success up our already 1220 goto err;
1198 * verified chain. The callback could still tell us to 1221 } else {
1199 * fail. 1222 /*
1200 */ 1223 * We did not find a chain. Bring back the failure
1201 if(!x509_vfy_callback_indicate_success(ctx->xsc)) { 1224 * case we wanted to the xsc if we saved one. If we
1202 /* The callback can change the error code */ 1225 * did not we should have just the leaf on the xsc.
1203 ctx->error = ctx->xsc->error; 1226 */
1204 goto err; 1227 if (!x509_verify_ctx_restore_xsc_error(ctx))
1205 } 1228 goto err;
1206 } else { 1229
1207 /* 1230 /*
1208 * We had a failure, indicate the failure, but 1231 * Safety net, ensure we have an error set in the
1209 * allow the callback to override at depth 0 1232 * failing case.
1210 */ 1233 */
1211 if (ctx->xsc->verify_cb(0, ctx->xsc)) { 1234 if (ctx->xsc->error == X509_V_OK) {
1212 ctx->xsc->error = X509_V_OK; 1235 if (ctx->error == X509_V_OK)
1213 return 1; 1236 ctx->error = X509_V_ERR_UNSPECIFIED;
1214 } 1237 ctx->xsc->error = ctx->error;
1215 } 1238 }
1239
1240 /*
1241 * Let the callback override the return value
1242 * at depth 0 if it chooses to
1243 */
1244 return ctx->xsc->verify_cb(0, ctx->xsc);
1216 } 1245 }
1217 return (ctx->chains_count); 1246
1247 /* We only ever find one chain in compat mode with an xsc. */
1248 return 1;
1218 1249
1219 err: 1250 err:
1220 if (ctx->error == X509_V_OK) 1251 if (ctx->error == X509_V_OK)
1221 ctx->error = X509_V_ERR_UNSPECIFIED; 1252 ctx->error = X509_V_ERR_UNSPECIFIED;
1222 if (ctx->xsc != NULL) 1253
1223 ctx->xsc->error = ctx->error; 1254 if (ctx->xsc != NULL) {
1255 if (ctx->xsc->error == X509_V_OK)
1256 ctx->xsc->error = X509_V_ERR_UNSPECIFIED;
1257 ctx->error = ctx->xsc->error;
1258 }
1259
1224 return 0; 1260 return 0;
1225} 1261}
1262
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c
index b044f4931e..db2125b48d 100644
--- a/src/lib/libcrypto/x509/x509_vfy.c
+++ b/src/lib/libcrypto/x509/x509_vfy.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: x509_vfy.c,v 1.97 2021/11/13 18:24:45 schwarze Exp $ */ 1/* $OpenBSD: x509_vfy.c,v 1.98 2021/11/24 05:38:12 beck Exp $ */
2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 2/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3 * All rights reserved. 3 * All rights reserved.
4 * 4 *
@@ -1989,8 +1989,12 @@ internal_verify(X509_STORE_CTX *ctx)
1989 return x509_vfy_internal_verify(ctx, 0); 1989 return x509_vfy_internal_verify(ctx, 0);
1990} 1990}
1991 1991
1992/*
1993 * Internal verify, but with a chain where the verification
1994 * math has already been performed.
1995 */
1992int 1996int
1993x509_vfy_callback_indicate_success(X509_STORE_CTX *ctx) 1997x509_vfy_callback_indicate_completion(X509_STORE_CTX *ctx)
1994{ 1998{
1995 return x509_vfy_internal_verify(ctx, 1); 1999 return x509_vfy_internal_verify(ctx, 1);
1996} 2000}