From b4e6b41aa03f2c8cbf9533d7820bec6d139b9ad7 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Mon, 18 Sep 2023 18:46:19 +0100 Subject: [PATCH 01/34] Use const-time interface throughout mbedtls_rsa_rsaes_oaep_decrypt Signed-off-by: Dave Rodgman --- library/rsa.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/library/rsa.c b/library/rsa.c index 02626b377..f4bf37b41 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -1541,8 +1541,8 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, { int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t ilen, i, pad_len; - unsigned char *p, pad_done; - int bad; + unsigned char *p; + mbedtls_ct_condition_t bad, pad_done; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; unsigned int hlen; @@ -1602,27 +1602,26 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, * Check contents, in "constant-time" */ p = buf; - bad = 0; - bad |= *p++; /* First byte must be 0 */ + bad = mbedtls_ct_bool(*p++); /* First byte must be 0 */ p += hlen; /* Skip seed */ /* Check lHash */ - bad |= mbedtls_ct_memcmp(lhash, p, hlen); + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool(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) */ pad_len = 0; - pad_done = 0; + pad_done = MBEDTLS_CT_FALSE; for (i = 0; i < ilen - 2 * hlen - 2; i++) { - pad_done |= p[i]; - pad_len += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 1; + pad_done = mbedtls_ct_bool_or(pad_done, mbedtls_ct_uint_ne(p[i], 0)); + pad_len += mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_bool_not(pad_done), 1); } p += pad_len; - bad |= *p++ ^ 0x01; + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_ne(*p++, 0x01)); /* * The only information "leaked" is whether the padding was correct or not @@ -1630,7 +1629,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between * the different error conditions. */ - if (bad != 0) { + if (bad != MBEDTLS_CT_FALSE) { ret = MBEDTLS_ERR_RSA_INVALID_PADDING; goto cleanup; } From 6b7e2a5809ac7960c40c2ab7c9468e9aeef41581 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Mon, 18 Sep 2023 19:00:44 +0100 Subject: [PATCH 02/34] Use CT interface in get_pkcs_padding Signed-off-by: Dave Rodgman --- library/cipher.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index de7f8378e..41cd96f78 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 #include @@ -848,7 +849,8 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i, pad_idx; - unsigned char padding_len, bad = 0; + unsigned char padding_len; + mbedtls_ct_condition_t bad = MBEDTLS_CT_FALSE; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; @@ -857,18 +859,19 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, padding_len = input[input_len - 1]; *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_uint_gt(padding_len, input_len); + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_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); + mbedtls_ct_condition_t dont_ignore = mbedtls_ct_uint_ge(i, pad_idx); + mbedtls_ct_condition_t different = mbedtls_ct_uint_ne(input[i], padding_len); + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(dont_ignore, different)); } - return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0); + return mbedtls_ct_uint_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ From 6cec41c3bb01e74f604aba45ba67977eee394ebb Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Mon, 18 Sep 2023 21:51:55 +0100 Subject: [PATCH 03/34] use CT interface in add_zeros_and_len_padding() Signed-off-by: Dave Rodgman --- library/cipher.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index 41cd96f78..6fe72052e 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -935,7 +935,8 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i, pad_idx; - unsigned char padding_len, bad = 0; + unsigned char padding_len; + mbedtls_ct_condition_t bad; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; @@ -945,16 +946,18 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, *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_uint_gt(padding_len, input_len); + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_uint_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); + mbedtls_ct_condition_t is_padding = mbedtls_ct_uint_ge(i, pad_idx); + mbedtls_ct_condition_t nonzero_pad_byte = mbedtls_ct_uint_if_else_0(is_padding, mbedtls_ct_bool(input[i])); + bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } - return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0); + return -((int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING)); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ From 89a9bd58874ba9b7bf19e2aa34d3793fef0cc044 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Tue, 19 Sep 2023 14:37:50 +0100 Subject: [PATCH 04/34] Use CT interface in get_one_and_zeros_padding Signed-off-by: Dave Rodgman --- library/cipher.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index 6fe72052e..469f1b0cc 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -894,24 +894,28 @@ static void add_one_and_zeros_padding(unsigned char *output, 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; - if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; } - bad = 0x80; + mbedtls_ct_condition_t in_padding = MBEDTLS_CT_TRUE; + mbedtls_ct_condition_t bad = MBEDTLS_CT_TRUE; + *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); + + for (int i = input_len - 1; i >= 0; i--) { + mbedtls_ct_condition_t is_nonzero = mbedtls_ct_bool(input[i]); + + mbedtls_ct_condition_t hit_first_nonzero = mbedtls_ct_bool_and(is_nonzero, in_padding); + + *data_len = mbedtls_ct_size_if(hit_first_nonzero, i, *data_len); + + bad = mbedtls_ct_uint_if(hit_first_nonzero, mbedtls_ct_uint_ne(input[i], 0x80), bad); + + in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } - return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0); - + return -((int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING)); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ From 1cfc43c77b83fbe3e26ab4b3641bf8087cc9b25e Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Tue, 19 Sep 2023 16:18:59 +0100 Subject: [PATCH 05/34] Rename mbedtls_ct_bool_xor to mbedtls_ct_bool_ne Signed-off-by: Dave Rodgman --- library/bignum.c | 2 +- library/constant_time_impl.h | 4 ++-- library/constant_time_internal.h | 10 +++++----- tests/suites/test_suite_constant_time.function | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/bignum.c b/library/bignum.c index 0a0022cd3..9c19fc9fb 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -83,7 +83,7 @@ int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, * That is if X is negative (X_is_negative == 1), then X < Y is true and it * is false if X is positive (X_is_negative == 0). */ - different_sign = mbedtls_ct_bool_xor(X_is_negative, Y_is_negative); // non-zero if different sign + different_sign = mbedtls_ct_bool_ne(X_is_negative, Y_is_negative); // true if different sign result = mbedtls_ct_bool_and(different_sign, X_is_negative); /* diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h index 8da15a84c..98a56632c 100644 --- a/library/constant_time_impl.h +++ b/library/constant_time_impl.h @@ -407,8 +407,8 @@ static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x, return ~mbedtls_ct_uint_gt(x, y); } -static inline mbedtls_ct_condition_t mbedtls_ct_bool_xor(mbedtls_ct_condition_t x, - mbedtls_ct_condition_t y) +static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x, + mbedtls_ct_condition_t y) { return (mbedtls_ct_condition_t) (x ^ y); } diff --git a/library/constant_time_internal.h b/library/constant_time_internal.h index 323edef45..50c08fa6b 100644 --- a/library/constant_time_internal.h +++ b/library/constant_time_internal.h @@ -194,11 +194,11 @@ static inline mbedtls_ct_condition_t mbedtls_ct_uint_ge(mbedtls_ct_uint_t x, static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y); -/** Boolean "xor" operation. +/** Boolean not-equals operation. * * Functionally equivalent to: * - * \p x ^ \p y + * \p x != \p y * * \param x The first value to analyze. * \param y The second value to analyze. @@ -206,11 +206,11 @@ static inline mbedtls_ct_condition_t mbedtls_ct_uint_le(mbedtls_ct_uint_t x, * \note This is more efficient than mbedtls_ct_uint_ne if both arguments are * mbedtls_ct_condition_t. * - * \return MBEDTLS_CT_TRUE if \p x ^ \p y, + * \return MBEDTLS_CT_TRUE if \p x != \p y, * otherwise MBEDTLS_CT_FALSE. */ -static inline mbedtls_ct_condition_t mbedtls_ct_bool_xor(mbedtls_ct_condition_t x, - mbedtls_ct_condition_t y); +static inline mbedtls_ct_condition_t mbedtls_ct_bool_ne(mbedtls_ct_condition_t x, + mbedtls_ct_condition_t y); /** Boolean "and" operation. * diff --git a/tests/suites/test_suite_constant_time.function b/tests/suites/test_suite_constant_time.function index 087ccdfd3..6ec203766 100644 --- a/tests/suites/test_suite_constant_time.function +++ b/tests/suites/test_suite_constant_time.function @@ -77,8 +77,8 @@ void mbedtls_ct_bool_xxx(char *x_str, char *y_str) expected = x1 <= y1 ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE; TEST_EQUAL(mbedtls_ct_uint_le(x, y), expected); - expected = (!!x1) ^ (!!y1) ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE; - TEST_EQUAL(mbedtls_ct_bool_xor(mbedtls_ct_bool(x), mbedtls_ct_bool(y)), expected); + expected = (!!x1) != (!!y1) ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE; + TEST_EQUAL(mbedtls_ct_bool_ne(mbedtls_ct_bool(x), mbedtls_ct_bool(y)), expected); expected = (!!x1) && (!!y1) ? MBEDTLS_CT_TRUE : MBEDTLS_CT_FALSE; TEST_EQUAL(mbedtls_ct_bool_and(mbedtls_ct_bool(x), mbedtls_ct_bool(y)), expected); From d8c68a948a0aa31ba38c9867ce8ab499984eb6c9 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Tue, 19 Sep 2023 16:19:38 +0100 Subject: [PATCH 06/34] Use CT interface in get_zeros_padding Signed-off-by: Dave Rodgman --- library/cipher.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index 469f1b0cc..0ab3f81a7 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -983,7 +983,7 @@ static int get_zeros_padding(unsigned char *input, size_t input_len, size_t *data_len) { size_t i; - unsigned char done = 0, prev_done; + mbedtls_ct_condition_t done = MBEDTLS_CT_FALSE, prev_done; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; @@ -992,8 +992,8 @@ static int get_zeros_padding(unsigned char *input, size_t input_len, *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_bool_or(done, mbedtls_ct_uint_ne(input[i-1], 0)); + *data_len = mbedtls_ct_size_if(mbedtls_ct_bool_ne(done, prev_done), i, *data_len); } return 0; From f8182d91a71eff605f0756ba361757dcc7109f4d Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Tue, 19 Sep 2023 16:25:17 +0100 Subject: [PATCH 07/34] Simplify add_zeros_padding Signed-off-by: Dave Rodgman --- library/cipher.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index 0ab3f81a7..d36d4d508 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -972,11 +972,7 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, static void add_zeros_padding(unsigned char *output, size_t output_len, size_t data_len) { - size_t i; - - for (i = data_len; i < output_len; i++) { - output[i] = 0x00; - } + memset(output + data_len, 0, output_len - data_len); } static int get_zeros_padding(unsigned char *input, size_t input_len, From 4fc14cc4ae276e9723d5d5de1610869726db9766 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Tue, 19 Sep 2023 19:45:54 +0100 Subject: [PATCH 08/34] Fix error in handling of return value from mbedtls_nist_kw_unwrap Signed-off-by: Dave Rodgman --- library/nist_kw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/nist_kw.c b/library/nist_kw.c index 3de1b6ade..d73e82fe4 100644 --- a/library/nist_kw.c +++ b/library/nist_kw.c @@ -421,8 +421,8 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; - ret = -((int) mbedtls_ct_uint_if_else_0(mbedtls_ct_uint_gt(padlen, 7), - -MBEDTLS_ERR_CIPHER_AUTH_FAILED)); + ret = -((int) mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7), + -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret)); padlen &= 7; /* Check padding in "constant-time" */ From 6be4bcff161cd535de566e7a35b6677b3bf84a75 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Tue, 19 Sep 2023 19:47:51 +0100 Subject: [PATCH 09/34] code style Signed-off-by: Dave Rodgman --- library/cipher.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/cipher.c b/library/cipher.c index d36d4d508..3274f3803 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -957,7 +957,8 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, pad_idx = input_len - padding_len; for (i = 0; i < input_len - 1; i++) { mbedtls_ct_condition_t is_padding = mbedtls_ct_uint_ge(i, pad_idx); - mbedtls_ct_condition_t nonzero_pad_byte = mbedtls_ct_uint_if_else_0(is_padding, mbedtls_ct_bool(input[i])); + mbedtls_ct_condition_t nonzero_pad_byte; + nonzero_pad_byte = mbedtls_ct_uint_if_else_0(is_padding, mbedtls_ct_bool(input[i])); bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } From 437500c5b1a7e2f4e4cbe864bd6c3deaeda6ff17 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Tue, 19 Sep 2023 21:36:43 +0100 Subject: [PATCH 10/34] Fix MSVC type complaint Signed-off-by: Dave Rodgman --- library/cipher.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/cipher.c b/library/cipher.c index 3274f3803..bead187a4 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -903,7 +903,7 @@ static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, *data_len = 0; - for (int i = input_len - 1; i >= 0; i--) { + for (ptrdiff_t i = (ptrdiff_t) (input_len) - 1; i >= 0; i--) { mbedtls_ct_condition_t is_nonzero = mbedtls_ct_bool(input[i]); mbedtls_ct_condition_t hit_first_nonzero = mbedtls_ct_bool_and(is_nonzero, in_padding); From 143f5f7c68f6f7bf1eb4b6359c916cfd7fd99ed2 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Tue, 19 Sep 2023 21:51:13 +0100 Subject: [PATCH 11/34] Add mbedtls_ct_bool_if and mbedtls_ct_bool_if_else_0 Signed-off-by: Dave Rodgman --- library/constant_time_impl.h | 14 ++++++++ library/constant_time_internal.h | 33 +++++++++++++++++++ .../suites/test_suite_constant_time.function | 3 ++ 3 files changed, 50 insertions(+) diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h index 98a56632c..513f146f9 100644 --- a/library/constant_time_impl.h +++ b/library/constant_time_impl.h @@ -350,6 +350,14 @@ static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition, return (unsigned) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, (mbedtls_ct_uint_t) if0); } +static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition, + mbedtls_ct_condition_t if1, + mbedtls_ct_condition_t if0) +{ + return (mbedtls_ct_condition_t) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) if1, + (mbedtls_ct_uint_t) if0); +} + #if defined(MBEDTLS_BIGNUM_C) static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t condition, @@ -373,6 +381,12 @@ static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t conditio return (unsigned) (condition & if1); } +static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition, + mbedtls_ct_condition_t if1) +{ + return (mbedtls_ct_condition_t) (condition & if1); +} + #if defined(MBEDTLS_BIGNUM_C) static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_condition_t condition, diff --git a/library/constant_time_internal.h b/library/constant_time_internal.h index 50c08fa6b..d3d8945d1 100644 --- a/library/constant_time_internal.h +++ b/library/constant_time_internal.h @@ -291,6 +291,22 @@ static inline unsigned mbedtls_ct_uint_if(mbedtls_ct_condition_t condition, unsigned if1, unsigned if0); +/** Choose between two mbedtls_ct_condition_t values. + * + * Functionally equivalent to: + * + * condition ? if1 : if0. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. + */ +static inline mbedtls_ct_condition_t mbedtls_ct_bool_if(mbedtls_ct_condition_t condition, + mbedtls_ct_condition_t if1, + mbedtls_ct_condition_t if0); + #if defined(MBEDTLS_BIGNUM_C) /** Choose between two mbedtls_mpi_uint values. @@ -327,6 +343,23 @@ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if(mbedtls_ct_condition_t con */ static inline unsigned mbedtls_ct_uint_if_else_0(mbedtls_ct_condition_t condition, unsigned if1); +/** Choose between an mbedtls_ct_condition_t and 0. + * + * Functionally equivalent to: + * + * condition ? if1 : 0. + * + * Functionally equivalent to mbedtls_ct_bool_if(condition, if1, 0) but + * results in smaller code size. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. + */ +static inline mbedtls_ct_condition_t mbedtls_ct_bool_if_else_0(mbedtls_ct_condition_t condition, + mbedtls_ct_condition_t if1); + /** Choose between a size_t value and 0. * * Functionally equivalent to: diff --git a/tests/suites/test_suite_constant_time.function b/tests/suites/test_suite_constant_time.function index 6ec203766..3d5fa7ff4 100644 --- a/tests/suites/test_suite_constant_time.function +++ b/tests/suites/test_suite_constant_time.function @@ -131,12 +131,15 @@ void mbedtls_ct_if(char *c_str, char *t_str, char *f_str) TEST_EQUAL(mbedtls_ct_if(c, t, f), expected); TEST_EQUAL(mbedtls_ct_size_if(c, t, f), (size_t) expected); TEST_EQUAL(mbedtls_ct_uint_if(c, t, f), (unsigned) expected); + TEST_EQUAL(mbedtls_ct_bool_if(c, mbedtls_ct_bool(t), mbedtls_ct_bool(f)), + mbedtls_ct_bool(expected)); #if defined(MBEDTLS_BIGNUM_C) TEST_EQUAL(mbedtls_ct_mpi_uint_if(c, t, f), (mbedtls_mpi_uint) expected); #endif TEST_EQUAL(mbedtls_ct_uint_if_else_0(c, t), (unsigned) expected0); TEST_EQUAL(mbedtls_ct_size_if_else_0(c, (size_t) t), (size_t) expected0); + TEST_EQUAL(mbedtls_ct_bool_if_else_0(c, mbedtls_ct_bool(t)), mbedtls_ct_bool(expected0)); #if defined(MBEDTLS_BIGNUM_C) TEST_EQUAL(mbedtls_ct_mpi_uint_if_else_0(c, t), (mbedtls_mpi_uint) expected0); #endif From fd96579ecd36cfb8cd940a755da4763ddd7d522e Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Tue, 19 Sep 2023 21:51:50 +0100 Subject: [PATCH 12/34] Use properly typed versions of mbedtls_ct_xxx_if Signed-off-by: Dave Rodgman --- library/cipher.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index bead187a4..73aaa5a17 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -910,7 +910,7 @@ static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, *data_len = mbedtls_ct_size_if(hit_first_nonzero, i, *data_len); - bad = mbedtls_ct_uint_if(hit_first_nonzero, mbedtls_ct_uint_ne(input[i], 0x80), bad); + bad = mbedtls_ct_bool_if(hit_first_nonzero, mbedtls_ct_uint_ne(input[i], 0x80), bad); in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } @@ -958,7 +958,7 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, for (i = 0; i < input_len - 1; i++) { mbedtls_ct_condition_t is_padding = mbedtls_ct_uint_ge(i, pad_idx); mbedtls_ct_condition_t nonzero_pad_byte; - nonzero_pad_byte = mbedtls_ct_uint_if_else_0(is_padding, mbedtls_ct_bool(input[i])); + nonzero_pad_byte = mbedtls_ct_bool_if_else_0(is_padding, mbedtls_ct_bool(input[i])); bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } From ee5464fab91cf6b6aad15d83b71a7deb28062008 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Wed, 20 Sep 2023 09:13:12 +0100 Subject: [PATCH 13/34] Simplify unnecessarily complex error code handling Signed-off-by: Dave Rodgman --- library/cipher.c | 4 ++-- library/nist_kw.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index 73aaa5a17..b398a6008 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -915,7 +915,7 @@ static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } - return -((int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING)); + return (int) mbedtls_ct_uint_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ @@ -962,7 +962,7 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } - return -((int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING)); + return (int) mbedtls_ct_uint_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ diff --git a/library/nist_kw.c b/library/nist_kw.c index d73e82fe4..b0d413718 100644 --- a/library/nist_kw.c +++ b/library/nist_kw.c @@ -421,8 +421,8 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; - ret = -((int) mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7), - -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret)); + ret = (int) mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7), + MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); padlen &= 7; /* Check padding in "constant-time" */ From e94cd0b99bedc83754a4dc7ea3fe28336356862e Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Wed, 20 Sep 2023 19:05:35 +0100 Subject: [PATCH 14/34] Correct use of mbedtls_ct_mpi_uint_if_else_0 Signed-off-by: Dave Rodgman --- library/rsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/rsa.c b/library/rsa.c index f4bf37b41..7c0ba0d2c 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -1617,7 +1617,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, pad_done = MBEDTLS_CT_FALSE; for (i = 0; i < ilen - 2 * hlen - 2; i++) { pad_done = mbedtls_ct_bool_or(pad_done, mbedtls_ct_uint_ne(p[i], 0)); - pad_len += mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_bool_not(pad_done), 1); + pad_len += mbedtls_ct_uint_if_else_0(mbedtls_ct_bool_not(pad_done), 1); } p += pad_len; From c62f7fcce914b24bb3b990695899d425c6bb6e0c Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Wed, 20 Sep 2023 19:06:02 +0100 Subject: [PATCH 15/34] Use more meaningful variable name in mbedtls_rsa_rsaes_oaep_decrypt Signed-off-by: Dave Rodgman --- library/rsa.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/rsa.c b/library/rsa.c index 7c0ba0d2c..0f16a3186 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -1542,7 +1542,7 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; size_t ilen, i, pad_len; unsigned char *p; - mbedtls_ct_condition_t bad, pad_done; + mbedtls_ct_condition_t bad, in_padding; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; unsigned int hlen; @@ -1614,10 +1614,10 @@ int mbedtls_rsa_rsaes_oaep_decrypt(mbedtls_rsa_context *ctx, /* Get zero-padding len, but always read till end of buffer * (minus one, for the 01 byte) */ pad_len = 0; - pad_done = MBEDTLS_CT_FALSE; + in_padding = MBEDTLS_CT_TRUE; for (i = 0; i < ilen - 2 * hlen - 2; i++) { - pad_done = mbedtls_ct_bool_or(pad_done, mbedtls_ct_uint_ne(p[i], 0)); - pad_len += mbedtls_ct_uint_if_else_0(mbedtls_ct_bool_not(pad_done), 1); + in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_uint_eq(p[i], 0)); + pad_len += mbedtls_ct_uint_if_else_0(in_padding, 1); } p += pad_len; From e834d6c9f23b6311ae2471a9a2eeb9ba9090f40e Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Wed, 20 Sep 2023 19:06:53 +0100 Subject: [PATCH 16/34] Move declaration for robustness against future edits Signed-off-by: Dave Rodgman --- library/cipher.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index b398a6008..8e8e5b5cc 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -850,7 +850,6 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, { size_t i, pad_idx; unsigned char padding_len; - mbedtls_ct_condition_t bad = MBEDTLS_CT_FALSE; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; @@ -859,7 +858,7 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, padding_len = input[input_len - 1]; *data_len = input_len - padding_len; - bad = mbedtls_ct_uint_gt(padding_len, input_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)); /* The number of bytes checked must be independent of padding_len, From c43a0a4adb4c06d17512e069d2debdb9f5d4c804 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Wed, 20 Sep 2023 19:07:22 +0100 Subject: [PATCH 17/34] rename dont_ignore to in_padding Signed-off-by: Dave Rodgman --- library/cipher.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index 8e8e5b5cc..9a5e465f4 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -865,9 +865,9 @@ static int get_pkcs_padding(unsigned char *input, size_t input_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++) { - mbedtls_ct_condition_t dont_ignore = mbedtls_ct_uint_ge(i, pad_idx); - mbedtls_ct_condition_t different = mbedtls_ct_uint_ne(input[i], padding_len); - bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(dont_ignore, different)); + mbedtls_ct_condition_t in_padding = mbedtls_ct_uint_ge(i, pad_idx); + mbedtls_ct_condition_t different = mbedtls_ct_uint_ne(input[i], padding_len); + bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different)); } return mbedtls_ct_uint_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); From 1cf181fd465cd62b49483a585a029c6053a2700b Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Wed, 20 Sep 2023 18:23:36 +0100 Subject: [PATCH 18/34] Reinstate more robust return value handling Signed-off-by: Dave Rodgman --- library/cipher.c | 6 +++--- library/nist_kw.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index 9a5e465f4..8b94198bd 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -870,7 +870,7 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different)); } - return mbedtls_ct_uint_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return -mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ @@ -914,7 +914,7 @@ static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } - return (int) mbedtls_ct_uint_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return -mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ @@ -961,7 +961,7 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } - return (int) mbedtls_ct_uint_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return -mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ diff --git a/library/nist_kw.c b/library/nist_kw.c index b0d413718..bde177584 100644 --- a/library/nist_kw.c +++ b/library/nist_kw.c @@ -421,8 +421,8 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; - ret = (int) mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7), - MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); + ret = -mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7), + -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret); padlen &= 7; /* Check padding in "constant-time" */ From 584a08f91d97361cf5705078bddb3c9510216626 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Wed, 20 Sep 2023 20:15:52 +0100 Subject: [PATCH 19/34] Add cast for MSVC Signed-off-by: Dave Rodgman --- library/cipher.c | 6 +++--- library/nist_kw.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index 8b94198bd..f521fc20b 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -870,7 +870,7 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different)); } - return -mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ @@ -914,7 +914,7 @@ static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } - return -mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ @@ -961,7 +961,7 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } - return -mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ diff --git a/library/nist_kw.c b/library/nist_kw.c index bde177584..d5b2e27fb 100644 --- a/library/nist_kw.c +++ b/library/nist_kw.c @@ -421,8 +421,8 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; - ret = -mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7), - -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret); + ret = -(int) mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7), + -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret); padlen &= 7; /* Check padding in "constant-time" */ From e50b5372660eb85c3d7363bdd98f5123b77c7440 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 10:58:36 +0100 Subject: [PATCH 20/34] Add mbedtls_ct_error_if Signed-off-by: Dave Rodgman --- library/constant_time_impl.h | 11 +++++++++++ library/constant_time_internal.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h index 513f146f9..34b33b0a4 100644 --- a/library/constant_time_impl.h +++ b/library/constant_time_impl.h @@ -397,6 +397,17 @@ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_conditio #endif /* MBEDTLS_BIGNUM_C */ +static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0) +{ + return -((int) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) (-if1), + (mbedtls_ct_uint_t) (-if0))); +} + +static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1) +{ + return -((int) (condition & (-if1))); +} + static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { diff --git a/library/constant_time_internal.h b/library/constant_time_internal.h index d3d8945d1..63eb10421 100644 --- a/library/constant_time_internal.h +++ b/library/constant_time_internal.h @@ -411,6 +411,35 @@ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, unsigned char c, unsigned char t); +/** Choose between two error values. The values must be zero or negative. + * + * Functionally equivalent to: + * + * condition ? if1 : if0. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. + */ +static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0); + +/** Choose between an error value and 0. The error value must be zero or negative. + * + * Functionally equivalent to: + * + * condition ? if1 : 0. + * + * Functionally equivalent to mbedtls_ct_error_if(condition, if1, 0) but + * results in smaller code size. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. + */ +static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1); /* ============================================================================ * Block memory operations From 1a404e8f345db10de811292365aa7dc46e1b7568 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 11:26:09 +0100 Subject: [PATCH 21/34] Use mbedtls_ct_error for CT error selection Signed-off-by: Dave Rodgman --- library/cipher.c | 6 +++--- library/nist_kw.c | 4 ++-- library/rsa.c | 8 +++----- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index f521fc20b..cfb240195 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -870,7 +870,7 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different)); } - return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ @@ -914,7 +914,7 @@ static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } - return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ @@ -961,7 +961,7 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } - return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ diff --git a/library/nist_kw.c b/library/nist_kw.c index d5b2e27fb..7bdc807bc 100644 --- a/library/nist_kw.c +++ b/library/nist_kw.c @@ -421,8 +421,8 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; - ret = -(int) mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7), - -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret); + ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7), + MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); padlen &= 7; /* Check padding in "constant-time" */ diff --git a/library/rsa.c b/library/rsa.c index 0f16a3186..3c538bf43 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -158,12 +158,10 @@ static int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input, * - 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_ct_uint_if( + ret = mbedtls_ct_error_if( bad, - (unsigned) (-(MBEDTLS_ERR_RSA_INVALID_PADDING)), - mbedtls_ct_uint_if_else_0( - output_too_large, - (unsigned) (-(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE))) + MBEDTLS_ERR_RSA_INVALID_PADDING, + mbedtls_ct_error_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ); /* If the padding is bad or the plaintext is too large, zero the From 93b3228d42559d6cc54d5e1352fa126bdf7c642e Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 11:29:41 +0100 Subject: [PATCH 22/34] Add tests for mbedtls_ct_error_if Signed-off-by: Dave Rodgman --- tests/suites/test_suite_constant_time.data | 25 +++++++++++++++++++ .../suites/test_suite_constant_time.function | 18 +++++++++++++ 2 files changed, 43 insertions(+) diff --git a/tests/suites/test_suite_constant_time.data b/tests/suites/test_suite_constant_time.data index 82ee869e4..fcd168990 100644 --- a/tests/suites/test_suite_constant_time.data +++ b/tests/suites/test_suite_constant_time.data @@ -646,6 +646,31 @@ mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0x7fffffffffffffff" mbedtls_ct_if 0xffffffffffffffff 0xffffffffffffffff 0xffffffffffffffff mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0xffffffffffffffff" +# These values exercise the case where an argument to mbedtls_ct_error_if is INT_MIN +mbedtls_ct_if 1 0x80000000 0xffffffff +mbedtls_ct_if:"1":"0x80000000":"0xffffffff" + +mbedtls_ct_if 1 0xffffffff 0x80000000 +mbedtls_ct_if:"1":"0xffffffff":"0x80000000" + +mbedtls_ct_if 0 0x80000000 0xffffffff +mbedtls_ct_if:"0":"0x80000000":"0xffffffff" + +mbedtls_ct_if 0 0xffffffff 0x80000000 +mbedtls_ct_if:"0":"0xffffffff":"0x80000000" + +mbedtls_ct_if 1 0x8000000000000000 0xffffffffffffffff +mbedtls_ct_if:"1":"0x8000000000000000":"0xffffffffffffffff" + +mbedtls_ct_if 1 0xffffffffffffffff 0x8000000000000000 +mbedtls_ct_if:"1":"0xffffffffffffffff":"0x8000000000000000" + +mbedtls_ct_if 0 0x8000000000000000 0xffffffffffffffff +mbedtls_ct_if:"0":"0x8000000000000000":"0xffffffffffffffff" + +mbedtls_ct_if 0 0xffffffffffffffff 0x8000000000000000 +mbedtls_ct_if:"0":"0xffffffffffffffff":"0x8000000000000000" + mbedtls_ct_zeroize_if 0x0 0 mbedtls_ct_zeroize_if:"0x0":0 diff --git a/tests/suites/test_suite_constant_time.function b/tests/suites/test_suite_constant_time.function index 3d5fa7ff4..ffcd4d102 100644 --- a/tests/suites/test_suite_constant_time.function +++ b/tests/suites/test_suite_constant_time.function @@ -124,9 +124,22 @@ void mbedtls_ct_if(char *c_str, char *t_str, char *f_str) mbedtls_ct_uint_t expected = c ? t : f; mbedtls_ct_uint_t expected0 = c ? t : 0; + /* Avoid UB by checking that -t will fit in an int, i.e., + * t <= abs(INT_MIN), and similar for f. + * Define ABS_INT_MIN in a way that avoids UB, then use it to + * check t and f before making them negative. + */ + #define ABS_INT_MIN (UINT_MAX - ((unsigned int)(INT_MIN)) + 1U) + int t_neg = t <= ABS_INT_MIN ? -t : INT_MIN; + int f_neg = f <= ABS_INT_MIN ? -f : INT_MIN; + int expected0_neg = c ? t_neg : 0; + int expected_neg = c ? t_neg : f_neg; + TEST_CF_SECRET(&c, sizeof(c)); TEST_CF_SECRET(&t, sizeof(t)); TEST_CF_SECRET(&f, sizeof(f)); + TEST_CF_SECRET(&t_neg, sizeof(t)); + TEST_CF_SECRET(&f_neg, sizeof(f)); TEST_EQUAL(mbedtls_ct_if(c, t, f), expected); TEST_EQUAL(mbedtls_ct_size_if(c, t, f), (size_t) expected); @@ -144,9 +157,14 @@ void mbedtls_ct_if(char *c_str, char *t_str, char *f_str) TEST_EQUAL(mbedtls_ct_mpi_uint_if_else_0(c, t), (mbedtls_mpi_uint) expected0); #endif + TEST_EQUAL(mbedtls_ct_error_if_else_0(c, t_neg), expected0_neg); + TEST_EQUAL(mbedtls_ct_error_if(c, t_neg, f_neg), expected_neg); + TEST_CF_PUBLIC(&c, sizeof(c)); TEST_CF_PUBLIC(&t, sizeof(t)); TEST_CF_PUBLIC(&f, sizeof(f)); + TEST_CF_PUBLIC(&t_neg, sizeof(t_neg)); + TEST_CF_PUBLIC(&f_neg, sizeof(f_neg)); } /* END_CASE */ From cc3c670670286f792ad2222ee0007d705b1a281b Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 16:33:26 +0100 Subject: [PATCH 23/34] Fix compiler cast warning Signed-off-by: Dave Rodgman --- tests/suites/test_suite_constant_time.function | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/suites/test_suite_constant_time.function b/tests/suites/test_suite_constant_time.function index ffcd4d102..5b25c5472 100644 --- a/tests/suites/test_suite_constant_time.function +++ b/tests/suites/test_suite_constant_time.function @@ -129,9 +129,9 @@ void mbedtls_ct_if(char *c_str, char *t_str, char *f_str) * Define ABS_INT_MIN in a way that avoids UB, then use it to * check t and f before making them negative. */ - #define ABS_INT_MIN (UINT_MAX - ((unsigned int)(INT_MIN)) + 1U) - int t_neg = t <= ABS_INT_MIN ? -t : INT_MIN; - int f_neg = f <= ABS_INT_MIN ? -f : INT_MIN; + #define ABS_INT_MIN (UINT_MAX - ((unsigned int) (INT_MIN)) + 1U) + int t_neg = t <= ABS_INT_MIN ? -((int) t) : INT_MIN; + int f_neg = f <= ABS_INT_MIN ? -((int) f) : INT_MIN; int expected0_neg = c ? t_neg : 0; int expected_neg = c ? t_neg : f_neg; From f81b2a14f22ae82750764bab66157b653af6bf81 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 19:22:43 +0100 Subject: [PATCH 24/34] Generalise mbedtls_ct_error_if to mbedtls_ct_int_if Signed-off-by: Dave Rodgman --- library/constant_time_impl.h | 10 +++++----- library/constant_time_internal.h | 11 +++++------ 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h index 34b33b0a4..9bfb2c58c 100644 --- a/library/constant_time_impl.h +++ b/library/constant_time_impl.h @@ -397,15 +397,15 @@ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_conditio #endif /* MBEDTLS_BIGNUM_C */ -static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0) +static inline int mbedtls_ct_int_if(mbedtls_ct_condition_t condition, int if1, int if0) { - return -((int) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) (-if1), - (mbedtls_ct_uint_t) (-if0))); + int a[2] = {if0, if1}; + return a[mbedtls_ct_uint_if_else_0(condition, 1)]; } -static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1) +static inline int mbedtls_ct_int_if_else_0(mbedtls_ct_condition_t condition, int if1) { - return -((int) (condition & (-if1))); + return mbedtls_ct_int_if(condition, if1, 0); } static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x, diff --git a/library/constant_time_internal.h b/library/constant_time_internal.h index 63eb10421..604268e33 100644 --- a/library/constant_time_internal.h +++ b/library/constant_time_internal.h @@ -411,7 +411,7 @@ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, unsigned char c, unsigned char t); -/** Choose between two error values. The values must be zero or negative. +/** Choose between two int values. * * Functionally equivalent to: * @@ -423,23 +423,22 @@ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. */ -static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0); +static inline int mbedtls_ct_int_if(mbedtls_ct_condition_t condition, int if1, int if0); -/** Choose between an error value and 0. The error value must be zero or negative. +/** Choose between an int value and 0. * * Functionally equivalent to: * * condition ? if1 : 0. * - * Functionally equivalent to mbedtls_ct_error_if(condition, if1, 0) but - * results in smaller code size. + * Functionally equivalent to mbedtls_ct_int_if(condition, if1, 0). * * \param condition Condition to test. * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. * * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. */ -static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1); +static inline int mbedtls_ct_int_if_else_0(mbedtls_ct_condition_t condition, int if1); /* ============================================================================ * Block memory operations From f1915f623d816faefba8f5a983e7c89a14a2fef0 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 19:22:59 +0100 Subject: [PATCH 25/34] Improve testing for mbedtls_ct_int_if Signed-off-by: Dave Rodgman --- tests/suites/test_suite_constant_time.function | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/tests/suites/test_suite_constant_time.function b/tests/suites/test_suite_constant_time.function index 5b25c5472..ff3eb462c 100644 --- a/tests/suites/test_suite_constant_time.function +++ b/tests/suites/test_suite_constant_time.function @@ -130,10 +130,12 @@ void mbedtls_ct_if(char *c_str, char *t_str, char *f_str) * check t and f before making them negative. */ #define ABS_INT_MIN (UINT_MAX - ((unsigned int) (INT_MIN)) + 1U) - int t_neg = t <= ABS_INT_MIN ? -((int) t) : INT_MIN; - int f_neg = f <= ABS_INT_MIN ? -((int) f) : INT_MIN; + int t_neg = (t <= ABS_INT_MIN) && (t <= INT_MAX) ? -((int) t) : INT_MIN; + int f_neg = (f <= ABS_INT_MIN) && (t <= INT_MAX) ? -((int) f) : INT_MIN; int expected0_neg = c ? t_neg : 0; int expected_neg = c ? t_neg : f_neg; + int t_fits_in_int = t <= INT_MAX; + int f_fits_in_int = f <= INT_MAX; TEST_CF_SECRET(&c, sizeof(c)); TEST_CF_SECRET(&t, sizeof(t)); @@ -157,8 +159,14 @@ void mbedtls_ct_if(char *c_str, char *t_str, char *f_str) TEST_EQUAL(mbedtls_ct_mpi_uint_if_else_0(c, t), (mbedtls_mpi_uint) expected0); #endif - TEST_EQUAL(mbedtls_ct_error_if_else_0(c, t_neg), expected0_neg); - TEST_EQUAL(mbedtls_ct_error_if(c, t_neg, f_neg), expected_neg); + if (t_fits_in_int) { + TEST_EQUAL(mbedtls_ct_int_if_else_0(c, (int) t), (int) expected0); + if (f_fits_in_int) { + TEST_EQUAL(mbedtls_ct_int_if(c, (int) t, (int) f), (int) expected); + } + } + TEST_EQUAL(mbedtls_ct_int_if_else_0(c, t_neg), expected0_neg); + TEST_EQUAL(mbedtls_ct_int_if(c, t_neg, f_neg), expected_neg); TEST_CF_PUBLIC(&c, sizeof(c)); TEST_CF_PUBLIC(&t, sizeof(t)); From 61f1beaccfeef99c8674fdc72650614397e30650 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 19:23:17 +0100 Subject: [PATCH 26/34] Update library to use mbedtls_ct_int_if Signed-off-by: Dave Rodgman --- library/cipher.c | 6 +++--- library/nist_kw.c | 4 ++-- library/rsa.c | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index cfb240195..a53fb4358 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -870,7 +870,7 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different)); } - return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return mbedtls_ct_int_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ @@ -914,7 +914,7 @@ static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } - return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return mbedtls_ct_int_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ @@ -961,7 +961,7 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } - return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return mbedtls_ct_int_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ diff --git a/library/nist_kw.c b/library/nist_kw.c index 7bdc807bc..1b4078e1b 100644 --- a/library/nist_kw.c +++ b/library/nist_kw.c @@ -421,8 +421,8 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; - ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7), - MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); + ret = mbedtls_ct_int_if(mbedtls_ct_uint_gt(padlen, 7), + MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); padlen &= 7; /* Check padding in "constant-time" */ diff --git a/library/rsa.c b/library/rsa.c index 3c538bf43..a233a8e7f 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -158,10 +158,10 @@ static int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input, * - 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 = mbedtls_ct_error_if( + ret = mbedtls_ct_int_if( bad, MBEDTLS_ERR_RSA_INVALID_PADDING, - mbedtls_ct_error_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) + mbedtls_ct_int_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ); /* If the padding is bad or the plaintext is too large, zero the From 530c3da698c9f8194ca8a711fd106dc14170f486 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 21:06:48 +0100 Subject: [PATCH 27/34] Improve implementation of mbedtls_ct_int_if Signed-off-by: Dave Rodgman --- library/constant_time_impl.h | 47 +++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h index 9bfb2c58c..afec89422 100644 --- a/library/constant_time_impl.h +++ b/library/constant_time_impl.h @@ -331,6 +331,42 @@ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, return (unsigned char) (~(low_mask | high_mask)) & to; } +static inline int mbedtls_ct_int_if(mbedtls_ct_condition_t condition, int if1, int if0) +{ + /* + * Use memcpy to avoid unsigned-to-signed conversion UB. + * + * Although this looks inefficient, in practice (for gcc and clang), + * the sizeof test is eliminated at compile-time, and identical code is generated + * as for mbedtls_ct_uint_if (for -Os and -O1 or higher). + */ + int result; + if (sizeof(int) <= sizeof(unsigned int)) { + unsigned int uif1 = 0, uif0 = 0; + memcpy(&uif1, &if1, sizeof(if1)); + memcpy(&uif0, &if0, sizeof(if0)); + unsigned int uresult = mbedtls_ct_uint_if(condition, uif1, uif0); + memcpy(&result, &uresult, sizeof(result)); + } else { + mbedtls_ct_memcpy_if(condition, (unsigned char *) &result, (const unsigned char *) &if1, + (const unsigned char *) &if0, sizeof(result)); + } + return result; +} + +static inline int mbedtls_ct_int_if_else_0(mbedtls_ct_condition_t condition, int if1) +{ + if (sizeof(int) <= sizeof(unsigned int)) { + unsigned int uif1 = 0; + memcpy(&uif1, &if1, sizeof(if1)); + unsigned int uresult = mbedtls_ct_uint_if_else_0(condition, uif1); + int result; + memcpy(&result, &uresult, sizeof(result)); + return result; + } else { + return mbedtls_ct_int_if(condition, if1, 0); + } +} /* ============================================================================ * Everything below here is trivial wrapper functions @@ -397,17 +433,6 @@ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_conditio #endif /* MBEDTLS_BIGNUM_C */ -static inline int mbedtls_ct_int_if(mbedtls_ct_condition_t condition, int if1, int if0) -{ - int a[2] = {if0, if1}; - return a[mbedtls_ct_uint_if_else_0(condition, 1)]; -} - -static inline int mbedtls_ct_int_if_else_0(mbedtls_ct_condition_t condition, int if1) -{ - return mbedtls_ct_int_if(condition, if1, 0); -} - static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { From 7ad37e40a6ed9e63975f6168fb9b61d46fcda5f0 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 21:53:31 +0100 Subject: [PATCH 28/34] Remove use of mbedtls_ct_int_if Signed-off-by: Dave Rodgman --- library/cipher.c | 6 +++--- library/nist_kw.c | 4 ++-- library/rsa.c | 8 +++++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index a53fb4358..f521fc20b 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -870,7 +870,7 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different)); } - return mbedtls_ct_int_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ @@ -914,7 +914,7 @@ static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } - return mbedtls_ct_int_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ @@ -961,7 +961,7 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } - return mbedtls_ct_int_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ diff --git a/library/nist_kw.c b/library/nist_kw.c index 1b4078e1b..d5b2e27fb 100644 --- a/library/nist_kw.c +++ b/library/nist_kw.c @@ -421,8 +421,8 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; - ret = mbedtls_ct_int_if(mbedtls_ct_uint_gt(padlen, 7), - MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); + ret = -(int) mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7), + -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret); padlen &= 7; /* Check padding in "constant-time" */ diff --git a/library/rsa.c b/library/rsa.c index a233a8e7f..0f16a3186 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -158,10 +158,12 @@ static int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input, * - 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 = mbedtls_ct_int_if( + ret = -(int) mbedtls_ct_uint_if( bad, - MBEDTLS_ERR_RSA_INVALID_PADDING, - mbedtls_ct_int_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) + (unsigned) (-(MBEDTLS_ERR_RSA_INVALID_PADDING)), + mbedtls_ct_uint_if_else_0( + output_too_large, + (unsigned) (-(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE))) ); /* If the padding is bad or the plaintext is too large, zero the From a9d70125a3c0042c9c0cc1095d6152e558dcae3f Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 21:53:54 +0100 Subject: [PATCH 29/34] Remove mbedtls_ct_int_if Signed-off-by: Dave Rodgman --- library/constant_time_impl.h | 36 -------------------------------- library/constant_time_internal.h | 28 ------------------------- 2 files changed, 64 deletions(-) diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h index afec89422..513f146f9 100644 --- a/library/constant_time_impl.h +++ b/library/constant_time_impl.h @@ -331,42 +331,6 @@ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, return (unsigned char) (~(low_mask | high_mask)) & to; } -static inline int mbedtls_ct_int_if(mbedtls_ct_condition_t condition, int if1, int if0) -{ - /* - * Use memcpy to avoid unsigned-to-signed conversion UB. - * - * Although this looks inefficient, in practice (for gcc and clang), - * the sizeof test is eliminated at compile-time, and identical code is generated - * as for mbedtls_ct_uint_if (for -Os and -O1 or higher). - */ - int result; - if (sizeof(int) <= sizeof(unsigned int)) { - unsigned int uif1 = 0, uif0 = 0; - memcpy(&uif1, &if1, sizeof(if1)); - memcpy(&uif0, &if0, sizeof(if0)); - unsigned int uresult = mbedtls_ct_uint_if(condition, uif1, uif0); - memcpy(&result, &uresult, sizeof(result)); - } else { - mbedtls_ct_memcpy_if(condition, (unsigned char *) &result, (const unsigned char *) &if1, - (const unsigned char *) &if0, sizeof(result)); - } - return result; -} - -static inline int mbedtls_ct_int_if_else_0(mbedtls_ct_condition_t condition, int if1) -{ - if (sizeof(int) <= sizeof(unsigned int)) { - unsigned int uif1 = 0; - memcpy(&uif1, &if1, sizeof(if1)); - unsigned int uresult = mbedtls_ct_uint_if_else_0(condition, uif1); - int result; - memcpy(&result, &uresult, sizeof(result)); - return result; - } else { - return mbedtls_ct_int_if(condition, if1, 0); - } -} /* ============================================================================ * Everything below here is trivial wrapper functions diff --git a/library/constant_time_internal.h b/library/constant_time_internal.h index 604268e33..d3d8945d1 100644 --- a/library/constant_time_internal.h +++ b/library/constant_time_internal.h @@ -411,34 +411,6 @@ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, unsigned char c, unsigned char t); -/** Choose between two int values. - * - * Functionally equivalent to: - * - * condition ? if1 : if0. - * - * \param condition Condition to test. - * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. - * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. - * - * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. - */ -static inline int mbedtls_ct_int_if(mbedtls_ct_condition_t condition, int if1, int if0); - -/** Choose between an int value and 0. - * - * Functionally equivalent to: - * - * condition ? if1 : 0. - * - * Functionally equivalent to mbedtls_ct_int_if(condition, if1, 0). - * - * \param condition Condition to test. - * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. - * - * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. - */ -static inline int mbedtls_ct_int_if_else_0(mbedtls_ct_condition_t condition, int if1); /* ============================================================================ * Block memory operations From 9d0869140ba9c725c35b6181b58df2307d3c55fb Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Thu, 21 Sep 2023 21:54:08 +0100 Subject: [PATCH 30/34] Remove tests for mbedtls_ct_int_if Signed-off-by: Dave Rodgman --- tests/suites/test_suite_constant_time.data | 25 ------------------ .../suites/test_suite_constant_time.function | 26 ------------------- 2 files changed, 51 deletions(-) diff --git a/tests/suites/test_suite_constant_time.data b/tests/suites/test_suite_constant_time.data index fcd168990..82ee869e4 100644 --- a/tests/suites/test_suite_constant_time.data +++ b/tests/suites/test_suite_constant_time.data @@ -646,31 +646,6 @@ mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0x7fffffffffffffff" mbedtls_ct_if 0xffffffffffffffff 0xffffffffffffffff 0xffffffffffffffff mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0xffffffffffffffff" -# These values exercise the case where an argument to mbedtls_ct_error_if is INT_MIN -mbedtls_ct_if 1 0x80000000 0xffffffff -mbedtls_ct_if:"1":"0x80000000":"0xffffffff" - -mbedtls_ct_if 1 0xffffffff 0x80000000 -mbedtls_ct_if:"1":"0xffffffff":"0x80000000" - -mbedtls_ct_if 0 0x80000000 0xffffffff -mbedtls_ct_if:"0":"0x80000000":"0xffffffff" - -mbedtls_ct_if 0 0xffffffff 0x80000000 -mbedtls_ct_if:"0":"0xffffffff":"0x80000000" - -mbedtls_ct_if 1 0x8000000000000000 0xffffffffffffffff -mbedtls_ct_if:"1":"0x8000000000000000":"0xffffffffffffffff" - -mbedtls_ct_if 1 0xffffffffffffffff 0x8000000000000000 -mbedtls_ct_if:"1":"0xffffffffffffffff":"0x8000000000000000" - -mbedtls_ct_if 0 0x8000000000000000 0xffffffffffffffff -mbedtls_ct_if:"0":"0x8000000000000000":"0xffffffffffffffff" - -mbedtls_ct_if 0 0xffffffffffffffff 0x8000000000000000 -mbedtls_ct_if:"0":"0xffffffffffffffff":"0x8000000000000000" - mbedtls_ct_zeroize_if 0x0 0 mbedtls_ct_zeroize_if:"0x0":0 diff --git a/tests/suites/test_suite_constant_time.function b/tests/suites/test_suite_constant_time.function index ff3eb462c..3d5fa7ff4 100644 --- a/tests/suites/test_suite_constant_time.function +++ b/tests/suites/test_suite_constant_time.function @@ -124,24 +124,9 @@ void mbedtls_ct_if(char *c_str, char *t_str, char *f_str) mbedtls_ct_uint_t expected = c ? t : f; mbedtls_ct_uint_t expected0 = c ? t : 0; - /* Avoid UB by checking that -t will fit in an int, i.e., - * t <= abs(INT_MIN), and similar for f. - * Define ABS_INT_MIN in a way that avoids UB, then use it to - * check t and f before making them negative. - */ - #define ABS_INT_MIN (UINT_MAX - ((unsigned int) (INT_MIN)) + 1U) - int t_neg = (t <= ABS_INT_MIN) && (t <= INT_MAX) ? -((int) t) : INT_MIN; - int f_neg = (f <= ABS_INT_MIN) && (t <= INT_MAX) ? -((int) f) : INT_MIN; - int expected0_neg = c ? t_neg : 0; - int expected_neg = c ? t_neg : f_neg; - int t_fits_in_int = t <= INT_MAX; - int f_fits_in_int = f <= INT_MAX; - TEST_CF_SECRET(&c, sizeof(c)); TEST_CF_SECRET(&t, sizeof(t)); TEST_CF_SECRET(&f, sizeof(f)); - TEST_CF_SECRET(&t_neg, sizeof(t)); - TEST_CF_SECRET(&f_neg, sizeof(f)); TEST_EQUAL(mbedtls_ct_if(c, t, f), expected); TEST_EQUAL(mbedtls_ct_size_if(c, t, f), (size_t) expected); @@ -159,20 +144,9 @@ void mbedtls_ct_if(char *c_str, char *t_str, char *f_str) TEST_EQUAL(mbedtls_ct_mpi_uint_if_else_0(c, t), (mbedtls_mpi_uint) expected0); #endif - if (t_fits_in_int) { - TEST_EQUAL(mbedtls_ct_int_if_else_0(c, (int) t), (int) expected0); - if (f_fits_in_int) { - TEST_EQUAL(mbedtls_ct_int_if(c, (int) t, (int) f), (int) expected); - } - } - TEST_EQUAL(mbedtls_ct_int_if_else_0(c, t_neg), expected0_neg); - TEST_EQUAL(mbedtls_ct_int_if(c, t_neg, f_neg), expected_neg); - TEST_CF_PUBLIC(&c, sizeof(c)); TEST_CF_PUBLIC(&t, sizeof(t)); TEST_CF_PUBLIC(&f, sizeof(f)); - TEST_CF_PUBLIC(&t_neg, sizeof(t_neg)); - TEST_CF_PUBLIC(&f_neg, sizeof(f_neg)); } /* END_CASE */ From fbe74a9e51d82f8d81e715cd4a681ef7f7376ce6 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Fri, 22 Sep 2023 09:43:49 +0100 Subject: [PATCH 31/34] Add mbedtls_ct_error_if, with tests Signed-off-by: Dave Rodgman --- library/constant_time_impl.h | 12 ++- library/constant_time_internal.h | 29 ++++++ tests/suites/test_suite_constant_time.data | 96 +++++++++++++++++++ .../suites/test_suite_constant_time.function | 21 ++++ 4 files changed, 157 insertions(+), 1 deletion(-) diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h index 513f146f9..d2750854b 100644 --- a/library/constant_time_impl.h +++ b/library/constant_time_impl.h @@ -331,7 +331,6 @@ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, return (unsigned char) (~(low_mask | high_mask)) & to; } - /* ============================================================================ * Everything below here is trivial wrapper functions */ @@ -397,6 +396,17 @@ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_conditio #endif /* MBEDTLS_BIGNUM_C */ +static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0) +{ + return -((int) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) (-if1), + (mbedtls_ct_uint_t) (-if0))); +} + +static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1) +{ + return -((int) (condition & (-if1))); +} + static inline mbedtls_ct_condition_t mbedtls_ct_uint_eq(mbedtls_ct_uint_t x, mbedtls_ct_uint_t y) { diff --git a/library/constant_time_internal.h b/library/constant_time_internal.h index d3d8945d1..3731107ec 100644 --- a/library/constant_time_internal.h +++ b/library/constant_time_internal.h @@ -411,6 +411,35 @@ static inline unsigned char mbedtls_ct_uchar_in_range_if(unsigned char low, unsigned char c, unsigned char t); +/** Choose between two error values. The values must be in the range [-32767..0]. + * + * Functionally equivalent to: + * + * condition ? if1 : if0. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * \param if0 Value to use if \p condition == MBEDTLS_CT_FALSE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise \c if0. + */ +static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0); + +/** Choose between an error value and 0. The error value must be in the range [-32767..0]. + * + * Functionally equivalent to: + * + * condition ? if1 : 0. + * + * Functionally equivalent to mbedtls_ct_error_if(condition, if1, 0) but + * results in smaller code size. + * + * \param condition Condition to test. + * \param if1 Value to use if \p condition == MBEDTLS_CT_TRUE. + * + * \return \c if1 if \p condition == MBEDTLS_CT_TRUE, otherwise 0. + */ +static inline int mbedtls_ct_error_if_else_0(mbedtls_ct_condition_t condition, int if1); /* ============================================================================ * Block memory operations diff --git a/tests/suites/test_suite_constant_time.data b/tests/suites/test_suite_constant_time.data index 82ee869e4..111fef6c4 100644 --- a/tests/suites/test_suite_constant_time.data +++ b/tests/suites/test_suite_constant_time.data @@ -646,6 +646,102 @@ mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0x7fffffffffffffff" mbedtls_ct_if 0xffffffffffffffff 0xffffffffffffffff 0xffffffffffffffff mbedtls_ct_if:"0xffffffffffffffff":"0xffffffffffffffff":"0xffffffffffffffff" +mbedtls_ct_error_if 0 0 0 +mbedtls_ct_error_if:0:0:0 + +mbedtls_ct_error_if 0 0 -1 +mbedtls_ct_error_if:0:0:-1 + +mbedtls_ct_error_if 0 0 -32766 +mbedtls_ct_error_if:0:0:-32766 + +mbedtls_ct_error_if 0 0 -32767 +mbedtls_ct_error_if:0:0:-32767 + +mbedtls_ct_error_if 0 -1 0 +mbedtls_ct_error_if:0:-1:0 + +mbedtls_ct_error_if 0 -1 -1 +mbedtls_ct_error_if:0:-1:-1 + +mbedtls_ct_error_if 0 -1 -32766 +mbedtls_ct_error_if:0:-1:-32766 + +mbedtls_ct_error_if 0 -1 -32767 +mbedtls_ct_error_if:0:-1:-32767 + +mbedtls_ct_error_if 0 -32766 0 +mbedtls_ct_error_if:0:-32766:0 + +mbedtls_ct_error_if 0 -32766 -1 +mbedtls_ct_error_if:0:-32766:-1 + +mbedtls_ct_error_if 0 -32766 -32766 +mbedtls_ct_error_if:0:-32766:-32766 + +mbedtls_ct_error_if 0 -32766 -32767 +mbedtls_ct_error_if:0:-32766:-32767 + +mbedtls_ct_error_if 0 -32767 0 +mbedtls_ct_error_if:0:-32767:0 + +mbedtls_ct_error_if 0 -32767 -1 +mbedtls_ct_error_if:0:-32767:-1 + +mbedtls_ct_error_if 0 -32767 -32766 +mbedtls_ct_error_if:0:-32767:-32766 + +mbedtls_ct_error_if 0 -32767 -32767 +mbedtls_ct_error_if:0:-32767:-32767 + +mbedtls_ct_error_if 1 0 0 +mbedtls_ct_error_if:1:0:0 + +mbedtls_ct_error_if 1 0 -1 +mbedtls_ct_error_if:1:0:-1 + +mbedtls_ct_error_if 1 0 -32766 +mbedtls_ct_error_if:1:0:-32766 + +mbedtls_ct_error_if 1 0 -32767 +mbedtls_ct_error_if:1:0:-32767 + +mbedtls_ct_error_if 1 -1 0 +mbedtls_ct_error_if:1:-1:0 + +mbedtls_ct_error_if 1 -1 -1 +mbedtls_ct_error_if:1:-1:-1 + +mbedtls_ct_error_if 1 -1 -32766 +mbedtls_ct_error_if:1:-1:-32766 + +mbedtls_ct_error_if 1 -1 -32767 +mbedtls_ct_error_if:1:-1:-32767 + +mbedtls_ct_error_if 1 -32766 0 +mbedtls_ct_error_if:1:-32766:0 + +mbedtls_ct_error_if 1 -32766 -1 +mbedtls_ct_error_if:1:-32766:-1 + +mbedtls_ct_error_if 1 -32766 -32766 +mbedtls_ct_error_if:1:-32766:-32766 + +mbedtls_ct_error_if 1 -32766 -32767 +mbedtls_ct_error_if:1:-32766:-32767 + +mbedtls_ct_error_if 1 -32767 0 +mbedtls_ct_error_if:1:-32767:0 + +mbedtls_ct_error_if 1 -32767 -1 +mbedtls_ct_error_if:1:-32767:-1 + +mbedtls_ct_error_if 1 -32767 -32766 +mbedtls_ct_error_if:1:-32767:-32766 + +mbedtls_ct_error_if 1 -32767 -32767 +mbedtls_ct_error_if:1:-32767:-32767 + mbedtls_ct_zeroize_if 0x0 0 mbedtls_ct_zeroize_if:"0x0":0 diff --git a/tests/suites/test_suite_constant_time.function b/tests/suites/test_suite_constant_time.function index 3d5fa7ff4..b9a78c8c6 100644 --- a/tests/suites/test_suite_constant_time.function +++ b/tests/suites/test_suite_constant_time.function @@ -114,6 +114,27 @@ void mbedtls_ct_uchar_in_range_if(int li, int hi, int ti) } /* END_CASE */ +/* BEGIN_CASE */ +void mbedtls_ct_error_if(int cond, int t, int f) +{ + mbedtls_ct_condition_t c = mbedtls_ct_bool(cond); + + mbedtls_ct_uint_t expected = c ? t : f; + mbedtls_ct_uint_t expected0 = c ? t : 0; + + TEST_CF_SECRET(&c, sizeof(c)); + TEST_CF_SECRET(&t, sizeof(t)); + TEST_CF_SECRET(&f, sizeof(f)); + + TEST_EQUAL(mbedtls_ct_error_if(c, t, f), expected); + TEST_EQUAL(mbedtls_ct_error_if_else_0(c, t), expected0); + + TEST_CF_PUBLIC(&c, sizeof(c)); + TEST_CF_PUBLIC(&t, sizeof(t)); + TEST_CF_PUBLIC(&f, sizeof(f)); +} +/* END_CASE */ + /* BEGIN_CASE */ void mbedtls_ct_if(char *c_str, char *t_str, char *f_str) { From d03f483dbe0b4ac13d77ad26362772082fad80d1 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Fri, 22 Sep 2023 09:52:15 +0100 Subject: [PATCH 32/34] Use mbedtls_ct_error_if Signed-off-by: Dave Rodgman --- library/cipher.c | 6 +++--- library/nist_kw.c | 4 ++-- library/rsa.c | 8 +++----- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/library/cipher.c b/library/cipher.c index f521fc20b..cfb240195 100644 --- a/library/cipher.c +++ b/library/cipher.c @@ -870,7 +870,7 @@ static int get_pkcs_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, mbedtls_ct_bool_and(in_padding, different)); } - return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ @@ -914,7 +914,7 @@ static int get_one_and_zeros_padding(unsigned char *input, size_t input_len, in_padding = mbedtls_ct_bool_and(in_padding, mbedtls_ct_bool_not(is_nonzero)); } - return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ @@ -961,7 +961,7 @@ static int get_zeros_and_len_padding(unsigned char *input, size_t input_len, bad = mbedtls_ct_bool_or(bad, nonzero_pad_byte); } - return -(int) mbedtls_ct_uint_if_else_0(bad, -MBEDTLS_ERR_CIPHER_INVALID_PADDING); + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ diff --git a/library/nist_kw.c b/library/nist_kw.c index d5b2e27fb..7bdc807bc 100644 --- a/library/nist_kw.c +++ b/library/nist_kw.c @@ -421,8 +421,8 @@ int mbedtls_nist_kw_unwrap(mbedtls_nist_kw_context *ctx, * larger than 8, because of the type wrap around. */ padlen = in_len - KW_SEMIBLOCK_LENGTH - Plen; - ret = -(int) mbedtls_ct_uint_if(mbedtls_ct_uint_gt(padlen, 7), - -MBEDTLS_ERR_CIPHER_AUTH_FAILED, -ret); + ret = mbedtls_ct_error_if(mbedtls_ct_uint_gt(padlen, 7), + MBEDTLS_ERR_CIPHER_AUTH_FAILED, ret); padlen &= 7; /* Check padding in "constant-time" */ diff --git a/library/rsa.c b/library/rsa.c index 0f16a3186..3c538bf43 100644 --- a/library/rsa.c +++ b/library/rsa.c @@ -158,12 +158,10 @@ static int mbedtls_ct_rsaes_pkcs1_v15_unpadding(unsigned char *input, * - 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_ct_uint_if( + ret = mbedtls_ct_error_if( bad, - (unsigned) (-(MBEDTLS_ERR_RSA_INVALID_PADDING)), - mbedtls_ct_uint_if_else_0( - output_too_large, - (unsigned) (-(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE))) + MBEDTLS_ERR_RSA_INVALID_PADDING, + mbedtls_ct_error_if_else_0(output_too_large, MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ); /* If the padding is bad or the plaintext is too large, zero the From c0633bc7779a96d4a746d425b0edb47fee276516 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Fri, 22 Sep 2023 10:54:43 +0100 Subject: [PATCH 33/34] Add comment Signed-off-by: Dave Rodgman --- library/constant_time_impl.h | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h index d2750854b..4246d2de8 100644 --- a/library/constant_time_impl.h +++ b/library/constant_time_impl.h @@ -398,6 +398,12 @@ static inline mbedtls_mpi_uint mbedtls_ct_mpi_uint_if_else_0(mbedtls_ct_conditio static inline int mbedtls_ct_error_if(mbedtls_ct_condition_t condition, int if1, int if0) { + /* Coverting int -> uint -> int here is safe, because we require if1 and if0 to be + * in the range -32767..0, and we require 32-bit int and uint types. + * + * This means that (0 <= -if0 < INT_MAX), so negating if0 is safe, and similarly for + * converting back to int. + */ return -((int) mbedtls_ct_if(condition, (mbedtls_ct_uint_t) (-if1), (mbedtls_ct_uint_t) (-if0))); } From 9fc868012c393725b7c8ee0ffa564de85745ac48 Mon Sep 17 00:00:00 2001 From: Dave Rodgman Date: Fri, 22 Sep 2023 10:56:13 +0100 Subject: [PATCH 34/34] Fix test error Signed-off-by: Dave Rodgman --- tests/suites/test_suite_constant_time.function | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/suites/test_suite_constant_time.function b/tests/suites/test_suite_constant_time.function index b9a78c8c6..31273652d 100644 --- a/tests/suites/test_suite_constant_time.function +++ b/tests/suites/test_suite_constant_time.function @@ -119,8 +119,8 @@ void mbedtls_ct_error_if(int cond, int t, int f) { mbedtls_ct_condition_t c = mbedtls_ct_bool(cond); - mbedtls_ct_uint_t expected = c ? t : f; - mbedtls_ct_uint_t expected0 = c ? t : 0; + int expected = c ? t : f; + int expected0 = c ? t : 0; TEST_CF_SECRET(&c, sizeof(c)); TEST_CF_SECRET(&t, sizeof(t));