diff --git a/src/arithmetic.rs b/src/arithmetic.rs index e3dc6c448..b240d9df2 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -17,6 +17,7 @@ mod constant; #[cfg(feature = "alloc")] pub mod bigint; +mod inout; pub mod montgomery; mod n0; @@ -24,4 +25,4 @@ mod n0; #[allow(dead_code)] const BIGINT_MODULUS_MAX_LIMBS: usize = 8192 / crate::limb::LIMB_BITS; -pub use constant::limbs_from_hex; +pub use self::{constant::limbs_from_hex, inout::InOut}; diff --git a/src/arithmetic/bigint.rs b/src/arithmetic/bigint.rs index f3d867550..e0be21c8b 100644 --- a/src/arithmetic/bigint.rs +++ b/src/arithmetic/bigint.rs @@ -42,8 +42,8 @@ pub(crate) use self::{ modulusvalue::OwnedModulusValue, private_exponent::PrivateExponent, }; +use super::{montgomery::*, InOut}; use crate::{ - arithmetic::montgomery::*, bits::BitLength, c, error, limb::{self, Limb, LIMB_BITS}, @@ -99,7 +99,13 @@ fn from_montgomery_amm(limbs: BoxedLimbs, m: &Modulus) -> Elem( where (AF, BF): ProductEncoding, { - limbs_mont_mul(&mut b.limbs, &a.limbs, m.limbs(), m.n0(), m.cpu_features()); + limbs_mul_mont( + InOut::InPlace(&mut b.limbs), + &a.limbs, + m.limbs(), + m.n0(), + m.cpu_features(), + ); Elem { limbs: b.limbs, encoding: PhantomData, @@ -467,7 +479,13 @@ pub fn elem_exp_consttime( let src1 = entry(previous, src1, num_limbs); let src2 = entry(previous, src2, num_limbs); let dst = entry_mut(rest, 0, num_limbs); - limbs_mont_product(dst, src1, src2, m.limbs(), m.n0(), m.cpu_features()); + limbs_mul_mont( + InOut::Disjoint(dst, src1), + src2, + m.limbs(), + m.n0(), + m.cpu_features(), + ); } let tmp = m.zero(); diff --git a/src/arithmetic/inout.rs b/src/arithmetic/inout.rs new file mode 100644 index 000000000..daafb4f5a --- /dev/null +++ b/src/arithmetic/inout.rs @@ -0,0 +1,19 @@ +// Copyright 2025 Brian Smith. +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +pub enum InOut<'io, T: ?Sized> { + InPlace(&'io mut T), + #[cfg_attr(target_arch = "x86_64", allow(dead_code))] + Disjoint(&'io mut T, &'io T), +} diff --git a/src/arithmetic/montgomery.rs b/src/arithmetic/montgomery.rs index 5f5a14a84..b58b4ef09 100644 --- a/src/arithmetic/montgomery.rs +++ b/src/arithmetic/montgomery.rs @@ -12,7 +12,7 @@ // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -pub use super::n0::N0; +pub use super::{n0::N0, InOut}; use crate::cpu; // Indicates that the element is not encoded; there is no *R* factor @@ -113,15 +113,24 @@ impl ProductEncoding for (RRR, RInverse) { use crate::{bssl, c, limb::Limb}; #[inline(always)] -unsafe fn mul_mont( - r: *mut Limb, - a: *const Limb, - b: *const Limb, - n: *const Limb, - n0: &N0, - num_limbs: c::size_t, - _: cpu::Features, -) { +pub(super) fn limbs_mul_mont(ra: InOut<[Limb]>, b: &[Limb], n: &[Limb], n0: &N0, _: cpu::Features) { + // XXX/TODO: All the `debug_assert_eq!` length checking needs to be + // replaced with enforcement that happens regardless of debug mode. + let (r, a) = match ra { + InOut::InPlace(r) => { + debug_assert_eq!(r.len(), n.len()); + (r.as_mut_ptr(), r.as_ptr()) + } + InOut::Disjoint(r, a) => { + debug_assert_eq!(r.len(), n.len()); + debug_assert_eq!(a.len(), n.len()); + (r.as_mut_ptr(), a.as_ptr()) + } + }; + debug_assert_eq!(b.len(), n.len()); + let b = b.as_ptr(); + let num_limbs = n.len(); + let n = n.as_ptr(); unsafe { bn_mul_mont(r, a, b, n, n0, num_limbs) } } @@ -249,71 +258,15 @@ prefixed_extern! { ); } -/// r *= a -pub(super) fn limbs_mont_mul( - r: &mut [Limb], - a: &[Limb], - m: &[Limb], - n0: &N0, - cpu_features: cpu::Features, -) { - debug_assert_eq!(r.len(), m.len()); - debug_assert_eq!(a.len(), m.len()); - unsafe { - mul_mont( - r.as_mut_ptr(), - r.as_ptr(), - a.as_ptr(), - m.as_ptr(), - n0, - r.len(), - cpu_features, - ) - } -} - -/// r = a * b -#[cfg(not(target_arch = "x86_64"))] -pub(super) fn limbs_mont_product( - r: &mut [Limb], - a: &[Limb], - b: &[Limb], - m: &[Limb], - n0: &N0, - cpu_features: cpu::Features, -) { - debug_assert_eq!(r.len(), m.len()); - debug_assert_eq!(a.len(), m.len()); - debug_assert_eq!(b.len(), m.len()); - - unsafe { - mul_mont( - r.as_mut_ptr(), - a.as_ptr(), - b.as_ptr(), - m.as_ptr(), - n0, - r.len(), - cpu_features, - ) - } -} - /// r = r**2 -pub(super) fn limbs_square_mont(r: &mut [Limb], m: &[Limb], n0: &N0, cpu_features: cpu::Features) { - debug_assert_eq!(r.len(), m.len()); - unsafe { - mul_mont( - r.as_mut_ptr(), - r.as_ptr(), - r.as_ptr(), - m.as_ptr(), - n0, - r.len(), - cpu_features, - ) - } +pub(super) fn limbs_square_mont(r: &mut [Limb], n: &[Limb], n0: &N0, _cpu: cpu::Features) { + debug_assert_eq!(r.len(), n.len()); + let r = r.as_mut_ptr(); + let num_limbs = n.len(); + let n = n.as_ptr(); + unsafe { bn_mul_mont(r, r, r, n, n0, num_limbs) } } + #[cfg(test)] mod tests { use super::*;