From 3c0f266ac336765f1196475faeb3bebe229a5076 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 4 Dec 2023 17:31:50 -0800 Subject: [PATCH 1/4] montgomery: Clarify minimum limb width for `bn_mul_mont`. --- src/arithmetic/bigint/modulus.rs | 11 ++----- src/arithmetic/montgomery.rs | 49 +++++++++----------------------- 2 files changed, 15 insertions(+), 45 deletions(-) diff --git a/src/arithmetic/bigint/modulus.rs b/src/arithmetic/bigint/modulus.rs index 3f87053c01..0df9c9acfd 100644 --- a/src/arithmetic/bigint/modulus.rs +++ b/src/arithmetic/bigint/modulus.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. -use super::{BoxedLimbs, Elem, PublicModulus, Unencoded, N0}; +use super::{super::montgomery, BoxedLimbs, Elem, PublicModulus, Unencoded, N0}; use crate::{ bits::BitLength, cpu, error, @@ -21,13 +21,6 @@ use crate::{ }; use core::marker::PhantomData; -/// The x86 implementation of `bn_mul_mont`, at least, requires at least 4 -/// limbs. For a long time we have required 4 limbs for all targets, though -/// this may be unnecessary. TODO: Replace this with -/// `n.len() < 256 / LIMB_BITS` so that 32-bit and 64-bit platforms behave the -/// same. -pub const MODULUS_MIN_LIMBS: usize = 4; - pub const MODULUS_MAX_LIMBS: usize = super::super::BIGINT_MODULUS_MAX_LIMBS; /// The modulus *m* for a ring ℤ/mℤ, along with the precomputed values needed @@ -93,7 +86,7 @@ impl OwnedModulus { if n.len() > MODULUS_MAX_LIMBS { return Err(error::KeyRejected::too_large()); } - if n.len() < MODULUS_MIN_LIMBS { + if n.len() < montgomery::MIN_LIMBS { return Err(error::KeyRejected::unexpected_error()); } if limb::limbs_are_even_constant_time(&n) != LimbMask::False { diff --git a/src/arithmetic/montgomery.rs b/src/arithmetic/montgomery.rs index b3bed1b14c..842a4c5d35 100644 --- a/src/arithmetic/montgomery.rs +++ b/src/arithmetic/montgomery.rs @@ -112,17 +112,24 @@ impl ProductEncoding for (RRR, RInverse) { #[allow(unused_imports)] use crate::{bssl, c, limb::Limb}; +/// The x86 implementation of `bn_mul_mont`, at least, requires at least 4 +/// limbs. For a long time we have required 4 limbs for all targets, though +/// this may be unnecessary. TODO: Replace this with +/// `n.len() < 256 / LIMB_BITS` so that 32-bit and 64-bit platforms behave the +/// same. +pub const MIN_LIMBS: usize = 4; + #[inline(always)] unsafe fn mul_mont( r: *mut Limb, a: *const Limb, b: *const Limb, - n: *const Limb, + m: &[Limb], n0: &N0, - num_limbs: c::size_t, _: cpu::Features, ) { - bn_mul_mont(r, a, b, n, n0, num_limbs) + debug_assert!(m.len() >= MIN_LIMBS); + bn_mul_mont(r, a, b, m.as_ptr(), n0, m.len()) } #[cfg(not(any( @@ -260,17 +267,7 @@ pub(super) fn limbs_mont_mul( ) { 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, - ) - } + unsafe { mul_mont(r.as_mut_ptr(), r.as_ptr(), a.as_ptr(), m, n0, cpu_features) } } /// r = a * b @@ -287,33 +284,13 @@ pub(super) fn limbs_mont_product( 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, - ) - } + unsafe { mul_mont(r.as_mut_ptr(), a.as_ptr(), b.as_ptr(), m, n0, cpu_features) } } /// r = r**2 pub(super) fn limbs_mont_square(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, - ) - } + unsafe { mul_mont(r.as_mut_ptr(), r.as_ptr(), r.as_ptr(), m, n0, cpu_features) } } #[cfg(test)] mod tests { From 3ef1209012c2a3ef398b9bf26c65dfb02d9c99cf Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 4 Dec 2023 17:43:59 -0800 Subject: [PATCH 2/4] montgomery: Avoid using `debug_assert!` for length checks. Always enforce the bounds checks for `bn_mul_mont`. --- src/arithmetic/bigint.rs | 17 ++++++++-------- src/arithmetic/montgomery.rs | 39 +++++++++++++++++++++++------------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/arithmetic/bigint.rs b/src/arithmetic/bigint.rs index b326c35e74..b973e89175 100644 --- a/src/arithmetic/bigint.rs +++ b/src/arithmetic/bigint.rs @@ -97,7 +97,7 @@ 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_mont_mul(&mut b.limbs, &a.limbs, m.limbs(), m.n0(), m.cpu_features()).unwrap(); Elem { limbs: b.limbs, encoding: PhantomData, @@ -203,7 +203,7 @@ fn elem_squared( where (E, E): ProductEncoding, { - limbs_mont_square(&mut a.limbs, m.limbs(), m.n0(), m.cpu_features()); + limbs_mont_square(&mut a.limbs, m.limbs(), m.n0(), m.cpu_features()).unwrap(); Elem { limbs: a.limbs, encoding: PhantomData, @@ -465,7 +465,7 @@ 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_mont_product(dst, src1, src2, m.limbs(), m.n0(), m.cpu_features())?; } let tmp = m.zero(); @@ -629,15 +629,16 @@ pub fn elem_exp_consttime( mut i: Window, num_limbs: usize, cpu_features: cpu::Features, - ) { + ) -> Result<(), error::Unspecified> { loop { scatter(table, acc, i, num_limbs); i *= 2; if i >= (TABLE_ENTRIES as Window) { break; } - limbs_mont_square(acc, m_cached, n0, cpu_features); + limbs_mont_square(acc, m_cached, n0, cpu_features)?; } + Ok(()) } // All entries in `table` will be Montgomery encoded. @@ -650,12 +651,12 @@ pub fn elem_exp_consttime( acc.copy_from_slice(base_cached); // Fill in entries 1, 2, 4, 8, 16. - scatter_powers_of_2(table, acc, m_cached, n0, 1, num_limbs, cpu_features); + scatter_powers_of_2(table, acc, m_cached, n0, 1, num_limbs, cpu_features)?; // Fill in entries 3, 6, 12, 24; 5, 10, 20, 30; 7, 14, 28; 9, 18; 11, 22; 13, 26; 15, 30; // 17; 19; 21; 23; 25; 27; 29; 31. for i in (3..(TABLE_ENTRIES as Window)).step_by(2) { limbs_mul_mont_gather5_amm(table, acc, base_cached, m_cached, n0, i - 1, num_limbs); - scatter_powers_of_2(table, acc, m_cached, n0, i, num_limbs, cpu_features); + scatter_powers_of_2(table, acc, m_cached, n0, i, num_limbs, cpu_features)?; } let acc = limb::fold_5_bit_windows( diff --git a/src/arithmetic/montgomery.rs b/src/arithmetic/montgomery.rs index 842a4c5d35..cba703b0ec 100644 --- a/src/arithmetic/montgomery.rs +++ b/src/arithmetic/montgomery.rs @@ -13,7 +13,7 @@ // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. pub use super::n0::N0; -use crate::cpu; +use crate::{cpu, error}; // Indicates that the element is not encoded; there is no *R* factor // that needs to be canceled out. @@ -127,9 +127,12 @@ unsafe fn mul_mont( m: &[Limb], n0: &N0, _: cpu::Features, -) { - debug_assert!(m.len() >= MIN_LIMBS); - bn_mul_mont(r, a, b, m.as_ptr(), n0, m.len()) +) -> Result<(), error::Unspecified> { + if m.len() < MIN_LIMBS { + return Err(error::Unspecified); + } + bn_mul_mont(r, a, b, m.as_ptr(), n0, m.len()); + Ok(()) } #[cfg(not(any( @@ -264,9 +267,10 @@ pub(super) fn limbs_mont_mul( m: &[Limb], n0: &N0, cpu_features: cpu::Features, -) { - debug_assert_eq!(r.len(), m.len()); - debug_assert_eq!(a.len(), m.len()); +) -> Result<(), error::Unspecified> { + if r.len() != m.len() || a.len() != m.len() { + return Err(error::Unspecified); + } unsafe { mul_mont(r.as_mut_ptr(), r.as_ptr(), a.as_ptr(), m, n0, cpu_features) } } @@ -279,19 +283,26 @@ pub(super) fn limbs_mont_product( 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()); - +) -> Result<(), error::Unspecified> { + if r.len() != m.len() || a.len() != m.len() || b.len() != m.len() { + return Err(error::Unspecified); + } unsafe { mul_mont(r.as_mut_ptr(), a.as_ptr(), b.as_ptr(), m, n0, cpu_features) } } /// r = r**2 -pub(super) fn limbs_mont_square(r: &mut [Limb], m: &[Limb], n0: &N0, cpu_features: cpu::Features) { - debug_assert_eq!(r.len(), m.len()); +pub(super) fn limbs_mont_square( + r: &mut [Limb], + m: &[Limb], + n0: &N0, + cpu_features: cpu::Features, +) -> Result<(), error::Unspecified> { + if r.len() != m.len() { + return Err(error::Unspecified); + } unsafe { mul_mont(r.as_mut_ptr(), r.as_ptr(), r.as_ptr(), m, n0, cpu_features) } } + #[cfg(test)] mod tests { use super::*; From 6d11f920376437a220ed3e6c56679859c44f61f9 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 4 Dec 2023 18:13:42 -0800 Subject: [PATCH 3/4] montgomery: Enforce maximum limb length with a runtime check. Further clarify the memory safety. --- src/arithmetic.rs | 4 ---- src/arithmetic/bigint.rs | 4 ++-- src/arithmetic/bigint/modulus.rs | 2 +- src/arithmetic/montgomery.rs | 12 +++++++++--- src/ec/suite_b/ops.rs | 7 ++++++- src/ec/suite_b/ops/elem.rs | 5 ++++- 6 files changed, 22 insertions(+), 12 deletions(-) diff --git a/src/arithmetic.rs b/src/arithmetic.rs index e3dc6c4489..1381f6dbac 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -20,8 +20,4 @@ pub mod bigint; pub mod montgomery; mod n0; - -#[allow(dead_code)] -const BIGINT_MODULUS_MAX_LIMBS: usize = 8192 / crate::limb::LIMB_BITS; - pub use constant::limbs_from_hex; diff --git a/src/arithmetic/bigint.rs b/src/arithmetic/bigint.rs index b973e89175..91e3542588 100644 --- a/src/arithmetic/bigint.rs +++ b/src/arithmetic/bigint.rs @@ -94,7 +94,7 @@ fn from_montgomery_amm(limbs: BoxedLimbs, m: &Modulus) -> Elem( // `limbs_from_mont_in_place` requires this. assert_eq!(a.limbs.len(), m.limbs().len() * 2); - let mut tmp = [0; MODULUS_MAX_LIMBS]; + let mut tmp = [0; MAX_LIMBS]; let tmp = &mut tmp[..a.limbs.len()]; tmp.copy_from_slice(&a.limbs); diff --git a/src/arithmetic/bigint/modulus.rs b/src/arithmetic/bigint/modulus.rs index 0df9c9acfd..74cffb656b 100644 --- a/src/arithmetic/bigint/modulus.rs +++ b/src/arithmetic/bigint/modulus.rs @@ -21,7 +21,7 @@ use crate::{ }; use core::marker::PhantomData; -pub const MODULUS_MAX_LIMBS: usize = super::super::BIGINT_MODULUS_MAX_LIMBS; +pub const MODULUS_MAX_LIMBS: usize = montgomery::MAX_LIMBS; /// The modulus *m* for a ring ℤ/mℤ, along with the precomputed values needed /// for efficient Montgomery multiplication modulo *m*. The value must be odd diff --git a/src/arithmetic/montgomery.rs b/src/arithmetic/montgomery.rs index cba703b0ec..8afbc55ab6 100644 --- a/src/arithmetic/montgomery.rs +++ b/src/arithmetic/montgomery.rs @@ -119,6 +119,12 @@ use crate::{bssl, c, limb::Limb}; /// same. pub const MIN_LIMBS: usize = 4; +/// Many functions, including assembly functions, will stack allocate +/// `n * MAX_LIMBS` (for some `n`) limbs to store temporary values. Reduce the +/// chance of stack overflows by limiting these functions according to the +/// maximum size of modulus we wish to support. +pub const MAX_LIMBS: usize = 8192 / crate::limb::LIMB_BITS; + #[inline(always)] unsafe fn mul_mont( r: *mut Limb, @@ -128,7 +134,7 @@ unsafe fn mul_mont( n0: &N0, _: cpu::Features, ) -> Result<(), error::Unspecified> { - if m.len() < MIN_LIMBS { + if m.len() < MIN_LIMBS || m.len() > MAX_LIMBS { return Err(error::Unspecified); } bn_mul_mont(r, a, b, m.as_ptr(), n0, m.len()); @@ -159,7 +165,7 @@ prefixed_export! { // Nothing aliases `n` let n = unsafe { core::slice::from_raw_parts(n, num_limbs) }; - let mut tmp = [0; 2 * super::BIGINT_MODULUS_MAX_LIMBS]; + let mut tmp = [0; 2 * MAX_LIMBS]; let tmp = &mut tmp[..(2 * num_limbs)]; { let a: &[Limb] = unsafe { core::slice::from_raw_parts(a, num_limbs) }; @@ -326,7 +332,7 @@ mod tests { ]; for (i, (r_input, a, w, expected_retval, expected_r)) in TEST_CASES.iter().enumerate() { - let mut r = [0; super::super::BIGINT_MODULUS_MAX_LIMBS]; + let mut r = [0; MAX_LIMBS]; let r = { let r = &mut r[..r_input.len()]; r.copy_from_slice(r_input); diff --git a/src/ec/suite_b/ops.rs b/src/ec/suite_b/ops.rs index 57e4c7aaa1..af4f25fd45 100644 --- a/src/ec/suite_b/ops.rs +++ b/src/ec/suite_b/ops.rs @@ -12,7 +12,12 @@ // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -use crate::{arithmetic::limbs_from_hex, arithmetic::montgomery::*, error, limb::*}; +use crate::{ + arithmetic::limbs_from_hex, + arithmetic::montgomery::{Encoding, ProductEncoding, Unencoded, R, RR}, + error, + limb::*, +}; use core::marker::PhantomData; pub use self::elem::*; diff --git a/src/ec/suite_b/ops/elem.rs b/src/ec/suite_b/ops/elem.rs index e8479f2af6..7b408e09c9 100644 --- a/src/ec/suite_b/ops/elem.rs +++ b/src/ec/suite_b/ops/elem.rs @@ -15,7 +15,7 @@ use crate::{ arithmetic::{ limbs_from_hex, - montgomery::{Encoding, ProductEncoding}, + montgomery::{self, Encoding, ProductEncoding}, }, limb::{Limb, LIMB_BITS}, }; @@ -129,3 +129,6 @@ pub fn unary_op_from_binary_op_assign( } pub const MAX_LIMBS: usize = (384 + (LIMB_BITS - 1)) / LIMB_BITS; + +#[allow(clippy::assertions_on_constants)] +const _MAX_LIMBS_IS_LESS_THAN_MAX_LIMBS: () = assert!(MAX_LIMBS <= montgomery::MAX_LIMBS); From 9a393e1e3f58d555336f51035c1d522d002e5a16 Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Mon, 4 Dec 2023 18:31:30 -0800 Subject: [PATCH 4/4] montgomery: Use a distinct error for length checks. --- src/arithmetic.rs | 2 ++ src/arithmetic/bigint.rs | 7 ++++--- src/arithmetic/error.rs | 32 ++++++++++++++++++++++++++++++++ src/arithmetic/montgomery.rs | 19 ++++++++++--------- src/rsa/keypair.rs | 3 ++- 5 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 src/arithmetic/error.rs diff --git a/src/arithmetic.rs b/src/arithmetic.rs index 1381f6dbac..4b9dfde397 100644 --- a/src/arithmetic.rs +++ b/src/arithmetic.rs @@ -17,7 +17,9 @@ mod constant; #[cfg(feature = "alloc")] pub mod bigint; +mod error; pub mod montgomery; mod n0; pub use constant::limbs_from_hex; +pub(crate) use error::ImpossibleLengthError; diff --git a/src/arithmetic/bigint.rs b/src/arithmetic/bigint.rs index 91e3542588..a5d79c1f3e 100644 --- a/src/arithmetic/bigint.rs +++ b/src/arithmetic/bigint.rs @@ -41,6 +41,7 @@ pub(crate) use self::{ modulus::{Modulus, OwnedModulus, MODULUS_MAX_LIMBS}, private_exponent::PrivateExponent, }; +use super::ImpossibleLengthError; use crate::{ arithmetic::montgomery::*, bits::BitLength, @@ -404,7 +405,7 @@ pub fn elem_exp_consttime( base: Elem, exponent: &PrivateExponent, m: &Modulus, -) -> Result, error::Unspecified> { +) -> Result, ImpossibleLengthError> { use crate::{bssl, limb::Window}; const WINDOW_BITS: usize = 5; @@ -490,7 +491,7 @@ pub fn elem_exp_consttime( base: Elem, exponent: &PrivateExponent, m: &Modulus, -) -> Result, error::Unspecified> { +) -> Result, ImpossibleLengthError> { use crate::{cpu, limb::LIMB_BYTES}; // Pretty much all the math here requires CPU feature detection to have @@ -629,7 +630,7 @@ pub fn elem_exp_consttime( mut i: Window, num_limbs: usize, cpu_features: cpu::Features, - ) -> Result<(), error::Unspecified> { + ) -> Result<(), ImpossibleLengthError> { loop { scatter(table, acc, i, num_limbs); i *= 2; diff --git a/src/arithmetic/error.rs b/src/arithmetic/error.rs new file mode 100644 index 0000000000..656ba4aa4d --- /dev/null +++ b/src/arithmetic/error.rs @@ -0,0 +1,32 @@ +// Copyright 2023 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. + +use crate::error; + +/// `ImpossibleLengthError` should never occur. +#[derive(Debug)] +pub struct ImpossibleLengthError(()); + +impl ImpossibleLengthError { + pub(super) fn new() -> Self { + // unreachable!(); + Self(()) + } +} + +impl From for error::Unspecified { + fn from(_: ImpossibleLengthError) -> Self { + Self + } +} diff --git a/src/arithmetic/montgomery.rs b/src/arithmetic/montgomery.rs index 8afbc55ab6..85de1027fd 100644 --- a/src/arithmetic/montgomery.rs +++ b/src/arithmetic/montgomery.rs @@ -13,7 +13,8 @@ // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. pub use super::n0::N0; -use crate::{cpu, error}; +use super::ImpossibleLengthError; +use crate::cpu; // Indicates that the element is not encoded; there is no *R* factor // that needs to be canceled out. @@ -133,9 +134,9 @@ unsafe fn mul_mont( m: &[Limb], n0: &N0, _: cpu::Features, -) -> Result<(), error::Unspecified> { +) -> Result<(), ImpossibleLengthError> { if m.len() < MIN_LIMBS || m.len() > MAX_LIMBS { - return Err(error::Unspecified); + return Err(ImpossibleLengthError::new()); } bn_mul_mont(r, a, b, m.as_ptr(), n0, m.len()); Ok(()) @@ -273,9 +274,9 @@ pub(super) fn limbs_mont_mul( m: &[Limb], n0: &N0, cpu_features: cpu::Features, -) -> Result<(), error::Unspecified> { +) -> Result<(), ImpossibleLengthError> { if r.len() != m.len() || a.len() != m.len() { - return Err(error::Unspecified); + return Err(ImpossibleLengthError::new()); } unsafe { mul_mont(r.as_mut_ptr(), r.as_ptr(), a.as_ptr(), m, n0, cpu_features) } } @@ -289,9 +290,9 @@ pub(super) fn limbs_mont_product( m: &[Limb], n0: &N0, cpu_features: cpu::Features, -) -> Result<(), error::Unspecified> { +) -> Result<(), ImpossibleLengthError> { if r.len() != m.len() || a.len() != m.len() || b.len() != m.len() { - return Err(error::Unspecified); + return Err(ImpossibleLengthError::new()); } unsafe { mul_mont(r.as_mut_ptr(), a.as_ptr(), b.as_ptr(), m, n0, cpu_features) } } @@ -302,9 +303,9 @@ pub(super) fn limbs_mont_square( m: &[Limb], n0: &N0, cpu_features: cpu::Features, -) -> Result<(), error::Unspecified> { +) -> Result<(), ImpossibleLengthError> { if r.len() != m.len() { - return Err(error::Unspecified); + return Err(ImpossibleLengthError::new()); } unsafe { mul_mont(r.as_mut_ptr(), r.as_ptr(), r.as_ptr(), m, n0, cpu_features) } } diff --git a/src/rsa/keypair.rs b/src/rsa/keypair.rs index a2012789e6..fc43cb36f8 100644 --- a/src/rsa/keypair.rs +++ b/src/rsa/keypair.rs @@ -21,6 +21,7 @@ use crate::{ arithmetic::{ bigint, montgomery::{R, RR, RRR}, + ImpossibleLengthError, }, bits::BitLength, cpu, digest, @@ -487,7 +488,7 @@ fn elem_exp_consttime( p: &PrivateCrtPrime, other_prime_len_bits: BitLength, cpu_features: cpu::Features, -) -> Result, error::Unspecified> { +) -> Result, ImpossibleLengthError> { let m = &p.modulus.modulus(cpu_features); let c_mod_m = bigint::elem_reduced(c, m, other_prime_len_bits); let c_mod_m = bigint::elem_mul(p.oneRRR.as_ref(), c_mod_m, m);