Merge fix for IOTSSL-480 - base64 overflow issue
diff --git a/ChangeLog b/ChangeLog
index 2aa7a21..c527e06 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -30,6 +30,13 @@
 = mbed TLS 2.1.1 released 2015-09-17
 
 Security
+   * Fix possible heap buffer overflow in base64_encoded() when the input
+     buffer is 512MB or larger on 32-bit platforms.
+     Found by Guido Vranken. Not trigerrable remotely in TLS.
+
+= mbed TLS 2.1.1 released 2015-09-17
+
+Security
    * Add countermeasure against Lenstra's RSA-CRT attack for PKCS#1 v1.5
      signatures. (Found by Florian Weimer, Red Hat.)
      https://securityblog.redhat.com/2015/09/02/factoring-rsa-keys-with-tls-perfect-forward-secrecy/
diff --git a/include/mbedtls/base64.h b/include/mbedtls/base64.h
index 28a3a4c..18e8312 100644
--- a/include/mbedtls/base64.h
+++ b/include/mbedtls/base64.h
@@ -24,6 +24,7 @@
 #define MBEDTLS_BASE64_H
 
 #include <stddef.h>
+#include <limits.h>
 
 #define MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL               -0x002A  /**< Output buffer too small. */
 #define MBEDTLS_ERR_BASE64_INVALID_CHARACTER              -0x002C  /**< Invalid character in input. */
@@ -44,6 +45,8 @@
  * \return         0 if successful, or MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL.
  *                 *olen is always updated to reflect the amount
  *                 of data that has (or would have) been written.
+ *                 If that length cannot be represented, then no data is
+ *                 written to the buffer and *olen is set to SIZE_T_MAX.
  *
  * \note           Call this function with dlen = 0 to obtain the
  *                 required buffer size in *olen
diff --git a/library/base64.c b/library/base64.c
index e468e2c..fc44c15 100644
--- a/library/base64.c
+++ b/library/base64.c
@@ -85,15 +85,16 @@
         return( 0 );
     }
 
-    n = ( slen << 3 ) / 6;
+    n = slen / 3 + ( slen % 3 != 0 );
 
-    switch( ( slen << 3 ) - ( n * 6 ) )
+    if( n > ( SIZE_T_MAX - 1 ) / 4 )
     {
-        case  2: n += 3; break;
-        case  4: n += 2; break;
-        default: break;
+        *olen = SIZE_T_MAX;
+        return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL );
     }
 
+    n *= 4;
+
     if( dlen < n + 1 )
     {
         *olen = n + 1;
diff --git a/tests/suites/test_suite_base64.data b/tests/suites/test_suite_base64.data
index 3b66da1..da99ffa 100644
--- a/tests/suites/test_suite_base64.data
+++ b/tests/suites/test_suite_base64.data
@@ -1,23 +1,41 @@
-Test case mbedtls_base64_encode #1
-mbedtls_base64_encode:"":"":1000:0
+Test case mbedtls_base64_encode #1 buffer just right
+mbedtls_base64_encode:"":"":0:0
 
-Test case mbedtls_base64_encode #2
-mbedtls_base64_encode:"f":"Zg==":1000:0
+Test case mbedtls_base64_encode #2 buffer just right
+mbedtls_base64_encode:"f":"Zg==":5:0
 
-Test case mbedtls_base64_encode #3
-mbedtls_base64_encode:"fo":"Zm8=":1000:0
+Test case mbedtls_base64_encode #2 buffer too small
+mbedtls_base64_encode:"f":"Zg==":4:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
 
-Test case mbedtls_base64_encode #4
-mbedtls_base64_encode:"foo":"Zm9v":1000:0
+Test case mbedtls_base64_encode #3 buffer just right
+mbedtls_base64_encode:"fo":"Zm8=":5:0
 
-Test case mbedtls_base64_encode #5
-mbedtls_base64_encode:"foob":"Zm9vYg==":1000:0
+Test case mbedtls_base64_encode #3 buffer too small
+mbedtls_base64_encode:"fo":"Zm8=":4:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
 
-Test case mbedtls_base64_encode #6
-mbedtls_base64_encode:"fooba":"Zm9vYmE=":1000:0
+Test case mbedtls_base64_encode #4 buffer just right
+mbedtls_base64_encode:"foo":"Zm9v":5:0
 
-Test case mbedtls_base64_encode #7
-mbedtls_base64_encode:"foobar":"Zm9vYmFy":1000:0
+Test case mbedtls_base64_encode #4 buffer too small
+mbedtls_base64_encode:"foo":"Zm9v":4:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
+
+Test case mbedtls_base64_encode #5 buffer just right
+mbedtls_base64_encode:"foob":"Zm9vYg==":9:0
+
+Test case mbedtls_base64_encode #5 buffer too small
+mbedtls_base64_encode:"foob":"Zm9vYg==":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
+
+Test case mbedtls_base64_encode #6 buffer just right
+mbedtls_base64_encode:"fooba":"Zm9vYmE=":9:0
+
+Test case mbedtls_base64_encode #6 buffer too small
+mbedtls_base64_encode:"fooba":"Zm9vYmE=":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
+
+Test case mbedtls_base64_encode #7 buffer just right
+mbedtls_base64_encode:"foobar":"Zm9vYmFy":9:0
+
+Test case mbedtls_base64_encode #7 buffer too small
+mbedtls_base64_encode:"foobar":"Zm9vYmFy":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
 
 Test case mbedtls_base64_decode #1
 mbedtls_base64_decode:"":"":0
@@ -40,12 +58,6 @@
 Test case mbedtls_base64_decode #7
 mbedtls_base64_decode:"Zm9vYmFy":"foobar":0
 
-Base64 encode (buffer size just right)
-mbedtls_base64_encode:"foobar":"Zm9vYmFy":9:0
-
-Base64 encode (buffer size too small)
-mbedtls_base64_encode:"foobar":"":8:MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL
-
 Base64 decode (Illegal character)
 mbedtls_base64_decode:"zm#=":"":MBEDTLS_ERR_BASE64_INVALID_CHARACTER