constant-time: Add 64-bit versions of the helpers

While we could use _Generic() C11 expression to let the compiler select
between the different versions, this only allows selection based on one
of the arguments, which seems a bit fragile.  So make this explicit for
now.  In the future we might consider using the overloadable attribute.
This commit is contained in:
Tobias Brunner
2026-07-24 08:47:35 +02:00
parent db3f4c2955
commit 1372335d30
@@ -36,6 +36,18 @@ static inline u_int constant_time_neq(uint32_t x, uint32_t y)
return ((x-y) | (y-x)) >> 31;
}
/**
* Check if the given values are not equal in constant time.
*
* @param x first value to check
* @param y second value to check
* @return 1 if values are not equal, 0 otherwise
*/
static inline u_int constant_time_neq64(uint64_t x, uint64_t y)
{
return ((x-y) | (y-x)) >> 63;
}
/**
* Check if the given values are equal in constant time.
*
@@ -48,6 +60,18 @@ static inline u_int constant_time_eq(uint32_t x, uint32_t y)
return 1 ^ constant_time_neq(x, y);
}
/**
* Check if the given values are equal in constant time.
*
* @param x first value to check
* @param y second value to check
* @return 1 if values are equal, 0 otherwise
*/
static inline u_int constant_time_eq64(uint64_t x, uint64_t y)
{
return 1 ^ constant_time_neq64(x, y);
}
/**
* Compare the two values and return 1 if the first argument is lower than
* the second in constant time.
@@ -61,6 +85,19 @@ static inline u_int constant_time_lt(uint32_t x, uint32_t y)
return (x ^ ((x^y) | ((x-y) ^ y))) >> 31;
}
/**
* Compare the two values and return 1 if the first argument is lower than
* the second in constant time.
*
* @param x first value to check
* @param y second value to check
* @return 1 if first value is lower than second
*/
static inline u_int constant_time_lt64(uint64_t x, uint64_t y)
{
return (x ^ ((x^y) | ((x-y) ^ y))) >> 63;
}
/**
* Compare the two values and return 1 if the first argument greater or equal to
* the second in constant time.
@@ -74,6 +111,19 @@ static inline u_int constant_time_ge(uint32_t x, uint32_t y)
return 1 ^ constant_time_lt(x, y);
}
/**
* Compare the two values and return 1 if the first argument greater or equal to
* the second in constant time.
*
* @param x first value to check
* @param y second value to check
* @return 1 if first value is greater or equal to the second
*/
static inline u_int constant_time_ge64(uint64_t x, uint64_t y)
{
return 1 ^ constant_time_lt64(x, y);
}
/**
* Return a 32-bit all bit-set mask if the given value is not 0.
*
@@ -85,6 +135,17 @@ static inline uint32_t constant_time_mask(uint32_t x)
return -(uint32_t)constant_time_neq(x, 0);
}
/**
* Return a 64-bit all bit-set mask if the given value is not 0.
*
* @param x value to check
* @return 0xffffffffffffffff if value is != 0, 0 otherwise
*/
static inline uint64_t constant_time_mask64(uint64_t x)
{
return -(uint64_t)constant_time_neq64(x, 0);
}
/**
* Select one of two values depending on whether the condition is != 0 or not.
* Basically equivalent to 'c ? x : y'.
@@ -100,4 +161,19 @@ static inline uint32_t constant_time_select(uint32_t x, uint32_t y, uint32_t c)
return (x & m) | (y & ~m);
}
/**
* Select one of two values depending on whether the condition is != 0 or not.
* Basically equivalent to 'c ? x : y'.
*
* @param x first value to select
* @param y second value to select
* @param c condition
* @return x if c is != 0, y otherwise
*/
static inline uint64_t constant_time_select64(uint64_t x, uint64_t y, uint64_t c)
{
uint64_t m = constant_time_mask64(c);
return (x & m) | (y & ~m);
}
#endif /** CONSTANT_TIME_H_ @} */