Skip to content

Commit

Permalink
Reduce risk of compiler value range propogation in FrodoKEM sampling
Browse files Browse the repository at this point in the history
No compiler has been found to perform optimizations that introduce
a side channel here, but the construct as written was somewhat risky.
  • Loading branch information
randombit committed Oct 19, 2024
1 parent 6babd82 commit ece851c
Showing 1 changed file with 8 additions and 5 deletions.
13 changes: 8 additions & 5 deletions src/lib/pubkey/frodokem/frodokem_common/frodo_matrix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,21 @@ FrodoMatrix FrodoMatrix::sample(const FrodoKEMConstants& constants,

load_le<uint16_t>(elements.data(), r.data(), n);

for(size_t i = 0; i < n; ++i) {
uint32_t sample = 0; // Avoid integral promotion
const uint16_t prnd = elements.at(i) >> 1; // Drop the least significant bit
const uint16_t sign = elements.at(i) & 0x1; // Pick the least significant bit
for(auto& elem : elements) {
const uint16_t prnd = CT::value_barrier(elem >> 1); // Drop the least significant bit
const auto sign = CT::Mask<uint16_t>::expand_bit(elem, 0); // Pick the least significant bit

uint32_t sample = 0; // Avoid integral promotion

// No need to compare with the last value.
for(size_t j = 0; j < constants.cdf_table_len() - 1; ++j) {
// Constant time comparison: 1 if CDF_TABLE[j] < s, 0 otherwise.
sample += CT::Mask<uint16_t>::is_lt(constants.cdf_table_at(j), prnd).if_set_return(1);
}
// Assuming that sign is either 0 or 1, flips sample iff sign = 1
elements.at(i) = static_cast<uint16_t>((-sign) ^ sample) + sign;
const uint16_t sample_u16 = static_cast<uint16_t>(sample);

elem = sign.select(~sample_u16, sample_u16) + (sign.value() & 1);
}

return FrodoMatrix(dimensions, std::move(elements));
Expand Down

0 comments on commit ece851c

Please sign in to comment.