Skip to content

Commit

Permalink
[WIP] Leverage const_mut_refs
Browse files Browse the repository at this point in the history
Replaces macro-based code sharing between the stack-allocated and
heap-allocated `*Uint` types with `const fn` using `const_mut_refs`.
  • Loading branch information
tarcieri committed Oct 16, 2024
1 parent b85c162 commit 522ea4a
Show file tree
Hide file tree
Showing 3 changed files with 153 additions and 156 deletions.
35 changes: 19 additions & 16 deletions .github/workflows/crypto-bigint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ jobs:
strategy:
matrix:
rust:
- 1.81.0 # MSRV
- stable
#- 1.81.0 # MSRV
- beta
target:
- thumbv7em-none-eabi
- wasm32-unknown-unknown
Expand All @@ -47,18 +47,18 @@ jobs:
matrix:
include:
# 32-bit Linux
#- target: i686-unknown-linux-gnu
# rust: 1.81.0 # MSRV
# deps: sudo apt update && sudo apt install gcc-multilib
- target: i686-unknown-linux-gnu
rust: 1.81.0 # MSRV
deps: sudo apt update && sudo apt install gcc-multilib
- target: i686-unknown-linux-gnu
rust: stable
rust: beta
deps: sudo apt update && sudo apt install gcc-multilib

# 64-bit Linux
#- target: x86_64-unknown-linux-gnu
# rust: 1.81.0 # MSRV
- target: x86_64-unknown-linux-gnu
rust: 1.81.0 # MSRV
- target: x86_64-unknown-linux-gnu
rust: stable
rust: beta
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
Expand All @@ -77,11 +77,11 @@ jobs:
include:
# ARM64
- target: aarch64-unknown-linux-gnu
rust: stable
rust: beta

# PPC32 (big endian)
- target: powerpc-unknown-linux-gnu
rust: stable
rust: beta

runs-on: ubuntu-latest
steps:
Expand All @@ -105,7 +105,10 @@ jobs:
with:
toolchain: nightly
- run: cargo update -Z minimal-versions
- run: cargo +stable build --release --all-features
- uses: dtolnay/rust-toolchain@master
with:
toolchain: beta
- run: cargo +beta build --release --all-features

miri:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -136,7 +139,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.81.0
toolchain: beta
components: clippy
- run: cargo clippy --all --all-features -- -D warnings

Expand All @@ -146,7 +149,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
toolchain: beta
components: rustfmt
- run: cargo fmt --all -- --check

Expand All @@ -156,7 +159,7 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: 1.81.0
toolchain: beta
- run: cargo build --benches
- run: cargo build --all-features --benches

Expand All @@ -166,5 +169,5 @@ jobs:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
toolchain: beta
- run: cargo doc --all-features
83 changes: 42 additions & 41 deletions src/modular/reduction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,43 +5,46 @@ use crate::{Limb, Odd, Uint};
#[cfg(feature = "alloc")]
use {crate::BoxedUint, subtle::Choice};

/// Implement the Montgomery reduction algorithm.
///
/// This is implemented as a macro to abstract over `const fn` and boxed use cases, since the latter
/// needs mutable references and thus the unstable `const_mut_refs` feature (rust-lang/rust#57349).
// TODO(tarcieri): change this into a `const fn` when `const_mut_refs` is stable
macro_rules! impl_montgomery_reduction {
($upper:expr, $lower:expr, $modulus:expr, $mod_neg_inv:expr, $limbs:expr) => {{
let mut meta_carry = Limb::ZERO;
let mut new_sum;

let mut i = 0;
while i < $limbs {
let u = $lower[i].wrapping_mul($mod_neg_inv);

let (_, mut carry) = $lower[i].mac(u, $modulus[0], Limb::ZERO);
let mut new_limb;

let mut j = 1;
while j < ($limbs - i) {
(new_limb, carry) = $lower[i + j].mac(u, $modulus[j], carry);
$lower[i + j] = new_limb;
j += 1;
}
while j < $limbs {
(new_limb, carry) = $upper[i + j - $limbs].mac(u, $modulus[j], carry);
$upper[i + j - $limbs] = new_limb;
j += 1;
}

(new_sum, meta_carry) = $upper[i].adc(carry, meta_carry);
$upper[i] = new_sum;

i += 1;
/// Algorithm 14.32 in Handbook of Applied Cryptography <https://cacr.uwaterloo.ca/hac/about/chap14.pdf>
const fn montgomery_reduction_inner(
upper: &mut [Limb],
lower: &mut [Limb],
modulus: &[Limb],
mod_neg_inv: Limb,
) -> Limb {
let nlimbs = modulus.len();
debug_assert!(nlimbs == upper.len());
debug_assert!(nlimbs == lower.len());

let mut meta_carry = Limb::ZERO;
let mut new_sum;

let mut i = 0;
while i < nlimbs {
let u = lower[i].wrapping_mul(mod_neg_inv);

let (_, mut carry) = lower[i].mac(u, modulus[0], Limb::ZERO);
let mut new_limb;

let mut j = 1;
while j < (nlimbs - i) {
(new_limb, carry) = lower[i + j].mac(u, modulus[j], carry);
lower[i + j] = new_limb;
j += 1;
}
while j < nlimbs {
(new_limb, carry) = upper[i + j - nlimbs].mac(u, modulus[j], carry);
upper[i + j - nlimbs] = new_limb;
j += 1;
}

(new_sum, meta_carry) = upper[i].adc(carry, meta_carry);
upper[i] = new_sum;

i += 1;
}

meta_carry
}};
meta_carry
}

/// Algorithm 14.32 in Handbook of Applied Cryptography <https://cacr.uwaterloo.ca/hac/about/chap14.pdf>
Expand All @@ -51,12 +54,11 @@ pub const fn montgomery_reduction<const LIMBS: usize>(
mod_neg_inv: Limb,
) -> Uint<LIMBS> {
let (mut lower, mut upper) = *lower_upper;
let meta_carry = impl_montgomery_reduction!(
upper.limbs,
lower.limbs,
let meta_carry = montgomery_reduction_inner(
&mut upper.limbs,
&mut lower.limbs,
&modulus.0.limbs,
mod_neg_inv,
LIMBS
);

// Division is simply taking the upper half of the limbs
Expand All @@ -79,8 +81,7 @@ pub(crate) fn montgomery_reduction_boxed_mut(
debug_assert_eq!(out.nlimbs(), modulus.nlimbs());

let (lower, upper) = x.limbs.split_at_mut(modulus.nlimbs());
let meta_carry =
impl_montgomery_reduction!(upper, lower, &modulus.limbs, mod_neg_inv, modulus.nlimbs());
let meta_carry = montgomery_reduction_inner(upper, lower, &modulus.limbs, mod_neg_inv);

out.limbs.copy_from_slice(upper);
let borrow = out.sbb_assign(modulus, Limb::ZERO);
Expand Down
Loading

0 comments on commit 522ea4a

Please sign in to comment.