diff --git a/src/algorithms/rsa.rs b/src/algorithms/rsa.rs index 19f064f6..183c4c49 100644 --- a/src/algorithms/rsa.rs +++ b/src/algorithms/rsa.rs @@ -69,30 +69,31 @@ pub fn rsa_decrypt( priv_key.dp(), priv_key.dq(), priv_key.qinv(), - priv_key.p_params(), - priv_key.q_params(), + priv_key.p(), + priv_key.q(), ) { - (Some(dp), Some(dq), Some(qinv), Some(p_params), Some(q_params)) if !is_multiprime => { + (Some(dp), Some(dq), Some(qinv), Some(p), Some(q)) if !is_multiprime => { // We have the precalculated values needed for the CRT. - let p = &priv_key.primes()[0]; - let q = &priv_key.primes()[1]; - // precomputed: dP = (1/e) mod (p-1) = d mod (p-1) // precomputed: dQ = (1/e) mod (q-1) = d mod (q-1) // TODO: it may be faster to convert to and from Montgomery with prepared parameters // (modulo `p` and `q`) rather than calculating the remainder directly. + // TODO(tarcieri): zeroize intermediates + let p_params = BoxedMontyParams::from(p.clone()); + let q_params = BoxedMontyParams::from(q.clone()); + // m1 = c^dP mod p - let p_wide = p_params.modulus().resize_unchecked(c.bits_precision()); + let p_wide = p.modulus().resize_unchecked(c.bits_precision()); let c_mod_dp = (&c % p_wide.as_nz_ref()).resize_unchecked(dp.bits_precision()); - let cp = BoxedMontyForm::new(c_mod_dp, p_params); + let cp = BoxedMontyForm::new(c_mod_dp, &p_params); let mut m1 = cp.pow(dp); // m2 = c^dQ mod q - let q_wide = q_params.modulus().resize_unchecked(c.bits_precision()); + let q_wide = q.modulus().resize_unchecked(c.bits_precision()); let c_mod_dq = (&c % q_wide.as_nz_ref()).resize_unchecked(dq.bits_precision()); - let cq = BoxedMontyForm::new(c_mod_dq, q_params); + let cq = BoxedMontyForm::new(c_mod_dq, &q_params); let m2 = cq.pow(dq).retrieve(); // Note that since `p` and `q` may have different `bits_precision`, @@ -101,7 +102,7 @@ pub fn rsa_decrypt( // (m1 - m2) mod p = (m1 mod p) - (m2 mod p) mod p let m2_mod_p = match p_params.bits_precision().cmp(&q_params.bits_precision()) { Ordering::Less => { - let p_wide = NonZero::new(p.clone()) + let p_wide = NonZero::new(priv_key.primes()[0].clone()) .expect("`p` is non-zero") .resize_unchecked(q_params.bits_precision()); (&m2 % p_wide).resize_unchecked(p_params.bits_precision()) @@ -109,7 +110,7 @@ pub fn rsa_decrypt( Ordering::Greater => (&m2).resize_unchecked(p_params.bits_precision()), Ordering::Equal => m2.clone(), }; - let m2r = BoxedMontyForm::new(m2_mod_p, p_params); + let m2r = BoxedMontyForm::new(m2_mod_p, &p_params); m1 -= &m2r; // precomputed: qInv = (1/q) mod p @@ -120,7 +121,7 @@ pub fn rsa_decrypt( // m = m2 + h.q let m2 = m2.try_resize(n.bits_precision()).ok_or(Error::Internal)?; let hq = h - .concatenating_mul(&q) + .concatenating_mul(&priv_key.primes()[1]) .try_resize(n.bits_precision()) .ok_or(Error::Internal)?; m2.wrapping_add(&hq) diff --git a/src/key.rs b/src/key.rs index b5d7e258..d96b16a7 100644 --- a/src/key.rs +++ b/src/key.rs @@ -27,6 +27,9 @@ use crate::errors::{Error, Result}; use crate::traits::keys::{CrtValue, PrivateKeyParts, PublicKeyParts}; use crate::traits::{PaddingScheme, SignatureScheme}; +/// Type we use for representing secret prime values. +pub(crate) type SecretPrime = crypto_bigint::modular::MontyParams; + /// Represents the public part of an RSA key. #[derive(Debug, Clone)] pub struct RsaPublicKey { @@ -125,28 +128,26 @@ impl ZeroizeOnDrop for RsaPrivateKey {} #[derive(Clone)] pub(crate) struct PrecomputedValues { + /// Montgomery params for `p` + pub(crate) p: SecretPrime, + /// Montgomery params for `q` + pub(crate) q: SecretPrime, /// D mod (P-1) pub(crate) dp: BoxedUint, /// D mod (Q-1) pub(crate) dq: BoxedUint, /// Q^-1 mod P pub(crate) qinv: BoxedMontyForm, - - /// Montgomery params for `p` - pub(crate) p_params: BoxedMontyParams, - /// Montgomery params for `q` - pub(crate) q_params: BoxedMontyParams, } impl ZeroizeOnDrop for PrecomputedValues {} impl Zeroize for PrecomputedValues { fn zeroize(&mut self) { + self.p.zeroize(); + self.q.zeroize(); self.dp.zeroize(); self.dq.zeroize(); - // TODO: once these have landed in crypto-bigint - // self.p_params.zeroize(); - // self.q_params.zeroize(); } } @@ -610,14 +611,10 @@ impl RsaPrivateKey { debug_assert_eq!(p_params.bits_precision(), p.bits_precision()); debug_assert_eq!(q_params.bits_precision(), q.bits_precision()); - self.precomputed = Some(PrecomputedValues { - dp, - dq, - qinv, - p_params, - q_params, - }); - + // TODO(tarcieri): zeroize intermediate parameters + let p = p_params.as_ref().clone(); + let q = q_params.as_ref().clone(); + self.precomputed = Some(PrecomputedValues { p, q, dp, dq, qinv }); Ok(()) } @@ -709,12 +706,12 @@ impl PrivateKeyParts for RsaPrivateKey { None } - fn p_params(&self) -> Option<&BoxedMontyParams> { - self.precomputed.as_ref().map(|p| &p.p_params) + fn p(&self) -> Option<&SecretPrime> { + self.precomputed.as_ref().map(|p| &p.p) } - fn q_params(&self) -> Option<&BoxedMontyParams> { - self.precomputed.as_ref().map(|p| &p.q_params) + fn q(&self) -> Option<&SecretPrime> { + self.precomputed.as_ref().map(|p| &p.q) } } diff --git a/src/traits/keys.rs b/src/traits/keys.rs index ee43bc66..e5aa970a 100644 --- a/src/traits/keys.rs +++ b/src/traits/keys.rs @@ -1,5 +1,6 @@ //! Traits related to the key components +use crate::key::SecretPrime; use alloc::boxed::Box; use crypto_bigint::{ modular::{BoxedMontyForm, BoxedMontyParams}, @@ -48,6 +49,12 @@ pub trait PrivateKeyParts: PublicKeyParts { /// Returns the prime factors. fn primes(&self) -> &[BoxedUint]; + /// Returns prime `p` if precomputed. + fn p(&self) -> Option<&SecretPrime>; + + /// Returns prime `q` if precomputed. + fn q(&self) -> Option<&SecretPrime>; + /// Returns the precomputed dp value, D mod (P-1) fn dp(&self) -> Option<&BoxedUint>; @@ -59,12 +66,6 @@ pub trait PrivateKeyParts: PublicKeyParts { /// Returns an iterator over the CRT Values fn crt_values(&self) -> Option<&[CrtValue]>; - - /// Returns the params for `p` if precomputed. - fn p_params(&self) -> Option<&BoxedMontyParams>; - - /// Returns the params for `q` if precomputed. - fn q_params(&self) -> Option<&BoxedMontyParams>; } /// Contains the precomputed Chinese remainder theorem values.