Fix mbedtls_base64_decode() accepting invalid inputs with 4n+1 digits

The last digit was ignored.

Signed-off-by: Gilles Peskine <Gilles.Peskine@arm.com>
diff --git a/ChangeLog.d/base64_decode.txt b/ChangeLog.d/base64_decode.txt
new file mode 100644
index 0000000..93dfef1
--- /dev/null
+++ b/ChangeLog.d/base64_decode.txt
@@ -0,0 +1,3 @@
+Bugfix
+   * Fix mbedtls_base64_decode() accepting invalid inputs with 4n+1 digits
+     (the last digit was ignored).
diff --git a/library/base64.c b/library/base64.c
index 9677dee..bff9123 100644
--- a/library/base64.c
+++ b/library/base64.c
@@ -183,6 +183,12 @@
         n++;
     }
 
+    /* In valid base64, the number of digits is always of the form
+     * 4n, 4n+2 or 4n+3. */
+    if ((n - equals) % 4 == 1) {
+        return MBEDTLS_ERR_BASE64_INVALID_CHARACTER;
+    }
+
     if (n == 0) {
         *olen = 0;
         return 0;
diff --git a/tests/suites/test_suite_base64.data b/tests/suites/test_suite_base64.data
index 9488df3..4d3b5b9 100644
--- a/tests/suites/test_suite_base64.data
+++ b/tests/suites/test_suite_base64.data
@@ -84,14 +84,14 @@
 # output when dlen < 3, but actually outputs 2 bytes if given a
 # buffer of 3 bytes or more.
 
-Base64 decode: 1 digit, 0 equals (sloppily accepted)
-mbedtls_base64_decode:"Y":"!":0
+Base64 decode: 1 digit, 0 equals (bad)
+mbedtls_base64_decode:"Y":"":MBEDTLS_ERR_BASE64_INVALID_CHARACTER
 
-Base64 decode: 1 digit, 1 equals (sloppily accepted)
-mbedtls_base64_decode:"Y":"!":0
+Base64 decode: 1 digit, 1 equals (bad)
+mbedtls_base64_decode:"Y":"":MBEDTLS_ERR_BASE64_INVALID_CHARACTER
 
-Base64 decode: 1 digit, 2 equals (sloppily accepted)
-mbedtls_base64_decode:"Y==":"!":0
+Base64 decode: 1 digit, 2 equals (bad)
+mbedtls_base64_decode:"Y==":"":MBEDTLS_ERR_BASE64_INVALID_CHARACTER
 
 Base64 decode: 1 digit, 3 equals (bad)
 mbedtls_base64_decode:"Y===":"!":MBEDTLS_ERR_BASE64_INVALID_CHARACTER
@@ -132,14 +132,14 @@
 Base64 decode: 4 digits, 3 equals (bad)
 mbedtls_base64_decode:"Y29t===":"com":MBEDTLS_ERR_BASE64_INVALID_CHARACTER
 
-Base64 decode: 5 digits, 0 equals (sloppily accepted)
-mbedtls_base64_decode:"Y29tc":"com!":0
+Base64 decode: 5 digits, 0 equals (bad)
+mbedtls_base64_decode:"Y29tc":"":MBEDTLS_ERR_BASE64_INVALID_CHARACTER
 
-Base64 decode: 5 digits, 1 equals (sloppily accepted)
-mbedtls_base64_decode:"Y29tc=":"com!":0
+Base64 decode: 5 digits, 1 equals (bad)
+mbedtls_base64_decode:"Y29tc=":"":MBEDTLS_ERR_BASE64_INVALID_CHARACTER
 
-Base64 decode: 5 digits, 2 equals (sloppily accepted)
-mbedtls_base64_decode:"Y29tc==":"com!":0
+Base64 decode: 5 digits, 2 equals (bad)
+mbedtls_base64_decode:"Y29tc==":"":MBEDTLS_ERR_BASE64_INVALID_CHARACTER
 
 Base64 decode: 5 digits, 3 equals (bad)
 mbedtls_base64_decode:"Y29tc===":"com!":MBEDTLS_ERR_BASE64_INVALID_CHARACTER