Fix timing side-channel in PKCS7 padding

Previously, we were checking if the last padding byte was in the range
1-16 and returning early if not. This was to prevent an integer overflow
in the output length.

Instead, do the checks in constant-time and conditionally set the output
length based on whether the padding is correct or not, preventing both
the side-channel and the integer overflow.

Signed-off-by: David Horstmann <david.horstmann@arm.com>
diff --git a/library/cipher.c b/library/cipher.c
index 5e14e1e..9be53b7 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -851,10 +851,6 @@
     }
 
     padding_len = input[input_len - 1];
-    if (padding_len == 0 || padding_len > input_len) {
-        return MBEDTLS_ERR_CIPHER_INVALID_PADDING;
-    }
-    *data_len = input_len - padding_len;
 
     mbedtls_ct_condition_t bad = mbedtls_ct_uint_gt(padding_len, input_len);
     bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_eq(padding_len, 0));
@@ -868,6 +864,9 @@
         bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different));
     }
 
+    /* If the padding is invalid, set the output length to 0 */
+    *data_len = mbedtls_ct_if(bad, 0, input_len - padding_len);
+
     return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING);
 }
 #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */