Skip to content

Commit

Permalink
bigint: NFC: Take oneRR out of OwnedModulus.
Browse files Browse the repository at this point in the history
`PublicModulus` and `PrivatePrime` are basically duplicates of
`OwnedModulusWithOne`. In the future we would like to create an
`OwnedModulus` that doesn't need 1RR to be calculated. Also in the
future we'd like to be able to "take" 1RR from a public modulus.
This change is a step towards those ends.
  • Loading branch information
briansmith committed Nov 23, 2023
1 parent 986fe1f commit 6de2724
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 70 deletions.
37 changes: 19 additions & 18 deletions src/arithmetic/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
use self::boxed_limbs::BoxedLimbs;
pub(crate) use self::{
modulus::{Modulus, OwnedModulusWithOne, MODULUS_MAX_LIMBS},
modulus::{Modulus, OwnedModulus, MODULUS_MAX_LIMBS},
private_exponent::PrivateExponent,
};
use super::n0::N0;
Expand Down Expand Up @@ -274,7 +274,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: &Modulus<M>) -> Self {
pub(crate) fn newRR(m: &Modulus<M>) -> Self {
// The number of limbs in the numbers involved.
let w = m.limbs().len();

Expand Down Expand Up @@ -808,16 +808,16 @@ mod tests {
|section, test_case| {
assert_eq!(section, "");

let m_ = consume_modulus::<M>(test_case, "M", cpu_features);
let m = m_.modulus();
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 = {
let bytes = test_case.consume_bytes("E");
PrivateExponent::from_be_bytes_for_test_only(untrusted::Input::from(&bytes), &m)
.expect("valid exponent")
};
let base = into_encoded(base, &m_);
let base = into_encoded(base, &m);
let actual_result = elem_exp_consttime(base, &e, &m).unwrap();
assert_elem_eq(&actual_result, &expected_result);

Expand All @@ -838,14 +838,14 @@ mod tests {
|section, test_case| {
assert_eq!(section, "");

let m_ = consume_modulus::<M>(test_case, "M", cpu_features);
let m = m_.modulus();
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);
Expand All @@ -863,12 +863,12 @@ mod tests {
|section, test_case| {
assert_eq!(section, "");

let m_ = consume_modulus::<M>(test_case, "M", cpu_features);
let m = m_.modulus();
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 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);
Expand Down Expand Up @@ -896,7 +896,7 @@ mod tests {
let other_modulus_len_bits = m_.len_bits();

let actual_result = elem_reduced(&a, &m, other_modulus_len_bits);
let oneRR = m_.oneRR();
let oneRR = One::newRR(&m);
let actual_result = elem_mul(oneRR.as_ref(), actual_result, &m);
assert_elem_eq(&actual_result, &expected_result);

Expand Down Expand Up @@ -930,7 +930,7 @@ mod tests {

#[test]
fn test_modulus_debug() {
let modulus = OwnedModulusWithOne::<M>::from_be_bytes(
let modulus = OwnedModulus::<M>::from_be_bytes(
untrusted::Input::from(&[0xff; LIMB_BYTES * MODULUS_MIN_LIMBS]),
cpu::features(),
)
Expand Down Expand Up @@ -965,9 +965,9 @@ mod tests {
test_case: &mut test::TestCase,
name: &str,
cpu_features: cpu::Features,
) -> OwnedModulusWithOne<M> {
) -> OwnedModulus<M> {
let value = test_case.consume_bytes(name);
OwnedModulusWithOne::from_be_bytes(untrusted::Input::from(&value), cpu_features).unwrap()
OwnedModulus::from_be_bytes(untrusted::Input::from(&value), cpu_features).unwrap()
}

fn consume_nonnegative(test_case: &mut test::TestCase, name: &str) -> Nonnegative {
Expand All @@ -983,7 +983,8 @@ mod tests {
}
}

fn into_encoded<M>(a: Elem<M, Unencoded>, m: &OwnedModulusWithOne<M>) -> Elem<M, R> {
elem_mul(m.oneRR().as_ref(), a, &m.modulus())
fn into_encoded<M>(a: Elem<M, Unencoded>, m: &Modulus<M>) -> Elem<M, R> {
let oneRR = One::newRR(m);
elem_mul(oneRR.as_ref(), a, m)
}
}
34 changes: 6 additions & 28 deletions src/arithmetic/bigint/modulus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +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::{
super::{montgomery::RR, n0::N0},
BoxedLimbs, Elem, One, PublicModulus, SmallerModulus, Unencoded,
};
use super::{super::n0::N0, BoxedLimbs, Elem, PublicModulus, SmallerModulus, Unencoded};
use crate::{
bits::BitLength,
cpu, error,
Expand All @@ -37,7 +34,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 OwnedModulusWithOne<M> {
pub struct OwnedModulus<M> {
limbs: BoxedLimbs<M>, // Also `value >= 3`.

// n0 * N == -1 (mod r).
Expand Down Expand Up @@ -77,34 +74,31 @@ pub struct OwnedModulusWithOne<M> {
// calculations instead of double-precision `u64` calculations.
n0: N0,

oneRR: One<M, RR>,

len_bits: BitLength,

cpu_features: cpu::Features,
}

impl<M: PublicModulus> Clone for OwnedModulusWithOne<M> {
impl<M: PublicModulus> Clone for OwnedModulus<M> {
fn clone(&self) -> Self {
Self {
limbs: self.limbs.clone(),
n0: self.n0,
oneRR: self.oneRR.clone(),
len_bits: self.len_bits,
cpu_features: self.cpu_features,
}
}
}

impl<M: PublicModulus> core::fmt::Debug for OwnedModulusWithOne<M> {
impl<M: PublicModulus> core::fmt::Debug for OwnedModulus<M> {
fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> Result<(), ::core::fmt::Error> {
fmt.debug_struct("Modulus")
// TODO: Print modulus value.
.finish()
}
}

impl<M> OwnedModulusWithOne<M> {
impl<M> OwnedModulus<M> {
pub(crate) fn from_be_bytes(
input: untrusted::Input,
cpu_features: cpu::Features,
Expand Down Expand Up @@ -151,31 +145,15 @@ impl<M> OwnedModulusWithOne<M> {
};

let len_bits = limb::limbs_minimal_bits(&n);
let oneRR = {
let partial = Modulus {
limbs: &n,
n0,
len_bits,
m: PhantomData,
cpu_features,
};

One::newRR(&partial)
};

Ok(Self {
limbs: n,
n0,
oneRR,
len_bits,
cpu_features,
})
}

pub fn oneRR(&self) -> &One<M, RR> {
&self.oneRR
}

pub fn to_elem<L>(&self, l: &Modulus<L>) -> Elem<L, Unencoded>
where
M: SmallerModulus<L>,
Expand All @@ -202,7 +180,7 @@ impl<M> OwnedModulusWithOne<M> {
}
}

impl<M: PublicModulus> OwnedModulusWithOne<M> {
impl<M: PublicModulus> OwnedModulus<M> {
pub fn be_bytes(&self) -> LeadingZerosStripped<impl ExactSizeIterator<Item = u8> + Clone + '_> {
LeadingZerosStripped::new(limb::unstripped_be_bytes(&self.limbs))
}
Expand Down
34 changes: 20 additions & 14 deletions src/rsa/keypair.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,10 @@ use super::{

/// RSA PKCS#1 1.5 signatures.
use crate::{
arithmetic::{bigint, montgomery::R},
arithmetic::{
bigint,
montgomery::{R, RR},
},
bits::BitLength,
cpu, digest,
error::{self, KeyRejected},
Expand Down Expand Up @@ -281,8 +284,8 @@ impl KeyPair {
cpu_features,
)?;

let n_one = public_key.inner().n().value().oneRR();
let n = &public_key.inner().n().value().modulus();
let n_one = public_key.inner().n().oneRR();
let n = &public_key.inner().n().value();

// 6.4.1.4.3 says to skip 6.4.1.2.1 Step 2.

Expand Down Expand Up @@ -316,7 +319,7 @@ impl KeyPair {
// checking p * q == 0 (mod n) is equivalent to checking p * q == n.
let q_mod_n = q.modulus.to_elem(n);
let p_mod_n = p.modulus.to_elem(n);
let p_mod_n = bigint::elem_mul(n_one.as_ref(), p_mod_n, n);
let p_mod_n = bigint::elem_mul(n_one, p_mod_n, n);
let pq_mod_n = bigint::elem_mul(&q_mod_n, p_mod_n, n);
if !pq_mod_n.is_zero() {
return Err(KeyRejected::inconsistent_components());
Expand Down Expand Up @@ -357,9 +360,9 @@ impl KeyPair {
// with an even modulus.

// Step 7.f.
let qInv = bigint::elem_mul(p.modulus.oneRR().as_ref(), qInv, pm);
let qInv = bigint::elem_mul(p.oneRR.as_ref(), qInv, pm);
let q_mod_p = bigint::elem_reduced(&q_mod_n, pm, q.modulus.len_bits());
let q_mod_p = bigint::elem_mul(p.modulus.oneRR().as_ref(), q_mod_p, pm);
let q_mod_p = bigint::elem_mul(p.oneRR.as_ref(), q_mod_p, pm);
bigint::verify_inverses_consttime(&qInv, q_mod_p, pm)
.map_err(|error::Unspecified| KeyRejected::inconsistent_components())?;

Expand Down Expand Up @@ -397,7 +400,8 @@ impl signature::KeyPair for KeyPair {
}

struct PrivatePrime<M> {
modulus: bigint::OwnedModulusWithOne<M>,
modulus: bigint::OwnedModulus<M>,
oneRR: bigint::One<M, RR>,
exponent: bigint::PrivateExponent,
}

Expand All @@ -410,7 +414,7 @@ impl<M> PrivatePrime<M> {
n_bits: BitLength,
cpu_features: cpu::Features,
) -> Result<Self, KeyRejected> {
let p = bigint::OwnedModulusWithOne::from_be_bytes(p, cpu_features)?;
let p = bigint::OwnedModulus::from_be_bytes(p, cpu_features)?;

// 5.c / 5.g:
//
Expand Down Expand Up @@ -445,8 +449,11 @@ impl<M> PrivatePrime<M> {
return Err(error::KeyRejected::private_modulus_len_not_multiple_of_512_bits());
}

let oneRR = bigint::One::newRR(&p.modulus());

Ok(Self {
modulus: p,
oneRR,
exponent: dP,
})
}
Expand All @@ -461,8 +468,8 @@ fn elem_exp_consttime<M>(
let c_mod_m = bigint::elem_reduced(c, m, other_prime_len_bits);
// 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, m);
let c_mod_m = bigint::elem_mul(p.modulus.oneRR().as_ref(), c_mod_m, m);
let c_mod_m = bigint::elem_mul(p.oneRR.as_ref(), c_mod_m, m);
let c_mod_m = bigint::elem_mul(p.oneRR.as_ref(), c_mod_m, m);
bigint::elem_exp_consttime(c_mod_m, &p.exponent, m)
}

Expand Down Expand Up @@ -537,9 +544,8 @@ 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_one = n.oneRR();
let n = &n.modulus();
let n = &self.public.inner().n().value();
let n_one = self.public.inner().n().oneRR();

// Step 1. The value zero is also rejected.
let base = bigint::Elem::from_be_bytes_padded(untrusted::Input::from(base), n)?;
Expand Down Expand Up @@ -568,7 +574,7 @@ impl KeyPair {
// non-modular arithmetic.
let h = bigint::elem_widen(h, n);
let q_mod_n = self.q.modulus.to_elem(n);
let q_mod_n = bigint::elem_mul(n_one.as_ref(), q_mod_n, n);
let q_mod_n = bigint::elem_mul(n_one, q_mod_n, n);
let q_times_h = bigint::elem_mul(&q_mod_n, h, n);
let m_2 = bigint::elem_widen(m_2, n);
let m = bigint::elem_add(m_2, q_times_h, n);
Expand Down
7 changes: 3 additions & 4 deletions src/rsa/public_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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().modulus();
let n = &self.n.value();

// The encoded value of the base must be the same length as the modulus,
// in bytes.
Expand Down Expand Up @@ -177,10 +177,9 @@ 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 = &n_.modulus();
let n = &self.n.value();

let base_r = bigint::elem_mul(n_.oneRR().as_ref(), base.clone(), n);
let base_r = bigint::elem_mul(self.n.oneRR(), 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
Expand Down
22 changes: 16 additions & 6 deletions src/rsa/public_modulus.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
use crate::{arithmetic::bigint, bits, cpu, error, rsa::N};
use crate::{
arithmetic::{bigint, montgomery::RR},
bits, cpu, error,
rsa::N,
};
use core::ops::RangeInclusive;

/// The modulus (n) of an RSA public key.
#[derive(Clone)]
pub struct PublicModulus {
value: bigint::OwnedModulusWithOne<N>,
value: bigint::OwnedModulus<N>,
oneRR: bigint::One<N, RR>,
}

/*
Expand Down Expand Up @@ -32,7 +37,7 @@ impl PublicModulus {
const MIN_BITS: bits::BitLength = bits::BitLength::from_usize_bits(1024);

// Step 3 / Step c for `n` (out of order).
let value = bigint::OwnedModulusWithOne::from_be_bytes(n, cpu_features)?;
let value = bigint::OwnedModulus::from_be_bytes(n, cpu_features)?;
let bits = value.len_bits();

// Step 1 / Step a. XXX: SP800-56Br1 and SP800-89 require the length of
Expand All @@ -47,8 +52,9 @@ impl PublicModulus {
if bits > max_bits {
return Err(error::KeyRejected::too_large());
}
let oneRR = bigint::One::newRR(&value.modulus());

Ok(Self { value })
Ok(Self { value, oneRR })
}

/// The big-endian encoding of the modulus.
Expand All @@ -63,7 +69,11 @@ impl PublicModulus {
self.value.len_bits()
}

pub(super) fn value(&self) -> &bigint::OwnedModulusWithOne<N> {
&self.value
pub(super) fn value(&self) -> bigint::Modulus<N> {
self.value.modulus()
}

pub(super) fn oneRR(&self) -> &bigint::Elem<N, RR> {
self.oneRR.as_ref()
}
}

0 comments on commit 6de2724

Please sign in to comment.