From 2de0f3c5dfda673e702276e6040043bca9c9d97b Mon Sep 17 00:00:00 2001 From: Conrado Gouvea Date: Wed, 7 Dec 2022 11:47:05 -0300 Subject: [PATCH] add bound to ConstantTimeEq in Scalar --- frost-core/Cargo.toml | 1 + frost-core/src/lib.rs | 7 ++++--- frost-ed448/src/lib.rs | 4 ++-- frost-p256/src/lib.rs | 6 ++---- frost-ristretto255/src/lib.rs | 6 ++---- frost-secp256k1/src/lib.rs | 5 ++--- 6 files changed, 13 insertions(+), 16 deletions(-) diff --git a/frost-core/Cargo.toml b/frost-core/Cargo.toml index 35debe6..d885f4b 100644 --- a/frost-core/Cargo.toml +++ b/frost-core/Cargo.toml @@ -23,6 +23,7 @@ digest = "0.10" hex = { version = "0.4.3", features = ["serde"] } rand_core = "0.6" serde = { version = "1", optional = true, features = ["derive"] } +subtle = "2.4.1" thiserror = "1.0" zeroize = { version = "1.5.4", default-features = false, features = ["derive"] } diff --git a/frost-core/src/lib.rs b/frost-core/src/lib.rs index 8e12b5a..accc60a 100644 --- a/frost-core/src/lib.rs +++ b/frost-core/src/lib.rs @@ -26,6 +26,7 @@ mod verifying_key; pub use error::Error; pub use signature::Signature; pub use signing_key::SigningKey; +pub use subtle::ConstantTimeEq; pub use verifying_key::VerifyingKey; /// A prime order finite field GF(q) over which all scalar values for our prime order group can be @@ -41,6 +42,7 @@ pub trait Field: Copy + Clone { type Scalar: Add + Copy + Clone + + ConstantTimeEq + Eq + Mul + PartialEq @@ -277,13 +279,12 @@ where } /// Generates a random nonzero scalar. -/// -/// It assumes that the Scalar Eq/PartialEq implementation is constant-time. pub(crate) fn random_nonzero(rng: &mut R) -> Scalar { + let zero = <::Field>::zero(); loop { let scalar = <::Field>::random(rng); - if scalar != <::Field>::zero() { + if scalar.ct_eq(&zero).into() { return scalar; } } diff --git a/frost-ed448/src/lib.rs b/frost-ed448/src/lib.rs index c686af3..8f12ede 100644 --- a/frost-ed448/src/lib.rs +++ b/frost-ed448/src/lib.rs @@ -12,7 +12,7 @@ use sha3::{ Shake256, }; -use frost_core::{frost, Ciphersuite, Field, Group}; +use frost_core::{frost, Ciphersuite, ConstantTimeEq, Field, Group}; #[cfg(test)] mod tests; @@ -37,7 +37,7 @@ impl Field for Ed448ScalarField { } fn invert(scalar: &Self::Scalar) -> Result { - if *scalar == ::zero() { + if scalar.ct_eq(&::zero()).into() { Err(Error::InvalidZeroScalar) } else { Ok(scalar.invert()) diff --git a/frost-p256/src/lib.rs b/frost-p256/src/lib.rs index 1d49d31..534015f 100644 --- a/frost-p256/src/lib.rs +++ b/frost-p256/src/lib.rs @@ -14,7 +14,7 @@ use p256::{ use rand_core::{CryptoRng, RngCore}; use sha2::{digest::Update, Digest, Sha256}; -use frost_core::{frost, Ciphersuite, Field, Group}; +use frost_core::{frost, Ciphersuite, ConstantTimeEq, Field, Group}; #[cfg(test)] mod tests; @@ -39,9 +39,7 @@ impl Field for P256ScalarField { } fn invert(scalar: &Self::Scalar) -> Result { - // [`p256::Scalar`]'s Eq/PartialEq does a constant-time comparison using - // `ConstantTimeEq` - if *scalar == ::zero() { + if scalar.ct_eq(&::zero()).into() { Err(Error::InvalidZeroScalar) } else { Ok(scalar.invert().unwrap()) diff --git a/frost-ristretto255/src/lib.rs b/frost-ristretto255/src/lib.rs index efb8c45..896066c 100644 --- a/frost-ristretto255/src/lib.rs +++ b/frost-ristretto255/src/lib.rs @@ -11,7 +11,7 @@ use curve25519_dalek::{ use rand_core::{CryptoRng, RngCore}; use sha2::{digest::Update, Digest, Sha512}; -use frost_core::{frost, Ciphersuite, Field, Group}; +use frost_core::{frost, Ciphersuite, ConstantTimeEq, Field, Group}; #[cfg(test)] mod tests; @@ -36,9 +36,7 @@ impl Field for RistrettoScalarField { } fn invert(scalar: &Self::Scalar) -> Result { - // [`curve25519_dalek::scalar::Scalar`]'s Eq/PartialEq does a constant-time comparison using - // `ConstantTimeEq` - if *scalar == ::zero() { + if scalar.ct_eq(&::zero()).into() { Err(Error::InvalidZeroScalar) } else { Ok(scalar.invert()) diff --git a/frost-secp256k1/src/lib.rs b/frost-secp256k1/src/lib.rs index 872572b..d1097d3 100644 --- a/frost-secp256k1/src/lib.rs +++ b/frost-secp256k1/src/lib.rs @@ -16,7 +16,7 @@ use k256::{ use rand_core::{CryptoRng, RngCore}; use sha2::{digest::Update, Digest, Sha256}; -use frost_core::{frost, Ciphersuite, Field, Group}; +use frost_core::{frost, Ciphersuite, ConstantTimeEq, Field, Group}; #[cfg(test)] mod tests; @@ -41,8 +41,7 @@ impl Field for Secp256K1ScalarField { } fn invert(scalar: &Self::Scalar) -> Result { - // [`Scalar`]'s Eq/PartialEq does a constant-time comparison - if *scalar == ::zero() { + if scalar.ct_eq(&::zero()).into() { Err(Error::InvalidZeroScalar) } else { Ok(scalar.invert().unwrap())