diff --git a/curve25519/solana-ed25519/src/field.rs b/curve25519/solana-ed25519/src/field.rs index 4f4e316..701ac9b 100644 --- a/curve25519/solana-ed25519/src/field.rs +++ b/curve25519/solana-ed25519/src/field.rs @@ -26,7 +26,6 @@ #![allow(unused_qualifications)] use subtle::Choice; -use subtle::ConditionallyNegatable; use subtle::ConditionallySelectable; use subtle::ConstantTimeEq; @@ -355,8 +354,15 @@ impl FieldElement { r.conditional_assign(&r_prime, flipped_sign_sqrt | flipped_sign_sqrt_i); // Choose the nonnegative square root. + // + // NOTE: written as negate-then-conditional-assign rather than + // `r.conditional_negate(r_is_negative)`: semantically identical and + // still constant-time, but it avoids subtle's `ConditionallyNegatable` + // blanket impl (whose `for<'a> &'a T: Neg` bound breaks the Aeneas + // verification toolchain; see verification/field/README.md). let r_is_negative = r.is_negative(); - r.conditional_negate(r_is_negative); + let r_neg = -&r; + r.conditional_assign(&r_neg, r_is_negative); let was_nonzero_square = correct_sign_sqrt | flipped_sign_sqrt; @@ -516,6 +522,7 @@ where #[cfg(test)] mod test { use crate::field::*; + use subtle::ConditionallyNegatable; /// Random element a of GF(2^255-19), from Sage /// a = 1070314506888354081329385823235218444233221\