1 use crate::error;
2 use crate::polyfill::{unwrap_const, ArrayFlatMap, LeadingZerosStripped};
3 use core::num::NonZeroU64;
4 
5 /// The exponent `e` of an RSA public key.
6 #[derive(Clone, Copy)]
7 pub struct PublicExponent(NonZeroU64);
8 
9 impl PublicExponent {
10     #[cfg(test)]
11     const ALL_CONSTANTS: [Self; 3] = [Self::_3, Self::_65537, Self::MAX];
12 
13     pub(super) const _3: Self = Self(unwrap_const(NonZeroU64::new(3)));
14     pub(super) const _65537: Self = Self(unwrap_const(NonZeroU64::new(65537)));
15 
16     // This limit was chosen to bound the performance of the simple
17     // exponentiation-by-squaring implementation in `elem_exp_vartime`. In
18     // particular, it helps mitigate theoretical resource exhaustion attacks. 33
19     // bits was chosen as the limit based on the recommendations in [1] and
20     // [2]. Windows CryptoAPI (at least older versions) doesn't support values
21     // larger than 32 bits [3], so it is unlikely that exponents larger than 32
22     // bits are being used for anything Windows commonly does.
23     //
24     // [1] https://www.imperialviolet.org/2012/03/16/rsae.html
25     // [2] https://www.imperialviolet.org/2012/03/17/rsados.html
26     // [3] https://msdn.microsoft.com/en-us/library/aa387685(VS.85).aspx
27     const MAX: Self = Self(unwrap_const(NonZeroU64::new((1u64 << 33) - 1)));
28 
from_be_bytes( input: untrusted::Input, min_value: Self, ) -> Result<Self, error::KeyRejected>29     pub(super) fn from_be_bytes(
30         input: untrusted::Input,
31         min_value: Self,
32     ) -> Result<Self, error::KeyRejected> {
33         // See `PublicKey::from_modulus_and_exponent` for background on the step
34         // numbering.
35 
36         if input.len() > 5 {
37             return Err(error::KeyRejected::too_large());
38         }
39         let value = input.read_all(error::KeyRejected::invalid_encoding(), |input| {
40             // The exponent can't be zero and it can't be prefixed with
41             // zero-valued bytes.
42             if input.peek(0) {
43                 return Err(error::KeyRejected::invalid_encoding());
44             }
45             let mut value = 0u64;
46             loop {
47                 let byte = input
48                     .read_byte()
49                     .map_err(|untrusted::EndOfInput| error::KeyRejected::invalid_encoding())?;
50                 value = (value << 8) | u64::from(byte);
51                 if input.at_end() {
52                     return Ok(value);
53                 }
54             }
55         })?;
56 
57         // Step 2 / Step b. NIST SP800-89 defers to FIPS 186-3, which requires
58         // `e >= 65537`. We enforce this when signing, but are more flexible in
59         // verification, for compatibility. Only small public exponents are
60         // supported.
61         let value = NonZeroU64::new(value).ok_or_else(error::KeyRejected::too_small)?;
62         if value < min_value.0 {
63             return Err(error::KeyRejected::too_small());
64         }
65         if value > Self::MAX.0 {
66             return Err(error::KeyRejected::too_large());
67         }
68 
69         // Step 3 / Step c.
70         if value.get() & 1 != 1 {
71             return Err(error::KeyRejected::invalid_component());
72         }
73 
74         Ok(Self(value))
75     }
76 
77     /// The big-endian encoding of the exponent.
78     ///
79     /// There are no leading zeros.
be_bytes(&self) -> impl ExactSizeIterator<Item = u8> + Clone + '_80     pub fn be_bytes(&self) -> impl ExactSizeIterator<Item = u8> + Clone + '_ {
81         // The `unwrap()` won't fail as `self.0` is only a few bytes long.
82         let bytes = ArrayFlatMap::new(core::iter::once(self.0.get()), u64::to_be_bytes).unwrap();
83         LeadingZerosStripped::new(bytes)
84     }
85 
value(self) -> NonZeroU6486     pub(super) fn value(self) -> NonZeroU64 {
87         self.0
88     }
89 }
90 
91 #[cfg(test)]
92 mod tests {
93     use super::*;
94 
95     #[test]
test_public_exponent_constants()96     fn test_public_exponent_constants() {
97         for value in PublicExponent::ALL_CONSTANTS.iter() {
98             let value: u64 = value.0.into();
99             assert_eq!(value & 1, 1);
100             assert!(value >= PublicExponent::_3.0.into()); // The absolute minimum.
101             assert!(value <= PublicExponent::MAX.0.into());
102         }
103     }
104 }
105