Skip to content

Commit

Permalink
Leverage const_mut_refs; MSRV 1.83 (#667)
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 authored Nov 30, 2024
1 parent 691aff8 commit 5ac4b3e
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 148 deletions.
13 changes: 8 additions & 5 deletions .github/workflows/crypto-bigint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
strategy:
matrix:
rust:
- 1.81.0 # MSRV
- 1.83.0 # MSRV
- stable
target:
- thumbv7em-none-eabi
Expand Down Expand Up @@ -48,15 +48,15 @@ jobs:
include:
# 32-bit Linux
- target: i686-unknown-linux-gnu
rust: 1.81.0 # MSRV
rust: 1.83.0 # MSRV
deps: sudo apt update && sudo apt install gcc-multilib
- target: i686-unknown-linux-gnu
rust: stable
deps: sudo apt update && sudo apt install gcc-multilib

# 64-bit Linux
- target: x86_64-unknown-linux-gnu
rust: 1.81.0 # MSRV
rust: 1.83.0 # MSRV
- target: x86_64-unknown-linux-gnu
rust: stable
steps:
Expand Down Expand Up @@ -105,6 +105,9 @@ jobs:
with:
toolchain: nightly
- run: cargo update -Z minimal-versions
- uses: dtolnay/rust-toolchain@master
with:
toolchain: stable
- run: cargo +stable build --release --all-features

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

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

Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ keywords = ["arbitrary", "crypto", "bignum", "integer", "precision"]
readme = "README.md"
resolver = "2"
edition = "2021"
rust-version = "1.81"
rust-version = "1.83"

[dependencies]
subtle = { version = "2.6", default-features = false }
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ microcontrollers).

## Minimum Supported Rust Version

This crate requires **Rust 1.81** at a minimum.
This crate requires **Rust 1.83** at a minimum.

We may change the MSRV in the future, but it will be accompanied by a minor
version bump.
Expand Down Expand Up @@ -68,7 +68,7 @@ dual licensed as above, without any additional terms or conditions.
[build-image]: https://github.com/RustCrypto/crypto-bigint/actions/workflows/crypto-bigint.yml/badge.svg
[build-link]: https://github.com/RustCrypto/crypto-bigint/actions/workflows/crypto-bigint.yml
[license-image]: https://img.shields.io/badge/license-Apache2.0/MIT-blue.svg
[rustc-image]: https://img.shields.io/badge/rustc-1.81+-blue.svg
[rustc-image]: https://img.shields.io/badge/rustc-1.83+-blue.svg
[chat-image]: https://img.shields.io/badge/zulip-join_chat-blue.svg
[chat-link]: https://rustcrypto.zulipchat.com/#narrow/stream/300602-crypto-bigint

Expand Down
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 5ac4b3e

Please sign in to comment.