Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 14 additions & 13 deletions src/algorithms/rsa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,30 +69,31 @@ pub fn rsa_decrypt<R: TryCryptoRng + ?Sized>(
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`,
Expand All @@ -101,15 +102,15 @@ pub fn rsa_decrypt<R: TryCryptoRng + ?Sized>(
// (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())
}
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
Expand All @@ -120,7 +121,7 @@ pub fn rsa_decrypt<R: TryCryptoRng + ?Sized>(
// 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)
Expand Down
37 changes: 17 additions & 20 deletions src/key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<BoxedUint>;

/// Represents the public part of an RSA key.
#[derive(Debug, Clone)]
pub struct RsaPublicKey {
Expand Down Expand Up @@ -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();
}
}

Expand Down Expand Up @@ -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(())
}

Expand Down Expand Up @@ -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)
}
}

Expand Down
13 changes: 7 additions & 6 deletions src/traits/keys.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! Traits related to the key components

use crate::key::SecretPrime;
use alloc::boxed::Box;
use crypto_bigint::{
modular::{BoxedMontyForm, BoxedMontyParams},
Expand Down Expand Up @@ -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>;

Expand All @@ -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.
Expand Down
Loading