diff --git a/src/kem/bike/additional_r4/decode_portable.c b/src/kem/bike/additional_r4/decode_portable.c index 846818386d..4afd313b38 100644 --- a/src/kem/bike/additional_r4/decode_portable.c +++ b/src/kem/bike/additional_r4/decode_portable.c @@ -37,7 +37,6 @@ rotr_big(OUT syndrome_t *out, IN const syndrome_t *in, IN size_t qw_num) _INLINE_ void rotr_small(OUT syndrome_t *out, IN const syndrome_t *in, IN const size_t bits) { - bike_static_assert(bits < 64, rotr_small_err); bike_static_assert(sizeof(*out) > (8 * R_QWORDS), rotr_small_qw_err); // Convert |bits| to 0/1 by using !!bits; then create a mask of 0 or diff --git a/src/kem/bike/additional_r4/gf2x_mul_base_portable.c b/src/kem/bike/additional_r4/gf2x_mul_base_portable.c index 86c21a1e28..62706b0480 100644 --- a/src/kem/bike/additional_r4/gf2x_mul_base_portable.c +++ b/src/kem/bike/additional_r4/gf2x_mul_base_portable.c @@ -41,14 +41,23 @@ void gf2x_mul_base_port(OUT uint64_t *c, u[7] = u[6] ^ b0m; // Step 2: Multiply two elements in parallel in positions i, i+s - l = u[LSB3(a0)] ^ (u[LSB3(a0 >> 3)] << 3); - h = (u[LSB3(a0 >> 3)] >> 61); + for (size_t i = 0; i < 8; ++i) { + // use a mask for secret-independent memory access + l ^= u[i] & secure_cmpeq64_mask(LSB3(a0), i); + l ^= (u[i] << 3) & secure_cmpeq64_mask(LSB3(a0 >> 3), i); + h ^= (u[i] >> 61) & secure_cmpeq64_mask(LSB3(a0 >> 3), i); + } for(size_t i = (2 * s); i < w; i += (2 * s)) { const size_t i2 = (i + s); - g1 = u[LSB3(a0 >> i)]; - g2 = u[LSB3(a0 >> i2)]; + g1 = 0; + g2 = 0; + for (size_t j = 0; j < 8; ++j) { + // use a mask for secret-independent memory access + g1 ^= u[j] & secure_cmpeq64_mask(LSB3(a0 >> i), j); + g2 ^= u[j] & secure_cmpeq64_mask(LSB3(a0 >> i2), j); + } l ^= (g1 << i) ^ (g2 << i2); h ^= (g1 >> (w - i)) ^ (g2 >> (w - i2)); diff --git a/src/kem/bike/additional_r4/utilities.h b/src/kem/bike/additional_r4/utilities.h index 06e033458e..af7340066b 100644 --- a/src/kem/bike/additional_r4/utilities.h +++ b/src/kem/bike/additional_r4/utilities.h @@ -138,6 +138,11 @@ _INLINE_ uint32_t secure_l32_mask(IN const uint32_t v1, IN const uint32_t v2) #endif } +// Return (-1) if v1 == v2, 0 otherwise +_INLINE_ uint64_t secure_cmpeq64_mask(IN const uint64_t v1, IN const uint64_t v2) { + return -(1 - ((uint64_t)((v1-v2) | (v2-v1)) >> 63)); +} + // bike_memcpy avoids the undefined behaviour of memcpy when byte_len=0 _INLINE_ void *bike_memcpy(void *dst, const void *src, size_t byte_len) { diff --git a/tests/constant_time/kem/passes/bike b/tests/constant_time/kem/passes/bike index 91ca6eb6ef..c9effe10b8 100644 --- a/tests/constant_time/kem/passes/bike +++ b/tests/constant_time/kem/passes/bike @@ -16,3 +16,9 @@ fun:_mm256_srli_epi64 fun:OQS_KEM_bike_*_rotate256_small } + +{ + Setting bits in a secret error vector + Memcheck:Cond + src:sampling_portable.c:44 # fun:OQS_KEM_bike_*_secure_set_bits_port +}