Add value_barriers in constant time select functions
The barriers prevent the compiler from narrowing down the possible value range of the mask and ~mask in the select statements, which avoids the recognition of the select and turning it into a conditional load or branch. Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org> Reviewed-by: Kurt Roeckx <kurt@roeckx.be> (Merged from https://github.com/openssl/openssl/pull/9217)
This commit is contained in:
parent
05f4eb2dc9
commit
04edd688b3
1 changed files with 58 additions and 4 deletions
|
@ -213,18 +213,72 @@ static ossl_inline unsigned char constant_time_eq_int_8(int a, int b)
|
||||||
return constant_time_eq_8((unsigned)(a), (unsigned)(b));
|
return constant_time_eq_8((unsigned)(a), (unsigned)(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns the value unmodified, but avoids optimizations.
|
||||||
|
* The barriers prevent the compiler from narrowing down the
|
||||||
|
* possible value range of the mask and ~mask in the select
|
||||||
|
* statements, which avoids the recognition of the select
|
||||||
|
* and turning it into a conditional load or branch.
|
||||||
|
*/
|
||||||
|
static ossl_inline unsigned int value_barrier(unsigned int a)
|
||||||
|
{
|
||||||
|
#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
|
||||||
|
unsigned int r;
|
||||||
|
__asm__("" : "=r"(r) : "0"(a));
|
||||||
|
#else
|
||||||
|
volatile unsigned int r = a;
|
||||||
|
#endif
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convenience method for uint32_t. */
|
||||||
|
static ossl_inline uint32_t value_barrier_32(uint32_t a)
|
||||||
|
{
|
||||||
|
#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
|
||||||
|
uint32_t r;
|
||||||
|
__asm__("" : "=r"(r) : "0"(a));
|
||||||
|
#else
|
||||||
|
volatile uint32_t r = a;
|
||||||
|
#endif
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convenience method for uint64_t. */
|
||||||
|
static ossl_inline uint64_t value_barrier_64(uint64_t a)
|
||||||
|
{
|
||||||
|
#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
|
||||||
|
uint64_t r;
|
||||||
|
__asm__("" : "=r"(r) : "0"(a));
|
||||||
|
#else
|
||||||
|
volatile uint64_t r = a;
|
||||||
|
#endif
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Convenience method for size_t. */
|
||||||
|
static ossl_inline size_t value_barrier_s(size_t a)
|
||||||
|
{
|
||||||
|
#if !defined(OPENSSL_NO_ASM) && defined(__GNUC__)
|
||||||
|
size_t r;
|
||||||
|
__asm__("" : "=r"(r) : "0"(a));
|
||||||
|
#else
|
||||||
|
volatile size_t r = a;
|
||||||
|
#endif
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
static ossl_inline unsigned int constant_time_select(unsigned int mask,
|
static ossl_inline unsigned int constant_time_select(unsigned int mask,
|
||||||
unsigned int a,
|
unsigned int a,
|
||||||
unsigned int b)
|
unsigned int b)
|
||||||
{
|
{
|
||||||
return (mask & a) | (~mask & b);
|
return (value_barrier(mask) & a) | (value_barrier(~mask) & b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ossl_inline size_t constant_time_select_s(size_t mask,
|
static ossl_inline size_t constant_time_select_s(size_t mask,
|
||||||
size_t a,
|
size_t a,
|
||||||
size_t b)
|
size_t b)
|
||||||
{
|
{
|
||||||
return (mask & a) | (~mask & b);
|
return (value_barrier_s(mask) & a) | (value_barrier_s(~mask) & b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
|
static ossl_inline unsigned char constant_time_select_8(unsigned char mask,
|
||||||
|
@ -249,13 +303,13 @@ static ossl_inline int constant_time_select_int_s(size_t mask, int a, int b)
|
||||||
static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
|
static ossl_inline uint32_t constant_time_select_32(uint32_t mask, uint32_t a,
|
||||||
uint32_t b)
|
uint32_t b)
|
||||||
{
|
{
|
||||||
return (mask & a) | (~mask & b);
|
return (value_barrier_32(mask) & a) | (value_barrier_32(~mask) & b);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
|
static ossl_inline uint64_t constant_time_select_64(uint64_t mask, uint64_t a,
|
||||||
uint64_t b)
|
uint64_t b)
|
||||||
{
|
{
|
||||||
return (mask & a) | (~mask & b);
|
return (value_barrier_64(mask) & a) | (value_barrier_64(~mask) & b);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Reference in a new issue