1 | use crate::{ |
2 | arithmetic::{bigint, montgomery::RR}, |
3 | bits::{self, FromUsizeBytes as _}, |
4 | cpu, error, |
5 | rsa::N, |
6 | }; |
7 | use core::ops::RangeInclusive; |
8 | |
9 | /// The modulus (n) of an RSA public key. |
10 | #[derive (Clone)] |
11 | pub struct PublicModulus { |
12 | value: bigint::OwnedModulus<N>, |
13 | oneRR: bigint::One<N, RR>, |
14 | } |
15 | |
16 | /* |
17 | impl 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 | |
23 | impl 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 | } |
81 | |