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