summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKurt Roeckx <kurt@roeckx.be>2020-01-02 23:25:27 +0100
committerKurt Roeckx <kurt@roeckx.be>2020-02-05 22:04:37 +0100
commitb744f915ca8bb37631909728dd2529289bda8438 (patch)
treee051ce8f2cf9a06de1a40d1c9b238dc33ba0d11f
parent4d9e8c95544d7a86765e6a46951dbe17b801875a (diff)
Stop accepting certificates signed using SHA1 at security level 1
Reviewed-by: Viktor Dukhovni <viktor@openssl.org> GH: #10786
-rw-r--r--CHANGES12
-rw-r--r--NEWS4
-rw-r--r--crypto/rsa/rsa_ameth.c20
-rw-r--r--crypto/x509/x509_set.c14
-rw-r--r--test/recipes/25-test_verify.t8
5 files changed, 53 insertions, 5 deletions
diff --git a/CHANGES b/CHANGES
index 1750162a10..7b18d51077 100644
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,18 @@
Changes between 1.1.1 and 3.0.0 [xx XXX xxxx]
+ *) X509 certificates signed using SHA1 are no longer allowed at security
+ level 1 and above.
+ In TLS/SSL the default security level is 1. It can be set either
+ using the cipher string with @SECLEVEL, or calling
+ SSL_CTX_set_security_level(). If the leaf certificate is signed with SHA-1,
+ a call to SSL_CTX_use_certificate() will fail if the security level is not
+ lowered first.
+ Outside TLS/SSL, the default security level is -1 (effectively 0). It can
+ be set using X509_VERIFY_PARAM_set_auth_level() or using the -auth_level
+ options of the apps.
+ [Kurt Roeckx]
+
*) Reworked the treatment of EC EVP_PKEYs with the SM2 curve to
automatically become EVP_PKEY_SM2 rather than EVP_PKEY_EC.
This means that applications don't have to look at the curve NID and
diff --git a/NEWS b/NEWS
index de439d6bb1..4d7f0d01c6 100644
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,10 @@
Major changes between OpenSSL 1.1.1 and OpenSSL 3.0.0 [under development]
+ o X509 certificates signed using SHA1 are no longer allowed at security
+ level 1 or higher. The default security level for TLS is 1, so
+ certificates signed using SHA1 are by default no longer trusted to
+ authenticate servers or clients.
o enable-crypto-mdebug and enable-crypto-mdebug-backtrace were mostly
disabled; the project uses address sanitize/leak-detect instead.
o Added OSSL_SERIALIZER, a generic serializer API.
diff --git a/crypto/rsa/rsa_ameth.c b/crypto/rsa/rsa_ameth.c
index 3246f33688..485ac35a6f 100644
--- a/crypto/rsa/rsa_ameth.c
+++ b/crypto/rsa/rsa_ameth.c
@@ -859,6 +859,7 @@ static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg,
uint32_t flags;
const EVP_MD *mgf1md = NULL, *md = NULL;
RSA_PSS_PARAMS *pss;
+ int secbits;
/* Sanity check: make sure it is PSS */
if (OBJ_obj2nid(sigalg->algorithm) != EVP_PKEY_RSA_PSS)
@@ -878,7 +879,24 @@ static int rsa_sig_info_set(X509_SIG_INFO *siginf, const X509_ALGOR *sigalg,
else
flags = 0;
/* Note: security bits half number of digest bits */
- X509_SIG_INFO_set(siginf, mdnid, EVP_PKEY_RSA_PSS, EVP_MD_size(md) * 4,
+ secbits = EVP_MD_size(md) * 4;
+ /*
+ * SHA1 and MD5 are known to be broken. Reduce security bits so that
+ * they're no longer accepted at security level 1. The real values don't
+ * really matter as long as they're lower than 80, which is our security
+ * level 1.
+ * https://eprint.iacr.org/2020/014 puts a chosen-prefix attack for SHA1 at
+ * 2^63.4
+ * https://documents.epfl.ch/users/l/le/lenstra/public/papers/lat.pdf
+ * puts a chosen-prefix attack for MD5 at 2^39.
+ */
+ if (mdnid == NID_sha1)
+ secbits = 64;
+ else if (mdnid == NID_md5_sha1)
+ secbits = 68;
+ else if (mdnid == NID_md5)
+ secbits = 39;
+ X509_SIG_INFO_set(siginf, mdnid, EVP_PKEY_RSA_PSS, secbits,
flags);
rv = 1;
err:
diff --git a/crypto/x509/x509_set.c b/crypto/x509/x509_set.c
index e325a57b29..97676c2ecd 100644
--- a/crypto/x509/x509_set.c
+++ b/crypto/x509/x509_set.c
@@ -222,6 +222,20 @@ static void x509_sig_info_init(X509_SIG_INFO *siginf, const X509_ALGOR *alg,
return;
/* Security bits: half number of bits in digest */
siginf->secbits = EVP_MD_size(md) * 4;
+ /*
+ * SHA1 and MD5 are known to be broken. Reduce security bits so that
+ * they're no longer accepted at security level 1. The real values don't
+ * really matter as long as they're lower than 80, which is our security
+ * level 1.
+ * https://eprint.iacr.org/2020/014 puts a chosen-prefix attack for SHA1 at
+ * 2^63.4
+ * https://documents.epfl.ch/users/l/le/lenstra/public/papers/lat.pdf
+ * puts a chosen-prefix attack for MD5 at 2^39.
+ */
+ if (mdnid == NID_sha1)
+ siginf->secbits = 63;
+ else if (mdnid == NID_md5)
+ siginf->secbits = 39;
switch (mdnid) {
case NID_sha1:
case NID_sha256:
diff --git a/test/recipes/25-test_verify.t b/test/recipes/25-test_verify.t
index 915c902b15..219e7e1149 100644
--- a/test/recipes/25-test_verify.t
+++ b/test/recipes/25-test_verify.t
@@ -336,14 +336,14 @@ ok(!verify("badalt9-cert", "sslserver", ["root-cert"], ["ncca1-cert", "ncca3-cer
ok(!verify("badalt10-cert", "sslserver", ["root-cert"], ["ncca1-cert", "ncca3-cert"], ),
"Name constraints nested DNS name excluded");
-ok(verify("ee-pss-sha1-cert", "sslserver", ["root-cert"], ["ca-cert"], ),
- "Certificate PSS signature using SHA1");
+ok(verify("ee-pss-sha1-cert", "sslserver", ["root-cert"], ["ca-cert"], "-auth_level", "0"),
+ "Accept PSS signature using SHA1 at auth level 0");
ok(verify("ee-pss-sha256-cert", "sslserver", ["root-cert"], ["ca-cert"], ),
"CA with PSS signature using SHA256");
-ok(!verify("ee-pss-sha1-cert", "sslserver", ["root-cert"], ["ca-cert"], "-auth_level", "2"),
- "Reject PSS signature using SHA1 and auth level 2");
+ok(!verify("ee-pss-sha1-cert", "sslserver", ["root-cert"], ["ca-cert"], "-auth_level", "1"),
+ "Reject PSS signature using SHA1 and auth level 1");
ok(verify("ee-pss-sha256-cert", "sslserver", ["root-cert"], ["ca-cert"], "-auth_level", "2"),
"PSS signature using SHA256 and auth level 2");