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