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/cipher.c b/library/cipher.c index de7f8378e..cfb240195 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,7 @@ 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; if (NULL == input || NULL == data_len) { return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; @@ -857,18 +858,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; + 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, * 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 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_ERR_CIPHER_INVALID_PADDING * (bad != 0); + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ @@ -891,24 +893,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 (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); + + *data_len = mbedtls_ct_size_if(hit_first_nonzero, i, *data_len); + + 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)); } - return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0); - + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ @@ -932,7 +938,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; @@ -942,16 +949,19 @@ 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; + 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); } - return MBEDTLS_ERR_CIPHER_INVALID_PADDING * (bad != 0); + return mbedtls_ct_error_if_else_0(bad, MBEDTLS_ERR_CIPHER_INVALID_PADDING); } #endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ @@ -962,18 +972,14 @@ 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, 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; @@ -982,8 +988,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; diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h index 8da15a84c..4246d2de8 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 */ @@ -350,6 +349,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 +380,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, @@ -383,6 +396,23 @@ 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) +{ + /* 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))); +} + +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) { @@ -407,8 +437,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..3731107ec 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. * @@ -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: @@ -378,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/library/nist_kw.c b/library/nist_kw.c index d73e82fe4..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 02626b377..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 @@ -1541,8 +1539,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, in_padding; unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; unsigned int hlen; @@ -1602,27 +1600,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; + in_padding = MBEDTLS_CT_TRUE; for (i = 0; i < ilen - 2 * hlen - 2; i++) { - pad_done |= p[i]; - pad_len += ((pad_done | (unsigned char) -pad_done) >> 7) ^ 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; - 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 +1627,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; } 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 087ccdfd3..31273652d 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); @@ -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); + + int expected = c ? t : f; + int 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) { @@ -131,12 +152,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