1 // Copyright 2015-2021 Brian Smith.
2 //
3 // Permission to use, copy, modify, and/or distribute this software for any
4 // purpose with or without fee is hereby granted, provided that the above
5 // copyright notice and this permission notice appear in all copies.
6 //
7 // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8 // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
10 // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15 use super::{PublicExponent, PublicModulus, N, PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN};
16 use crate::{
17 arithmetic::bigint,
18 bits, cpu, error,
19 io::{self, der, der_writer},
20 limb::LIMB_BYTES,
21 };
22 use alloc::boxed::Box;
23
24 /// An RSA Public Key.
25 #[derive(Clone)]
26 pub struct PublicKey {
27 n: PublicModulus,
28 e: PublicExponent,
29 serialized: Box<[u8]>,
30 }
31
32 derive_debug_self_as_ref_hex_bytes!(PublicKey);
33
34 impl PublicKey {
from_modulus_and_exponent( n: untrusted::Input, e: untrusted::Input, n_min_bits: bits::BitLength, n_max_bits: bits::BitLength, e_min_value: PublicExponent, cpu_features: cpu::Features, ) -> Result<Self, error::KeyRejected>35 pub(super) fn from_modulus_and_exponent(
36 n: untrusted::Input,
37 e: untrusted::Input,
38 n_min_bits: bits::BitLength,
39 n_max_bits: bits::BitLength,
40 e_min_value: PublicExponent,
41 cpu_features: cpu::Features,
42 ) -> Result<Self, error::KeyRejected> {
43 let n_bytes = n;
44 let e_bytes = e;
45
46 // This is an incomplete implementation of NIST SP800-56Br1 Section
47 // 6.4.2.2, "Partial Public-Key Validation for RSA." That spec defers
48 // to NIST SP800-89 Section 5.3.3, "(Explicit) Partial Public Key
49 // Validation for RSA," "with the caveat that the length of the modulus
50 // shall be a length that is specified in this Recommendation." In
51 // SP800-89, two different sets of steps are given, one set numbered,
52 // and one set lettered. TODO: Document this in the end-user
53 // documentation for RSA keys.
54
55 let n = PublicModulus::from_be_bytes(n, n_min_bits..=n_max_bits, cpu_features)?;
56
57 let e = PublicExponent::from_be_bytes(e, e_min_value)?;
58
59 // If `n` is less than `e` then somebody has probably accidentally swapped
60 // them. The largest acceptable `e` is smaller than the smallest acceptable
61 // `n`, so no additional checks need to be done.
62
63 // XXX: Steps 4 & 5 / Steps d, e, & f are not implemented. This is also the
64 // case in most other commonly-used crypto libraries.
65
66 // TODO: Remove this re-parsing, and stop allocating this here.
67 // Instead we should serialize on demand without allocation, from
68 // `Modulus::be_bytes()` and `Exponent::be_bytes()`.
69 let n_bytes = io::Positive::from_be_bytes(n_bytes)
70 .map_err(|_: error::Unspecified| error::KeyRejected::unexpected_error())?;
71 let e_bytes = io::Positive::from_be_bytes(e_bytes)
72 .map_err(|_: error::Unspecified| error::KeyRejected::unexpected_error())?;
73 let serialized = der_writer::write_all(der::Tag::Sequence, &|output| {
74 der_writer::write_positive_integer(output, &n_bytes);
75 der_writer::write_positive_integer(output, &e_bytes);
76 });
77
78 Ok(Self { n, e, serialized })
79 }
80
81 /// The length, in bytes, of the public modulus.
82 ///
83 /// The modulus length is rounded up to a whole number of bytes if its
84 /// bit length isn't a multiple of 8.
modulus_len(&self) -> usize85 pub fn modulus_len(&self) -> usize {
86 self.n().len_bits().as_usize_bytes_rounded_up()
87 }
88
89 /// The public modulus.
90 #[inline]
n(&self) -> &PublicModulus91 pub(super) fn n(&self) -> &PublicModulus {
92 &self.n
93 }
94
95 /// The public exponent.
96 #[inline]
e(&self) -> PublicExponent97 pub(super) fn e(&self) -> PublicExponent {
98 self.e
99 }
100
101 /// Calculates base**e (mod n), filling the first part of `out_buffer` with
102 /// the result.
103 ///
104 /// This is constant-time with respect to the value in `base` (only).
105 ///
106 /// The result will be a slice of the encoded bytes of the result within
107 /// `out_buffer`, if successful.
exponentiate<'out>( &self, base: untrusted::Input, out_buffer: &'out mut [u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN], ) -> Result<&'out [u8], error::Unspecified>108 pub(super) fn exponentiate<'out>(
109 &self,
110 base: untrusted::Input,
111 out_buffer: &'out mut [u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN],
112 ) -> Result<&'out [u8], error::Unspecified> {
113 let n = &self.n.value();
114
115 // The encoded value of the base must be the same length as the modulus,
116 // in bytes.
117 if base.len() != self.n.len_bits().as_usize_bytes_rounded_up() {
118 return Err(error::Unspecified);
119 }
120
121 // RFC 8017 Section 5.2.2: RSAVP1.
122
123 // Step 1.
124 let s = bigint::Elem::from_be_bytes_padded(base, n)?;
125 if s.is_zero() {
126 return Err(error::Unspecified);
127 }
128
129 // Step 2.
130 let m = self.exponentiate_elem(s);
131
132 // Step 3.
133 Ok(fill_be_bytes_n(m, self.n.len_bits(), out_buffer))
134 }
135
136 /// Calculates base**e (mod n).
137 ///
138 /// This is constant-time with respect to `base` only.
exponentiate_elem(&self, base: bigint::Elem<N>) -> bigint::Elem<N>139 pub(super) fn exponentiate_elem(&self, base: bigint::Elem<N>) -> bigint::Elem<N> {
140 let n = self.n.value();
141
142 let base = bigint::elem_mul(n.oneRR().as_ref(), base, n);
143 // During RSA public key operations the exponent is almost always either
144 // 65537 (0b10000000000000001) or 3 (0b11), both of which have a Hamming
145 // weight of 2. The maximum bit length and maximum Hamming weight of the
146 // exponent is bounded by the value of `PublicExponent::MAX`.
147 bigint::elem_exp_vartime(base, self.e.value(), &n.as_partial()).into_unencoded(n)
148 }
149 }
150
151 // XXX: Refactor `signature::KeyPair` to get rid of this.
152 impl AsRef<[u8]> for PublicKey {
as_ref(&self) -> &[u8]153 fn as_ref(&self) -> &[u8] {
154 &self.serialized
155 }
156 }
157
158 /// Returns the big-endian representation of `elem` that is
159 /// the same length as the minimal-length big-endian representation of
160 /// the modulus `n`.
161 ///
162 /// `n_bits` must be the bit length of the public modulus `n`.
fill_be_bytes_n( elem: bigint::Elem<N>, n_bits: bits::BitLength, out: &mut [u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN], ) -> &[u8]163 fn fill_be_bytes_n(
164 elem: bigint::Elem<N>,
165 n_bits: bits::BitLength,
166 out: &mut [u8; PUBLIC_KEY_PUBLIC_MODULUS_MAX_LEN],
167 ) -> &[u8] {
168 let n_bytes = n_bits.as_usize_bytes_rounded_up();
169 let n_bytes_padded = ((n_bytes + (LIMB_BYTES - 1)) / LIMB_BYTES) * LIMB_BYTES;
170 let out = &mut out[..n_bytes_padded];
171 elem.fill_be_bytes(out);
172 let (padding, out) = out.split_at(n_bytes_padded - n_bytes);
173 assert!(padding.iter().all(|&b| b == 0));
174 out
175 }
176