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