Skip to content

Commit a32abfa

Browse files
committed
finding 8: make is_zero constant-time.
1 parent 45736e9 commit a32abfa

2 files changed

Lines changed: 21 additions & 2 deletions

File tree

barretenberg/cpp/src/barretenberg/ecc/fields/field_impl.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -752,8 +752,13 @@ template <class T> constexpr uint64_t field<T>::is_msb_set_word() const noexcept
752752

753753
template <class T> constexpr bool field<T>::is_zero() const noexcept
754754
{
755-
return ((data[0] | data[1] | data[2] | data[3]) == 0) ||
756-
(data[0] == T::modulus_0 && data[1] == T::modulus_1 && data[2] == T::modulus_2 && data[3] == T::modulus_3);
755+
// Use bitwise OR (not || or && operator) so neither chain short-circuits: the running time must not depend on
756+
// whether the value is zero, on which limb of the modulus first matches/diverges, or on which form
757+
// (raw 0 vs the modulus) is being tested.
758+
const uint64_t raw_zero = data[0] | data[1] | data[2] | data[3];
759+
const uint64_t mod_zero =
760+
(data[0] ^ T::modulus_0) | (data[1] ^ T::modulus_1) | (data[2] ^ T::modulus_2) | (data[3] ^ T::modulus_3);
761+
return static_cast<bool>(static_cast<uint64_t>(raw_zero == 0) | static_cast<uint64_t>(mod_zero == 0));
757762
}
758763

759764
template <class T> constexpr field<T> field<T>::get_root_of_unity(size_t subgroup_size) noexcept

barretenberg/cpp/src/barretenberg/ecc/fields/prime_field.test.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,20 @@ TYPED_TEST(PrimeFieldTest, CompileTimeEquality)
117117
static_assert(!(a == f));
118118
}
119119

120+
TYPED_TEST(PrimeFieldTest, IsZeroOnModulusForm)
121+
{
122+
using F = TypeParam;
123+
124+
F modulus_form{ F::modulus.data[0], F::modulus.data[1], F::modulus.data[2], F::modulus.data[3] };
125+
EXPECT_TRUE(modulus_form.is_zero());
126+
127+
F prefix_match{ F::modulus.data[0], F::modulus.data[1], F::modulus.data[2], F::modulus.data[3] - 1 };
128+
EXPECT_FALSE(prefix_match.is_zero());
129+
130+
F first_limb_only{ F::modulus.data[0], 0, 0, 0 };
131+
EXPECT_FALSE(first_limb_only.is_zero());
132+
}
133+
120134
TYPED_TEST(PrimeFieldTest, CompileTimeSmallAddSubMul)
121135
{
122136
using F = TypeParam;

0 commit comments

Comments
 (0)