diff options
author | beck <> | 2022-11-13 18:37:32 +0000 |
---|---|---|
committer | beck <> | 2022-11-13 18:37:32 +0000 |
commit | b10fff2d2486c7f66b4a443e8ad68ef2b2021928 (patch) | |
tree | 92c8eb7340d7ea5f92ee37794cea4b1cb98a4c26 | |
parent | b2adf01da2682fbf7809dc301d850a728803bffd (diff) | |
download | openbsd-b10fff2d2486c7f66b4a443e8ad68ef2b2021928.tar.gz openbsd-b10fff2d2486c7f66b4a443e8ad68ef2b2021928.tar.bz2 openbsd-b10fff2d2486c7f66b4a443e8ad68ef2b2021928.zip |
Check certificate extensions in trusted certificates.
Historically the standards let the implementation decide to
either check or ignore the certificate properties of trust anchors.
You could either use them simply as a source of a public key which
was trusted for everything, or you were also permitted to check the
certificate properties and fully enforce them. Hooray for freedumb.
OpenSSL changed to checking these with :
commit 0daccd4dc1f1ac62181738a91714f35472e50f3c
Author: Viktor Dukhovni <openssl-users@dukhovni.org>
Date: Thu Jan 28 03:01:45 2016 -0500
BoringSSL currently does not check them, as it also inherited
the previous OpenSSL behaviour. It will change to check them in
the future.
(https://bugs.chromium.org/p/boringssl/issues/detail?id=533)
-rw-r--r-- | src/lib/libcrypto/x509/x509_internal.h | 3 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_trs.c | 20 | ||||
-rw-r--r-- | src/lib/libcrypto/x509/x509_vfy.c | 49 |
3 files changed, 64 insertions, 8 deletions
diff --git a/src/lib/libcrypto/x509/x509_internal.h b/src/lib/libcrypto/x509/x509_internal.h index beafd365ed..9e80b2d2cf 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.20 2022/11/11 12:02:34 beck Exp $ */ | 1 | /* $OpenBSD: x509_internal.h,v 1.21 2022/11/13 18:37:32 beck Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> | 3 | * Copyright (c) 2020 Bob Beck <beck@openbsd.org> |
4 | * | 4 | * |
@@ -134,6 +134,7 @@ int x509_constraints_check(struct x509_constraints_names *names, | |||
134 | struct x509_constraints_names *excluded, int *error); | 134 | struct x509_constraints_names *excluded, int *error); |
135 | int x509_constraints_chain(STACK_OF(X509) *chain, int *error, | 135 | int x509_constraints_chain(STACK_OF(X509) *chain, int *error, |
136 | int *depth); | 136 | int *depth); |
137 | int x509_check_trust_no_compat(X509 *x, int id, int flags); | ||
137 | void x509_verify_cert_info_populate(X509 *cert); | 138 | void x509_verify_cert_info_populate(X509 *cert); |
138 | int x509_vfy_check_security_level(X509_STORE_CTX *ctx); | 139 | int x509_vfy_check_security_level(X509_STORE_CTX *ctx); |
139 | 140 | ||
diff --git a/src/lib/libcrypto/x509/x509_trs.c b/src/lib/libcrypto/x509/x509_trs.c index a967edf933..23eca4927b 100644 --- a/src/lib/libcrypto/x509/x509_trs.c +++ b/src/lib/libcrypto/x509/x509_trs.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: x509_trs.c,v 1.26 2022/11/10 16:52:19 beck Exp $ */ | 1 | /* $OpenBSD: x509_trs.c,v 1.27 2022/11/13 18:37:32 beck Exp $ */ |
2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL | 2 | /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL |
3 | * project 1999. | 3 | * project 1999. |
4 | */ | 4 | */ |
@@ -110,8 +110,8 @@ int | |||
110 | return oldtrust; | 110 | return oldtrust; |
111 | } | 111 | } |
112 | 112 | ||
113 | int | 113 | static int |
114 | X509_check_trust(X509 *x, int id, int flags) | 114 | X509_check_trust_internal(X509 *x, int id, int flags, int compat) |
115 | { | 115 | { |
116 | X509_TRUST *pt; | 116 | X509_TRUST *pt; |
117 | int idx; | 117 | int idx; |
@@ -132,7 +132,7 @@ X509_check_trust(X509 *x, int id, int flags) | |||
132 | rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); | 132 | rv = obj_trust(NID_anyExtendedKeyUsage, x, 0); |
133 | if (rv != X509_TRUST_UNTRUSTED) | 133 | if (rv != X509_TRUST_UNTRUSTED) |
134 | return rv; | 134 | return rv; |
135 | return trust_compat(NULL, x, 0); | 135 | return compat && trust_compat(NULL, x, 0); |
136 | } | 136 | } |
137 | idx = X509_TRUST_get_by_id(id); | 137 | idx = X509_TRUST_get_by_id(id); |
138 | if (idx == -1) | 138 | if (idx == -1) |
@@ -142,6 +142,18 @@ X509_check_trust(X509 *x, int id, int flags) | |||
142 | } | 142 | } |
143 | 143 | ||
144 | int | 144 | int |
145 | X509_check_trust(X509 *x, int id, int flags) | ||
146 | { | ||
147 | return X509_check_trust_internal(x, id, flags, /*compat =*/1); | ||
148 | } | ||
149 | |||
150 | int | ||
151 | x509_check_trust_no_compat(X509 *x, int id, int flags) | ||
152 | { | ||
153 | return X509_check_trust_internal(x, id, flags, /*compat =*/0); | ||
154 | } | ||
155 | |||
156 | int | ||
145 | X509_TRUST_get_count(void) | 157 | X509_TRUST_get_count(void) |
146 | { | 158 | { |
147 | if (!trtable) | 159 | if (!trtable) |
diff --git a/src/lib/libcrypto/x509/x509_vfy.c b/src/lib/libcrypto/x509/x509_vfy.c index fb87877e72..11bf3d9292 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.103 2022/08/31 07:15:31 tb Exp $ */ | 1 | /* $OpenBSD: x509_vfy.c,v 1.104 2022/11/13 18:37:32 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 | * |
@@ -724,6 +724,43 @@ get_issuer_sk(X509 **issuer, X509_STORE_CTX *ctx, X509 *x) | |||
724 | return 0; | 724 | return 0; |
725 | } | 725 | } |
726 | 726 | ||
727 | /* | ||
728 | * X509_check_purpose is special. | ||
729 | * 0 is bad, 1 is good, values > 1 are maybe good for web pki necromancy | ||
730 | * and certificates that were checked into software unit tests years ago | ||
731 | * that nobody knows how to change. (Netscape Server Gated Crypto Forever!) | ||
732 | */ | ||
733 | #define PURPOSE_GOOD(x) (x == 1) | ||
734 | #define PURPOSE_BAD(x) (x == 0) | ||
735 | static int | ||
736 | check_purpose(X509_STORE_CTX *ctx, X509 *x, int purpose, int depth, | ||
737 | int must_be_ca) | ||
738 | { | ||
739 | int purpose_check, trust; | ||
740 | |||
741 | purpose_check = X509_check_purpose(x, purpose, must_be_ca > 0); | ||
742 | trust = X509_TRUST_UNTRUSTED; | ||
743 | |||
744 | /* | ||
745 | * For trusted certificates we want to see whether any auxiliary trust | ||
746 | * settings for the desired purpose override the purpose constraints | ||
747 | * from the certificate EKU. | ||
748 | */ | ||
749 | if (depth >= ctx->num_untrusted && purpose == ctx->param->purpose) | ||
750 | trust = x509_check_trust_no_compat(x, ctx->param->trust, 0); | ||
751 | |||
752 | /* XXX STRICT should really be the default */ | ||
753 | if (trust != X509_TRUST_REJECTED && !PURPOSE_BAD(purpose_check)) { | ||
754 | return PURPOSE_GOOD(purpose_check) || | ||
755 | (ctx->param->flags & X509_V_FLAG_X509_STRICT) == 0; | ||
756 | } | ||
757 | |||
758 | ctx->error = X509_V_ERR_INVALID_PURPOSE; | ||
759 | ctx->error_depth = depth; | ||
760 | ctx->current_cert = x; | ||
761 | return ctx->verify_cb(0, ctx); | ||
762 | } | ||
763 | |||
727 | /* Check a certificate chains extensions for consistency | 764 | /* Check a certificate chains extensions for consistency |
728 | * with the supplied purpose | 765 | * with the supplied purpose |
729 | */ | 766 | */ |
@@ -740,6 +777,7 @@ x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx) | |||
740 | int proxy_path_length = 0; | 777 | int proxy_path_length = 0; |
741 | int purpose; | 778 | int purpose; |
742 | int allow_proxy_certs; | 779 | int allow_proxy_certs; |
780 | size_t chain_len; | ||
743 | 781 | ||
744 | cb = ctx->verify_cb; | 782 | cb = ctx->verify_cb; |
745 | 783 | ||
@@ -763,8 +801,8 @@ x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx) | |||
763 | purpose = ctx->param->purpose; | 801 | purpose = ctx->param->purpose; |
764 | } | 802 | } |
765 | 803 | ||
766 | /* Check all untrusted certificates */ | 804 | chain_len = sk_X509_num(ctx->chain); |
767 | for (i = 0; i < ctx->num_untrusted; i++) { | 805 | for (i = 0; i < chain_len; i++) { |
768 | int ret; | 806 | int ret; |
769 | x = sk_X509_value(ctx->chain, i); | 807 | x = sk_X509_value(ctx->chain, i); |
770 | if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && | 808 | if (!(ctx->param->flags & X509_V_FLAG_IGNORE_CRITICAL) && |
@@ -818,6 +856,11 @@ x509_vfy_check_chain_extensions(X509_STORE_CTX *ctx) | |||
818 | if (!ok) | 856 | if (!ok) |
819 | goto end; | 857 | goto end; |
820 | } | 858 | } |
859 | if (purpose > 0) { | ||
860 | ok = check_purpose(ctx, x, purpose, i, must_be_ca); | ||
861 | if (!ok) | ||
862 | goto end; | ||
863 | } | ||
821 | if (ctx->param->purpose > 0) { | 864 | if (ctx->param->purpose > 0) { |
822 | ret = X509_check_purpose(x, purpose, must_be_ca > 0); | 865 | ret = X509_check_purpose(x, purpose, must_be_ca > 0); |
823 | if ((ret == 0) || | 866 | if ((ret == 0) || |