Move mbedtls_cf_rsaes_pkcs1_v15_unpadding function to the constant-time module

Signed-off-by: Gabor Mezei <gabor.mezei@arm.com>
diff --git a/library/constant_time.c b/library/constant_time.c
index aa291d7..712008a 100644
--- a/library/constant_time.c
+++ b/library/constant_time.c
@@ -29,6 +29,7 @@
 #include "mbedtls/ssl_internal.h"
 #endif
 
+#include <string.h>
 
 /* constant-time buffer comparison */
 int mbedtls_ssl_safer_memcmp( const void *a, const void *b, size_t n )
@@ -710,3 +711,152 @@
 }
 
 #endif /* MBEDTLS_BIGNUM_C */
+
+#if defined(MBEDTLS_PKCS1_V15) && defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_RSA_ALT)
+
+int mbedtls_cf_rsaes_pkcs1_v15_unpadding( int mode,
+                                          size_t ilen,
+                                          size_t *olen,
+                                          unsigned char *output,
+                                          size_t output_max_len,
+                                          unsigned char *buf )
+{
+    int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
+    size_t i, plaintext_max_size;
+
+    /* The following variables take sensitive values: their value must
+     * not leak into the observable behavior of the function other than
+     * the designated outputs (output, olen, return value). Otherwise
+     * this would open the execution of the function to
+     * side-channel-based variants of the Bleichenbacher padding oracle
+     * attack. Potential side channels include overall timing, memory
+     * access patterns (especially visible to an adversary who has access
+     * to a shared memory cache), and branches (especially visible to
+     * an adversary who has access to a shared code cache or to a shared
+     * branch predictor). */
+    size_t pad_count = 0;
+    unsigned bad = 0;
+    unsigned char pad_done = 0;
+    size_t plaintext_size = 0;
+    unsigned output_too_large;
+
+    plaintext_max_size = mbedtls_cf_size_if( output_max_len > ilen - 11,
+                                             ilen - 11,
+                                             output_max_len );
+
+    /* Check and get padding length in constant time and constant
+     * memory trace. The first byte must be 0. */
+    bad |= buf[0];
+
+    if( mode == MBEDTLS_RSA_PRIVATE )
+    {
+        /* Decode EME-PKCS1-v1_5 padding: 0x00 || 0x02 || PS || 0x00
+         * where PS must be at least 8 nonzero bytes. */
+        bad |= buf[1] ^ MBEDTLS_RSA_CRYPT;
+
+        /* Read the whole buffer. Set pad_done to nonzero if we find
+         * the 0x00 byte and remember the padding length in pad_count. */
+        for( i = 2; i < ilen; i++ )
+        {
+            pad_done  |= ((buf[i] | (unsigned char)-buf[i]) >> 7) ^ 1;
+            pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1;
+        }
+    }
+    else
+    {
+        /* Decode EMSA-PKCS1-v1_5 padding: 0x00 || 0x01 || PS || 0x00
+         * where PS must be at least 8 bytes with the value 0xFF. */
+        bad |= buf[1] ^ MBEDTLS_RSA_SIGN;
+
+        /* Read the whole buffer. Set pad_done to nonzero if we find
+         * the 0x00 byte and remember the padding length in pad_count.
+         * If there's a non-0xff byte in the padding, the padding is bad. */
+        for( i = 2; i < ilen; i++ )
+        {
+            pad_done |= mbedtls_cf_uint_if( buf[i], 0, 1 );
+            pad_count += mbedtls_cf_uint_if( pad_done, 0, 1 );
+            bad |= mbedtls_cf_uint_if( pad_done, 0, buf[i] ^ 0xFF );
+        }
+    }
+
+    /* If pad_done is still zero, there's no data, only unfinished padding. */
+    bad |= mbedtls_cf_uint_if( pad_done, 0, 1 );
+
+    /* There must be at least 8 bytes of padding. */
+    bad |= mbedtls_cf_size_gt( 8, pad_count );
+
+    /* If the padding is valid, set plaintext_size to the number of
+     * remaining bytes after stripping the padding. If the padding
+     * is invalid, avoid leaking this fact through the size of the
+     * output: use the maximum message size that fits in the output
+     * buffer. Do it without branches to avoid leaking the padding
+     * validity through timing. RSA keys are small enough that all the
+     * size_t values involved fit in unsigned int. */
+    plaintext_size = mbedtls_cf_uint_if(
+                        bad, (unsigned) plaintext_max_size,
+                        (unsigned) ( ilen - pad_count - 3 ) );
+
+    /* Set output_too_large to 0 if the plaintext fits in the output
+     * buffer and to 1 otherwise. */
+    output_too_large = mbedtls_cf_size_gt( plaintext_size,
+                                           plaintext_max_size );
+
+    /* Set ret without branches to avoid timing attacks. Return:
+     * - INVALID_PADDING if the padding is bad (bad != 0).
+     * - OUTPUT_TOO_LARGE if the padding is good but the decrypted
+     *   plaintext does not fit in the output buffer.
+     * - 0 if the padding is correct. */
+    ret = - (int) mbedtls_cf_uint_if(
+                    bad, - MBEDTLS_ERR_RSA_INVALID_PADDING,
+                    mbedtls_cf_uint_if( output_too_large,
+                                        - MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE,
+                                        0 ) );
+
+    /* If the padding is bad or the plaintext is too large, zero the
+     * data that we're about to copy to the output buffer.
+     * We need to copy the same amount of data
+     * from the same buffer whether the padding is good or not to
+     * avoid leaking the padding validity through overall timing or
+     * through memory or cache access patterns. */
+    bad = mbedtls_cf_uint_mask( bad | output_too_large );
+    for( i = 11; i < ilen; i++ )
+        buf[i] &= ~bad;
+
+    /* If the plaintext is too large, truncate it to the buffer size.
+     * Copy anyway to avoid revealing the length through timing, because
+     * revealing the length is as bad as revealing the padding validity
+     * for a Bleichenbacher attack. */
+    plaintext_size = mbedtls_cf_uint_if( output_too_large,
+                                         (unsigned) plaintext_max_size,
+                                         (unsigned) plaintext_size );
+
+    /* Move the plaintext to the leftmost position where it can start in
+     * the working buffer, i.e. make it start plaintext_max_size from
+     * the end of the buffer. Do this with a memory access trace that
+     * does not depend on the plaintext size. After this move, the
+     * starting location of the plaintext is no longer sensitive
+     * information. */
+    mbedtls_cf_mem_move_to_left( buf + ilen - plaintext_max_size,
+                                 plaintext_max_size,
+                                 plaintext_max_size - plaintext_size );
+
+    /* Finally copy the decrypted plaintext plus trailing zeros into the output
+     * buffer. If output_max_len is 0, then output may be an invalid pointer
+     * and the result of memcpy() would be undefined; prevent undefined
+     * behavior making sure to depend only on output_max_len (the size of the
+     * user-provided output buffer), which is independent from plaintext
+     * length, validity of padding, success of the decryption, and other
+     * secrets. */
+    if( output_max_len != 0 )
+        memcpy( output, buf + ilen - plaintext_max_size, plaintext_max_size );
+
+    /* Report the amount of data we copied to the output buffer. In case
+     * of errors (bad padding or output too large), the value of *olen
+     * when this function returns is not specified. Making it equivalent
+     * to the good case limits the risks of leaking the padding validity. */
+    *olen = plaintext_size;
+
+    return( ret );
+}
+
+#endif /* MBEDTLS_PKCS1_V15 && MBEDTLS_RSA_C && ! MBEDTLS_RSA_ALT */