Skip to content

Commit

Permalink
p384: const fn field arithmetic (#589)
Browse files Browse the repository at this point in the history
Uses the `fiat-constify` tool to mechanically transform `fiat-crypto`
generated field implementations into `const fn`:

https://github.com/RustCrypto/utils/tree/master/fiat-constify

Resulting code has been run through `rustfmt` prior to checking it in:

    rustfmt 1.4.38-stable (fe5b13d6 2022-05-18)

The following are criterion benchmarks after the translation. While
these values are within the threshold of noise I experience running them
on a semi-busy desktop computer (MacBook w\ 2.3 GHz 8-Core Intel Core i9)
they do paint a picture of a slight performance regression.

field element operations/mul
                        time:   [60.361 ns 60.755 ns 61.170 ns]
                        change: [+3.0611% +4.1805% +5.1398%] (p = 0.00 < 0.05)
                        Performance has regressed.

field element operations/square
                        time:   [59.143 ns 59.508 ns 59.924 ns]
                        change: [+4.8440% +5.5441% +6.2283%] (p = 0.00 < 0.05)
                        Performance has regressed.

field element operations/invert
                        time:   [49.713 us 50.069 us 50.481 us]
                        change: [+14.227% +15.283% +16.277%] (p = 0.00 < 0.05)
                        Performance has regressed.

field element operations/sqrt
                        time:   [24.936 us 25.064 us 25.206 us]
                        change: [+3.0874% +3.9261% +4.7805%] (p = 0.00 < 0.05)
                        Performance has regressed.

point operations/point-scalar mul
                        time:   [532.24 us 535.29 us 538.62 us]
                        change: [+2.4804% +3.2221% +3.9748%] (p = 0.00 < 0.05)
                        Performance has regressed.

scalar operations/sub   time:   [7.1834 ns 7.2272 ns 7.2688 ns]
                        change: [+13.036% +13.817% +14.551%] (p = 0.00 < 0.05)
                        Performance has regressed.

scalar operations/add   time:   [9.5314 ns 9.5797 ns 9.6287 ns]
                        change: [+1.2331% +1.9875% +2.6816%] (p = 0.00 < 0.05)
                        Performance has regressed.

scalar operations/mul   time:   [59.303 ns 59.530 ns 59.779 ns]
                        change: [+5.0340% +5.6533% +6.2711%] (p = 0.00 < 0.05)
                        Performance has regressed.

scalar operations/negate
                        time:   [6.6648 ns 6.6915 ns 6.7244 ns]
                        change: [+0.1937% +1.0485% +1.8021%] (p = 0.01 < 0.05)
                        Change within noise threshold.

scalar operations/invert
                        time:   [49.255 us 49.365 us 49.489 us]
                        change: [+12.196% +13.079% +13.937%] (p = 0.00 < 0.05)
                        Performance has regressed.
  • Loading branch information
tarcieri authored Jun 2, 2022
1 parent c15c227 commit 593ec93
Show file tree
Hide file tree
Showing 7 changed files with 17,519 additions and 17,615 deletions.
5 changes: 1 addition & 4 deletions p384/src/arithmetic/field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@

#[cfg_attr(target_pointer_width = "32", path = "field/p384_32.rs")]
#[cfg_attr(target_pointer_width = "64", path = "field/p384_64.rs")]
#[allow(dead_code, rustdoc::broken_intra_doc_links)]
#[rustfmt::skip]
mod field_impl;

use self::field_impl::*;
Expand Down Expand Up @@ -118,8 +116,7 @@ mod tests {
/// Test that the precomputed `FieldElement::ONE` constant is correct.
#[test]
fn one() {
let mut one_mont = Default::default();
fiat_p384_to_montgomery(&mut one_mont, U384::ONE.as_ref());
let one_mont = fiat_p384_to_montgomery(U384::ONE.as_ref());
assert_eq!(FieldElement(one_mont.into()), FieldElement::ONE);
}

Expand Down
6,855 changes: 3,344 additions & 3,511 deletions p384/src/arithmetic/field/p384_32.rs

Large diffs are not rendered by default.

2,609 changes: 1,293 additions & 1,316 deletions p384/src/arithmetic/field/p384_64.rs

Large diffs are not rendered by default.

69 changes: 21 additions & 48 deletions p384/src/arithmetic/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,7 @@ macro_rules! impl_sec1_field_element {
///
/// Used incorrectly this can lead to invalid results!
fn from_uint_unchecked(w: $uint) -> Self {
let mut mont = <$uint>::default();
$to_mont(mont.as_mut(), w.as_ref());
Self(mont)
Self($to_mont(w.as_ref()).into())
}

/// Returns the big-endian encoding of this [`
Expand All @@ -156,9 +154,7 @@ macro_rules! impl_sec1_field_element {
/// `] in canonical form.
#[inline]
pub fn to_canonical(self) -> $uint {
let mut ret = <$uint>::default();
$from_mont(ret.as_mut(), self.as_ref());
ret
$from_mont(self.as_ref()).into()
}

/// Determine if this [`
Expand Down Expand Up @@ -203,65 +199,50 @@ macro_rules! impl_sec1_field_element {
type XLimbs = [Word; LIMBS + 1];

let mut d: Word = 1;
let mut f = XLimbs::default();
$msat(&mut f);
let mut f = $msat();

let mut g = XLimbs::default();
$from_mont((&mut g[..LIMBS]).try_into().unwrap(), self.as_ref());
g[..LIMBS].copy_from_slice(&$from_mont(self.as_ref()));

let mut r = <$arr>::from(Self::ONE.0);
let mut v = <$arr>::default();
let mut precomp = <$arr>::default();
$divstep_precomp(&mut precomp);

let mut out1 = Word::default();
let mut out2 = XLimbs::default();
let mut out3 = XLimbs::default();
let mut out4 = <$arr>::default();
let mut out5 = <$arr>::default();
let precomp = $divstep_precomp();

let mut i: usize = 0;

while i < ITERATIONS - ITERATIONS % 2 {
$divstep(
&mut out1, &mut out2, &mut out3, &mut out4, &mut out5, d, &f, &g, &v, &r,
);
$divstep(
&mut d, &mut f, &mut g, &mut v, &mut r, out1, &out2, &out3, &out4, &out5,
);
let (out1, out2, out3, out4, out5) = $divstep(d, &f, &g, &v, &r);
let (out1, out2, out3, out4, out5) = $divstep(out1, &out2, &out3, &out4, &out5);
d = out1;
f = out2;
g = out3;
v = out4;
r = out5;
i += 2;
}

if ITERATIONS % 2 != 0 {
$divstep(
&mut out1, &mut out2, &mut out3, &mut out4, &mut out5, d, &f, &g, &v, &r,
);
let (_out1, out2, _out3, out4, _out5) = $divstep(d, &f, &g, &v, &r);
v = out4;
f = out2;
}

let mut v_opp = <$uint>::default();
$neg(v_opp.as_mut(), &v);

let v_opp = <$uint>::from($neg(&v));
let v = <$uint>::from(v);

let s = ::elliptic_curve::subtle::Choice::from(
((f[f.len() - 1] >> Limb::BIT_SIZE - 1) & 1) as u8,
);

let v = <$uint>::conditional_select(&v, &v_opp, s);

let mut ret = <$uint>::default();
$mul(ret.as_mut(), v.as_ref(), &precomp);
::elliptic_curve::subtle::CtOption::new(Self(ret), !self.is_zero())
let ret = $mul(v.as_ref(), &precomp);
::elliptic_curve::subtle::CtOption::new(Self(ret.into()), !self.is_zero())
}

/// Compute modular square.
#[must_use]
pub fn square(&self) -> Self {
let mut ret = <$uint>::default();
$square(ret.as_mut(), self.as_ref());
Self(ret)
Self($square(self.as_ref()).into())
}
}

Expand Down Expand Up @@ -406,9 +387,7 @@ macro_rules! impl_sec1_field_element {

#[inline]
fn neg(self) -> $fe {
let mut ret = <$uint>::default();
$neg(ret.as_mut(), self.as_ref());
Self(ret)
Self($neg(self.as_ref()).into())
}
}
};
Expand All @@ -423,9 +402,7 @@ macro_rules! impl_field_op {

#[inline]
fn $op_fn(self, rhs: $fe) -> $fe {
let mut out = <$uint>::default();
$func(out.as_mut(), self.as_ref(), rhs.as_ref());
$fe(out)
$fe($func(self.as_ref(), rhs.as_ref()).into())
}
}

Expand All @@ -434,9 +411,7 @@ macro_rules! impl_field_op {

#[inline]
fn $op_fn(self, rhs: &$fe) -> $fe {
let mut out = <$uint>::default();
$func(out.as_mut(), self.as_ref(), rhs.as_ref());
$fe(out)
$fe($func(self.as_ref(), rhs.as_ref()).into())
}
}

Expand All @@ -445,9 +420,7 @@ macro_rules! impl_field_op {

#[inline]
fn $op_fn(self, rhs: &$fe) -> $fe {
let mut out = <$uint>::default();
$func(out.as_mut(), self.as_ref(), rhs.as_ref());
$fe(out)
$fe($func(self.as_ref(), rhs.as_ref()).into())
}
}
};
Expand Down
5 changes: 1 addition & 4 deletions p384/src/arithmetic/scalar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
clippy::too_many_arguments,
clippy::unnecessary_cast
)]
#[allow(dead_code, rustdoc::broken_intra_doc_links)]
#[rustfmt::skip]
mod scalar_impl;

use self::scalar_impl::*;
Expand Down Expand Up @@ -258,8 +256,7 @@ mod tests {
/// Test that the precomputed `Scalar::ONE` constant is correct.
#[test]
fn one() {
let mut one_mont = Default::default();
fiat_p384_scalar_to_montgomery(&mut one_mont, U384::ONE.as_ref());
let one_mont = fiat_p384_scalar_to_montgomery(U384::ONE.as_ref());
assert_eq!(Scalar(one_mont.into()), Scalar::ONE);
}

Expand Down
Loading

0 comments on commit 593ec93

Please sign in to comment.