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//! ```
26use cfg_if::cfg_if;
27use foreign_types::{ForeignType, ForeignTypeRef};
28use libc::c_int;
29use std::fmt;
30use std::mem;
31use std::ptr;
32
33use crate::bn::{BigNum, BigNumRef};
34use crate::error::ErrorStack;
35use crate::pkey::{HasPrivate, HasPublic, Private, Public};
36use crate::util::ForeignTypeRefExt;
37use crate::{cvt, cvt_n, cvt_p, LenType};
38use 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)]
46pub struct Padding(c_int);
47
48impl 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.
55    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)]
61    pub fn as_raw(&self) -> c_int {
62        self.0
63    }
64}
65
66generic_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
77impl<T> Clone for Rsa<T> {
78    fn clone(&self) -> Rsa<T> {
79        (**self).to_owned()
80    }
81}
82
83impl<T> ToOwned for RsaRef<T> {
84    type Owned = Rsa<T>;
85
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
94impl<T> RsaRef<T>
95where
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)]
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)]
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)]
177    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)]
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)]
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)]
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)]
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)]
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)]
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
250impl<T> RsaRef<T>
251where
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)]
288    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)]
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)]
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)]
348    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)]
358    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
367impl 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
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
423pub struct RsaPrivateKeyBuilder {
424    rsa: Rsa<Private>,
425}
426
427impl 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
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
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
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.
486    pub fn build(self) -> Rsa<Private> {
487        self.rsa
488    }
489}
490
491impl 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)]
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)]
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)]
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
577impl<T> fmt::Debug for Rsa<T> {
578    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
579        write!(f, "Rsa")
580    }
581}
582
583cfg_if! {
584    if #[cfg(any(ossl110, libressl273, boringssl))] {
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)]
680mod test {
681    use crate::symm::Cipher;
682
683    use super::*;
684
685    #[test]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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]
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)]
842    fn clone() {
843        let key = Rsa::generate(2048).unwrap();
844        drop(key.clone());
845    }
846
847    #[test]
848    fn generate_with_e() {
849        let e = BigNum::from_u32(0x10001).unwrap();
850        Rsa::generate_with_e(2048, &e).unwrap();
851    }
852}
853