diff --git a/src/arithmetic/bigint.rs b/src/arithmetic/bigint.rs index 15b24ab8d..331254c46 100644 --- a/src/arithmetic/bigint.rs +++ b/src/arithmetic/bigint.rs @@ -346,6 +346,12 @@ impl One { } } +impl One { + pub(crate) fn newRRR(One(oneRR): One, m: &Modulus) -> Self { + Self(elem_squared(oneRR, m)) + } +} + impl AsRef> for One { fn as_ref(&self) -> &Elem { &self.0 diff --git a/src/arithmetic/montgomery.rs b/src/arithmetic/montgomery.rs index 1eeebd02f..1e1adfba5 100644 --- a/src/arithmetic/montgomery.rs +++ b/src/arithmetic/montgomery.rs @@ -22,6 +22,12 @@ pub enum Unencoded {} #[derive(Copy, Clone)] pub enum R {} +// Indicates the element is encoded three times; the value has three +// *R* factors that need to be canceled out. +#[allow(clippy::upper_case_acronyms)] +#[derive(Copy, Clone)] +pub enum RRR {} + // Indicates the element is encoded twice; the value has two *R* // factors that need to be canceled out. #[derive(Copy, Clone)] @@ -34,6 +40,7 @@ pub enum RInverse {} pub trait Encoding {} +impl Encoding for RRR {} impl Encoding for RR {} impl Encoding for R {} impl Encoding for Unencoded {} @@ -44,6 +51,10 @@ pub trait ReductionEncoding { type Output: Encoding; } +impl ReductionEncoding for RRR { + type Output = RR; +} + impl ReductionEncoding for RR { type Output = R; } @@ -67,6 +78,10 @@ impl ProductEncoding for (R, E) { type Output = E; } +impl ProductEncoding for (RR, RR) { + type Output = RRR; +} + impl ProductEncoding for (RInverse, E) where E::Output: ReductionEncoding, @@ -87,6 +102,10 @@ impl ProductEncoding for (RR, RInverse) { type Output = <(RInverse, RR) as ProductEncoding>::Output; } +impl ProductEncoding for (RRR, RInverse) { + type Output = <(RInverse, RRR) as ProductEncoding>::Output; +} + #[allow(unused_imports)] use { super::n0::N0, diff --git a/src/rsa/keypair.rs b/src/rsa/keypair.rs index 44e50b3d2..657a7bc93 100644 --- a/src/rsa/keypair.rs +++ b/src/rsa/keypair.rs @@ -20,7 +20,7 @@ use super::{ use crate::{ arithmetic::{ bigint, - montgomery::{R, RR}, + montgomery::{R, RR, RRR}, }, bits::BitLength, cpu, digest, @@ -443,7 +443,7 @@ impl PrivatePrime { struct PrivateCrtPrime { modulus: bigint::OwnedModulus, - oneRR: bigint::One, + oneRRR: bigint::One, exponent: bigint::PrivateExponent, } @@ -451,8 +451,9 @@ impl PrivateCrtPrime { /// Constructs a `PrivateCrtPrime` from the private prime `p` and `dP` where /// dP == d % (p - 1). fn new(p: PrivatePrime, dP: untrusted::Input) -> Result { + let m = &p.modulus.modulus(); // [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.modulus.modulus()) + let dP = bigint::PrivateExponent::from_be_bytes_padded(dP, m) .map_err(|error::Unspecified| KeyRejected::inconsistent_components())?; // XXX: Steps 7.d and 7.e are omitted. We don't check that @@ -464,9 +465,11 @@ impl PrivateCrtPrime { // and `e`. TODO: Either prove that what we do is sufficient, or make // it so. + let oneRRR = bigint::One::newRRR(p.oneRR, m); + Ok(Self { modulus: p.modulus, - oneRR: p.oneRR, + oneRRR, exponent: dP, }) } @@ -479,10 +482,7 @@ fn elem_exp_consttime( ) -> Result, error::Unspecified> { let m = &p.modulus.modulus(); 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.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.oneRRR.as_ref(), c_mod_m, m); bigint::elem_exp_consttime(c_mod_m, &p.exponent, m) }