1 |
jpp |
1.1 |
From c63599ee9708d543205a9173207ee7167315c624 Mon Sep 17 00:00:00 2001 |
2 |
|
|
From: Clemens Lang <cllang@redhat.com> |
3 |
|
|
Date: Tue, 1 Mar 2022 15:44:18 +0100 |
4 |
|
|
Subject: [PATCH] Allow SHA1 in seclevel 2 if rh-allow-sha1-signatures = yes |
5 |
|
|
|
6 |
|
|
References: rhbz#2055796 |
7 |
|
|
--- |
8 |
|
|
crypto/x509/x509_vfy.c | 19 ++++++++++- |
9 |
|
|
doc/man5/config.pod | 7 +++- |
10 |
|
|
ssl/t1_lib.c | 64 ++++++++++++++++++++++++++++------- |
11 |
|
|
test/recipes/25-test_verify.t | 7 ++-- |
12 |
|
|
4 files changed, 79 insertions(+), 18 deletions(-) |
13 |
|
|
|
14 |
|
|
diff --git a/crypto/x509/x509_vfy.c b/crypto/x509/x509_vfy.c |
15 |
|
|
index ff3ca83de6..a549c1c111 100644 |
16 |
|
|
--- a/crypto/x509/x509_vfy.c |
17 |
|
|
+++ b/crypto/x509/x509_vfy.c |
18 |
|
|
@@ -25,6 +25,7 @@ |
19 |
|
|
#include <openssl/objects.h> |
20 |
|
|
#include <openssl/core_names.h> |
21 |
|
|
#include "internal/dane.h" |
22 |
|
|
+#include "internal/sslconf.h" |
23 |
|
|
#include "crypto/x509.h" |
24 |
|
|
#include "x509_local.h" |
25 |
|
|
|
26 |
|
|
@@ -3440,14 +3441,30 @@ static int check_sig_level(X509_STORE_CTX *ctx, X509 *cert) |
27 |
|
|
{ |
28 |
|
|
int secbits = -1; |
29 |
|
|
int level = ctx->param->auth_level; |
30 |
|
|
+ int nid; |
31 |
|
|
+ OSSL_LIB_CTX *libctx = NULL; |
32 |
|
|
|
33 |
|
|
if (level <= 0) |
34 |
|
|
return 1; |
35 |
|
|
if (level > NUM_AUTH_LEVELS) |
36 |
|
|
level = NUM_AUTH_LEVELS; |
37 |
|
|
|
38 |
|
|
- if (!X509_get_signature_info(cert, NULL, NULL, &secbits, NULL)) |
39 |
|
|
+ if (ctx->libctx) |
40 |
|
|
+ libctx = ctx->libctx; |
41 |
|
|
+ else if (cert->libctx) |
42 |
|
|
+ libctx = cert->libctx; |
43 |
|
|
+ else |
44 |
|
|
+ libctx = OSSL_LIB_CTX_get0_global_default(); |
45 |
|
|
+ |
46 |
|
|
+ if (!X509_get_signature_info(cert, &nid, NULL, &secbits, NULL)) |
47 |
|
|
return 0; |
48 |
|
|
|
49 |
|
|
+ if (nid == NID_sha1 |
50 |
|
|
+ && ossl_ctx_legacy_digest_signatures_allowed(libctx, 0) |
51 |
|
|
+ && ctx->param->auth_level < 3) |
52 |
|
|
+ /* When rh-allow-sha1-signatures = yes and security level <= 2, |
53 |
|
|
+ * explicitly allow SHA1 for backwards compatibility. */ |
54 |
|
|
+ return 1; |
55 |
|
|
+ |
56 |
|
|
return secbits >= minbits_table[level - 1]; |
57 |
|
|
} |
58 |
|
|
diff --git a/doc/man5/config.pod b/doc/man5/config.pod |
59 |
|
|
index aa1be5ca7f..aa69e2b844 100644 |
60 |
|
|
--- a/doc/man5/config.pod |
61 |
|
|
+++ b/doc/man5/config.pod |
62 |
|
|
@@ -305,7 +305,12 @@ When set to B<no>, any attempt to create or verify a signature with a SHA1 |
63 |
|
|
digest will fail. For compatibility with older versions of OpenSSL, set this |
64 |
|
|
option to B<yes>. This setting also affects TLS, where signature algorithms |
65 |
|
|
that use SHA1 as digest will no longer be supported if this option is set to |
66 |
|
|
-B<no>. |
67 |
|
|
+B<no>. Note that enabling B<rh-allow-sha1-signatures> will allow TLS signature |
68 |
|
|
+algorithms that use SHA1 in security level 2, despite the definition of |
69 |
|
|
+security level 2 of 112 bits of security, which SHA1 does not meet. Because |
70 |
|
|
+TLS 1.1 or lower use MD5-SHA1 as pseudorandom function (PRF) to derive key |
71 |
|
|
+material, disabling B<rh-allow-sha1-signatures> requires the use of TLS 1.2 or |
72 |
|
|
+newer. |
73 |
|
|
|
74 |
|
|
=item B<fips_mode> (deprecated) |
75 |
|
|
|
76 |
|
|
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c |
77 |
|
|
index 4b74ee1a34..5f089de107 100644 |
78 |
|
|
--- a/ssl/t1_lib.c |
79 |
|
|
+++ b/ssl/t1_lib.c |
80 |
|
|
@@ -20,6 +20,7 @@ |
81 |
|
|
#include <openssl/bn.h> |
82 |
|
|
#include <openssl/provider.h> |
83 |
|
|
#include <openssl/param_build.h> |
84 |
|
|
+#include "crypto/x509.h" |
85 |
|
|
#include "internal/sslconf.h" |
86 |
|
|
#include "internal/nelem.h" |
87 |
|
|
#include "internal/sizes.h" |
88 |
|
|
@@ -1561,19 +1562,27 @@ int tls12_check_peer_sigalg(SSL *s, uint16_t sig, EVP_PKEY *pkey) |
89 |
|
|
SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_UNKNOWN_DIGEST); |
90 |
|
|
return 0; |
91 |
|
|
} |
92 |
|
|
- /* |
93 |
|
|
- * Make sure security callback allows algorithm. For historical |
94 |
|
|
- * reasons we have to pass the sigalg as a two byte char array. |
95 |
|
|
- */ |
96 |
|
|
- sigalgstr[0] = (sig >> 8) & 0xff; |
97 |
|
|
- sigalgstr[1] = sig & 0xff; |
98 |
|
|
- secbits = sigalg_security_bits(s->ctx, lu); |
99 |
|
|
- if (secbits == 0 || |
100 |
|
|
- !ssl_security(s, SSL_SECOP_SIGALG_CHECK, secbits, |
101 |
|
|
- md != NULL ? EVP_MD_get_type(md) : NID_undef, |
102 |
|
|
- (void *)sigalgstr)) { |
103 |
|
|
- SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE); |
104 |
|
|
- return 0; |
105 |
|
|
+ |
106 |
|
|
+ if (lu->hash == NID_sha1 |
107 |
|
|
+ && ossl_ctx_legacy_digest_signatures_allowed(s->ctx->libctx, 0) |
108 |
|
|
+ && SSL_get_security_level(s) < 3) { |
109 |
|
|
+ /* when rh-allow-sha1-signatures = yes and security level <= 2, |
110 |
|
|
+ * explicitly allow SHA1 for backwards compatibility */ |
111 |
|
|
+ } else { |
112 |
|
|
+ /* |
113 |
|
|
+ * Make sure security callback allows algorithm. For historical |
114 |
|
|
+ * reasons we have to pass the sigalg as a two byte char array. |
115 |
|
|
+ */ |
116 |
|
|
+ sigalgstr[0] = (sig >> 8) & 0xff; |
117 |
|
|
+ sigalgstr[1] = sig & 0xff; |
118 |
|
|
+ secbits = sigalg_security_bits(s->ctx, lu); |
119 |
|
|
+ if (secbits == 0 || |
120 |
|
|
+ !ssl_security(s, SSL_SECOP_SIGALG_CHECK, secbits, |
121 |
|
|
+ md != NULL ? EVP_MD_get_type(md) : NID_undef, |
122 |
|
|
+ (void *)sigalgstr)) { |
123 |
|
|
+ SSLfatal(s, SSL_AD_HANDSHAKE_FAILURE, SSL_R_WRONG_SIGNATURE_TYPE); |
124 |
|
|
+ return 0; |
125 |
|
|
+ } |
126 |
|
|
} |
127 |
|
|
/* Store the sigalg the peer uses */ |
128 |
|
|
s->s3.tmp.peer_sigalg = lu; |
129 |
|
|
@@ -2106,6 +2115,14 @@ static int tls12_sigalg_allowed(const SSL *s, int op, const SIGALG_LOOKUP *lu) |
130 |
|
|
} |
131 |
|
|
} |
132 |
|
|
|
133 |
|
|
+ if (lu->hash == NID_sha1 |
134 |
|
|
+ && ossl_ctx_legacy_digest_signatures_allowed(s->ctx->libctx, 0) |
135 |
|
|
+ && SSL_get_security_level(s) < 3) { |
136 |
|
|
+ /* when rh-allow-sha1-signatures = yes and security level <= 2, |
137 |
|
|
+ * explicitly allow SHA1 for backwards compatibility */ |
138 |
|
|
+ return 1; |
139 |
|
|
+ } |
140 |
|
|
+ |
141 |
|
|
/* Finally see if security callback allows it */ |
142 |
|
|
secbits = sigalg_security_bits(s->ctx, lu); |
143 |
|
|
sigalgstr[0] = (lu->sigalg >> 8) & 0xff; |
144 |
|
|
@@ -2977,6 +2994,8 @@ static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op) |
145 |
|
|
{ |
146 |
|
|
/* Lookup signature algorithm digest */ |
147 |
|
|
int secbits, nid, pknid; |
148 |
|
|
+ OSSL_LIB_CTX *libctx = NULL; |
149 |
|
|
+ |
150 |
|
|
/* Don't check signature if self signed */ |
151 |
|
|
if ((X509_get_extension_flags(x) & EXFLAG_SS) != 0) |
152 |
|
|
return 1; |
153 |
|
|
@@ -2985,6 +3004,25 @@ static int ssl_security_cert_sig(SSL *s, SSL_CTX *ctx, X509 *x, int op) |
154 |
|
|
/* If digest NID not defined use signature NID */ |
155 |
|
|
if (nid == NID_undef) |
156 |
|
|
nid = pknid; |
157 |
|
|
+ |
158 |
|
|
+ if (x && x->libctx) |
159 |
|
|
+ libctx = x->libctx; |
160 |
|
|
+ else if (ctx && ctx->libctx) |
161 |
|
|
+ libctx = ctx->libctx; |
162 |
|
|
+ else if (s && s->ctx && s->ctx->libctx) |
163 |
|
|
+ libctx = s->ctx->libctx; |
164 |
|
|
+ else |
165 |
|
|
+ libctx = OSSL_LIB_CTX_get0_global_default(); |
166 |
|
|
+ |
167 |
|
|
+ if (nid == NID_sha1 |
168 |
|
|
+ && ossl_ctx_legacy_digest_signatures_allowed(libctx, 0) |
169 |
|
|
+ && ((s != NULL && SSL_get_security_level(s) < 3) |
170 |
|
|
+ || (ctx != NULL && SSL_CTX_get_security_level(ctx) < 3) |
171 |
|
|
+ )) |
172 |
|
|
+ /* When rh-allow-sha1-signatures = yes and security level <= 2, |
173 |
|
|
+ * explicitly allow SHA1 for backwards compatibility. */ |
174 |
|
|
+ return 1; |
175 |
|
|
+ |
176 |
|
|
if (s) |
177 |
|
|
return ssl_security(s, op, secbits, nid, x); |
178 |
|
|
else |
179 |
|
|
diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t |
180 |
|
|
index 700bbd849c..2de1d76b5e 100644 |
181 |
|
|
--- a/test/recipes/25-test_verify.t |
182 |
|
|
+++ b/test/recipes/25-test_verify.t |
183 |
|
|
@@ -29,7 +29,7 @@ sub verify { |
184 |
|
|
run(app([@args])); |
185 |
|
|
} |
186 |
|
|
|
187 |
|
|
-plan tests => 163; |
188 |
|
|
+plan tests => 162; |
189 |
|
|
|
190 |
|
|
# Canonical success |
191 |
|
|
ok(verify("ee-cert", "sslserver", ["root-cert"], ["ca-cert"]), |
192 |
|
|
@@ -387,8 +387,9 @@ ok(verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "0" |
193 |
|
|
ok(verify("ee-pss-sha256-cert", "", ["root-cert"], ["ca-cert"], ), |
194 |
|
|
"CA with PSS signature using SHA256"); |
195 |
|
|
|
196 |
|
|
-ok(!verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "1"), |
197 |
|
|
- "Reject PSS signature using SHA1 and auth level 1"); |
198 |
|
|
+## rh-allow-sha1-signatures=yes allows this to pass despite -auth_level 1 |
199 |
|
|
+#ok(!verify("ee-pss-sha1-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "1"), |
200 |
|
|
+# "Reject PSS signature using SHA1 and auth level 1"); |
201 |
|
|
|
202 |
|
|
ok(verify("ee-pss-sha256-cert", "", ["root-cert"], ["ca-cert"], "-auth_level", "2"), |
203 |
|
|
"PSS signature using SHA256 and auth level 2"); |
204 |
|
|
-- |
205 |
|
|
2.35.1 |
206 |
|
|
|