diff --git a/library/constant_time_impl.h b/library/constant_time_impl.h index 513f146f9c..d2750854bf 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 d3d8945d13..3731107eca 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 82ee869e4c..111fef6c4e 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 3d5fa7ff41..b9a78c8c68 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) {