diff options
author | tb <> | 2021-11-24 09:28:56 +0000 |
---|---|---|
committer | tb <> | 2021-11-24 09:28:56 +0000 |
commit | 2c0e7f8ac54f86297f1f41b51254e4b672dc9a6c (patch) | |
tree | 43f0280ff3795786784edb02273862918922c8ba | |
parent | a091f55fdff9699931b85df586c79f5ffe01d616 (diff) | |
download | openbsd-2c0e7f8ac54f86297f1f41b51254e4b672dc9a6c.tar.gz openbsd-2c0e7f8ac54f86297f1f41b51254e4b672dc9a6c.tar.bz2 openbsd-2c0e7f8ac54f86297f1f41b51254e4b672dc9a6c.zip |
In some situations, the verifier would discard the error on an unvalidatedlibressl-v3.4.3libressl-v3.4.2
certificate 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.
This is patches/common/006_x509.patch.sig
-rw-r--r-- | src/lib/libcrypto/x509/x509_internal.h | 4 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_verify.c | 129 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.c | 8 |
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 8891aecb13..9878b6febd 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.12 2021/09/03 08:58:53 beck Exp $ */ | 1 | /* $OpenBSD: x509_internal.h,v 1.12.2.1 2021/11/24 09:28:55 tb Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> | 3 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> |
4 | * | 4 | * |
@@ -90,7 +90,7 @@ int x509_vfy_check_revocation(X509_STORE_CTX *ctx); | |||
90 | int x509_vfy_check_policy(X509_STORE_CTX *ctx); | 90 | int x509_vfy_check_policy(X509_STORE_CTX *ctx); |
91 | int x509_vfy_check_trust(X509_STORE_CTX *ctx); | 91 | int x509_vfy_check_trust(X509_STORE_CTX *ctx); |
92 | int x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx); | 92 | int x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx); |
93 | int x509_vfy_callback_indicate_success(X509_STORE_CTX *ctx); | 93 | int x509_vfy_callback_indicate_completion(X509_STORE_CTX *ctx); |
94 | void x509v3_cache_extensions(X509 *x); | 94 | void x509v3_cache_extensions(X509 *x); |
95 | X509 *x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x); | 95 | X509 *x509_vfy_lookup_cert_match(X509_STORE_CTX *ctx, X509 *x); |
96 | 96 | ||
diff --git a/src/lib/libcrypto/x509/x509_verify.c b/src/lib/libcrypto/x509/x509_verify.c index e49fbdee48..5ff7c50653 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.49 2021/09/09 15:09:43 beck Exp $ */ | 1 | /* $OpenBSD: x509_verify.c,v 1.49.2.1 2021/11/24 09:28:56 tb 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 | * |
@@ -1171,62 +1171,99 @@ x509_verify(struct x509_verify_ctx *ctx, X509 *leaf, char *name) | |||
1171 | x509_verify_chain_free(current_chain); | 1171 | x509_verify_chain_free(current_chain); |
1172 | 1172 | ||
1173 | /* | 1173 | /* |
1174 | * Bring back the failure case we wanted to the xsc if | 1174 | * Do the new verifier style return, where we don't have an xsc |
1175 | * we saved one. | 1175 | * that allows a crazy callback to turn invalid things into valid. |
1176 | */ | 1176 | */ |
1177 | if (!x509_verify_ctx_restore_xsc_error(ctx)) | 1177 | if (ctx->xsc == NULL) { |
1178 | goto err; | 1178 | /* |
1179 | * Safety net: | ||
1180 | * We could not find a validated chain, and for some reason do not | ||
1181 | * have an error set. | ||
1182 | */ | ||
1183 | if (ctx->chains_count == 0 && ctx->error == X509_V_OK) | ||
1184 | ctx->error = X509_V_ERR_UNSPECIFIED; | ||
1185 | |||
1186 | /* | ||
1187 | * If we are not using an xsc, and have no possibility for the | ||
1188 | * crazy OpenSSL callback API changing the results of | ||
1189 | * validation steps (because the callback can make validation | ||
1190 | * proceed in the presence of invalid certs), any chains we | ||
1191 | * have here are correctly built and verified. | ||
1192 | */ | ||
1193 | if (ctx->chains_count > 0) | ||
1194 | ctx->error = X509_V_OK; | ||
1195 | |||
1196 | return ctx->chains_count; | ||
1197 | } | ||
1179 | 1198 | ||
1180 | /* | 1199 | /* |
1181 | * Safety net: | 1200 | * Otherwise we are doing compatibility with an xsc, which means that we |
1182 | * We could not find a validated chain, and for some reason do not | 1201 | * will have one chain, which might actually be a bogus chain because |
1183 | * have an error set. | 1202 | * the callback told us to ignore errors and proceed to build an invalid |
1203 | * chain. Possible return values from this include returning 1 with an | ||
1204 | * invalid chain and a value of xsc->error != X509_V_OK (It's tradition | ||
1205 | * that makes it ok). | ||
1184 | */ | 1206 | */ |
1185 | if (ctx->chains_count == 0 && ctx->error == X509_V_OK) { | ||
1186 | ctx->error = X509_V_ERR_UNSPECIFIED; | ||
1187 | if (ctx->xsc != NULL && ctx->xsc->error != X509_V_OK) | ||
1188 | ctx->error = ctx->xsc->error; | ||
1189 | } | ||
1190 | 1207 | ||
1191 | /* Clear whatever errors happened if we have any validated chain */ | 1208 | if (ctx->chains_count > 0) { |
1192 | if (ctx->chains_count > 0) | 1209 | /* |
1193 | ctx->error = X509_V_OK; | 1210 | * The chain we have using an xsc might not be a verified chain |
1211 | * if the callback perverted things while we built it to ignore | ||
1212 | * failures and proceed with chain building. We put this chain | ||
1213 | * and the error associated with it on the xsc. | ||
1214 | */ | ||
1215 | if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0], 1, 1)) | ||
1216 | goto err; | ||
1194 | 1217 | ||
1195 | if (ctx->xsc != NULL) { | 1218 | /* |
1196 | ctx->xsc->error = ctx->error; | 1219 | * Call the callback for completion up our built |
1197 | if (ctx->chains_count > 0) { | 1220 | * chain. The callback could still tell us to |
1198 | /* Take the first chain we found. */ | 1221 | * fail. Since this chain might exist as the result of |
1199 | if (!x509_verify_ctx_set_xsc_chain(ctx, ctx->chains[0], | 1222 | * callback doing perversions, we could still return |
1200 | 1, 1)) | 1223 | * "success" with something other than X509_V_OK set |
1201 | goto err; | 1224 | * as the error. |
1202 | ctx->xsc->error = X509_V_OK; | 1225 | */ |
1203 | /* | 1226 | if (!x509_vfy_callback_indicate_completion(ctx->xsc)) |
1204 | * Call the callback indicating success up our already | 1227 | goto err; |
1205 | * verified chain. The callback could still tell us to | 1228 | } else { |
1206 | * fail. | 1229 | /* |
1207 | */ | 1230 | * We did not find a chain. Bring back the failure |
1208 | if(!x509_vfy_callback_indicate_success(ctx->xsc)) { | 1231 | * case we wanted to the xsc if we saved one. If we |
1209 | /* The callback can change the error code */ | 1232 | * did not we should have just the leaf on the xsc. |
1210 | ctx->error = ctx->xsc->error; | 1233 | */ |
1211 | goto err; | 1234 | if (!x509_verify_ctx_restore_xsc_error(ctx)) |
1212 | } | 1235 | goto err; |
1213 | } else { | 1236 | |
1214 | /* | 1237 | /* |
1215 | * We had a failure, indicate the failure, but | 1238 | * Safety net, ensure we have an error set in the |
1216 | * allow the callback to override at depth 0 | 1239 | * failing case. |
1217 | */ | 1240 | */ |
1218 | if (ctx->xsc->verify_cb(0, ctx->xsc)) { | 1241 | if (ctx->xsc->error == X509_V_OK) { |
1219 | ctx->xsc->error = X509_V_OK; | 1242 | if (ctx->error == X509_V_OK) |
1220 | return 1; | 1243 | ctx->error = X509_V_ERR_UNSPECIFIED; |
1221 | } | 1244 | ctx->xsc->error = ctx->error; |
1222 | } | 1245 | } |
1246 | |||
1247 | /* | ||
1248 | * Let the callback override the return value | ||
1249 | * at depth 0 if it chooses to | ||
1250 | */ | ||
1251 | return ctx->xsc->verify_cb(0, ctx->xsc); | ||
1223 | } | 1252 | } |
1224 | return (ctx->chains_count); | 1253 | |
1254 | /* We only ever find one chain in compat mode with an xsc. */ | ||
1255 | return 1; | ||
1225 | 1256 | ||
1226 | err: | 1257 | err: |
1227 | if (ctx->error == X509_V_OK) | 1258 | if (ctx->error == X509_V_OK) |
1228 | ctx->error = X509_V_ERR_UNSPECIFIED; | 1259 | ctx->error = X509_V_ERR_UNSPECIFIED; |
1229 | if (ctx->xsc != NULL) | 1260 | |
1230 | ctx->xsc->error = ctx->error; | 1261 | if (ctx->xsc != NULL) { |
1262 | if (ctx->xsc->error == X509_V_OK) | ||
1263 | ctx->xsc->error = X509_V_ERR_UNSPECIFIED; | ||
1264 | ctx->error = ctx->xsc->error; | ||
1265 | } | ||
1266 | |||
1231 | return 0; | 1267 | return 0; |
1232 | } | 1268 | } |
1269 | |||
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c index 2f69017e96..1f52779911 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.89 2021/09/03 08:58:53 beck Exp $ */ | 1 | /* $OpenBSD: x509_vfy.c,v 1.89.2.1 2021/11/24 09:28:56 tb 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 | * |
@@ -1960,8 +1960,12 @@ internal_verify(X509_STORE_CTX *ctx) | |||
1960 | return x509_vfy_internal_verify(ctx, 0); | 1960 | return x509_vfy_internal_verify(ctx, 0); |
1961 | } | 1961 | } |
1962 | 1962 | ||
1963 | /* | ||
1964 | * Internal verify, but with a chain where the verification | ||
1965 | * math has already been performed. | ||
1966 | */ | ||
1963 | int | 1967 | int |
1964 | x509_vfy_callback_indicate_success(X509_STORE_CTX *ctx) | 1968 | x509_vfy_callback_indicate_completion(X509_STORE_CTX *ctx) |
1965 | { | 1969 | { |
1966 | return x509_vfy_internal_verify(ctx, 1); | 1970 | return x509_vfy_internal_verify(ctx, 1); |
1967 | } | 1971 | } |