Accept spaces at end of line/buffer in base64
diff --git a/ChangeLog b/ChangeLog
index 6244af3..8e74c0b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -35,6 +35,7 @@
      POLARSSL_ERR_SSL_UNEXPECTED_MESSAGE on harmless alerts.
    * POLARSSL_MPI_MAX_SIZE now defaults to 1024 in order to allow 8192 bits
      RSA keys.
+   * Accept spaces at end of line or end of buffer in base64_decode().
 
 = PolarSSL 1.3.8 released 2014-07-11
 Security
diff --git a/library/base64.c b/library/base64.c
index 39a8323..e6c3569 100644
--- a/library/base64.c
+++ b/library/base64.c
@@ -147,8 +147,21 @@
     uint32_t j, x;
     unsigned char *p;
 
+    /* First pass: check for validity and get output length */
     for( i = n = j = 0; i < slen; i++ )
     {
+        /* Skip spaces before checking for EOL */
+        x = 0;
+        while( i < slen && src[i] == ' ' )
+        {
+            ++i;
+            ++x;
+        }
+
+        /* Spaces at end of buffer are OK */
+        if( i == slen )
+            break;
+
         if( ( slen - i ) >= 2 &&
             src[i] == '\r' && src[i + 1] == '\n' )
             continue;
@@ -156,6 +169,10 @@
         if( src[i] == '\n' )
             continue;
 
+        /* Space inside a line is an error */
+        if( x != 0 )
+            return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
+
         if( src[i] == '=' && ++j > 2 )
             return( POLARSSL_ERR_BASE64_INVALID_CHARACTER );
 
@@ -182,7 +199,7 @@
 
    for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
    {
-        if( *src == '\r' || *src == '\n' )
+        if( *src == '\r' || *src == '\n' || *src == ' ' )
             continue;
 
         j -= ( base64_dec_map[*src] == 64 );
diff --git a/tests/data_files/server7_all_space.crt b/tests/data_files/server7_all_space.crt
index 12b5e05..a979830 100644
--- a/tests/data_files/server7_all_space.crt
+++ b/tests/data_files/server7_all_space.crt
@@ -1,7 +1,7 @@
 -----BEGIN CERTIFICATE-----
 MIIDwjCCAaqgAwIBAgIBEDANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJOTDER
 MA8GA1UEChMIUG9sYXJTU0wxJjAkBgNVBAMTHVBvbGFyU1NMIFRlc3QgSW50ZXJt
-ZWRpYXRlIENBMB4XDTEzMDkyNDE2MTIyNFoXDTIzMDkyMjE2MTIyNFowNDELMAkG 
+ZWRpYXRlIENBMB4XDTEzMDkyNDE2MTIyNFoXDTIzMDkyMjE2MTIyNFowNDELMAk G
 A1UEBhMCTkwxETAPBgNVBAoTCFBvbGFyU1NMMRIwEAYDVQQDEwlsb2NhbGhvc3Qw
 WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQcbffp2qXqoZyychmoCRxzrd4Vu96m
 47NPBehtEC46aTeXgDnBdf++znABrAtfXBRNQz8ARIeYBmskr22rlKjyo4GVMIGS
@@ -37,7 +37,7 @@
 kGPOEGgvlPnIIXAawouxCaNYEh5Uw871YMSPT28rLdFr49dwYOtDg9foA8hDIW2P
 d6KXbrZteesvA1nYzEOs+3AjrbT79Md2W8Bz9bqBVNlNOESSqm4kiCJFmslm/6br
 Np0MSQd+o22PQ4xRtmP6UsTfU0ueiMpYc8TYYhMbfnfFyo4m707ebcflPbBEN2dg
-updQ66cvfCJB0QJt9upafY0lpdV1qUkCAwEAAaOBoDCBnTAdBgNVHQ4EFgQUOHfY 
+updQ66cvfCJB0QJt9upafY0lpdV1qUkCAwEAAaOBoDCBnTAdBgNVHQ4EFgQUOHf Y
 a3ecKHeCi07YG6ke95QWtw4wbgYDVR0jBGcwZYAUnW0gJEkBPyvLeLUZvH4kydv7
 NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UE
 AxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAwGA1UdEwQFMAMBAf8w
diff --git a/tests/data_files/server7_pem_space.crt b/tests/data_files/server7_pem_space.crt
index e28e0e7..0ef0fc7 100644
--- a/tests/data_files/server7_pem_space.crt
+++ b/tests/data_files/server7_pem_space.crt
@@ -1,7 +1,7 @@
 -----BEGIN CERTIFICATE-----
 MIIDwjCCAaqgAwIBAgIBEDANBgkqhkiG9w0BAQsFADBIMQswCQYDVQQGEwJOTDER
 MA8GA1UEChMIUG9sYXJTU0wxJjAkBgNVBAMTHVBvbGFyU1NMIFRlc3QgSW50ZXJt
-ZWRpYXRlIENBMB4XDTEzMDkyNDE2MTIyNFoXDTIzMDkyMjE2MTIyNFowNDELMAkG 
+ZWRpYXRlIENBMB4XDTEzMDkyNDE2MTIyNFoXDTIzMDkyMjE2MTIyNFowNDELMAk G
 A1UEBhMCTkwxETAPBgNVBAoTCFBvbGFyU1NMMRIwEAYDVQQDEwlsb2NhbGhvc3Qw
 WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAAQcbffp2qXqoZyychmoCRxzrd4Vu96m
 47NPBehtEC46aTeXgDnBdf++znABrAtfXBRNQz8ARIeYBmskr22rlKjyo4GVMIGS
diff --git a/tests/suites/test_suite_base64.data b/tests/suites/test_suite_base64.data
index 4508d89..117adc5 100644
--- a/tests/suites/test_suite_base64.data
+++ b/tests/suites/test_suite_base64.data
@@ -55,6 +55,78 @@
 Base64 decode (Invalid char after equal signs)
 base64_decode:"zm=masd":"":POLARSSL_ERR_BASE64_INVALID_CHARACTER
 
+Base64 decode (Space inside string)
+base64_decode:"zm masd":"":POLARSSL_ERR_BASE64_INVALID_CHARACTER
+
+Base64 decode "Zm9vYmFy" (no newline nor '\0' at end)
+base64_decode_hex_src:"5a6d3976596d4679":"foobar":0
+
+Base64 decode "Zm9vYmFy\n" (LF at end)
+base64_decode_hex_src:"5a6d3976596d46790a":"foobar":0
+
+Base64 decode "Zm9vYmFy\r\n" (CRLF at end)
+base64_decode_hex_src:"5a6d3976596d46790d0a":"foobar":0
+
+Base64 decode "Zm9vYmFy\r" (CR at end)
+base64_decode_hex_src:"5a6d3976596d46790d":"":POLARSSL_ERR_BASE64_INVALID_CHARACTER
+
+Base64 decode "Zm9vYmFy " (SP at end)
+base64_decode_hex_src:"5a6d3976596d467920":"foobar":0
+
+Base64 decode "Zm9vYmFy \n" (SP+LF at end)
+base64_decode_hex_src:"5a6d3976596d4679200a":"foobar":0
+
+Base64 decode "Zm9vYmFy \r\n" (SP+CRLF at end)
+base64_decode_hex_src:"5a6d3976596d4679200d0a":"foobar":0
+
+Base64 decode "Zm9vYmFy \r" (SP+CR at end)
+base64_decode_hex_src:"5a6d3976596d4679200d":"":POLARSSL_ERR_BASE64_INVALID_CHARACTER
+
+Base64 decode "Zm9vYmFy  " (2SP at end)
+base64_decode_hex_src:"5a6d3976596d46792020":"foobar":0
+
+Base64 decode "Zm9vYmFy  \n" (2SP+LF at end)
+base64_decode_hex_src:"5a6d3976596d467920200a":"foobar":0
+
+Base64 decode "Zm9vYmFy  \r\n" (2SP+CRLF at end)
+base64_decode_hex_src:"5a6d3976596d467920200d0a":"foobar":0
+
+Base64 decode "Zm9vYmFy  \r" (2SP+CR at end)
+base64_decode_hex_src:"5a6d3976596d467920200d":"":POLARSSL_ERR_BASE64_INVALID_CHARACTER
+
+Base64 decode "Zm9vYmF\ny" (LF inside)
+base64_decode_hex_src:"5a6d3976596d460a79":"foobar":0
+
+Base64 decode "Zm9vYmF\ry" (CRLF inside)
+base64_decode_hex_src:"5a6d3976596d460d0a79":"foobar":0
+
+Base64 decode "Zm9vYmF\ry" (CR inside)
+base64_decode_hex_src:"5a6d3976596d460d79":"":POLARSSL_ERR_BASE64_INVALID_CHARACTER
+
+Base64 decode "Zm9vYmF y" (SP inside)
+base64_decode_hex_src:"5a6d3976596d462079":"":POLARSSL_ERR_BASE64_INVALID_CHARACTER
+
+Base64 decode "Zm9vYmF \ny" (SP+LF inside)
+base64_decode_hex_src:"5a6d3976596d46200a79":"foobar":0
+
+Base64 decode "Zm9vYmF \ry" (SP+CRLF inside)
+base64_decode_hex_src:"5a6d3976596d46200d0a79":"foobar":0
+
+Base64 decode "Zm9vYmF \ry" (SP+CR inside)
+base64_decode_hex_src:"5a6d3976596d46200d79":"":POLARSSL_ERR_BASE64_INVALID_CHARACTER
+
+Base64 decode "Zm9vYmF  y" (2SP inside)
+base64_decode_hex_src:"5a6d3976596d46202079":"":POLARSSL_ERR_BASE64_INVALID_CHARACTER
+
+Base64 decode "Zm9vYmF  \ny" (2SP+LF inside)
+base64_decode_hex_src:"5a6d3976596d4620200a79":"foobar":0
+
+Base64 decode "Zm9vYmF  \ry" (2SP+CRLF inside)
+base64_decode_hex_src:"5a6d3976596d4620200d0a79":"foobar":0
+
+Base64 decode "Zm9vYmF  \ry" (2SP+CR inside)
+base64_decode_hex_src:"5a6d3976596d4620200d79":"":POLARSSL_ERR_BASE64_INVALID_CHARACTER
+
 Base64 encode hex #1
 base64_encode_hex:"010203040506070809":"AQIDBAUGBwgJ":13:0
 
@@ -85,3 +157,4 @@
 Base64 Selftest
 depends_on:POLARSSL_SELF_TEST
 base64_selftest:
+
diff --git a/tests/suites/test_suite_base64.function b/tests/suites/test_suite_base64.function
index de39df6..01d8aa6 100644
--- a/tests/suites/test_suite_base64.function
+++ b/tests/suites/test_suite_base64.function
@@ -33,7 +33,7 @@
     unsigned char src_str[1000];
     unsigned char dst_str[1000];
     size_t len = 1000;
-    int res; 
+    int res;
 
     memset(src_str, 0x00, 1000);
     memset(dst_str, 0x00, 1000);
@@ -95,6 +95,28 @@
 }
 /* END_CASE */
 
+/* BEGIN_CASE */
+void base64_decode_hex_src( char *src_hex, char *dst_ref, int result )
+{
+    unsigned char dst[1000] = { 0 };
+    unsigned char *src;
+    size_t src_len, len;
+
+    src = unhexify_alloc( src_hex, &src_len );
+
+    len = sizeof( dst );
+    TEST_ASSERT( base64_decode( dst, &len, src, src_len ) == result );
+    if( result == 0 )
+    {
+        TEST_ASSERT( len == strlen( dst_ref ) );
+        TEST_ASSERT( memcmp( dst, dst_ref, len ) == 0 );
+    }
+
+exit:
+    polarssl_free( src );
+}
+/* END_CASE */
+
 /* BEGIN_CASE depends_on:POLARSSL_SELF_TEST */
 void base64_selftest()
 {