Skip to content

Commit 2b9e941

Browse files
committed
[WIP] Minimum modulus size checks
Changes the existing checked APIs to respect a minimum modulus size in addition to a maximum one. Note: several tests fail because of this, so we'll need to go through them and convert to an unchecked API where appropriate (or decide if the test is bogus to begin with)
1 parent 1ffef57 commit 2b9e941

File tree

2 files changed

+37
-10
lines changed

2 files changed

+37
-10
lines changed

src/errors.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ pub enum Error {
4040
/// Invalid coefficient.
4141
InvalidCoefficient,
4242

43+
/// Modulus too small.
44+
ModulusTooSmall,
45+
4346
/// Modulus too large.
4447
ModulusTooLarge,
4548

@@ -92,6 +95,7 @@ impl core::fmt::Display for Error {
9295
Error::InvalidModulus => write!(f, "invalid modulus"),
9396
Error::InvalidExponent => write!(f, "invalid exponent"),
9497
Error::InvalidCoefficient => write!(f, "invalid coefficient"),
98+
Error::ModulusTooSmall => write!(f, "modulus too small"),
9599
Error::ModulusTooLarge => write!(f, "modulus too large"),
96100
Error::PublicExponentTooSmall => write!(f, "public exponent too small"),
97101
Error::PublicExponentTooLarge => write!(f, "public exponent too large"),

src/key.rs

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use alloc::vec::Vec;
22
use core::cmp::Ordering;
33
use core::fmt;
44
use core::hash::{Hash, Hasher};
5+
use core::ops::Range;
56

67
use crypto_bigint::modular::{BoxedMontyForm, BoxedMontyParams};
78
use crypto_bigint::{BoxedUint, Integer, NonZero, Odd, Resize};
@@ -215,20 +216,30 @@ impl RsaPublicKey {
215216
/// Maximum value of the public exponent `e`.
216217
pub const MAX_PUB_EXPONENT: u64 = (1 << 33) - 1;
217218

218-
/// Maximum size of the modulus `n` in bits.
219+
/// Default minimum size of the modulus `n` in bits.
220+
pub const MIN_SIZE: usize = 1024;
221+
222+
/// Default maximum size of the modulus `n` in bits.
219223
pub const MAX_SIZE: usize = 4096;
220224

221225
/// Create a new public key from its components.
222226
///
223227
/// This function accepts public keys with a modulus size up to 4096-bits,
224228
/// i.e. [`RsaPublicKey::MAX_SIZE`].
225229
pub fn new(n: BoxedUint, e: BoxedUint) -> Result<Self> {
226-
Self::new_with_max_size(n, e, Self::MAX_SIZE)
230+
Self::new_with_size_limits(n, e, Self::MIN_SIZE..Self::MAX_SIZE)
227231
}
228232

229233
/// Create a new public key from its components.
230-
pub fn new_with_max_size(n: BoxedUint, e: BoxedUint, max_size: usize) -> Result<Self> {
231-
check_public_with_max_size(&n, &e, max_size)?;
234+
///
235+
/// Accepts a third argument which specifies a range of allowed sizes from minimum to maximum
236+
/// in bits, which by default is `1024..4096`.
237+
pub fn new_with_size_limits(
238+
n: BoxedUint,
239+
e: BoxedUint,
240+
size_range_bits: Range<usize>,
241+
) -> Result<Self> {
242+
check_public_with_size_range(&n, &e, size_range_bits)?;
232243

233244
let n_odd = Odd::new(n.clone())
234245
.into_option()
@@ -244,7 +255,7 @@ impl RsaPublicKey {
244255
///
245256
/// This method is not recommended, and only intended for unusual use cases.
246257
/// Most applications should use [`RsaPublicKey::new`] or
247-
/// [`RsaPublicKey::new_with_max_size`] instead.
258+
/// [`RsaPublicKey::new_with_size_limits`] instead.
248259
pub fn new_unchecked(n: BoxedUint, e: BoxedUint) -> Self {
249260
let n_odd = Odd::new(n.clone()).expect("n must be odd");
250261
let n_params = BoxedMontyParams::new(n_odd);
@@ -613,16 +624,28 @@ impl PrivateKeyParts for RsaPrivateKey {
613624
}
614625
}
615626

616-
/// Check that the public key is well formed and has an exponent within acceptable bounds.
627+
/// Check that the public key is well-formed and has an exponent within acceptable bounds.
617628
#[inline]
618629
pub fn check_public(public_key: &impl PublicKeyParts) -> Result<()> {
619-
check_public_with_max_size(public_key.n(), public_key.e(), RsaPublicKey::MAX_SIZE)
630+
check_public_with_size_range(
631+
public_key.n(),
632+
public_key.e(),
633+
RsaPublicKey::MIN_SIZE..RsaPublicKey::MAX_SIZE,
634+
)
620635
}
621636

622-
/// Check that the public key is well formed and has an exponent within acceptable bounds.
637+
/// Check that the public key is well-formed and has an exponent within acceptable bounds.
623638
#[inline]
624-
fn check_public_with_max_size(n: &BoxedUint, e: &BoxedUint, max_size: usize) -> Result<()> {
625-
if n.bits_precision() as usize > max_size {
639+
fn check_public_with_size_range(
640+
n: &BoxedUint,
641+
e: &BoxedUint,
642+
size_range_bits: Range<usize>,
643+
) -> Result<()> {
644+
if (n.bits_precision() as usize) < size_range_bits.start {
645+
return Err(Error::ModulusTooSmall);
646+
}
647+
648+
if (n.bits_precision() as usize) > size_range_bits.end {
626649
return Err(Error::ModulusTooLarge);
627650
}
628651

0 commit comments

Comments
 (0)