aboutsummaryrefslogtreecommitdiff
path: root/crypto/x509v3
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@google.com>2017-09-18 16:51:56 -0400
committerAndy Polyakov <appro@openssl.org>2017-09-22 22:00:55 +0200
commit8545051c3652bce7bb962afcb6879c4a6288bc67 (patch)
tree03f47ed1bb5c20496f6ed891540e0490265791df /crypto/x509v3
parent79b4444d81e2b9f21c60d7bf6511200e3e41d6fd (diff)
downloadopenssl-8545051c3652bce7bb962afcb6879c4a6288bc67.zip
openssl-8545051c3652bce7bb962afcb6879c4a6288bc67.tar.gz
openssl-8545051c3652bce7bb962afcb6879c4a6288bc67.tar.bz2
Guard against DoS in name constraints handling.
This guards against the name constraints check consuming large amounts of CPU time when certificates in the presented chain contain an excessive number of names (specifically subject email names or subject alternative DNS names) and/or name constraints. Name constraints checking compares the names presented in a certificate against the name constraints included in a certificate higher up in the chain using two nested for loops. Move the name constraints check so that it happens after signature verification so peers cannot exploit this using a chain with invalid signatures. Also impose a hard limit on the number of name constraints check loop iterations to further mitigate the issue. Thanks to NCC for finding this issue. Fix written by Martin Kreichgauer. Reviewed-by: Rich Salz <rsalz@openssl.org> Reviewed-by: Andy Polyakov <appro@openssl.org> (Merged from https://github.com/openssl/openssl/pull/4393)
Diffstat (limited to 'crypto/x509v3')
-rw-r--r--crypto/x509v3/v3_ncons.c31
1 files changed, 30 insertions, 1 deletions
diff --git a/crypto/x509v3/v3_ncons.c b/crypto/x509v3/v3_ncons.c
index 7731bac..561128e 100644
--- a/crypto/x509v3/v3_ncons.c
+++ b/crypto/x509v3/v3_ncons.c
@@ -9,6 +9,7 @@
#include "e_os.h" /* for strncasecmp */
#include "internal/cryptlib.h"
+#include <limits.h>
#include <stdio.h>
#include "internal/asn1_int.h"
#include <openssl/asn1t.h>
@@ -166,6 +167,22 @@ static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
return 1;
}
+#define NAME_CHECK_MAX (1 << 20)
+
+static int add_lengths(int *out, int a, int b)
+{
+ /* sk_FOO_num(NULL) returns -1 but is effectively 0 when iterating. */
+ if (a < 0)
+ a = 0;
+ if (b < 0)
+ b = 0;
+
+ if (a > INT_MAX - b)
+ return 0;
+ *out = a + b;
+ return 1;
+}
+
/*-
* Check a certificate conforms to a specified set of constraints.
* Return values:
@@ -180,11 +197,23 @@ static int print_nc_ipadd(BIO *bp, ASN1_OCTET_STRING *ip)
int NAME_CONSTRAINTS_check(X509 *x, NAME_CONSTRAINTS *nc)
{
- int r, i;
+ int r, i, name_count, constraint_count;
X509_NAME *nm;
nm = X509_get_subject_name(x);
+ /*
+ * Guard against certificates with an excessive number of names or
+ * constraints causing a computationally expensive name constraints check.
+ */
+ if (!add_lengths(&name_count, X509_NAME_entry_count(nm),
+ sk_GENERAL_NAME_num(x->altname))
+ || !add_lengths(&constraint_count,
+ sk_GENERAL_SUBTREE_num(nc->permittedSubtrees),
+ sk_GENERAL_SUBTREE_num(nc->excludedSubtrees))
+ || (name_count > 0 && constraint_count > NAME_CHECK_MAX / name_count))
+ return X509_V_ERR_UNSPECIFIED;
+
if (X509_NAME_entry_count(nm) > 0) {
GENERAL_NAME gntmp;
gntmp.type = GEN_DIRNAME;