Merge pull request #1082 from daverodgman/padding-ct-changelog-2.28
Backport 2.28: Add Changelog for CT fixes
diff --git a/library/ccm.c b/library/ccm.c
index 2d2695e..79a04a2 100644
--- a/library/ccm.c
+++ b/library/ccm.c
@@ -33,6 +33,7 @@
#include "mbedtls/ccm.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
+#include "mbedtls/constant_time.h"
#include <string.h>
@@ -362,7 +363,6 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
- unsigned char i;
int diff;
CCM_VALIDATE_RET(ctx != NULL);
@@ -379,9 +379,7 @@
}
/* Check tag in "constant-time" */
- for (diff = 0, i = 0; i < tag_len; i++) {
- diff |= tag[i] ^ check_tag[i];
- }
+ diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
if (diff != 0) {
mbedtls_platform_zeroize(output, length);
diff --git a/library/chachapoly.c b/library/chachapoly.c
index ceb4292..547ffb2 100644
--- a/library/chachapoly.c
+++ b/library/chachapoly.c
@@ -25,6 +25,7 @@
#include "mbedtls/chachapoly.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
+#include "mbedtls/constant_time.h"
#include <string.h>
@@ -337,7 +338,6 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
- size_t i;
int diff;
CHACHAPOLY_VALIDATE_RET(ctx != NULL);
CHACHAPOLY_VALIDATE_RET(nonce != NULL);
@@ -353,9 +353,7 @@
}
/* Check tag in "constant-time" */
- for (diff = 0, i = 0; i < sizeof(check_tag); i++) {
- diff |= tag[i] ^ check_tag[i];
- }
+ diff = mbedtls_ct_memcmp(tag, check_tag, sizeof(check_tag));
if (diff != 0) {
mbedtls_platform_zeroize(output, length);
diff --git a/library/cipher.c b/library/cipher.c
index 4b715d4..09ca686 100644
--- a/library/cipher.c
+++ b/library/cipher.c
@@ -30,6 +30,7 @@
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "mbedtls/constant_time.h"
+#include "constant_time_internal.h"
#include <stdlib.h>
#include <string.h>
@@ -748,17 +749,17 @@
*data_len = input_len - padding_len;
/* Avoid logical || since it results in a branch */
- bad |= padding_len > input_len;
- bad |= padding_len == 0;
+ bad |= ~mbedtls_ct_size_mask_ge(input_len, padding_len);
+ bad |= mbedtls_ct_size_bool_eq(padding_len, 0);
/* The number of bytes checked must be independent of padding_len,
* so pick input_len, which is usually 8 or 16 (one block) */
pad_idx = input_len - padding_len;
for (i = 0; i < input_len; i++) {
- bad |= (input[i] ^ padding_len) * (i >= pad_idx);
+ size_t mask = mbedtls_ct_size_mask_ge(i, pad_idx);
+ bad |= (input[i] ^ padding_len) & mask;
}
-
- return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+ return -(int) mbedtls_ct_uint_if(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING, 0);
}
#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */
@@ -781,24 +782,29 @@
static int get_one_and_zeros_padding(unsigned char *input, size_t input_len,
size_t *data_len)
{
- size_t i;
- unsigned char done = 0, prev_done, bad;
+ unsigned int bad = 1;
if (NULL == input || NULL == data_len) {
return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA;
}
- bad = 0x80;
*data_len = 0;
- for (i = input_len; i > 0; i--) {
- prev_done = done;
- done |= (input[i - 1] != 0);
- *data_len |= (i - 1) * (done != prev_done);
- bad ^= input[i - 1] * (done != prev_done);
+ size_t in_padding = ~0;
+
+ for (ptrdiff_t i = (ptrdiff_t) (input_len) - 1; i >= 0; i--) {
+ size_t is_nonzero = mbedtls_ct_uint_mask(input[i]);
+
+ size_t hit_first_nonzero = is_nonzero & in_padding;
+
+ *data_len = (*data_len & ~hit_first_nonzero) | ((size_t) i & hit_first_nonzero);
+
+ bad = mbedtls_ct_uint_if((unsigned int) hit_first_nonzero,
+ !mbedtls_ct_size_bool_eq(input[i], 0x80), bad);
+
+ in_padding = in_padding & ~is_nonzero;
}
- return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
-
+ return -(int) mbedtls_ct_uint_if(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING, 0);
}
#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */
@@ -832,16 +838,17 @@
*data_len = input_len - padding_len;
/* Avoid logical || since it results in a branch */
- bad |= padding_len > input_len;
- bad |= padding_len == 0;
+ bad |= mbedtls_ct_size_mask_ge(padding_len, input_len + 1);
+ bad |= mbedtls_ct_size_bool_eq(padding_len, 0);
/* The number of bytes checked must be independent of padding_len */
pad_idx = input_len - padding_len;
for (i = 0; i < input_len - 1; i++) {
- bad |= input[i] * (i >= pad_idx);
+ size_t mask = mbedtls_ct_size_mask_ge(i, pad_idx);
+ bad |= input[i] & mask;
}
- return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0);
+ return -(int) mbedtls_ct_uint_if(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING, 0);
}
#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */
@@ -872,8 +879,9 @@
*data_len = 0;
for (i = input_len; i > 0; i--) {
prev_done = done;
- done |= (input[i-1] != 0);
- *data_len |= i * (done != prev_done);
+ done |= !mbedtls_ct_size_bool_eq(input[i-1], 0);
+ size_t mask = mbedtls_ct_size_mask(done ^ prev_done);
+ *data_len |= i & mask;
}
return 0;
diff --git a/library/constant_time.c b/library/constant_time.c
index c0f53bb..2307ed5 100644
--- a/library/constant_time.c
+++ b/library/constant_time.c
@@ -80,7 +80,8 @@
#endif
}
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || \
+ defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC)
size_t mbedtls_ct_size_mask(size_t value)
{
@@ -96,7 +97,8 @@
#endif
}
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+#endif /* defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) ||
+ defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC) */
#if defined(MBEDTLS_BIGNUM_C)
@@ -116,7 +118,8 @@
#endif /* MBEDTLS_BIGNUM_C */
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) || \
+ defined(MBEDTLS_CIPHER_MODE_CBC)
/** Constant-flow mask generation for "less than" comparison:
* - if \p x < \p y, return all-bits 1, that is (size_t) -1
@@ -151,7 +154,8 @@
return ~mbedtls_ct_size_mask_lt(x, y);
}
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+#endif /* defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) ||
+ defined(MBEDTLS_CIPHER_MODE_CBC) */
#if defined(MBEDTLS_BASE64_C)
diff --git a/library/constant_time_internal.h b/library/constant_time_internal.h
index 402cf14..0ba8a7a 100644
--- a/library/constant_time_internal.h
+++ b/library/constant_time_internal.h
@@ -45,7 +45,8 @@
*/
unsigned mbedtls_ct_uint_mask(unsigned value);
-#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC)
+#if defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || \
+ defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC)
/** Turn a value into a mask:
* - if \p value == 0, return the all-bits 0 mask, aka 0
@@ -60,7 +61,8 @@
*/
size_t mbedtls_ct_size_mask(size_t value);
-#endif /* MBEDTLS_SSL_SOME_MODES_USE_MAC */
+#endif /* defined(MBEDTLS_SSL_SOME_MODES_USE_MAC) || defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) ||
+ defined(MBEDTLS_NIST_KW_C) || defined(MBEDTLS_CIPHER_MODE_CBC) */
#if defined(MBEDTLS_BIGNUM_C)
@@ -79,7 +81,8 @@
#endif /* MBEDTLS_BIGNUM_C */
-#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC)
+#if defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) || \
+ defined(MBEDTLS_CIPHER_MODE_CBC)
/** Constant-flow mask generation for "greater or equal" comparison:
* - if \p x >= \p y, return all-bits 1, that is (size_t) -1
@@ -97,7 +100,8 @@
size_t mbedtls_ct_size_mask_ge(size_t x,
size_t y);
-#endif /* MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC */
+#endif /* defined(MBEDTLS_SSL_SOME_SUITES_USE_TLS_CBC) || defined(MBEDTLS_NIST_KW_C) ||
+ defined(MBEDTLS_CIPHER_MODE_CBC) */
/** Constant-flow boolean "equal" comparison:
* return x == y
diff --git a/library/gcm.c b/library/gcm.c
index 0c958c7..71e7b2e 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -35,6 +35,7 @@
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
+#include "mbedtls/constant_time.h"
#include <string.h>
@@ -478,7 +479,6 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
unsigned char check_tag[16];
- size_t i;
int diff;
GCM_VALIDATE_RET(ctx != NULL);
@@ -495,9 +495,7 @@
}
/* Check tag in "constant-time" */
- for (diff = 0, i = 0; i < tag_len; i++) {
- diff |= tag[i] ^ check_tag[i];
- }
+ diff = mbedtls_ct_memcmp(tag, check_tag, tag_len);
if (diff != 0) {
mbedtls_platform_zeroize(output, length);
diff --git a/library/nist_kw.c b/library/nist_kw.c
index 5817bf4..4ff5e41 100644
--- a/library/nist_kw.c
+++ b/library/nist_kw.c
@@ -35,6 +35,7 @@
#include "mbedtls/platform_util.h"
#include "mbedtls/error.h"
#include "mbedtls/constant_time.h"
+#include "constant_time_internal.h"
#include <stdint.h>
#include <string.h>
@@ -335,7 +336,7 @@
int ret = 0;
size_t i, olen;
unsigned char A[KW_SEMIBLOCK_LENGTH];
- unsigned char diff, bad_padding = 0;
+ unsigned char diff;
*out_len = 0;
if (out_size < in_len - KW_SEMIBLOCK_LENGTH) {
@@ -420,18 +421,13 @@
* larger than 8, because of the type wrap around.
*/
padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen;
- if (padlen > 7) {
- padlen &= 7;
- ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED;
- }
+ ret = -(int) mbedtls_ct_uint_if(padlen & ~7, -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret);
+ padlen &= 7;
/* Check padding in "constant-time" */
for (diff = 0, i = 0; i < KW_SEMIBLOCK_LENGTH; i++) {
- if (i >= KW_SEMIBLOCK_LENGTH - padlen) {
- diff |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
- } else {
- bad_padding |= output[*out_len - KW_SEMIBLOCK_LENGTH + i];
- }
+ size_t mask = mbedtls_ct_size_mask_ge(i, KW_SEMIBLOCK_LENGTH - padlen);
+ diff |= (unsigned char) (mask & output[*out_len - KW_SEMIBLOCK_LENGTH + i]);
}
if (diff != 0) {
@@ -454,7 +450,6 @@
*out_len = 0;
}
- mbedtls_platform_zeroize(&bad_padding, sizeof(bad_padding));
mbedtls_platform_zeroize(&diff, sizeof(diff));
mbedtls_platform_zeroize(A, sizeof(A));
diff --git a/library/rsa.c b/library/rsa.c
index f44b2c3..01d0eb0 100644
--- a/library/rsa.c
+++ b/library/rsa.c
@@ -1351,7 +1351,8 @@
{
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
size_t ilen, i, pad_len;
- unsigned char *p, bad, pad_done;
+ unsigned char *p, pad_done;
+ int bad;
unsigned char buf[MBEDTLS_MPI_MAX_SIZE];
unsigned char lhash[MBEDTLS_MD_MAX_SIZE];
unsigned int hlen;
@@ -1439,9 +1440,8 @@
p += hlen; /* Skip seed */
/* Check lHash */
- for (i = 0; i < hlen; i++) {
- bad |= lhash[i] ^ *p++;
- }
+ bad |= mbedtls_ct_memcmp(lhash, p, hlen);
+ p += hlen;
/* Get zero-padding len, but always read till end of buffer
* (minus one, for the 01 byte) */