rsa: Use dynamic checks for widening conversions.

Remove `SmallerModulus` and instead do the check dynamically. This
eliminates the last `unsafe impl` regarding the modulus
relationships. The uses of `elem_widen` won't ever fail but since
they are in an already-fallible function they wo't hurt.
This commit is contained in:
Brian Smith 2023-11-22 19:26:55 -08:00
parent 1855573098
commit 2ad2fcb912
2 changed files with 10 additions and 19 deletions

View File

@ -56,18 +56,6 @@ mod boxed_limbs;
mod modulus;
mod private_exponent;
/// A modulus *s* that is smaller than another modulus *l* so every element of
/// /s is also an element of /l.
///
/// # Safety
///
/// Some logic may assume that the invariant holds when accessing limbs within
/// a value, e.g. by assuming the larger modulus has at least as many limbs.
/// TODO: Any such logic should be encapsulated here, or this trait should be
/// made non-`unsafe`. (In retrospect, this shouldn't have been made an `unsafe`
/// trait preemptively.)
pub unsafe trait SmallerModulus<L> {}
pub trait PublicModulus {}
/// Elements of /m for some modulus *m*.
@ -224,13 +212,17 @@ where
}
}
pub fn elem_widen<Larger, Smaller: SmallerModulus<Larger>>(
pub fn elem_widen<Larger, Smaller>(
a: Elem<Smaller, Unencoded>,
m: &Modulus<Larger>,
) -> Elem<Larger, Unencoded> {
smaller_modulus_bits: BitLength,
) -> Result<Elem<Larger, Unencoded>, error::Unspecified> {
if smaller_modulus_bits >= m.len_bits() {
return Err(error::Unspecified);
}
let mut r = m.zero();
r.limbs[..a.limbs.len()].copy_from_slice(&a.limbs);
r
Ok(r)
}
// TODO: Document why this works for all Montgomery factors.

View File

@ -497,11 +497,9 @@ fn elem_exp_consttime<M>(
#[derive(Copy, Clone)]
enum P {}
unsafe impl bigint::SmallerModulus<N> for P {}
#[derive(Copy, Clone)]
enum Q {}
unsafe impl bigint::SmallerModulus<N> for Q {}
impl KeyPair {
/// Computes the signature of `msg` and writes it into `signature`.
@ -591,11 +589,12 @@ impl KeyPair {
// necessary because `h < p` and `p * q == n` implies `h * q < n`.
// Modular arithmetic is used simply to avoid implementing
// non-modular arithmetic.
let h = bigint::elem_widen(h, n);
let p_bits = self.p.modulus.len_bits();
let h = bigint::elem_widen(h, n, p_bits)?;
let q_mod_n = self.q.modulus.to_elem(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_2 = bigint::elem_widen(m_2, n, q_bits)?;
let m = bigint::elem_add(m_2, q_times_h, n);
// Step 2.b.v isn't needed since there are only two primes.