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