• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015-2016 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::super::{keypair, padding::RsaEncoding, public};
16 
17 /// RSA PKCS#1 1.5 signatures.
18 use crate::{
19     digest,
20     error::{self, KeyRejected},
21     io::{self, der, der_writer},
22     rand, signature,
23 };
24 use alloc::boxed::Box;
25 use core::convert::TryFrom;
26 
27 /// An RSA key pair, used for signing.
28 pub struct RsaKeyPair {
29     inner: keypair::RsaKeyPair,
30     public_key: RsaSubjectPublicKey,
31 }
32 
33 impl core::fmt::Debug for RsaKeyPair {
fmt(&self, fmt: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error>34     fn fmt(&self, fmt: &mut core::fmt::Formatter) -> Result<(), core::fmt::Error> {
35         self.inner.fmt(fmt)
36     }
37 }
38 
39 impl RsaKeyPair {
40     /// Parses an unencrypted PKCS#8-encoded RSA private key.
41     ///
42     /// Only two-prime (not multi-prime) keys are supported. The public modulus
43     /// (n) must be at least 2047 bits. The public modulus must be no larger
44     /// than 4096 bits. It is recommended that the public modulus be exactly
45     /// 2048 or 3072 bits. The public exponent must be at least 65537.
46     ///
47     /// This will generate a 2048-bit RSA private key of the correct form using
48     /// OpenSSL's command line tool:
49     ///
50     /// ```sh
51     ///    openssl genpkey -algorithm RSA \
52     ///        -pkeyopt rsa_keygen_bits:2048 \
53     ///        -pkeyopt rsa_keygen_pubexp:65537 | \
54     ///      openssl pkcs8 -topk8 -nocrypt -outform der > rsa-2048-private-key.pk8
55     /// ```
56     ///
57     /// This will generate a 3072-bit RSA private key of the correct form:
58     ///
59     /// ```sh
60     ///    openssl genpkey -algorithm RSA \
61     ///        -pkeyopt rsa_keygen_bits:3072 \
62     ///        -pkeyopt rsa_keygen_pubexp:65537 | \
63     ///      openssl pkcs8 -topk8 -nocrypt -outform der > rsa-3072-private-key.pk8
64     /// ```
65     ///
66     /// Often, keys generated for use in OpenSSL-based software are stored in
67     /// the Base64 “PEM” format without the PKCS#8 wrapper. Such keys can be
68     /// converted to binary PKCS#8 form using the OpenSSL command line tool like
69     /// this:
70     ///
71     /// ```sh
72     /// openssl pkcs8 -topk8 -nocrypt -outform der \
73     ///     -in rsa-2048-private-key.pem > rsa-2048-private-key.pk8
74     /// ```
75     ///
76     /// Base64 (“PEM”) PKCS#8-encoded keys can be converted to the binary PKCS#8
77     /// form like this:
78     ///
79     /// ```sh
80     /// openssl pkcs8 -nocrypt -outform der \
81     ///     -in rsa-2048-private-key.pem > rsa-2048-private-key.pk8
82     /// ```
83     ///
84     /// The private key is validated according to [NIST SP-800-56B rev. 1]
85     /// section 6.4.1.4.3, crt_pkv (Intended Exponent-Creation Method Unknown),
86     /// with the following exceptions:
87     ///
88     /// * Section 6.4.1.2.1, Step 1: Neither a target security level nor an
89     ///   expected modulus length is provided as a parameter, so checks
90     ///   regarding these expectations are not done.
91     /// * Section 6.4.1.2.1, Step 3: Since neither the public key nor the
92     ///   expected modulus length is provided as a parameter, the consistency
93     ///   check between these values and the private key's value of n isn't
94     ///   done.
95     /// * Section 6.4.1.2.1, Step 5: No primality tests are done, both for
96     ///   performance reasons and to avoid any side channels that such tests
97     ///   would provide.
98     /// * Section 6.4.1.2.1, Step 6, and 6.4.1.4.3, Step 7:
99     ///     * *ring* has a slightly looser lower bound for the values of `p`
100     ///     and `q` than what the NIST document specifies. This looser lower
101     ///     bound matches what most other crypto libraries do. The check might
102     ///     be tightened to meet NIST's requirements in the future. Similarly,
103     ///     the check that `p` and `q` are not too close together is skipped
104     ///     currently, but may be added in the future.
105     ///     - The validity of the mathematical relationship of `dP`, `dQ`, `e`
106     ///     and `n` is verified only during signing. Some size checks of `d`,
107     ///     `dP` and `dQ` are performed at construction, but some NIST checks
108     ///     are skipped because they would be expensive and/or they would leak
109     ///     information through side channels. If a preemptive check of the
110     ///     consistency of `dP`, `dQ`, `e` and `n` with each other is
111     ///     necessary, that can be done by signing any message with the key
112     ///     pair.
113     ///
114     ///     * `d` is not fully validated, neither at construction nor during
115     ///     signing. This is OK as far as *ring*'s usage of the key is
116     ///     concerned because *ring* never uses the value of `d` (*ring* always
117     ///     uses `p`, `q`, `dP` and `dQ` via the Chinese Remainder Theorem,
118     ///     instead). However, *ring*'s checks would not be sufficient for
119     ///     validating a key pair for use by some other system; that other
120     ///     system must check the value of `d` itself if `d` is to be used.
121     ///
122     /// In addition to the NIST requirements, *ring* requires that `p > q` and
123     /// that `e` must be no more than 33 bits.
124     ///
125     /// See [RFC 5958] and [RFC 3447 Appendix A.1.2] for more details of the
126     /// encoding of the key.
127     ///
128     /// [NIST SP-800-56B rev. 1]:
129     ///     http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br1.pdf
130     ///
131     /// [RFC 3447 Appendix A.1.2]:
132     ///     https://tools.ietf.org/html/rfc3447#appendix-A.1.2
133     ///
134     /// [RFC 5958]:
135     ///     https://tools.ietf.org/html/rfc5958
from_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected>136     pub fn from_pkcs8(pkcs8: &[u8]) -> Result<Self, KeyRejected> {
137         keypair::RsaKeyPair::from_pkcs8(pkcs8).map(From::from)
138     }
139 
140     /// Parses an RSA private key that is not inside a PKCS#8 wrapper.
141     ///
142     /// The private key must be encoded as a binary DER-encoded ASN.1
143     /// `RSAPrivateKey` as described in [RFC 3447 Appendix A.1.2]). In all other
144     /// respects, this is just like `from_pkcs8()`. See the documentation for
145     /// `from_pkcs8()` for more details.
146     ///
147     /// It is recommended to use `from_pkcs8()` (with a PKCS#8-encoded key)
148     /// instead.
149     ///
150     /// [RFC 3447 Appendix A.1.2]:
151     ///     https://tools.ietf.org/html/rfc3447#appendix-A.1.2
152     ///
153     /// [NIST SP-800-56B rev. 1]:
154     ///     http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-56Br1.pdf
from_der(input: &[u8]) -> Result<Self, KeyRejected>155     pub fn from_der(input: &[u8]) -> Result<Self, KeyRejected> {
156         keypair::RsaKeyPair::from_der(input).map(From::from)
157     }
158 
159     /// Returns a reference to the public key.
160     #[inline]
public(&self) -> &public::Key161     pub fn public(&self) -> &public::Key {
162         self.inner.public()
163     }
164 
165     /// Returns the length in bytes of the key pair's public modulus.
166     ///
167     /// A signature has the same length as the public modulus.
168     #[inline]
public_modulus_len(&self) -> usize169     pub fn public_modulus_len(&self) -> usize {
170         self.public().n().len()
171     }
172 }
173 
174 impl From<keypair::RsaKeyPair> for RsaKeyPair {
from(inner: keypair::RsaKeyPair) -> Self175     fn from(inner: keypair::RsaKeyPair) -> Self {
176         let public_key = RsaSubjectPublicKey::from(inner.public());
177         Self { inner, public_key }
178     }
179 }
180 
181 impl<Public, Private> TryFrom<&keypair::Components<Public, Private>> for RsaKeyPair
182 where
183     Public: AsRef<[u8]> + core::fmt::Debug,
184     Private: AsRef<[u8]>,
185 {
186     type Error = KeyRejected;
187 
try_from(components: &keypair::Components<Public, Private>) -> Result<Self, Self::Error>188     fn try_from(components: &keypair::Components<Public, Private>) -> Result<Self, Self::Error> {
189         keypair::RsaKeyPair::try_from(components).map(From::from)
190     }
191 }
192 
193 impl signature::KeyPair for RsaKeyPair {
194     type PublicKey = RsaSubjectPublicKey;
195 
196     #[inline]
public_key(&self) -> &Self::PublicKey197     fn public_key(&self) -> &Self::PublicKey {
198         &self.public_key
199     }
200 }
201 
202 /// A serialized RSA public key.
203 #[derive(Clone)]
204 pub struct RsaSubjectPublicKey(Box<[u8]>);
205 
206 impl AsRef<[u8]> for RsaSubjectPublicKey {
as_ref(&self) -> &[u8]207     fn as_ref(&self) -> &[u8] {
208         self.0.as_ref()
209     }
210 }
211 
212 derive_debug_self_as_ref_hex_bytes!(RsaSubjectPublicKey);
213 
214 impl From<&public::Key> for RsaSubjectPublicKey {
from(key: &public::Key) -> Self215     fn from(key: &public::Key) -> Self {
216         // The public key `n` and `e` are always positive.
217         fn positive(bytes: &[u8]) -> io::Positive {
218             io::Positive::new_non_empty_without_leading_zeros(untrusted::Input::from(bytes))
219                 .unwrap()
220         }
221 
222         let n = key.n().to_be_bytes();
223         let e = key.e().to_be_bytes();
224 
225         let bytes = der_writer::write_all(der::Tag::Sequence, &|output| {
226             der_writer::write_positive_integer(output, &positive(&n));
227             der_writer::write_positive_integer(output, &positive(&e));
228         });
229         RsaSubjectPublicKey(bytes)
230     }
231 }
232 
233 impl RsaSubjectPublicKey {
234     /// The public modulus (n).
modulus(&self) -> io::Positive235     pub fn modulus(&self) -> io::Positive {
236         // Parsing won't fail because we serialized it ourselves.
237         let (public_key, _exponent) =
238             super::super::parse_public_key(untrusted::Input::from(self.as_ref())).unwrap();
239         public_key
240     }
241 
242     /// The public exponent (e).
exponent(&self) -> io::Positive243     pub fn exponent(&self) -> io::Positive {
244         // Parsing won't fail because we serialized it ourselves.
245         let (_public_key, exponent) =
246             super::super::parse_public_key(untrusted::Input::from(self.as_ref())).unwrap();
247         exponent
248     }
249 }
250 
251 impl RsaKeyPair {
252     /// Sign `msg`. `msg` is digested using the digest algorithm from
253     /// `padding_alg` and the digest is then padded using the padding algorithm
254     /// from `padding_alg`. The signature it written into `signature`;
255     /// `signature`'s length must be exactly the length returned by
256     /// `public_modulus_len()`. `rng` may be used to randomize the padding
257     /// (e.g. for PSS).
258     ///
259     /// Many other crypto libraries have signing functions that takes a
260     /// precomputed digest as input, instead of the message to digest. This
261     /// function does *not* take a precomputed digest; instead, `sign`
262     /// calculates the digest itself.
263     ///
264     /// Lots of effort has been made to make the signing operations close to
265     /// constant time to protect the private key from side channel attacks. On
266     /// x86-64, this is done pretty well, but not perfectly. On other
267     /// platforms, it is done less perfectly.
sign( &self, padding_alg: &'static dyn RsaEncoding, rng: &dyn rand::SecureRandom, msg: &[u8], signature: &mut [u8], ) -> Result<(), error::Unspecified>268     pub fn sign(
269         &self,
270         padding_alg: &'static dyn RsaEncoding,
271         rng: &dyn rand::SecureRandom,
272         msg: &[u8],
273         signature: &mut [u8],
274     ) -> Result<(), error::Unspecified> {
275         let m_hash = digest::digest(padding_alg.digest_alg(), msg);
276         padding_alg.encode(m_hash, signature, self.public().n().len_bits(), rng)?;
277         self.inner.rsa_private_in_place(signature)
278     }
279 }
280 
281 #[cfg(test)]
282 mod tests {
283     // We intentionally avoid `use super::*` so that we are sure to use only
284     // the public API; this ensures that enough of the API is public.
285     use crate::{rand, signature};
286     use alloc::vec;
287 
288     // `KeyPair::sign` requires that the output buffer is the same length as
289     // the public key modulus. Test what happens when it isn't the same length.
290     #[test]
test_signature_rsa_pkcs1_sign_output_buffer_len()291     fn test_signature_rsa_pkcs1_sign_output_buffer_len() {
292         // Sign the message "hello, world", using PKCS#1 v1.5 padding and the
293         // SHA256 digest algorithm.
294         const MESSAGE: &[u8] = b"hello, world";
295         let rng = rand::SystemRandom::new();
296 
297         const PRIVATE_KEY_DER: &[u8] = include_bytes!("signature_rsa_example_private_key.der");
298         let key_pair = signature::RsaKeyPair::from_der(PRIVATE_KEY_DER).unwrap();
299 
300         // The output buffer is one byte too short.
301         let mut signature = vec![0; key_pair.public().n().len() - 1];
302 
303         assert!(key_pair
304             .sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
305             .is_err());
306 
307         // The output buffer is the right length.
308         signature.push(0);
309         assert!(key_pair
310             .sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
311             .is_ok());
312 
313         // The output buffer is one byte too long.
314         signature.push(0);
315         assert!(key_pair
316             .sign(&signature::RSA_PKCS1_SHA256, &rng, MESSAGE, &mut signature)
317             .is_err());
318     }
319 }
320