From 52d600db9500aaa372d7b4dc681148c18428b9c1 Mon Sep 17 00:00:00 2001 From: Henry de Valence Date: Wed, 24 Jan 2018 10:58:22 -0800 Subject: [PATCH] Implement public-facing ops traits on all combos of &T/T The public-facing types with arithmetic operations are: - `Scalar`s - `ExtendedPoint`s - `RistrettoPoint`s For these types we define operators with all combinations of borrowed and non-borrowed inputs, to avoid forcing API consumers to write extra ampersands. Since all of the operations involved with these types are expensive relative to the cost of an unnecessary copy, this isn't a big deal. The `MontgomeryPoint` struct isn't included in the above because it's only useful for scalar multiplication. This commit is based on work by @UnlawfulMonad. --- build.rs | 5 ++ src/edwards.rs | 23 ++++++++- src/lib.rs | 4 ++ src/macros.rs | 123 +++++++++++++++++++++++++++++++++++++++++++++++ src/ristretto.rs | 22 +++++++++ src/scalar.rs | 19 ++++++++ 6 files changed, 195 insertions(+), 1 deletion(-) create mode 100644 src/macros.rs diff --git a/build.rs b/build.rs index 2c30435..6b6e652 100644 --- a/build.rs +++ b/build.rs @@ -26,6 +26,11 @@ extern crate serde; #[cfg(feature = "yolocrypto")] extern crate stdsimd; +// Macros come first! +#[path="src/macros.rs"] +#[macro_use] +mod macros; + // Public modules #[path="src/scalar.rs"] diff --git a/src/edwards.rs b/src/edwards.rs index 5fca4e9..4af3ec5 100644 --- a/src/edwards.rs +++ b/src/edwards.rs @@ -378,12 +378,16 @@ impl<'a, 'b> Add<&'b ExtendedPoint> for &'a ExtendedPoint { } } +define_add_variants!(LHS = ExtendedPoint, RHS = ExtendedPoint, Output = ExtendedPoint); + impl<'b> AddAssign<&'b ExtendedPoint> for ExtendedPoint { fn add_assign(&mut self, _rhs: &'b ExtendedPoint) { *self = (self as &ExtendedPoint) + _rhs; } } +define_add_assign_variants!(LHS = ExtendedPoint, RHS = ExtendedPoint); + impl<'a, 'b> Sub<&'b ExtendedPoint> for &'a ExtendedPoint { type Output = ExtendedPoint; fn sub(self, other: &'b ExtendedPoint) -> ExtendedPoint { @@ -391,12 +395,16 @@ impl<'a, 'b> Sub<&'b ExtendedPoint> for &'a ExtendedPoint { } } +define_sub_variants!(LHS = ExtendedPoint, RHS = ExtendedPoint, Output = ExtendedPoint); + impl<'b> SubAssign<&'b ExtendedPoint> for ExtendedPoint { fn sub_assign(&mut self, _rhs: &'b ExtendedPoint) { *self = (self as &ExtendedPoint) - _rhs; } } +define_sub_assign_variants!(LHS = ExtendedPoint, RHS = ExtendedPoint); + // ------------------------------------------------------------------------ // Negation // ------------------------------------------------------------------------ @@ -414,6 +422,14 @@ impl<'a> Neg for &'a ExtendedPoint { } } +impl Neg for ExtendedPoint { + type Output = ExtendedPoint; + + fn neg(self) -> ExtendedPoint { + -&self + } +} + // ------------------------------------------------------------------------ // Scalar multiplication // ------------------------------------------------------------------------ @@ -425,6 +441,11 @@ impl<'b> MulAssign<&'b Scalar> for ExtendedPoint { } } +define_mul_assign_variants!(LHS = ExtendedPoint, RHS = Scalar); + +define_mul_variants!(LHS = ExtendedPoint, RHS = Scalar, Output = ExtendedPoint); +define_mul_variants!(LHS = Scalar, RHS = ExtendedPoint, Output = ExtendedPoint); + impl<'a, 'b> Mul<&'b Scalar> for &'a ExtendedPoint { type Output = ExtendedPoint; /// Scalar multiplication: compute `scalar * self`. @@ -478,7 +499,7 @@ impl<'a, 'b> Mul<&'b ExtendedPoint> for &'a Scalar { /// For scalar multiplication of a basepoint, /// `EdwardsBasepointTable` is approximately 4x faster. fn mul(self, point: &'b ExtendedPoint) -> ExtendedPoint { - point * &self + point * self } } diff --git a/src/lib.rs b/src/lib.rs index 6c4ed32..0baf368 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -68,6 +68,10 @@ extern crate serde; #[cfg(all(test, feature = "serde"))] extern crate serde_cbor; +// Internal macros. Must come first! +#[macro_use] +pub(crate) mod macros; + //------------------------------------------------------------------------ // curve25519-dalek public modules //------------------------------------------------------------------------ diff --git a/src/macros.rs b/src/macros.rs new file mode 100644 index 0000000..448d32c --- /dev/null +++ b/src/macros.rs @@ -0,0 +1,123 @@ +// -*- mode: rust; -*- +// +// This file is part of curve25519-dalek. +// Copyright (c) 2016-2017 Isis Lovecruft, Henry de Valence +// See LICENSE for licensing information. +// +// Authors: +// - Isis Agora Lovecruft +// - Henry de Valence + +//! Internal macros. + +/// Define borrow and non-borrow variants of `Add`. +macro_rules! define_add_variants { + (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => { + impl<'b> Add<&'b $rhs> for $lhs { + type Output = $out; + fn add(self, rhs: &'b $rhs) -> $out { + &self + rhs + } + } + + impl<'a> Add<$rhs> for &'a $lhs { + type Output = $out; + fn add(self, rhs: $rhs) -> $out { + self + &rhs + } + } + + impl Add<$rhs> for $lhs { + type Output = $out; + fn add(self, rhs: $rhs) -> $out { + &self + &rhs + } + } + } +} + +/// Define non-borrow variants of `AddAssign`. +macro_rules! define_add_assign_variants { + (LHS = $lhs:ty, RHS = $rhs:ty) => { + impl AddAssign<$rhs> for $lhs { + fn add_assign(&mut self, rhs: $rhs) { + *self += &rhs; + } + } + } +} + +/// Define borrow and non-borrow variants of `Sub`. +macro_rules! define_sub_variants { + (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => { + impl<'b> Sub<&'b $rhs> for $lhs { + type Output = $out; + fn sub(self, rhs: &'b $rhs) -> $out { + &self - rhs + } + } + + impl<'a> Sub<$rhs> for &'a $lhs { + type Output = $out; + fn sub(self, rhs: $rhs) -> $out { + self - &rhs + } + } + + impl Sub<$rhs> for $lhs { + type Output = $out; + fn sub(self, rhs: $rhs) -> $out { + &self - &rhs + } + } + } +} + +/// Define non-borrow variants of `SubAssign`. +macro_rules! define_sub_assign_variants { + (LHS = $lhs:ty, RHS = $rhs:ty) => { + impl SubAssign<$rhs> for $lhs { + fn sub_assign(&mut self, rhs: $rhs) { + *self -= &rhs; + } + } + } +} + +/// Define borrow and non-borrow variants of `Mul`. +macro_rules! define_mul_variants { + (LHS = $lhs:ty, RHS = $rhs:ty, Output = $out:ty) => { + impl<'b> Mul<&'b $rhs> for $lhs { + type Output = $out; + fn mul(self, rhs: &'b $rhs) -> $out { + &self * rhs + } + } + + impl<'a> Mul<$rhs> for &'a $lhs { + type Output = $out; + fn mul(self, rhs: $rhs) -> $out { + self * &rhs + } + } + + impl Mul<$rhs> for $lhs { + type Output = $out; + fn mul(self, rhs: $rhs) -> $out { + &self * &rhs + } + } + } +} + +/// Define non-borrow variants of `MulAssign`. +macro_rules! define_mul_assign_variants { + (LHS = $lhs:ty, RHS = $rhs:ty) => { + impl MulAssign<$rhs> for $lhs { + fn mul_assign(&mut self, rhs: $rhs) { + *self *= &rhs; + } + } + } +} + diff --git a/src/ristretto.rs b/src/ristretto.rs index ee6260e..40d667b 100644 --- a/src/ristretto.rs +++ b/src/ristretto.rs @@ -925,12 +925,16 @@ impl<'a, 'b> Add<&'b RistrettoPoint> for &'a RistrettoPoint { } } +define_add_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint, Output = RistrettoPoint); + impl<'b> AddAssign<&'b RistrettoPoint> for RistrettoPoint { fn add_assign(&mut self, _rhs: &RistrettoPoint) { *self = (self as &RistrettoPoint) + _rhs; } } +define_add_assign_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint); + impl<'a, 'b> Sub<&'b RistrettoPoint> for &'a RistrettoPoint { type Output = RistrettoPoint; @@ -939,12 +943,16 @@ impl<'a, 'b> Sub<&'b RistrettoPoint> for &'a RistrettoPoint { } } +define_sub_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint, Output = RistrettoPoint); + impl<'b> SubAssign<&'b RistrettoPoint> for RistrettoPoint { fn sub_assign(&mut self, _rhs: &RistrettoPoint) { *self = (self as &RistrettoPoint) - _rhs; } } +define_sub_assign_variants!(LHS = RistrettoPoint, RHS = RistrettoPoint); + impl<'a> Neg for &'a RistrettoPoint { type Output = RistrettoPoint; @@ -953,6 +961,14 @@ impl<'a> Neg for &'a RistrettoPoint { } } +impl Neg for RistrettoPoint { + type Output = RistrettoPoint; + + fn neg(self) -> RistrettoPoint { + -&self + } +} + impl<'b> MulAssign<&'b Scalar> for RistrettoPoint { fn mul_assign(&mut self, scalar: &'b Scalar) { let result = (self as &RistrettoPoint) * scalar; @@ -977,6 +993,12 @@ impl<'a, 'b> Mul<&'b RistrettoPoint> for &'a Scalar { } } +define_mul_assign_variants!(LHS = RistrettoPoint, RHS = Scalar); + +define_mul_variants!(LHS = RistrettoPoint, RHS = Scalar, Output = RistrettoPoint); +define_mul_variants!(LHS = Scalar, RHS = RistrettoPoint, Output = RistrettoPoint); + + /// Given a vector of (possibly secret) scalars and a vector of /// (possibly secret) points, compute `c_1 P_1 + ... + c_n P_n`. /// diff --git a/src/scalar.rs b/src/scalar.rs index 8d12b4e..64a59bc 100644 --- a/src/scalar.rs +++ b/src/scalar.rs @@ -186,6 +186,8 @@ impl<'b> MulAssign<&'b Scalar> for Scalar { } } +define_mul_assign_variants!(LHS = Scalar, RHS = Scalar); + impl<'a, 'b> Mul<&'b Scalar> for &'a Scalar { type Output = Scalar; fn mul(self, _rhs: &'b Scalar) -> Scalar { @@ -193,12 +195,16 @@ impl<'a, 'b> Mul<&'b Scalar> for &'a Scalar { } } +define_mul_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar); + impl<'b> AddAssign<&'b Scalar> for Scalar { fn add_assign(&mut self, _rhs: &'b Scalar) { *self = UnpackedScalar::add(&self.unpack(), &_rhs.unpack()).pack(); } } +define_add_assign_variants!(LHS = Scalar, RHS = Scalar); + impl<'a, 'b> Add<&'b Scalar> for &'a Scalar { type Output = Scalar; fn add(self, _rhs: &'b Scalar) -> Scalar { @@ -206,12 +212,16 @@ impl<'a, 'b> Add<&'b Scalar> for &'a Scalar { } } +define_add_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar); + impl<'b> SubAssign<&'b Scalar> for Scalar { fn sub_assign(&mut self, _rhs: &'b Scalar) { *self = UnpackedScalar::sub(&self.unpack(), &_rhs.unpack()).pack(); } } +define_sub_assign_variants!(LHS = Scalar, RHS = Scalar); + impl<'a, 'b> Sub<&'b Scalar> for &'a Scalar { type Output = Scalar; fn sub(self, _rhs: &'b Scalar) -> Scalar { @@ -219,6 +229,8 @@ impl<'a, 'b> Sub<&'b Scalar> for &'a Scalar { } } +define_sub_variants!(LHS = Scalar, RHS = Scalar, Output = Scalar); + impl<'a> Neg for &'a Scalar { type Output = Scalar; fn neg(self) -> Scalar { @@ -226,6 +238,13 @@ impl<'a> Neg for &'a Scalar { } } +impl<'a> Neg for Scalar { + type Output = Scalar; + fn neg(self) -> Scalar { + -&self + } +} + impl ConditionallyAssignable for Scalar { /// Conditionally assign another Scalar to this one. ///