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