Large limbs for constant inputs to conditional_negate
Description
The function bigfield::conditional_negate
is implemented as follows for constant arguments:
template <typename Builder, typename T>
bigfield<Builder, T> bigfield<Builder, T>::conditional_negate(const bool_t<Builder>& predicate) const
{
Builder* ctx = context ? context : predicate.context;
if (is_constant() && predicate.is_constant()) {
if (predicate.get_value()) {
uint512_t out_val = (modulus_u512 - get_value()) % modulus_u512;
return bigfield(ctx, out_val.lo);
}
return *this;
}
// ...
}
The calculation of the return value will involve an underflow and wraparound modulo the native circuit prime modulus if get_value()
returns an unsigned integer that is bigger than the emulated prime modulus . This would make the result incorrect.
Impact
Should conditional_negate
be used for constant arguments, with the value to be negated being bigger than , then the return value will be incorrect. Most operations for constant bigfield
elements will reduce modulo , so their results will not have vulnerable form. It is possible to construct such constants with the usual bigfield
constructors, however.
Recommendations
Reduce get_value()
modulo modulus_u512
before subtracting it.
Remediation
This issue has been acknowledged by Aztec, and a fix was implemented in commit 718d5b7c↗.