Add EVP_EncodedLength.

Several callers of EVP_EncodeBlock are doing ad-hoc versions of this
function without any overflow checks.

Change-Id: I4d0cad2347ea8c44b42465e8b14b2783db69ee8f
Reviewed-on: https://boringssl-review.googlesource.com/1511
Reviewed-by: David Benjamin <davidben@chromium.org>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/base64/base64.c b/crypto/base64/base64.c
index 4cd95d6..2336cf5 100644
--- a/crypto/base64/base64.c
+++ b/crypto/base64/base64.c
@@ -402,3 +402,21 @@
 
   return ret;
 }
+
+int EVP_EncodedLength(size_t *out_len, size_t len) {
+  if (len + 2 < len) {
+    return 0;
+  }
+  len += 2;
+  len /= 3;
+  if (((len << 2) >> 2) != len) {
+    return 0;
+  }
+  len <<= 2;
+  if (len + 1 < len) {
+    return 0;
+  }
+  len++;
+  *out_len = len;
+  return 1;
+}
diff --git a/crypto/err/err.c b/crypto/err/err.c
index 9d29f1c..a06e159 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -659,6 +659,7 @@
     {ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED, "function should not be called"},
     {ERR_R_PASSED_NULL_PARAMETER, "passed a null parameter"},
     {ERR_R_INTERNAL_ERROR, "internal error"},
+    {ERR_R_OVERFLOW, "overflow"},
 
     {ERR_PACK(ERR_LIB_SYS, SYS_F_fopen, 0), "fopen"},
     {ERR_PACK(ERR_LIB_SYS, SYS_F_fclose, 0), "fclose"},
diff --git a/crypto/x509/x509spki.c b/crypto/x509/x509spki.c
index 243a7d2..0b0b4fa 100644
--- a/crypto/x509/x509spki.c
+++ b/crypto/x509/x509spki.c
@@ -102,14 +102,20 @@
 {
 	unsigned char *der_spki, *p;
 	char *b64_str;
+	size_t b64_len;
 	int der_len;
 	der_len = i2d_NETSCAPE_SPKI(spki, NULL);
+	if (!EVP_EncodedLength(&b64_len, der_len))
+		{
+		OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_encode, ERR_R_OVERFLOW);
+		return NULL;
+		}
 	der_spki = OPENSSL_malloc(der_len);
 	if (der_spki == NULL) {
 		OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_encode, ERR_R_MALLOC_FAILURE);
 		return NULL;
 	}
-	b64_str = OPENSSL_malloc((der_len + 2) / 3 * 4 + 1);
+	b64_str = OPENSSL_malloc(b64_len);
 	if (b64_str == NULL) {
 		OPENSSL_free(der_spki);
 		OPENSSL_PUT_ERROR(X509, NETSCAPE_SPKI_b64_encode, ERR_R_MALLOC_FAILURE);
diff --git a/include/openssl/base64.h b/include/openssl/base64.h
index 38cb0ee..521004a 100644
--- a/include/openssl/base64.h
+++ b/include/openssl/base64.h
@@ -102,6 +102,12 @@
 OPENSSL_EXPORT size_t
     EVP_EncodeBlock(uint8_t *dst, const uint8_t *src, size_t src_len);
 
+/* EVP_EncodedLength sets |*out_len| to the number of bytes that will be needed
+ * to call |EVP_EncodeBlock| on an input of length |len|. This includes the
+ * final NUL that |EVP_EncodeBlock| writes. It returns one on success or zero
+ * on error. */
+int EVP_EncodedLength(size_t *out_len, size_t len);
+
 
 /* Decoding */
 
diff --git a/include/openssl/err.h b/include/openssl/err.h
index 8ebd73f..d8e7cd5 100644
--- a/include/openssl/err.h
+++ b/include/openssl/err.h
@@ -444,6 +444,7 @@
 #define ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED (2 | ERR_R_FATAL)
 #define ERR_R_PASSED_NULL_PARAMETER (3 | ERR_R_FATAL)
 #define ERR_R_INTERNAL_ERROR (4 | ERR_R_FATAL)
+#define ERR_R_OVERFLOW (5 | ERR_R_FATAL)
 
 /* System error functions */
 #define SYS_F_fopen 100