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