1 //! Rivest–Shamir–Adleman cryptosystem
2 //!
3 //! RSA is one of the earliest asymmetric public key encryption schemes.
4 //! Like many other cryptosystems, RSA relies on the presumed difficulty of a hard
5 //! mathematical problem, namely factorization of the product of two large prime
6 //! numbers. At the moment there does not exist an algorithm that can factor such
7 //! large numbers in reasonable time. RSA is used in a wide variety of
8 //! applications including digital signatures and key exchanges such as
9 //! establishing a TLS/SSL connection.
10 //!
11 //! The RSA acronym is derived from the first letters of the surnames of the
12 //! algorithm's founding trio.
13 //!
14 //! # Example
15 //!
16 //! Generate a 2048-bit RSA key pair and use the public key to encrypt some data.
17 //!
18 //! ```rust
19 //!
20 //! extern crate openssl;
21 //!
22 //! use openssl::rsa::{Rsa, Padding};
23 //!
24 //! fn main() {
25 //!     let rsa = Rsa::generate(2048).unwrap();
26 //!     let data = b"foobar";
27 //!     let mut buf = vec![0; rsa.size() as usize];
28 //!     let encrypted_len = rsa.public_encrypt(data, &mut buf, Padding::PKCS1).unwrap();
29 //! }
30 //! ```
31 use ffi;
32 use foreign_types::{ForeignType, ForeignTypeRef};
33 use libc::c_int;
34 use std::fmt;
35 use std::mem;
36 use std::ptr;
37 
38 use bn::{BigNum, BigNumRef};
39 use error::ErrorStack;
40 use pkey::{HasPrivate, HasPublic, Private, Public};
41 use {cvt, cvt_n, cvt_p};
42 
43 /// Type of encryption padding to use.
44 ///
45 /// Random length padding is primarily used to prevent attackers from
46 /// predicting or knowing the exact length of a plaintext message that
47 /// can possibly lead to breaking encryption.
48 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
49 pub struct Padding(c_int);
50 
51 impl Padding {
52     pub const NONE: Padding = Padding(ffi::RSA_NO_PADDING);
53     pub const PKCS1: Padding = Padding(ffi::RSA_PKCS1_PADDING);
54     pub const PKCS1_OAEP: Padding = Padding(ffi::RSA_PKCS1_OAEP_PADDING);
55     pub const PKCS1_PSS: Padding = Padding(ffi::RSA_PKCS1_PSS_PADDING);
56 
57     /// Creates a `Padding` from an integer representation.
from_raw(value: c_int) -> Padding58     pub fn from_raw(value: c_int) -> Padding {
59         Padding(value)
60     }
61 
62     /// Returns the integer representation of `Padding`.
63     #[allow(clippy::trivially_copy_pass_by_ref)]
as_raw(&self) -> c_int64     pub fn as_raw(&self) -> c_int {
65         self.0
66     }
67 }
68 
69 generic_foreign_type_and_impl_send_sync! {
70     type CType = ffi::RSA;
71     fn drop = ffi::RSA_free;
72 
73     /// An RSA key.
74     pub struct Rsa<T>;
75 
76     /// Reference to `RSA`
77     pub struct RsaRef<T>;
78 }
79 
80 impl<T> Clone for Rsa<T> {
clone(&self) -> Rsa<T>81     fn clone(&self) -> Rsa<T> {
82         (**self).to_owned()
83     }
84 }
85 
86 impl<T> ToOwned for RsaRef<T> {
87     type Owned = Rsa<T>;
88 
to_owned(&self) -> Rsa<T>89     fn to_owned(&self) -> Rsa<T> {
90         unsafe {
91             ffi::RSA_up_ref(self.as_ptr());
92             Rsa::from_ptr(self.as_ptr())
93         }
94     }
95 }
96 
97 impl<T> RsaRef<T>
98 where
99     T: HasPrivate,
100 {
101     private_key_to_pem! {
102         /// Serializes the private key to a PEM-encoded PKCS#1 RSAPrivateKey structure.
103         ///
104         /// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
105         ///
106         /// This corresponds to [`PEM_write_bio_RSAPrivateKey`].
107         ///
108         /// [`PEM_write_bio_RSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_RSAPrivateKey.html
109         private_key_to_pem,
110         /// Serializes the private key to a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
111         ///
112         /// The output will have a header of `-----BEGIN RSA PRIVATE KEY-----`.
113         ///
114         /// This corresponds to [`PEM_write_bio_RSAPrivateKey`].
115         ///
116         /// [`PEM_write_bio_RSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_write_bio_RSAPrivateKey.html
117         private_key_to_pem_passphrase,
118         ffi::PEM_write_bio_RSAPrivateKey
119     }
120 
121     to_der! {
122         /// Serializes the private key to a DER-encoded PKCS#1 RSAPrivateKey structure.
123         ///
124         /// This corresponds to [`i2d_RSAPrivateKey`].
125         ///
126         /// [`i2d_RSAPrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_RSAPrivateKey.html
127         private_key_to_der,
128         ffi::i2d_RSAPrivateKey
129     }
130 
131     /// Decrypts data using the private key, returning the number of decrypted bytes.
132     ///
133     /// # Panics
134     ///
135     /// Panics if `self` has no private components, or if `to` is smaller
136     /// than `self.size()`.
private_decrypt( &self, from: &[u8], to: &mut [u8], padding: Padding, ) -> Result<usize, ErrorStack>137     pub fn private_decrypt(
138         &self,
139         from: &[u8],
140         to: &mut [u8],
141         padding: Padding,
142     ) -> Result<usize, ErrorStack> {
143         assert!(from.len() <= i32::max_value() as usize);
144         assert!(to.len() >= self.size() as usize);
145 
146         unsafe {
147             let len = cvt_n(ffi::RSA_private_decrypt(
148                 from.len() as c_int,
149                 from.as_ptr(),
150                 to.as_mut_ptr(),
151                 self.as_ptr(),
152                 padding.0,
153             ))?;
154             Ok(len as usize)
155         }
156     }
157 
158     /// Encrypts data using the private key, returning the number of encrypted bytes.
159     ///
160     /// # Panics
161     ///
162     /// Panics if `self` has no private components, or if `to` is smaller
163     /// than `self.size()`.
private_encrypt( &self, from: &[u8], to: &mut [u8], padding: Padding, ) -> Result<usize, ErrorStack>164     pub fn private_encrypt(
165         &self,
166         from: &[u8],
167         to: &mut [u8],
168         padding: Padding,
169     ) -> Result<usize, ErrorStack> {
170         assert!(from.len() <= i32::max_value() as usize);
171         assert!(to.len() >= self.size() as usize);
172 
173         unsafe {
174             let len = cvt_n(ffi::RSA_private_encrypt(
175                 from.len() as c_int,
176                 from.as_ptr(),
177                 to.as_mut_ptr(),
178                 self.as_ptr(),
179                 padding.0,
180             ))?;
181             Ok(len as usize)
182         }
183     }
184 
185     /// Returns a reference to the private exponent of the key.
186     ///
187     /// This corresponds to [`RSA_get0_key`].
188     ///
189     /// [`RSA_get0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
d(&self) -> &BigNumRef190     pub fn d(&self) -> &BigNumRef {
191         unsafe {
192             let mut d = ptr::null();
193             RSA_get0_key(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut d);
194             BigNumRef::from_ptr(d as *mut _)
195         }
196     }
197 
198     /// Returns a reference to the first factor of the exponent of the key.
199     ///
200     /// This corresponds to [`RSA_get0_factors`].
201     ///
202     /// [`RSA_get0_factors`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
p(&self) -> Option<&BigNumRef>203     pub fn p(&self) -> Option<&BigNumRef> {
204         unsafe {
205             let mut p = ptr::null();
206             RSA_get0_factors(self.as_ptr(), &mut p, ptr::null_mut());
207             if p.is_null() {
208                 None
209             } else {
210                 Some(BigNumRef::from_ptr(p as *mut _))
211             }
212         }
213     }
214 
215     /// Returns a reference to the second factor of the exponent of the key.
216     ///
217     /// This corresponds to [`RSA_get0_factors`].
218     ///
219     /// [`RSA_get0_factors`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
q(&self) -> Option<&BigNumRef>220     pub fn q(&self) -> Option<&BigNumRef> {
221         unsafe {
222             let mut q = ptr::null();
223             RSA_get0_factors(self.as_ptr(), ptr::null_mut(), &mut q);
224             if q.is_null() {
225                 None
226             } else {
227                 Some(BigNumRef::from_ptr(q as *mut _))
228             }
229         }
230     }
231 
232     /// Returns a reference to the first exponent used for CRT calculations.
233     ///
234     /// This corresponds to [`RSA_get0_crt_params`].
235     ///
236     /// [`RSA_get0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
dmp1(&self) -> Option<&BigNumRef>237     pub fn dmp1(&self) -> Option<&BigNumRef> {
238         unsafe {
239             let mut dp = ptr::null();
240             RSA_get0_crt_params(self.as_ptr(), &mut dp, ptr::null_mut(), ptr::null_mut());
241             if dp.is_null() {
242                 None
243             } else {
244                 Some(BigNumRef::from_ptr(dp as *mut _))
245             }
246         }
247     }
248 
249     /// Returns a reference to the second exponent used for CRT calculations.
250     ///
251     /// This corresponds to [`RSA_get0_crt_params`].
252     ///
253     /// [`RSA_get0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
dmq1(&self) -> Option<&BigNumRef>254     pub fn dmq1(&self) -> Option<&BigNumRef> {
255         unsafe {
256             let mut dq = ptr::null();
257             RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), &mut dq, ptr::null_mut());
258             if dq.is_null() {
259                 None
260             } else {
261                 Some(BigNumRef::from_ptr(dq as *mut _))
262             }
263         }
264     }
265 
266     /// Returns a reference to the coefficient used for CRT calculations.
267     ///
268     /// This corresponds to [`RSA_get0_crt_params`].
269     ///
270     /// [`RSA_get0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
iqmp(&self) -> Option<&BigNumRef>271     pub fn iqmp(&self) -> Option<&BigNumRef> {
272         unsafe {
273             let mut qi = ptr::null();
274             RSA_get0_crt_params(self.as_ptr(), ptr::null_mut(), ptr::null_mut(), &mut qi);
275             if qi.is_null() {
276                 None
277             } else {
278                 Some(BigNumRef::from_ptr(qi as *mut _))
279             }
280         }
281     }
282 
283     /// Validates RSA parameters for correctness
284     ///
285     /// This corresponds to [`RSA_check_key`].
286     ///
287     /// [`RSA_check_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_check_key.html
check_key(&self) -> Result<bool, ErrorStack>288     pub fn check_key(&self) -> Result<bool, ErrorStack> {
289         unsafe {
290             let result = ffi::RSA_check_key(self.as_ptr()) as i32;
291             if result == -1 {
292                 Err(ErrorStack::get())
293             } else {
294                 Ok(result == 1)
295             }
296         }
297     }
298 }
299 
300 impl<T> RsaRef<T>
301 where
302     T: HasPublic,
303 {
304     to_pem! {
305         /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
306         ///
307         /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
308         ///
309         /// This corresponds to [`PEM_write_bio_RSA_PUBKEY`].
310         ///
311         /// [`PEM_write_bio_RSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/pem.html
312         public_key_to_pem,
313         ffi::PEM_write_bio_RSA_PUBKEY
314     }
315 
316     to_der! {
317         /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
318         ///
319         /// This corresponds to [`i2d_RSA_PUBKEY`].
320         ///
321         /// [`i2d_RSA_PUBKEY`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_RSA_PUBKEY.html
322         public_key_to_der,
323         ffi::i2d_RSA_PUBKEY
324     }
325 
326     to_pem! {
327         /// Serializes the public key into a PEM-encoded PKCS#1 RSAPublicKey structure.
328         ///
329         /// The output will have a header of `-----BEGIN RSA PUBLIC KEY-----`.
330         ///
331         /// This corresponds to [`PEM_write_bio_RSAPublicKey`].
332         ///
333         /// [`PEM_write_bio_RSAPublicKey`]: https://www.openssl.org/docs/man1.0.2/crypto/pem.html
334         public_key_to_pem_pkcs1,
335         ffi::PEM_write_bio_RSAPublicKey
336     }
337 
338     to_der! {
339         /// Serializes the public key into a DER-encoded PKCS#1 RSAPublicKey structure.
340         ///
341         /// This corresponds to [`i2d_RSAPublicKey`].
342         ///
343         /// [`i2d_RSAPublicKey`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_RSAPublicKey.html
344         public_key_to_der_pkcs1,
345         ffi::i2d_RSAPublicKey
346     }
347 
348     /// Returns the size of the modulus in bytes.
349     ///
350     /// This corresponds to [`RSA_size`].
351     ///
352     /// [`RSA_size`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_size.html
size(&self) -> u32353     pub fn size(&self) -> u32 {
354         unsafe { ffi::RSA_size(self.as_ptr()) as u32 }
355     }
356 
357     /// Decrypts data using the public key, returning the number of decrypted bytes.
358     ///
359     /// # Panics
360     ///
361     /// Panics if `to` is smaller than `self.size()`.
public_decrypt( &self, from: &[u8], to: &mut [u8], padding: Padding, ) -> Result<usize, ErrorStack>362     pub fn public_decrypt(
363         &self,
364         from: &[u8],
365         to: &mut [u8],
366         padding: Padding,
367     ) -> Result<usize, ErrorStack> {
368         assert!(from.len() <= i32::max_value() as usize);
369         assert!(to.len() >= self.size() as usize);
370 
371         unsafe {
372             let len = cvt_n(ffi::RSA_public_decrypt(
373                 from.len() as c_int,
374                 from.as_ptr(),
375                 to.as_mut_ptr(),
376                 self.as_ptr(),
377                 padding.0,
378             ))?;
379             Ok(len as usize)
380         }
381     }
382 
383     /// Encrypts data using the public key, returning the number of encrypted bytes.
384     ///
385     /// # Panics
386     ///
387     /// Panics if `to` is smaller than `self.size()`.
public_encrypt( &self, from: &[u8], to: &mut [u8], padding: Padding, ) -> Result<usize, ErrorStack>388     pub fn public_encrypt(
389         &self,
390         from: &[u8],
391         to: &mut [u8],
392         padding: Padding,
393     ) -> Result<usize, ErrorStack> {
394         assert!(from.len() <= i32::max_value() as usize);
395         assert!(to.len() >= self.size() as usize);
396 
397         unsafe {
398             let len = cvt_n(ffi::RSA_public_encrypt(
399                 from.len() as c_int,
400                 from.as_ptr(),
401                 to.as_mut_ptr(),
402                 self.as_ptr(),
403                 padding.0,
404             ))?;
405             Ok(len as usize)
406         }
407     }
408 
409     /// Returns a reference to the modulus of the key.
410     ///
411     /// This corresponds to [`RSA_get0_key`].
412     ///
413     /// [`RSA_get0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
n(&self) -> &BigNumRef414     pub fn n(&self) -> &BigNumRef {
415         unsafe {
416             let mut n = ptr::null();
417             RSA_get0_key(self.as_ptr(), &mut n, ptr::null_mut(), ptr::null_mut());
418             BigNumRef::from_ptr(n as *mut _)
419         }
420     }
421 
422     /// Returns a reference to the public exponent of the key.
423     ///
424     /// This corresponds to [`RSA_get0_key`].
425     ///
426     /// [`RSA_get0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_get0_key.html
e(&self) -> &BigNumRef427     pub fn e(&self) -> &BigNumRef {
428         unsafe {
429             let mut e = ptr::null();
430             RSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut e, ptr::null_mut());
431             BigNumRef::from_ptr(e as *mut _)
432         }
433     }
434 }
435 
436 impl Rsa<Public> {
437     /// Creates a new RSA key with only public components.
438     ///
439     /// `n` is the modulus common to both public and private key.
440     /// `e` is the public exponent.
441     ///
442     /// This corresponds to [`RSA_new`] and uses [`RSA_set0_key`].
443     ///
444     /// [`RSA_new`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_new.html
445     /// [`RSA_set0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_key.html
from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack>446     pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
447         unsafe {
448             let rsa = cvt_p(ffi::RSA_new())?;
449             RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), ptr::null_mut());
450             mem::forget((n, e));
451             Ok(Rsa::from_ptr(rsa))
452         }
453     }
454 
455     from_pem! {
456         /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing an RSA key.
457         ///
458         /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
459         ///
460         /// This corresponds to [`PEM_read_bio_RSA_PUBKEY`].
461         ///
462         /// [`PEM_read_bio_RSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_RSA_PUBKEY.html
463         public_key_from_pem,
464         Rsa<Public>,
465         ffi::PEM_read_bio_RSA_PUBKEY
466     }
467 
468     from_pem! {
469         /// Decodes a PEM-encoded PKCS#1 RSAPublicKey structure.
470         ///
471         /// The input should have a header of `-----BEGIN RSA PUBLIC KEY-----`.
472         ///
473         /// This corresponds to [`PEM_read_bio_RSAPublicKey`].
474         ///
475         /// [`PEM_read_bio_RSAPublicKey`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_RSAPublicKey.html
476         public_key_from_pem_pkcs1,
477         Rsa<Public>,
478         ffi::PEM_read_bio_RSAPublicKey
479     }
480 
481     from_der! {
482         /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing an RSA key.
483         ///
484         /// This corresponds to [`d2i_RSA_PUBKEY`].
485         ///
486         /// [`d2i_RSA_PUBKEY`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_RSA_PUBKEY.html
487         public_key_from_der,
488         Rsa<Public>,
489         ffi::d2i_RSA_PUBKEY
490     }
491 
492     from_der! {
493         /// Decodes a DER-encoded PKCS#1 RSAPublicKey structure.
494         ///
495         /// This corresponds to [`d2i_RSAPublicKey`].
496         ///
497         /// [`d2i_RSAPublicKey`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_RSA_PUBKEY.html
498         public_key_from_der_pkcs1,
499         Rsa<Public>,
500         ffi::d2i_RSAPublicKey
501     }
502 }
503 
504 pub struct RsaPrivateKeyBuilder {
505     rsa: Rsa<Private>,
506 }
507 
508 impl RsaPrivateKeyBuilder {
509     /// Creates a new `RsaPrivateKeyBuilder`.
510     ///
511     /// `n` is the modulus common to both public and private key.
512     /// `e` is the public exponent and `d` is the private exponent.
513     ///
514     /// This corresponds to [`RSA_new`] and uses [`RSA_set0_key`].
515     ///
516     /// [`RSA_new`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_new.html
517     /// [`RSA_set0_key`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_key.html
new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack>518     pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
519         unsafe {
520             let rsa = cvt_p(ffi::RSA_new())?;
521             RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), d.as_ptr());
522             mem::forget((n, e, d));
523             Ok(RsaPrivateKeyBuilder {
524                 rsa: Rsa::from_ptr(rsa),
525             })
526         }
527     }
528 
529     /// Sets the factors of the Rsa key.
530     ///
531     /// `p` and `q` are the first and second factors of `n`.
532     ///
533     /// This correspond to [`RSA_set0_factors`].
534     ///
535     /// [`RSA_set0_factors`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_factors.html
536     // FIXME should be infallible
set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack>537     pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
538         unsafe {
539             RSA_set0_factors(self.rsa.as_ptr(), p.as_ptr(), q.as_ptr());
540             mem::forget((p, q));
541         }
542         Ok(self)
543     }
544 
545     /// Sets the Chinese Remainder Theorem params of the Rsa key.
546     ///
547     /// `dmp1`, `dmq1`, and `iqmp` are the exponents and coefficient for
548     /// CRT calculations which is used to speed up RSA operations.
549     ///
550     /// This correspond to [`RSA_set0_crt_params`].
551     ///
552     /// [`RSA_set0_crt_params`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_set0_crt_params.html
553     // FIXME should be infallible
set_crt_params( self, dmp1: BigNum, dmq1: BigNum, iqmp: BigNum, ) -> Result<RsaPrivateKeyBuilder, ErrorStack>554     pub fn set_crt_params(
555         self,
556         dmp1: BigNum,
557         dmq1: BigNum,
558         iqmp: BigNum,
559     ) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
560         unsafe {
561             RSA_set0_crt_params(
562                 self.rsa.as_ptr(),
563                 dmp1.as_ptr(),
564                 dmq1.as_ptr(),
565                 iqmp.as_ptr(),
566             );
567             mem::forget((dmp1, dmq1, iqmp));
568         }
569         Ok(self)
570     }
571 
572     /// Returns the Rsa key.
build(self) -> Rsa<Private>573     pub fn build(self) -> Rsa<Private> {
574         self.rsa
575     }
576 }
577 
578 impl Rsa<Private> {
579     /// Creates a new RSA key with private components (public components are assumed).
580     ///
581     /// This a convenience method over
582     /// `Rsa::build(n, e, d)?.set_factors(p, q)?.set_crt_params(dmp1, dmq1, iqmp)?.build()`
583     #[allow(clippy::too_many_arguments, clippy::many_single_char_names)]
from_private_components( n: BigNum, e: BigNum, d: BigNum, p: BigNum, q: BigNum, dmp1: BigNum, dmq1: BigNum, iqmp: BigNum, ) -> Result<Rsa<Private>, ErrorStack>584     pub fn from_private_components(
585         n: BigNum,
586         e: BigNum,
587         d: BigNum,
588         p: BigNum,
589         q: BigNum,
590         dmp1: BigNum,
591         dmq1: BigNum,
592         iqmp: BigNum,
593     ) -> Result<Rsa<Private>, ErrorStack> {
594         Ok(RsaPrivateKeyBuilder::new(n, e, d)?
595             .set_factors(p, q)?
596             .set_crt_params(dmp1, dmq1, iqmp)?
597             .build())
598     }
599 
600     /// Generates a public/private key pair with the specified size.
601     ///
602     /// The public exponent will be 65537.
603     ///
604     /// This corresponds to [`RSA_generate_key_ex`].
605     ///
606     /// [`RSA_generate_key_ex`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_generate_key_ex.html
generate(bits: u32) -> Result<Rsa<Private>, ErrorStack>607     pub fn generate(bits: u32) -> Result<Rsa<Private>, ErrorStack> {
608         let e = BigNum::from_u32(ffi::RSA_F4 as u32)?;
609         Rsa::generate_with_e(bits, &e)
610     }
611 
612     /// Generates a public/private key pair with the specified size and a custom exponent.
613     ///
614     /// Unless you have specific needs and know what you're doing, use `Rsa::generate` instead.
615     ///
616     /// This corresponds to [`RSA_generate_key_ex`].
617     ///
618     /// [`RSA_generate_key_ex`]: https://www.openssl.org/docs/man1.1.0/crypto/RSA_generate_key_ex.html
generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack>619     pub fn generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack> {
620         unsafe {
621             let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?);
622             cvt(ffi::RSA_generate_key_ex(
623                 rsa.0,
624                 bits as c_int,
625                 e.as_ptr(),
626                 ptr::null_mut(),
627             ))?;
628             Ok(rsa)
629         }
630     }
631 
632     // FIXME these need to identify input formats
633     private_key_from_pem! {
634         /// Deserializes a private key from a PEM-encoded PKCS#1 RSAPrivateKey structure.
635         ///
636         /// This corresponds to [`PEM_read_bio_RSAPrivateKey`].
637         ///
638         /// [`PEM_read_bio_RSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_RSAPrivateKey.html
639         private_key_from_pem,
640 
641         /// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
642         ///
643         /// This corresponds to [`PEM_read_bio_RSAPrivateKey`].
644         ///
645         /// [`PEM_read_bio_RSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_RSAPrivateKey.html
646         private_key_from_pem_passphrase,
647 
648         /// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
649         ///
650         /// The callback should fill the password into the provided buffer and return its length.
651         ///
652         /// This corresponds to [`PEM_read_bio_RSAPrivateKey`].
653         ///
654         /// [`PEM_read_bio_RSAPrivateKey`]: https://www.openssl.org/docs/man1.1.0/crypto/PEM_read_bio_RSAPrivateKey.html
655         private_key_from_pem_callback,
656         Rsa<Private>,
657         ffi::PEM_read_bio_RSAPrivateKey
658     }
659 
660     from_der! {
661         /// Decodes a DER-encoded PKCS#1 RSAPrivateKey structure.
662         ///
663         /// This corresponds to [`d2i_RSAPrivateKey`].
664         ///
665         /// [`d2i_RSAPrivateKey`]: https://www.openssl.org/docs/man1.0.2/crypto/d2i_RSA_PUBKEY.html
666         private_key_from_der,
667         Rsa<Private>,
668         ffi::d2i_RSAPrivateKey
669     }
670 }
671 
672 impl<T> fmt::Debug for Rsa<T> {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result673     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
674         write!(f, "Rsa")
675     }
676 }
677 
678 cfg_if! {
679     if #[cfg(any(ossl110, libressl273))] {
680         use ffi::{
681             RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_set0_key, RSA_set0_factors,
682             RSA_set0_crt_params,
683         };
684     } else {
685         #[allow(bad_style)]
686         unsafe fn RSA_get0_key(
687             r: *const ffi::RSA,
688             n: *mut *const ffi::BIGNUM,
689             e: *mut *const ffi::BIGNUM,
690             d: *mut *const ffi::BIGNUM,
691         ) {
692             if !n.is_null() {
693                 *n = (*r).n;
694             }
695             if !e.is_null() {
696                 *e = (*r).e;
697             }
698             if !d.is_null() {
699                 *d = (*r).d;
700             }
701         }
702 
703         #[allow(bad_style)]
704         unsafe fn RSA_get0_factors(
705             r: *const ffi::RSA,
706             p: *mut *const ffi::BIGNUM,
707             q: *mut *const ffi::BIGNUM,
708         ) {
709             if !p.is_null() {
710                 *p = (*r).p;
711             }
712             if !q.is_null() {
713                 *q = (*r).q;
714             }
715         }
716 
717         #[allow(bad_style)]
718         unsafe fn RSA_get0_crt_params(
719             r: *const ffi::RSA,
720             dmp1: *mut *const ffi::BIGNUM,
721             dmq1: *mut *const ffi::BIGNUM,
722             iqmp: *mut *const ffi::BIGNUM,
723         ) {
724             if !dmp1.is_null() {
725                 *dmp1 = (*r).dmp1;
726             }
727             if !dmq1.is_null() {
728                 *dmq1 = (*r).dmq1;
729             }
730             if !iqmp.is_null() {
731                 *iqmp = (*r).iqmp;
732             }
733         }
734 
735         #[allow(bad_style)]
736         unsafe fn RSA_set0_key(
737             r: *mut ffi::RSA,
738             n: *mut ffi::BIGNUM,
739             e: *mut ffi::BIGNUM,
740             d: *mut ffi::BIGNUM,
741         ) -> c_int {
742             (*r).n = n;
743             (*r).e = e;
744             (*r).d = d;
745             1
746         }
747 
748         #[allow(bad_style)]
749         unsafe fn RSA_set0_factors(
750             r: *mut ffi::RSA,
751             p: *mut ffi::BIGNUM,
752             q: *mut ffi::BIGNUM,
753         ) -> c_int {
754             (*r).p = p;
755             (*r).q = q;
756             1
757         }
758 
759         #[allow(bad_style)]
760         unsafe fn RSA_set0_crt_params(
761             r: *mut ffi::RSA,
762             dmp1: *mut ffi::BIGNUM,
763             dmq1: *mut ffi::BIGNUM,
764             iqmp: *mut ffi::BIGNUM,
765         ) -> c_int {
766             (*r).dmp1 = dmp1;
767             (*r).dmq1 = dmq1;
768             (*r).iqmp = iqmp;
769             1
770         }
771     }
772 }
773 
774 #[cfg(test)]
775 mod test {
776     use symm::Cipher;
777 
778     use super::*;
779 
780     #[test]
test_from_password()781     fn test_from_password() {
782         let key = include_bytes!("../test/rsa-encrypted.pem");
783         Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
784     }
785 
786     #[test]
test_from_password_callback()787     fn test_from_password_callback() {
788         let mut password_queried = false;
789         let key = include_bytes!("../test/rsa-encrypted.pem");
790         Rsa::private_key_from_pem_callback(key, |password| {
791             password_queried = true;
792             password[..6].copy_from_slice(b"mypass");
793             Ok(6)
794         })
795         .unwrap();
796 
797         assert!(password_queried);
798     }
799 
800     #[test]
test_to_password()801     fn test_to_password() {
802         let key = Rsa::generate(2048).unwrap();
803         let pem = key
804             .private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
805             .unwrap();
806         Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
807         assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
808     }
809 
810     #[test]
test_public_encrypt_private_decrypt_with_padding()811     fn test_public_encrypt_private_decrypt_with_padding() {
812         let key = include_bytes!("../test/rsa.pem.pub");
813         let public_key = Rsa::public_key_from_pem(key).unwrap();
814 
815         let mut result = vec![0; public_key.size() as usize];
816         let original_data = b"This is test";
817         let len = public_key
818             .public_encrypt(original_data, &mut result, Padding::PKCS1)
819             .unwrap();
820         assert_eq!(len, 256);
821 
822         let pkey = include_bytes!("../test/rsa.pem");
823         let private_key = Rsa::private_key_from_pem(pkey).unwrap();
824         let mut dec_result = vec![0; private_key.size() as usize];
825         let len = private_key
826             .private_decrypt(&result, &mut dec_result, Padding::PKCS1)
827             .unwrap();
828 
829         assert_eq!(&dec_result[..len], original_data);
830     }
831 
832     #[test]
test_private_encrypt()833     fn test_private_encrypt() {
834         let k0 = super::Rsa::generate(512).unwrap();
835         let k0pkey = k0.public_key_to_pem().unwrap();
836         let k1 = super::Rsa::public_key_from_pem(&k0pkey).unwrap();
837 
838         let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
839 
840         let mut emesg = vec![0; k0.size() as usize];
841         k0.private_encrypt(&msg, &mut emesg, Padding::PKCS1)
842             .unwrap();
843         let mut dmesg = vec![0; k1.size() as usize];
844         let len = k1
845             .public_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
846             .unwrap();
847         assert_eq!(msg, &dmesg[..len]);
848     }
849 
850     #[test]
test_public_encrypt()851     fn test_public_encrypt() {
852         let k0 = super::Rsa::generate(512).unwrap();
853         let k0pkey = k0.private_key_to_pem().unwrap();
854         let k1 = super::Rsa::private_key_from_pem(&k0pkey).unwrap();
855 
856         let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
857 
858         let mut emesg = vec![0; k0.size() as usize];
859         k0.public_encrypt(&msg, &mut emesg, Padding::PKCS1).unwrap();
860         let mut dmesg = vec![0; k1.size() as usize];
861         let len = k1
862             .private_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
863             .unwrap();
864         assert_eq!(msg, &dmesg[..len]);
865     }
866 
867     #[test]
test_public_key_from_pem_pkcs1()868     fn test_public_key_from_pem_pkcs1() {
869         let key = include_bytes!("../test/pkcs1.pem.pub");
870         Rsa::public_key_from_pem_pkcs1(key).unwrap();
871     }
872 
873     #[test]
874     #[should_panic]
test_public_key_from_pem_pkcs1_file_panic()875     fn test_public_key_from_pem_pkcs1_file_panic() {
876         let key = include_bytes!("../test/key.pem.pub");
877         Rsa::public_key_from_pem_pkcs1(key).unwrap();
878     }
879 
880     #[test]
test_public_key_to_pem_pkcs1()881     fn test_public_key_to_pem_pkcs1() {
882         let keypair = super::Rsa::generate(512).unwrap();
883         let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
884         super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
885     }
886 
887     #[test]
888     #[should_panic]
test_public_key_from_pem_pkcs1_generate_panic()889     fn test_public_key_from_pem_pkcs1_generate_panic() {
890         let keypair = super::Rsa::generate(512).unwrap();
891         let pubkey_pem = keypair.public_key_to_pem().unwrap();
892         super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
893     }
894 
895     #[test]
test_pem_pkcs1_encrypt()896     fn test_pem_pkcs1_encrypt() {
897         let keypair = super::Rsa::generate(2048).unwrap();
898         let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
899         let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
900         let msg = b"Hello, world!";
901 
902         let mut encrypted = vec![0; pubkey.size() as usize];
903         let len = pubkey
904             .public_encrypt(msg, &mut encrypted, Padding::PKCS1)
905             .unwrap();
906         assert!(len > msg.len());
907         let mut decrypted = vec![0; keypair.size() as usize];
908         let len = keypair
909             .private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1)
910             .unwrap();
911         assert_eq!(len, msg.len());
912         assert_eq!(&decrypted[..len], msg);
913     }
914 
915     #[test]
test_pem_pkcs1_padding()916     fn test_pem_pkcs1_padding() {
917         let keypair = super::Rsa::generate(2048).unwrap();
918         let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
919         let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
920         let msg = b"foo";
921 
922         let mut encrypted1 = vec![0; pubkey.size() as usize];
923         let mut encrypted2 = vec![0; pubkey.size() as usize];
924         let len1 = pubkey
925             .public_encrypt(msg, &mut encrypted1, Padding::PKCS1)
926             .unwrap();
927         let len2 = pubkey
928             .public_encrypt(msg, &mut encrypted2, Padding::PKCS1)
929             .unwrap();
930         assert!(len1 > (msg.len() + 1));
931         assert_eq!(len1, len2);
932         assert_ne!(encrypted1, encrypted2);
933     }
934 
935     #[test]
936     #[allow(clippy::redundant_clone)]
clone()937     fn clone() {
938         let key = Rsa::generate(2048).unwrap();
939         drop(key.clone());
940     }
941 
942     #[test]
generate_with_e()943     fn generate_with_e() {
944         let e = BigNum::from_u32(0x10001).unwrap();
945         Rsa::generate_with_e(2048, &e).unwrap();
946     }
947 }
948