Rename PartialModulus to Modulus, Modulus to OwnedModulusWithOne.

Originally we only had `Modulus`. Then we had a need for a
temporary `Modulus` without `oneRR` so we created `PartialModulus`.
However, there is really nothing "partial" about them. So, improve
the naming by renaming `PartialModulus` to `Modulus` and `Modulus`
to `OwnedModulusWithOne`. In the future we may refactor things
further to separate the ownership aspect from the "has oneRR"
aspect.

Instead of just doing a straightforward rename, take this
opportunity to refactor the code so that it uses the new `Modulus`
whenever `oneRR()` isn't used. This eliminates the duplication of
the APIs of the two modulus types, and the duplication of
`elem_mul` and `elem_mul_`.
This commit is contained in:
Brian Smith 2023-11-02 16:49:28 -07:00
parent 69d1dd34e6
commit e51c88a986
5 changed files with 99 additions and 115 deletions

View File

@ -38,7 +38,7 @@
use self::boxed_limbs::BoxedLimbs;
pub(crate) use self::{
modulus::{Modulus, PartialModulus, MODULUS_MAX_LIMBS},
modulus::{Modulus, OwnedModulusWithOne, MODULUS_MAX_LIMBS},
private_exponent::PrivateExponent,
};
use super::n0::N0;
@ -186,20 +186,9 @@ impl<M> Elem<M, Unencoded> {
}
pub fn elem_mul<M, AF, BF>(
a: &Elem<M, AF>,
b: Elem<M, BF>,
m: &Modulus<M>,
) -> Elem<M, <(AF, BF) as ProductEncoding>::Output>
where
(AF, BF): ProductEncoding,
{
elem_mul_(a, b, &m.as_partial())
}
fn elem_mul_<M, AF, BF>(
a: &Elem<M, AF>,
mut b: Elem<M, BF>,
m: &PartialModulus<M>,
m: &Modulus<M>,
) -> Elem<M, <(AF, BF) as ProductEncoding>::Output>
where
(AF, BF): ProductEncoding,
@ -211,7 +200,7 @@ where
}
}
fn elem_mul_by_2<M, AF>(a: &mut Elem<M, AF>, m: &PartialModulus<M>) {
fn elem_mul_by_2<M, AF>(a: &mut Elem<M, AF>, m: &Modulus<M>) {
prefixed_extern! {
fn LIMBS_shl_mod(r: *mut Limb, a: *const Limb, m: *const Limb, num_limbs: c::size_t);
}
@ -254,7 +243,7 @@ pub fn elem_reduced<Larger, Smaller: NotMuchSmallerModulus<Larger>>(
fn elem_squared<M, E>(
mut a: Elem<M, E>,
m: &PartialModulus<M>,
m: &Modulus<M>,
) -> Elem<M, <(E, E) as ProductEncoding>::Output>
where
(E, E): ProductEncoding,
@ -316,7 +305,7 @@ impl<M> One<M, RR> {
// values, using `LIMB_BITS` here, rather than `N0::LIMBS_USED * LIMB_BITS`,
// is correct because R**2 will still be a multiple of the latter as
// `N0::LIMBS_USED` is either one or two.
fn newRR(m: &PartialModulus<M>, m_bits: bits::BitLength) -> Self {
fn newRR(m: &Modulus<M>, m_bits: bits::BitLength) -> Self {
let m_bits = m_bits.as_usize_bits();
let r = (m_bits + (LIMB_BITS - 1)) / LIMB_BITS * LIMB_BITS;
@ -390,7 +379,7 @@ impl<M: PublicModulus, E> Clone for One<M, E> {
pub(crate) fn elem_exp_vartime<M>(
base: Elem<M, R>,
exponent: NonZeroU64,
m: &PartialModulus<M>,
m: &Modulus<M>,
) -> Elem<M, R> {
// Use what [Knuth] calls the "S-and-X binary method", i.e. variable-time
// square-and-multiply that scans the exponent from the most significant
@ -417,7 +406,7 @@ pub(crate) fn elem_exp_vartime<M>(
bit >>= 1;
acc = elem_squared(acc, m);
if (exponent & bit) != 0 {
acc = elem_mul_(&base, acc, m);
acc = elem_mul(&base, acc, m);
}
}
acc
@ -426,17 +415,20 @@ pub(crate) fn elem_exp_vartime<M>(
/// Uses Fermat's Little Theorem to calculate modular inverse in constant time.
pub fn elem_inverse_consttime<M: Prime>(
a: Elem<M, R>,
m: &Modulus<M>,
m: &OwnedModulusWithOne<M>,
) -> Result<Elem<M, Unencoded>, error::Unspecified> {
elem_exp_consttime(a, &PrivateExponent::for_flt(m), m)
elem_exp_consttime(a, &PrivateExponent::for_flt(&m.modulus()), m)
}
#[cfg(not(target_arch = "x86_64"))]
pub fn elem_exp_consttime<M>(
base: Elem<M, R>,
exponent: &PrivateExponent,
m: &Modulus<M>,
m: &OwnedModulusWithOne<M>,
) -> Result<Elem<M, Unencoded>, error::Unspecified> {
let oneRR = m.oneRR();
let m = &m.modulus();
use crate::{bssl, limb::Window};
const WINDOW_BITS: usize = 5;
@ -469,7 +461,7 @@ pub fn elem_exp_consttime<M>(
mut tmp: Elem<M, R>,
) -> (Elem<M, R>, Elem<M, R>) {
for _ in 0..WINDOW_BITS {
acc = elem_squared(acc, &m.as_partial());
acc = elem_squared(acc, m);
}
gather(table, &mut tmp, i);
let acc = elem_mul(&tmp, acc, m);
@ -489,7 +481,7 @@ pub fn elem_exp_consttime<M>(
// `table` was initialized to zero and hasn't changed.
debug_assert!(acc.iter().all(|&value| value == 0));
acc[0] = 1;
limbs_mont_mul(acc, &m.oneRR().0.limbs, m.limbs(), m.n0(), m.cpu_features());
limbs_mont_mul(acc, &oneRR.0.limbs, m.limbs(), m.n0(), m.cpu_features());
}
entry_mut(&mut table, 1, num_limbs).copy_from_slice(&base.limbs);
@ -527,10 +519,13 @@ pub fn elem_exp_consttime<M>(
pub fn elem_exp_consttime<M>(
base: Elem<M, R>,
exponent: &PrivateExponent,
m: &Modulus<M>,
m: &OwnedModulusWithOne<M>,
) -> Result<Elem<M, Unencoded>, error::Unspecified> {
use crate::limb::LIMB_BYTES;
let oneRR = m.oneRR();
let m = &m.modulus();
// Pretty much all the math here requires CPU feature detection to have
// been done. `cpu_features` isn't threaded through all the internal
// functions, so just make it clear that it has been done at this point.
@ -685,7 +680,7 @@ pub fn elem_exp_consttime<M>(
// encode it.
debug_assert!(acc.iter().all(|&value| value == 0));
acc[0] = 1;
limbs_mont_mul(acc, &m.oneRR().0.limbs, m_cached, n0, cpu_features);
limbs_mont_mul(acc, &oneRR.0.limbs, m_cached, n0, cpu_features);
scatter(table, acc, 0, num_limbs);
// acc = base**1 (i.e. base).
@ -853,7 +848,8 @@ mod tests {
|section, test_case| {
assert_eq!(section, "");
let m = consume_modulus::<M>(test_case, "M", cpu_features);
let m_ = consume_modulus::<M>(test_case, "M", cpu_features);
let m = m_.modulus();
let expected_result = consume_elem(test_case, "ModExp", &m);
let base = consume_elem(test_case, "A", &m);
let e = {
@ -861,8 +857,8 @@ mod tests {
PrivateExponent::from_be_bytes_for_test_only(untrusted::Input::from(&bytes), &m)
.expect("valid exponent")
};
let base = into_encoded(base, &m);
let actual_result = elem_exp_consttime(base, &e, &m).unwrap();
let base = into_encoded(base, &m_);
let actual_result = elem_exp_consttime(base, &e, &m_).unwrap();
assert_elem_eq(&actual_result, &expected_result);
Ok(())
@ -882,13 +878,14 @@ mod tests {
|section, test_case| {
assert_eq!(section, "");
let m = consume_modulus::<M>(test_case, "M", cpu_features);
let m_ = consume_modulus::<M>(test_case, "M", cpu_features);
let m = m_.modulus();
let expected_result = consume_elem(test_case, "ModMul", &m);
let a = consume_elem(test_case, "A", &m);
let b = consume_elem(test_case, "B", &m);
let b = into_encoded(b, &m);
let a = into_encoded(a, &m);
let b = into_encoded(b, &m_);
let a = into_encoded(a, &m_);
let actual_result = elem_mul(&a, b, &m);
let actual_result = actual_result.into_unencoded(&m);
assert_elem_eq(&actual_result, &expected_result);
@ -906,12 +903,13 @@ mod tests {
|section, test_case| {
assert_eq!(section, "");
let m = consume_modulus::<M>(test_case, "M", cpu_features);
let m_ = consume_modulus::<M>(test_case, "M", cpu_features);
let m = m_.modulus();
let expected_result = consume_elem(test_case, "ModSquare", &m);
let a = consume_elem(test_case, "A", &m);
let a = into_encoded(a, &m);
let actual_result = elem_squared(a, &m.as_partial());
let a = into_encoded(a, &m_);
let actual_result = elem_squared(a, &m);
let actual_result = actual_result.into_unencoded(&m);
assert_elem_eq(&actual_result, &expected_result);
@ -932,13 +930,14 @@ mod tests {
unsafe impl SmallerModulus<MM> for M {}
unsafe impl NotMuchSmallerModulus<MM> for M {}
let m = consume_modulus::<M>(test_case, "M", cpu_features);
let m_ = consume_modulus::<M>(test_case, "M", cpu_features);
let m = m_.modulus();
let expected_result = consume_elem(test_case, "R", &m);
let a =
consume_elem_unchecked::<MM>(test_case, "A", expected_result.limbs.len() * 2);
let actual_result = elem_reduced(&a, &m);
let oneRR = m.oneRR();
let oneRR = m_.oneRR();
let actual_result = elem_mul(oneRR.as_ref(), actual_result, &m);
assert_elem_eq(&actual_result, &expected_result);
@ -961,11 +960,11 @@ mod tests {
unsafe impl SlightlySmallerModulus<N> for QQ {}
let qq = consume_modulus::<QQ>(test_case, "QQ", cpu_features);
let expected_result = consume_elem::<QQ>(test_case, "R", &qq);
let expected_result = consume_elem::<QQ>(test_case, "R", &qq.modulus());
let n = consume_modulus::<N>(test_case, "N", cpu_features);
let a = consume_elem::<N>(test_case, "A", &n);
let a = consume_elem::<N>(test_case, "A", &n.modulus());
let actual_result = elem_reduced_once(&a, &qq);
let actual_result = elem_reduced_once(&a, &qq.modulus());
assert_elem_eq(&actual_result, &expected_result);
Ok(())
@ -975,7 +974,7 @@ mod tests {
#[test]
fn test_modulus_debug() {
let (modulus, _) = Modulus::<M>::from_be_bytes_with_bit_length(
let (modulus, _) = OwnedModulusWithOne::<M>::from_be_bytes_with_bit_length(
untrusted::Input::from(&[0xff; LIMB_BYTES * MODULUS_MIN_LIMBS]),
cpu::features(),
)
@ -1010,11 +1009,13 @@ mod tests {
test_case: &mut test::TestCase,
name: &str,
cpu_features: cpu::Features,
) -> Modulus<M> {
) -> OwnedModulusWithOne<M> {
let value = test_case.consume_bytes(name);
let (value, _) =
Modulus::from_be_bytes_with_bit_length(untrusted::Input::from(&value), cpu_features)
.unwrap();
let (value, _) = OwnedModulusWithOne::from_be_bytes_with_bit_length(
untrusted::Input::from(&value),
cpu_features,
)
.unwrap();
value
}
@ -1031,7 +1032,7 @@ mod tests {
}
}
fn into_encoded<M>(a: Elem<M, Unencoded>, m: &Modulus<M>) -> Elem<M, R> {
elem_mul(m.oneRR().as_ref(), a, m)
fn into_encoded<M>(a: Elem<M, Unencoded>, m: &OwnedModulusWithOne<M>) -> Elem<M, R> {
elem_mul(m.oneRR().as_ref(), a, &m.modulus())
}
}

View File

@ -14,7 +14,7 @@
use super::{
super::{
montgomery::{Unencoded, R, RR},
montgomery::{Unencoded, RR},
n0::N0,
},
BoxedLimbs, Elem, Nonnegative, One, PublicModulus, SlightlySmallerModulus, SmallerModulus,
@ -39,7 +39,7 @@ pub const MODULUS_MAX_LIMBS: usize = super::super::BIGINT_MODULUS_MAX_LIMBS;
/// for efficient Montgomery multiplication modulo *m*. The value must be odd
/// and larger than 2. The larger-than-1 requirement is imposed, at least, by
/// the modular inversion code.
pub struct Modulus<M> {
pub struct OwnedModulusWithOne<M> {
limbs: BoxedLimbs<M>, // Also `value >= 3`.
// n0 * N == -1 (mod r).
@ -84,7 +84,7 @@ pub struct Modulus<M> {
cpu_features: cpu::Features,
}
impl<M: PublicModulus> Clone for Modulus<M> {
impl<M: PublicModulus> Clone for OwnedModulusWithOne<M> {
fn clone(&self) -> Self {
Self {
limbs: self.limbs.clone(),
@ -95,7 +95,7 @@ impl<M: PublicModulus> Clone for Modulus<M> {
}
}
impl<M: PublicModulus> core::fmt::Debug for Modulus<M> {
impl<M: PublicModulus> core::fmt::Debug for OwnedModulusWithOne<M> {
fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> Result<(), ::core::fmt::Error> {
fmt.debug_struct("Modulus")
// TODO: Print modulus value.
@ -103,7 +103,7 @@ impl<M: PublicModulus> core::fmt::Debug for Modulus<M> {
}
}
impl<M> Modulus<M> {
impl<M> OwnedModulusWithOne<M> {
pub(crate) fn from_be_bytes_with_bit_length(
input: untrusted::Input,
cpu_features: cpu::Features,
@ -173,7 +173,7 @@ impl<M> Modulus<M> {
let bits = limb::limbs_minimal_bits(&n);
let oneRR = {
let partial = PartialModulus {
let partial = Modulus {
limbs: &n,
n0: n0.clone(),
m: PhantomData,
@ -194,35 +194,6 @@ impl<M> Modulus<M> {
))
}
#[inline]
pub(super) fn cpu_features(&self) -> cpu::Features {
self.cpu_features
}
#[inline]
pub(super) fn limbs(&self) -> &[Limb] {
&self.limbs
}
#[inline]
pub(super) fn n0(&self) -> &N0 {
&self.n0
}
pub(super) fn zero<E>(&self) -> Elem<M, E> {
Elem {
limbs: BoxedLimbs::zero(self.limbs().len()),
encoding: PhantomData,
}
}
// TODO: Get rid of this
pub(super) fn one(&self) -> Elem<M, Unencoded> {
let mut r = self.zero();
r.limbs[0] = 1;
r
}
pub fn oneRR(&self) -> &One<M, RR> {
&self.oneRR
}
@ -232,15 +203,14 @@ impl<M> Modulus<M> {
M: SmallerModulus<L>,
{
// TODO: Encode this assertion into the `where` above.
assert_eq!(self.limbs().len(), l.limbs().len());
assert_eq!(self.limbs.len(), l.limbs.len());
Elem {
limbs: BoxedLimbs::new_unchecked(self.limbs.clone().into_limbs()),
encoding: PhantomData,
}
}
pub(crate) fn as_partial(&self) -> PartialModulus<M> {
PartialModulus {
pub fn modulus(&self) -> Modulus<M> {
Modulus {
limbs: &self.limbs,
n0: self.n0.clone(),
m: PhantomData,
@ -249,28 +219,35 @@ impl<M> Modulus<M> {
}
}
impl<M: PublicModulus> Modulus<M> {
impl<M: PublicModulus> OwnedModulusWithOne<M> {
pub fn be_bytes(&self) -> LeadingZerosStripped<impl ExactSizeIterator<Item = u8> + Clone + '_> {
LeadingZerosStripped::new(limb::unstripped_be_bytes(&self.limbs))
}
}
pub(crate) struct PartialModulus<'a, M> {
pub struct Modulus<'a, M> {
limbs: &'a [Limb],
n0: N0,
m: PhantomData<M>,
cpu_features: cpu::Features,
}
impl<M> PartialModulus<'_, M> {
impl<M> Modulus<'_, M> {
// TODO: XXX Avoid duplication with `Modulus`.
pub(super) fn zero(&self) -> Elem<M, R> {
pub(super) fn zero<E>(&self) -> Elem<M, E> {
Elem {
limbs: BoxedLimbs::zero(self.limbs.len()),
encoding: PhantomData,
}
}
// TODO: Get rid of this
pub(super) fn one(&self) -> Elem<M, Unencoded> {
let mut r = self.zero();
r.limbs[0] = 1;
r
}
#[inline]
pub(super) fn limbs(&self) -> &[Limb] {
self.limbs
@ -282,7 +259,7 @@ impl<M> PartialModulus<'_, M> {
}
#[inline]
pub fn cpu_features(&self) -> cpu::Features {
pub(crate) fn cpu_features(&self) -> cpu::Features {
self.cpu_features
}
}

View File

@ -39,7 +39,7 @@ pub struct KeyPair {
// completely unnecessary since `elem_reduced` seems to be able to reduce
// an `Elem<N>` directly to an `Elem<Q>`. TODO: Verify that is true and
// eliminate this.
qq: bigint::Modulus<QQ>,
qq: bigint::OwnedModulusWithOne<QQ>,
// TODO: Eliminate `q_mod_n` entirely since it is a bad space:time trade-off.
// Also, this is the only non-temporary `Elem` so if we eliminate this, we
@ -313,7 +313,8 @@ impl KeyPair {
cpu_features,
)?;
let n = public_key.inner().n().value();
let n_one = public_key.inner().n().value().oneRR();
let n = &public_key.inner().n().value().modulus();
// 6.4.1.4.3 says to skip 6.4.1.2.1 Step 2.
@ -369,7 +370,7 @@ impl KeyPair {
// 0 < q < p < n. We check that q and p are close to sqrt(n) and then
// assume that these preconditions are enough to let us assume that
// checking p * q == 0 (mod n) is equivalent to checking p * q == n.
let q_mod_n = bigint::elem_mul(n.oneRR().as_ref(), q_mod_n_decoded.clone(), n);
let q_mod_n = bigint::elem_mul(n_one.as_ref(), q_mod_n_decoded.clone(), n);
let p_mod_n = p
.to_elem(n)
.map_err(|error::Unspecified| KeyRejected::inconsistent_components())?;
@ -404,20 +405,21 @@ impl KeyPair {
// Step 7.a.
let p = PrivatePrime::new(p, dP, cpu_features)?;
let pm = &p.modulus.modulus();
// Step 7.b.
let q = PrivatePrime::new(q, dQ, cpu_features)?;
let q_mod_p = q.modulus.to_elem(&p.modulus);
let q_mod_p = q.modulus.to_elem(pm);
// Step 7.c.
let qInv = if let Some(qInv) = qInv {
bigint::Elem::from_be_bytes_padded(qInv, &p.modulus)
bigint::Elem::from_be_bytes_padded(qInv, pm)
.map_err(|error::Unspecified| KeyRejected::invalid_component())?
} else {
// We swapped `p` and `q` above, so we need to calculate `qInv`.
// Step 7.f below will verify `qInv` is correct.
let q_mod_p = bigint::elem_mul(p.modulus.oneRR().as_ref(), q_mod_p.clone(), &p.modulus);
let q_mod_p = bigint::elem_mul(p.modulus.oneRR().as_ref(), q_mod_p.clone(), pm);
bigint::elem_inverse_consttime(q_mod_p, &p.modulus)
.map_err(|error::Unspecified| KeyRejected::unexpected_error())?
};
@ -427,11 +429,11 @@ impl KeyPair {
// with an even modulus.
// Step 7.f.
let qInv = bigint::elem_mul(p.modulus.oneRR().as_ref(), qInv, &p.modulus);
bigint::verify_inverses_consttime(&qInv, q_mod_p, &p.modulus)
let qInv = bigint::elem_mul(p.modulus.oneRR().as_ref(), qInv, pm);
bigint::verify_inverses_consttime(&qInv, q_mod_p, pm)
.map_err(|error::Unspecified| KeyRejected::inconsistent_components())?;
let qq = bigint::Modulus::from_elem(
let qq = bigint::OwnedModulusWithOne::from_elem(
bigint::elem_mul(&q_mod_n, q_mod_n_decoded, n),
cpu_features,
)?;
@ -472,7 +474,7 @@ impl signature::KeyPair for KeyPair {
}
struct PrivatePrime<M: Prime> {
modulus: bigint::Modulus<M>,
modulus: bigint::OwnedModulusWithOne<M>,
exponent: bigint::PrivateExponent,
}
@ -484,13 +486,14 @@ impl<M: Prime> PrivatePrime<M> {
dP: untrusted::Input,
cpu_features: cpu::Features,
) -> Result<Self, KeyRejected> {
let (p, p_bits) = bigint::Modulus::from_nonnegative_with_bit_length(p, cpu_features)?;
let (p, p_bits) =
bigint::OwnedModulusWithOne::from_nonnegative_with_bit_length(p, cpu_features)?;
if p_bits.as_usize_bits() % 512 != 0 {
return Err(error::KeyRejected::private_modulus_len_not_multiple_of_512_bits());
}
// [NIST SP-800-56B rev. 1] 6.4.1.4.3 - Steps 7.a & 7.b.
let dP = bigint::PrivateExponent::from_be_bytes_padded(dP, &p)
let dP = bigint::PrivateExponent::from_be_bytes_padded(dP, &p.modulus())
.map_err(|error::Unspecified| KeyRejected::inconsistent_components())?;
// XXX: Steps 7.d and 7.e are omitted. We don't check that
@ -517,11 +520,12 @@ where
M: bigint::NotMuchSmallerModulus<MM>,
M: Prime,
{
let c_mod_m = bigint::elem_reduced(c, &p.modulus);
let m = &p.modulus.modulus();
let c_mod_m = bigint::elem_reduced(c, m);
// We could precompute `oneRRR = elem_squared(&p.oneRR`) as mentioned
// in the Smooth CRT-RSA paper.
let c_mod_m = bigint::elem_mul(p.modulus.oneRR().as_ref(), c_mod_m, &p.modulus);
let c_mod_m = bigint::elem_mul(p.modulus.oneRR().as_ref(), c_mod_m, &p.modulus);
let c_mod_m = bigint::elem_mul(p.modulus.oneRR().as_ref(), c_mod_m, m);
let c_mod_m = bigint::elem_mul(p.modulus.oneRR().as_ref(), c_mod_m, m);
bigint::elem_exp_consttime(c_mod_m, &p.exponent, &p.modulus)
}
@ -618,7 +622,7 @@ impl KeyPair {
// RFC 8017 Section 5.1.2: RSADP, using the Chinese Remainder Theorem
// with Garner's algorithm.
let n = self.public.inner().n().value();
let n = &self.public.inner().n().value().modulus();
// Step 1. The value zero is also rejected.
let base = bigint::Elem::from_be_bytes_padded(untrusted::Input::from(base), n)?;
@ -628,13 +632,13 @@ impl KeyPair {
// Step 2.b.i.
let m_1 = elem_exp_consttime(&c, &self.p)?;
let c_mod_qq = bigint::elem_reduced_once(&c, &self.qq);
let c_mod_qq = bigint::elem_reduced_once(&c, &self.qq.modulus());
let m_2 = elem_exp_consttime(&c_mod_qq, &self.q)?;
// Step 2.b.ii isn't needed since there are only two primes.
// Step 2.b.iii.
let p = &self.p.modulus;
let p = &self.p.modulus.modulus();
let m_2 = bigint::elem_widen(m_2, p);
let m_1_minus_m_2 = bigint::elem_sub(m_1, &m_2, p);
let h = bigint::elem_mul(&self.qInv, m_1_minus_m_2, p);

View File

@ -145,7 +145,7 @@ impl Inner {
base: untrusted::Input,
out_buffer: &'out mut [u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN],
) -> Result<&'out [u8], error::Unspecified> {
let n = &self.n.value();
let n = &self.n.value().modulus();
// The encoded value of the base must be the same length as the modulus,
// in bytes.
@ -177,15 +177,16 @@ impl Inner {
// The exponent was already checked to be odd.
debug_assert_ne!(exponent_without_low_bit, self.e.value());
let n = self.n.value();
let n_ = self.n.value();
let n = &n_.modulus();
let base_r = bigint::elem_mul(n.oneRR().as_ref(), base.clone(), n);
let base_r = bigint::elem_mul(n_.oneRR().as_ref(), base.clone(), n);
// During RSA public key operations the exponent is almost always either
// 65537 (0b10000000000000001) or 3 (0b11), both of which have a Hamming
// weight of 2. The maximum bit length and maximum Hamming weight of the
// exponent is bounded by the value of `PublicExponent::MAX`.
let acc = bigint::elem_exp_vartime(base_r, exponent_without_low_bit, &n.as_partial());
let acc = bigint::elem_exp_vartime(base_r, exponent_without_low_bit, n);
// Now do the multiplication for the low bit and convert out of the Montgomery domain.
bigint::elem_mul(&base, acc, n)

View File

@ -4,7 +4,7 @@ use core::ops::RangeInclusive;
/// The modulus (n) of an RSA public key.
#[derive(Clone)]
pub struct PublicModulus {
value: bigint::Modulus<N>,
value: bigint::OwnedModulusWithOne<N>,
bits: bits::BitLength,
}
@ -33,7 +33,8 @@ impl PublicModulus {
const MIN_BITS: bits::BitLength = bits::BitLength::from_usize_bits(1024);
// Step 3 / Step c for `n` (out of order).
let (value, bits) = bigint::Modulus::from_be_bytes_with_bit_length(n, cpu_features)?;
let (value, bits) =
bigint::OwnedModulusWithOne::from_be_bytes_with_bit_length(n, cpu_features)?;
// Step 1 / Step a. XXX: SP800-56Br1 and SP800-89 require the length of
// the public modulus to be exactly 2048 or 3072 bits, but we are more
@ -63,7 +64,7 @@ impl PublicModulus {
self.bits
}
pub(super) fn value(&self) -> &bigint::Modulus<N> {
pub(super) fn value(&self) -> &bigint::OwnedModulusWithOne<N> {
&self.value
}
}