diff --git a/src/window.rs b/src/window.rs index 3b01422..4afe63e 100644 --- a/src/window.rs +++ b/src/window.rs @@ -27,6 +27,9 @@ use backend::serial::curve_models::AffineNielsPoint; use zeroize::Zeroize; +macro_rules! impl_lookup_table { + (Name = $name:ident, Size = $size:expr, SizeNeg = $neg:expr, SizeRange = $range:expr, ConversionRange = $conv_range:expr) => { + /// A lookup table of precomputed multiples of a point \\(P\\), used to /// compute \\( xP \\) for \\( -8 \leq x \leq 8 \\). /// @@ -37,19 +40,17 @@ use zeroize::Zeroize; /// only `pub(crate)` so that we can write hardcoded constants, so it's /// still technically possible. It would be nice to prevent direct /// access to the table. -/// -/// XXX make this generic with respect to table size #[derive(Copy, Clone)] -pub struct LookupTable(pub(crate) [T; 8]); +pub struct $name(pub(crate) [T; $size]); -impl LookupTable +impl $name where T: Identity + ConditionallySelectable + ConditionallyNegatable, { /// Given \\(-8 \leq x \leq 8\\), return \\(xP\\) in constant time. pub fn select(&self, x: i8) -> T { - debug_assert!(x >= -8); - debug_assert!(x <= 8); + debug_assert!(x >= $neg); + debug_assert!(x as i16 <= $size as i16); // XXX We have to convert to i16s here for the radix-256 case.. this is wrong. // Compute xabs = |x| let xmask = x >> 7; @@ -57,9 +58,9 @@ where // Set t = 0 * P = identity let mut t = T::identity(); - for j in 1..9 { + for j in $range { // Copy `points[j-1] == j*P` onto `t` in constant time if `|x| == j`. - let c = (xabs as u8).ct_eq(&(j as u8)); + let c = (xabs as u16).ct_eq(&(j as u16)); t.conditional_assign(&self.0[j - 1], c); } // Now t == |x| * P. @@ -72,48 +73,68 @@ where } } -impl Default for LookupTable { - fn default() -> LookupTable { - LookupTable([T::default(); 8]) +impl Default for $name { + fn default() -> $name { + $name([T::default(); $size]) } } -impl Debug for LookupTable { +impl Debug for $name { fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { - write!(f, "LookupTable({:?})", self.0) + write!(f, "{:?}(", stringify!($name))?; + + for x in self.0.iter() { + write!(f, "{:?}", x)?; + } + + write!(f, ")") } } -impl<'a> From<&'a EdwardsPoint> for LookupTable { +impl<'a> From<&'a EdwardsPoint> for $name { fn from(P: &'a EdwardsPoint) -> Self { - let mut points = [P.to_projective_niels(); 8]; - for j in 0..7 { + let mut points = [P.to_projective_niels(); $size]; + for j in $conv_range { points[j + 1] = (P + &points[j]).to_extended().to_projective_niels(); } - LookupTable(points) + $name(points) } } -impl<'a> From<&'a EdwardsPoint> for LookupTable { +impl<'a> From<&'a EdwardsPoint> for $name { fn from(P: &'a EdwardsPoint) -> Self { - let mut points = [P.to_affine_niels(); 8]; + let mut points = [P.to_affine_niels(); $size]; // XXX batch inversion would be good if perf mattered here - for j in 0..7 { + for j in $conv_range { points[j + 1] = (P + &points[j]).to_extended().to_affine_niels() } - LookupTable(points) + $name(points) } } -impl Zeroize for LookupTable +impl Zeroize for $name where T: Copy + Default + Zeroize { fn zeroize(&mut self) { - self.0.zeroize(); + for x in self.0.iter_mut() { + x.zeroize(); + } } } +}} // End macro_rules! impl_lookup_table + +// The first one has to be named "LookupTable" because it's used as a constructor for consts. +impl_lookup_table! {Name = LookupTable, Size = 8, SizeNeg = -8, SizeRange = 1 .. 9, ConversionRange = 0 .. 7} // radix-16 +impl_lookup_table! {Name = LookupTableRadix32, Size = 16, SizeNeg = -16, SizeRange = 1 .. 17, ConversionRange = 0 .. 15} // radix-32 +impl_lookup_table! {Name = LookupTableRadix64, Size = 32, SizeNeg = -32, SizeRange = 1 .. 33, ConversionRange = 0 .. 31} // radix-64 +impl_lookup_table! {Name = LookupTableRadix128, Size = 64, SizeNeg = -64, SizeRange = 1 .. 65, ConversionRange = 0 .. 63} // radix-128 +impl_lookup_table! {Name = LookupTableRadix256, Size = 128, SizeNeg = -128, SizeRange = 1 .. 129, ConversionRange = 0 .. 127} // radix-256 + +// For homogeneity we then alias it to "LookupTableRadix16". +pub type LookupTableRadix16 = LookupTable; + /// Holds odd multiples 1A, 3A, ..., 15A of a point A. #[derive(Copy, Clone)] pub(crate) struct NafLookupTable5(pub(crate) [T; 8]);