Add checks to X509_NAME_oneline()

Sanity check field lengths and sums to avoid potential overflows and reject
excessively large X509_NAME structures.

Issue reported by Guido Vranken.

(Imported from upstream's 9b08619cb45e75541809b1154c90e1a00450e537.)

Change-Id: Ib2e1e7cd086f9c3f0d689d61947f8ec3e9220049
Reviewed-on: https://boringssl-review.googlesource.com/7842
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/err/x509.errordata b/crypto/err/x509.errordata
index a1d49b7..5687c30 100644
--- a/crypto/err/x509.errordata
+++ b/crypto/err/x509.errordata
@@ -17,6 +17,7 @@
 X509,116,KEY_VALUES_MISMATCH
 X509,117,LOADING_CERT_DIR
 X509,118,LOADING_DEFAULTS
+X509,135,NAME_TOO_LONG
 X509,119,NEWER_CRL_NOT_NEWER
 X509,120,NOT_PKCS7_SIGNED_DATA
 X509,121,NO_CERTIFICATES_INCLUDED
diff --git a/crypto/x509/x509_obj.c b/crypto/x509/x509_obj.c
index 2195216..a7f31e0 100644
--- a/crypto/x509/x509_obj.c
+++ b/crypto/x509/x509_obj.c
@@ -64,6 +64,13 @@
 #include <openssl/obj.h>
 #include <openssl/x509.h>
 
+/*
+ * Limit to ensure we don't overflow: much greater than
+ * anything enountered in practice.
+ */
+
+#define NAME_ONELINE_MAX    (1024 * 1024)
+
 char *X509_NAME_oneline(X509_NAME *a, char *buf, int len)
 {
     X509_NAME_ENTRY *ne;
@@ -110,6 +117,10 @@
 
         type = ne->value->type;
         num = ne->value->length;
+        if (num > NAME_ONELINE_MAX) {
+            OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG);
+            goto end;
+        }
         q = ne->value->data;
 
         if ((type == V_ASN1_GENERALSTRING) && ((num % 4) == 0)) {
@@ -137,6 +148,10 @@
 
         lold = l;
         l += 1 + l1 + 1 + l2;
+        if (l > NAME_ONELINE_MAX) {
+            OPENSSL_PUT_ERROR(X509, X509_R_NAME_TOO_LONG);
+            goto end;
+        }
         if (b != NULL) {
             if (!BUF_MEM_grow(b, l + 1))
                 goto err;
@@ -176,7 +191,7 @@
     return (p);
  err:
     OPENSSL_PUT_ERROR(X509, ERR_R_MALLOC_FAILURE);
-    if (b != NULL)
-        BUF_MEM_free(b);
+ end:
+    BUF_MEM_free(b);
     return (NULL);
 }
diff --git a/include/openssl/x509.h b/include/openssl/x509.h
index 4b977b9..bbc263e 100644
--- a/include/openssl/x509.h
+++ b/include/openssl/x509.h
@@ -1262,5 +1262,6 @@
 #define X509_R_UNSUPPORTED_ALGORITHM 132
 #define X509_R_WRONG_LOOKUP_TYPE 133
 #define X509_R_WRONG_TYPE 134
+#define X509_R_NAME_TOO_LONG 135
 
 #endif