230 lines
5.9 KiB
Diff
230 lines
5.9 KiB
Diff
diff --git a/crypto/asn1/a_verify.c b/crypto/asn1/a_verify.c
|
|
index 3ffd934..23271be 100644
|
|
--- a/crypto/asn1/a_verify.c
|
|
+++ b/crypto/asn1/a_verify.c
|
|
@@ -56,6 +56,9 @@
|
|
* [including the GNU Public Licence.]
|
|
*/
|
|
|
|
+/* for secure_getenv */
|
|
+#define _GNU_SOURCE
|
|
+
|
|
#include <stdio.h>
|
|
#include <time.h>
|
|
|
|
@@ -133,6 +136,30 @@ int ASN1_verify(i2d_of_void *i2d, X509_ALGOR *a, ASN1_BIT_STRING *signature,
|
|
|
|
#endif
|
|
|
|
+static int legacy_mds[] = { NID_md5, NID_sha, NID_md4, NID_md2, 0 };
|
|
+extern int private_ossl_allowed_legacy_mds[];
|
|
+
|
|
+static int is_md_legacy_disallowed(int mdnid)
|
|
+{
|
|
+ int i;
|
|
+
|
|
+ if (mdnid == NID_md5 && secure_getenv("OPENSSL_ENABLE_MD5_VERIFY") != NULL)
|
|
+ return 0;
|
|
+
|
|
+ for (i = 0; legacy_mds[i] != 0; ++i) {
|
|
+ if (mdnid == legacy_mds[i]) {
|
|
+ int j;
|
|
+
|
|
+ for (j = 0; private_ossl_allowed_legacy_mds[j] != 0; ++j) {
|
|
+ if (mdnid == private_ossl_allowed_legacy_mds[j])
|
|
+ return 0;
|
|
+ }
|
|
+ return 1;
|
|
+ }
|
|
+ }
|
|
+ return 0;
|
|
+}
|
|
+
|
|
int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
|
|
ASN1_BIT_STRING *signature, void *asn, EVP_PKEY *pkey)
|
|
{
|
|
@@ -174,6 +201,10 @@ int ASN1_item_verify(const ASN1_ITEM *it, X509_ALGOR *a,
|
|
if (ret != 2)
|
|
goto err;
|
|
ret = -1;
|
|
+ } else if (is_md_legacy_disallowed(mdnid)) {
|
|
+ ASN1err(ASN1_F_ASN1_ITEM_VERIFY,
|
|
+ ASN1_R_UNKNOWN_MESSAGE_DIGEST_ALGORITHM);
|
|
+ goto err;
|
|
} else {
|
|
const EVP_MD *type;
|
|
type = EVP_get_digestbynid(mdnid);
|
|
diff --git a/crypto/o_init.c b/crypto/o_init.c
|
|
index 2f754ef..59439c2 100644
|
|
--- a/crypto/o_init.c
|
|
+++ b/crypto/o_init.c
|
|
@@ -55,6 +55,12 @@
|
|
|
|
#include <e_os.h>
|
|
#include <openssl/err.h>
|
|
+# include <stdio.h>
|
|
+# include <string.h>
|
|
+# include <strings.h>
|
|
+# include <ctype.h>
|
|
+# include <openssl/dh.h>
|
|
+# include <openssl/objects.h>
|
|
#ifdef OPENSSL_FIPS
|
|
# include <sys/types.h>
|
|
# include <sys/stat.h>
|
|
@@ -89,6 +95,121 @@ static void init_fips_mode(void)
|
|
}
|
|
#endif
|
|
|
|
+# define LEGACY_SETTINGS_FILE "/etc/pki/tls/legacy-settings"
|
|
+
|
|
+# define NUM_MAX_LEGACY_MDS 8
|
|
+
|
|
+int private_ossl_allowed_legacy_mds[NUM_MAX_LEGACY_MDS + 1]; /* zero terminated */
|
|
+
|
|
+int private_ossl_minimum_dh_bits;
|
|
+
|
|
+#if !defined(_WIN32)
|
|
+static void parse_legacy_mds(char *p)
|
|
+{
|
|
+ int idx = 0;
|
|
+ char *e = p;
|
|
+
|
|
+ while (p[0] != '\0') {
|
|
+ while (e[0] != '\0' && !isspace(e[0]) && e[0] != ',') {
|
|
+ ++e;
|
|
+ }
|
|
+ if (e[0] != '\0') {
|
|
+ e[0] = '\0';
|
|
+ ++e;
|
|
+ }
|
|
+
|
|
+ if (strcasecmp(p, "md5") == 0) {
|
|
+ private_ossl_allowed_legacy_mds[idx++] = NID_md5;
|
|
+ } else if (strcasecmp(p, "md4") == 0) {
|
|
+ private_ossl_allowed_legacy_mds[idx++] = NID_md4;
|
|
+ } else if (strcasecmp(p, "sha") == 0) {
|
|
+ private_ossl_allowed_legacy_mds[idx++] = NID_sha;
|
|
+ } else if (strcasecmp(p, "md2") == 0) {
|
|
+ private_ossl_allowed_legacy_mds[idx++] = NID_md2;
|
|
+ }
|
|
+
|
|
+ if (idx >=
|
|
+ sizeof(private_ossl_allowed_legacy_mds) /
|
|
+ sizeof(private_ossl_allowed_legacy_mds[0])) {
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ while (e[0] == ',' || isspace(e[0])) {
|
|
+ ++e;
|
|
+ }
|
|
+
|
|
+ p = e;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void parse_minimum_dh_bits(char *p)
|
|
+{
|
|
+ private_ossl_minimum_dh_bits = strtol(p, NULL, 10);
|
|
+ if (private_ossl_minimum_dh_bits < 512
|
|
+ || private_ossl_minimum_dh_bits > OPENSSL_DH_MAX_MODULUS_BITS) {
|
|
+ /* use default */
|
|
+ private_ossl_minimum_dh_bits = 0;
|
|
+ }
|
|
+}
|
|
+
|
|
+static void load_legacy_settings(void)
|
|
+{
|
|
+ FILE *f;
|
|
+ char *line = NULL;
|
|
+ size_t len = 0;
|
|
+
|
|
+ if ((f = fopen(LEGACY_SETTINGS_FILE, "r")) == NULL) {
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ while (getline(&line, &len, f) > 0) {
|
|
+ char *p = line, *e, *val;
|
|
+
|
|
+ /* skip initial whitespace */
|
|
+ while (isspace(p[0])) {
|
|
+ ++p;
|
|
+ }
|
|
+
|
|
+ e = p;
|
|
+
|
|
+ while (e[0] != '\0' && !isspace(e[0])) {
|
|
+ ++e;
|
|
+ }
|
|
+
|
|
+ /* terminate name, skip whitespace between name and value */
|
|
+ if (e[0] != '\0') {
|
|
+ e[0] = '\0';
|
|
+ ++e;
|
|
+ while (isspace(e[0])) {
|
|
+ ++e;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ val = e;
|
|
+
|
|
+ e = e + strlen(val);
|
|
+
|
|
+ /* trim terminating whitespace */
|
|
+ while (e > val) {
|
|
+ --e;
|
|
+ if (isspace(e[0])) {
|
|
+ e[0] = '\0';
|
|
+ } else {
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (strcasecmp(p, "LegacySigningMDs") == 0) {
|
|
+ parse_legacy_mds(val);
|
|
+ } else if (strcasecmp(line, "MinimumDHBits") == 0) {
|
|
+ parse_minimum_dh_bits(val);
|
|
+ }
|
|
+ /* simply skip other unrecognized lines */
|
|
+ }
|
|
+ (void)fclose(f);
|
|
+}
|
|
+#endif
|
|
+
|
|
/*
|
|
* Perform any essential OpenSSL initialization operations. Currently only
|
|
* sets FIPS callbacks
|
|
@@ -100,6 +221,10 @@ void OPENSSL_init_library(void)
|
|
if (done)
|
|
return;
|
|
done = 1;
|
|
+
|
|
+#if !defined(_WIN32)
|
|
+ load_legacy_settings();
|
|
+#endif
|
|
#ifdef OPENSSL_FIPS
|
|
RAND_init_fips();
|
|
init_fips_mode();
|
|
diff --git a/ssl/s3_clnt.c b/ssl/s3_clnt.c
|
|
index 32f2f1a..6734e8a 100644
|
|
--- a/ssl/s3_clnt.c
|
|
+++ b/ssl/s3_clnt.c
|
|
@@ -3500,6 +3500,8 @@ int ssl3_send_client_certificate(SSL *s)
|
|
|
|
#define has_bits(i,m) (((i)&(m)) == (m))
|
|
|
|
+extern int private_ossl_minimum_dh_bits;
|
|
+
|
|
int ssl3_check_cert_and_algorithm(SSL *s)
|
|
{
|
|
int i, idx;
|
|
@@ -3630,8 +3632,7 @@ int ssl3_check_cert_and_algorithm(SSL *s)
|
|
DH_free(dh_srvr);
|
|
}
|
|
|
|
- if ((!SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 1024)
|
|
- || (SSL_C_IS_EXPORT(s->s3->tmp.new_cipher) && dh_size < 512)) {
|
|
+ if (dh_size < (private_ossl_minimum_dh_bits ? private_ossl_minimum_dh_bits : 1024)) {
|
|
SSLerr(SSL_F_SSL3_CHECK_CERT_AND_ALGORITHM, SSL_R_DH_KEY_TOO_SMALL);
|
|
goto f_err;
|
|
}
|