ring/rsa/
public_modulus.rs

1use crate::{
2    arithmetic::{bigint, montgomery::RR},
3    bits::{self, FromUsizeBytes as _},
4    cpu, error,
5    rsa::N,
6};
7use core::ops::RangeInclusive;
8
9/// The modulus (n) of an RSA public key.
10#[derive(Clone)]
11pub struct PublicModulus {
12    value: bigint::OwnedModulus<N>,
13    oneRR: bigint::One<N, RR>,
14}
15
16/*
17impl core::fmt::Debug for PublicModulus {
18    fn fmt(&self, fmt: &mut ::core::fmt::Formatter) -> Result<(), ::core::fmt::Error> {
19        self.value.fmt(fmt)
20    }
21}*/
22
23impl PublicModulus {
24    pub(super) fn from_be_bytes(
25        n: untrusted::Input,
26        allowed_bit_lengths: RangeInclusive<bits::BitLength>,
27        cpu_features: cpu::Features,
28    ) -> Result<Self, error::KeyRejected> {
29        // See `PublicKey::from_modulus_and_exponent` for background on the step
30        // numbering.
31
32        let min_bits = *allowed_bit_lengths.start();
33        let max_bits = *allowed_bit_lengths.end();
34
35        // `pkcs1_encode` depends on this not being small. Otherwise,
36        // `pkcs1_encode` would generate padding that is invalid (too few 0xFF
37        // bytes) for very small keys.
38        const MIN_BITS: bits::BitLength = bits::BitLength::from_usize_bits(1024);
39
40        // Step 3 / Step c for `n` (out of order).
41        let value = bigint::OwnedModulus::from_be_bytes(n)?;
42        let bits = value.len_bits();
43
44        // Step 1 / Step a. XXX: SP800-56Br1 and SP800-89 require the length of
45        // the public modulus to be exactly 2048 or 3072 bits, but we are more
46        // flexible to be compatible with other commonly-used crypto libraries.
47        assert!(min_bits >= MIN_BITS);
48        let bits_rounded_up =
49            bits::BitLength::from_usize_bytes(bits.as_usize_bytes_rounded_up()).unwrap(); // TODO: safe?
50        if bits_rounded_up < min_bits {
51            return Err(error::KeyRejected::too_small());
52        }
53        if bits > max_bits {
54            return Err(error::KeyRejected::too_large());
55        }
56        let oneRR = bigint::One::newRR(&value.modulus(cpu_features));
57
58        Ok(Self { value, oneRR })
59    }
60
61    /// The big-endian encoding of the modulus.
62    ///
63    /// There are no leading zeros.
64    pub fn be_bytes(&self) -> impl ExactSizeIterator<Item = u8> + Clone + '_ {
65        self.value.be_bytes()
66    }
67
68    /// The length of the modulus in bits.
69    pub fn len_bits(&self) -> bits::BitLength {
70        self.value.len_bits()
71    }
72
73    pub(super) fn value(&self, cpu_features: cpu::Features) -> bigint::Modulus<N> {
74        self.value.modulus(cpu_features)
75    }
76
77    pub(super) fn oneRR(&self) -> &bigint::Elem<N, RR> {
78        self.oneRR.as_ref()
79    }
80}