openssl/
rsa.rs

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 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 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    pub fn check_key(&self) -> Result<bool, ErrorStack> {
238        unsafe {
239            let result = ffi::RSA_check_key(self.as_ptr());
240            if result != 1 {
241                let errors = ErrorStack::get();
242                if errors.errors().is_empty() {
243                    Ok(false)
244                } else {
245                    Err(errors)
246                }
247            } else {
248                Ok(true)
249            }
250        }
251    }
252}
253
254impl<T> RsaRef<T>
255where
256    T: HasPublic,
257{
258    to_pem! {
259        /// Serializes the public key into a PEM-encoded SubjectPublicKeyInfo structure.
260        ///
261        /// The output will have a header of `-----BEGIN PUBLIC KEY-----`.
262        #[corresponds(PEM_write_bio_RSA_PUBKEY)]
263        public_key_to_pem,
264        ffi::PEM_write_bio_RSA_PUBKEY
265    }
266
267    to_der! {
268        /// Serializes the public key into a DER-encoded SubjectPublicKeyInfo structure.
269        #[corresponds(i2d_RSA_PUBKEY)]
270        public_key_to_der,
271        ffi::i2d_RSA_PUBKEY
272    }
273
274    to_pem! {
275        /// Serializes the public key into a PEM-encoded PKCS#1 RSAPublicKey structure.
276        ///
277        /// The output will have a header of `-----BEGIN RSA PUBLIC KEY-----`.
278        #[corresponds(PEM_write_bio_RSAPublicKey)]
279        public_key_to_pem_pkcs1,
280        ffi::PEM_write_bio_RSAPublicKey
281    }
282
283    to_der! {
284        /// Serializes the public key into a DER-encoded PKCS#1 RSAPublicKey structure.
285        #[corresponds(i2d_RSAPublicKey)]
286        public_key_to_der_pkcs1,
287        ffi::i2d_RSAPublicKey
288    }
289
290    /// Returns the size of the modulus in bytes.
291    #[corresponds(RSA_size)]
292    pub fn size(&self) -> u32 {
293        unsafe { ffi::RSA_size(self.as_ptr()) as u32 }
294    }
295
296    /// Decrypts data using the public key, returning the number of decrypted bytes.
297    ///
298    /// # Panics
299    ///
300    /// Panics if `to` is smaller than `self.size()`.
301    #[corresponds(RSA_public_decrypt)]
302    pub fn public_decrypt(
303        &self,
304        from: &[u8],
305        to: &mut [u8],
306        padding: Padding,
307    ) -> Result<usize, ErrorStack> {
308        assert!(from.len() <= i32::MAX as usize);
309        assert!(to.len() >= self.size() as usize);
310
311        unsafe {
312            let len = cvt_n(ffi::RSA_public_decrypt(
313                from.len() as LenType,
314                from.as_ptr(),
315                to.as_mut_ptr(),
316                self.as_ptr(),
317                padding.0,
318            ))?;
319            Ok(len as usize)
320        }
321    }
322
323    /// Encrypts data using the public key, returning the number of encrypted bytes.
324    ///
325    /// # Panics
326    ///
327    /// Panics if `to` is smaller than `self.size()`.
328    #[corresponds(RSA_public_encrypt)]
329    pub fn public_encrypt(
330        &self,
331        from: &[u8],
332        to: &mut [u8],
333        padding: Padding,
334    ) -> Result<usize, ErrorStack> {
335        assert!(from.len() <= i32::MAX as usize);
336        assert!(to.len() >= self.size() as usize);
337
338        unsafe {
339            let len = cvt_n(ffi::RSA_public_encrypt(
340                from.len() as LenType,
341                from.as_ptr(),
342                to.as_mut_ptr(),
343                self.as_ptr(),
344                padding.0,
345            ))?;
346            Ok(len as usize)
347        }
348    }
349
350    /// Returns a reference to the modulus of the key.
351    #[corresponds(RSA_get0_key)]
352    pub fn n(&self) -> &BigNumRef {
353        unsafe {
354            let mut n = ptr::null();
355            RSA_get0_key(self.as_ptr(), &mut n, ptr::null_mut(), ptr::null_mut());
356            BigNumRef::from_const_ptr(n)
357        }
358    }
359
360    /// Returns a reference to the public exponent of the key.
361    #[corresponds(RSA_get0_key)]
362    pub fn e(&self) -> &BigNumRef {
363        unsafe {
364            let mut e = ptr::null();
365            RSA_get0_key(self.as_ptr(), ptr::null_mut(), &mut e, ptr::null_mut());
366            BigNumRef::from_const_ptr(e)
367        }
368    }
369}
370
371impl Rsa<Public> {
372    /// Creates a new RSA key with only public components.
373    ///
374    /// `n` is the modulus common to both public and private key.
375    /// `e` is the public exponent.
376    ///
377    /// This corresponds to [`RSA_new`] and uses [`RSA_set0_key`].
378    ///
379    /// [`RSA_new`]: https://www.openssl.org/docs/manmaster/crypto/RSA_new.html
380    /// [`RSA_set0_key`]: https://www.openssl.org/docs/manmaster/crypto/RSA_set0_key.html
381    pub fn from_public_components(n: BigNum, e: BigNum) -> Result<Rsa<Public>, ErrorStack> {
382        unsafe {
383            let rsa = cvt_p(ffi::RSA_new())?;
384            RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), ptr::null_mut());
385            mem::forget((n, e));
386            Ok(Rsa::from_ptr(rsa))
387        }
388    }
389
390    from_pem! {
391        /// Decodes a PEM-encoded SubjectPublicKeyInfo structure containing an RSA key.
392        ///
393        /// The input should have a header of `-----BEGIN PUBLIC KEY-----`.
394        #[corresponds(PEM_read_bio_RSA_PUBKEY)]
395        public_key_from_pem,
396        Rsa<Public>,
397        ffi::PEM_read_bio_RSA_PUBKEY
398    }
399
400    from_pem! {
401        /// Decodes a PEM-encoded PKCS#1 RSAPublicKey structure.
402        ///
403        /// The input should have a header of `-----BEGIN RSA PUBLIC KEY-----`.
404        #[corresponds(PEM_read_bio_RSAPublicKey)]
405        public_key_from_pem_pkcs1,
406        Rsa<Public>,
407        ffi::PEM_read_bio_RSAPublicKey
408    }
409
410    from_der! {
411        /// Decodes a DER-encoded SubjectPublicKeyInfo structure containing an RSA key.
412        #[corresponds(d2i_RSA_PUBKEY)]
413        public_key_from_der,
414        Rsa<Public>,
415        ffi::d2i_RSA_PUBKEY
416    }
417
418    from_der! {
419        /// Decodes a DER-encoded PKCS#1 RSAPublicKey structure.
420        #[corresponds(d2i_RSAPublicKey)]
421        public_key_from_der_pkcs1,
422        Rsa<Public>,
423        ffi::d2i_RSAPublicKey
424    }
425}
426
427pub struct RsaPrivateKeyBuilder {
428    rsa: Rsa<Private>,
429}
430
431impl RsaPrivateKeyBuilder {
432    /// Creates a new `RsaPrivateKeyBuilder`.
433    ///
434    /// `n` is the modulus common to both public and private key.
435    /// `e` is the public exponent and `d` is the private exponent.
436    ///
437    /// This corresponds to [`RSA_new`] and uses [`RSA_set0_key`].
438    ///
439    /// [`RSA_new`]: https://www.openssl.org/docs/manmaster/crypto/RSA_new.html
440    /// [`RSA_set0_key`]: https://www.openssl.org/docs/manmaster/crypto/RSA_set0_key.html
441    pub fn new(n: BigNum, e: BigNum, d: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
442        unsafe {
443            let rsa = cvt_p(ffi::RSA_new())?;
444            RSA_set0_key(rsa, n.as_ptr(), e.as_ptr(), d.as_ptr());
445            mem::forget((n, e, d));
446            Ok(RsaPrivateKeyBuilder {
447                rsa: Rsa::from_ptr(rsa),
448            })
449        }
450    }
451
452    /// Sets the factors of the Rsa key.
453    ///
454    /// `p` and `q` are the first and second factors of `n`.
455    #[corresponds(RSA_set0_factors)]
456    // FIXME should be infallible
457    pub fn set_factors(self, p: BigNum, q: BigNum) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
458        unsafe {
459            RSA_set0_factors(self.rsa.as_ptr(), p.as_ptr(), q.as_ptr());
460            mem::forget((p, q));
461        }
462        Ok(self)
463    }
464
465    /// Sets the Chinese Remainder Theorem params of the Rsa key.
466    ///
467    /// `dmp1`, `dmq1`, and `iqmp` are the exponents and coefficient for
468    /// CRT calculations which is used to speed up RSA operations.
469    #[corresponds(RSA_set0_crt_params)]
470    // FIXME should be infallible
471    pub fn set_crt_params(
472        self,
473        dmp1: BigNum,
474        dmq1: BigNum,
475        iqmp: BigNum,
476    ) -> Result<RsaPrivateKeyBuilder, ErrorStack> {
477        unsafe {
478            RSA_set0_crt_params(
479                self.rsa.as_ptr(),
480                dmp1.as_ptr(),
481                dmq1.as_ptr(),
482                iqmp.as_ptr(),
483            );
484            mem::forget((dmp1, dmq1, iqmp));
485        }
486        Ok(self)
487    }
488
489    /// Returns the Rsa key.
490    pub fn build(self) -> Rsa<Private> {
491        self.rsa
492    }
493}
494
495impl Rsa<Private> {
496    /// Creates a new RSA key with private components (public components are assumed).
497    ///
498    /// This a convenience method over:
499    /// ```
500    /// # use openssl::rsa::RsaPrivateKeyBuilder;
501    /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
502    /// # let bn = || openssl::bn::BigNum::new().unwrap();
503    /// # let (n, e, d, p, q, dmp1, dmq1, iqmp) = (bn(), bn(), bn(), bn(), bn(), bn(), bn(), bn());
504    /// RsaPrivateKeyBuilder::new(n, e, d)?
505    ///     .set_factors(p, q)?
506    ///     .set_crt_params(dmp1, dmq1, iqmp)?
507    ///     .build();
508    /// # Ok(()) }
509    /// ```
510    #[allow(clippy::too_many_arguments, clippy::many_single_char_names)]
511    pub fn from_private_components(
512        n: BigNum,
513        e: BigNum,
514        d: BigNum,
515        p: BigNum,
516        q: BigNum,
517        dmp1: BigNum,
518        dmq1: BigNum,
519        iqmp: BigNum,
520    ) -> Result<Rsa<Private>, ErrorStack> {
521        Ok(RsaPrivateKeyBuilder::new(n, e, d)?
522            .set_factors(p, q)?
523            .set_crt_params(dmp1, dmq1, iqmp)?
524            .build())
525    }
526
527    /// Generates a public/private key pair with the specified size.
528    ///
529    /// The public exponent will be 65537.
530    #[corresponds(RSA_generate_key_ex)]
531    pub fn generate(bits: u32) -> Result<Rsa<Private>, ErrorStack> {
532        let e = BigNum::from_u32(ffi::RSA_F4 as u32)?;
533        Rsa::generate_with_e(bits, &e)
534    }
535
536    /// Generates a public/private key pair with the specified size and a custom exponent.
537    ///
538    /// Unless you have specific needs and know what you're doing, use `Rsa::generate` instead.
539    #[corresponds(RSA_generate_key_ex)]
540    pub fn generate_with_e(bits: u32, e: &BigNumRef) -> Result<Rsa<Private>, ErrorStack> {
541        unsafe {
542            let rsa = Rsa::from_ptr(cvt_p(ffi::RSA_new())?);
543            cvt(ffi::RSA_generate_key_ex(
544                rsa.0,
545                bits as c_int,
546                e.as_ptr(),
547                ptr::null_mut(),
548            ))?;
549            Ok(rsa)
550        }
551    }
552
553    // FIXME these need to identify input formats
554    private_key_from_pem! {
555        /// Deserializes a private key from a PEM-encoded PKCS#1 RSAPrivateKey structure.
556        #[corresponds(PEM_read_bio_RSAPrivateKey)]
557        private_key_from_pem,
558
559        /// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
560        #[corresponds(PEM_read_bio_RSAPrivateKey)]
561        private_key_from_pem_passphrase,
562
563        /// Deserializes a private key from a PEM-encoded encrypted PKCS#1 RSAPrivateKey structure.
564        ///
565        /// The callback should fill the password into the provided buffer and return its length.
566        #[corresponds(PEM_read_bio_RSAPrivateKey)]
567        private_key_from_pem_callback,
568        Rsa<Private>,
569        ffi::PEM_read_bio_RSAPrivateKey
570    }
571
572    from_der! {
573        /// Decodes a DER-encoded PKCS#1 RSAPrivateKey structure.
574        #[corresponds(d2i_RSAPrivateKey)]
575        private_key_from_der,
576        Rsa<Private>,
577        ffi::d2i_RSAPrivateKey
578    }
579}
580
581impl<T> fmt::Debug for Rsa<T> {
582    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
583        write!(f, "Rsa")
584    }
585}
586
587cfg_if! {
588    if #[cfg(any(ossl110, libressl273, boringssl, awslc))] {
589        use ffi::{
590            RSA_get0_key, RSA_get0_factors, RSA_get0_crt_params, RSA_set0_key, RSA_set0_factors,
591            RSA_set0_crt_params,
592        };
593    } else {
594        #[allow(bad_style)]
595        unsafe fn RSA_get0_key(
596            r: *const ffi::RSA,
597            n: *mut *const ffi::BIGNUM,
598            e: *mut *const ffi::BIGNUM,
599            d: *mut *const ffi::BIGNUM,
600        ) {
601            if !n.is_null() {
602                *n = (*r).n;
603            }
604            if !e.is_null() {
605                *e = (*r).e;
606            }
607            if !d.is_null() {
608                *d = (*r).d;
609            }
610        }
611
612        #[allow(bad_style)]
613        unsafe fn RSA_get0_factors(
614            r: *const ffi::RSA,
615            p: *mut *const ffi::BIGNUM,
616            q: *mut *const ffi::BIGNUM,
617        ) {
618            if !p.is_null() {
619                *p = (*r).p;
620            }
621            if !q.is_null() {
622                *q = (*r).q;
623            }
624        }
625
626        #[allow(bad_style)]
627        unsafe fn RSA_get0_crt_params(
628            r: *const ffi::RSA,
629            dmp1: *mut *const ffi::BIGNUM,
630            dmq1: *mut *const ffi::BIGNUM,
631            iqmp: *mut *const ffi::BIGNUM,
632        ) {
633            if !dmp1.is_null() {
634                *dmp1 = (*r).dmp1;
635            }
636            if !dmq1.is_null() {
637                *dmq1 = (*r).dmq1;
638            }
639            if !iqmp.is_null() {
640                *iqmp = (*r).iqmp;
641            }
642        }
643
644        #[allow(bad_style)]
645        unsafe fn RSA_set0_key(
646            r: *mut ffi::RSA,
647            n: *mut ffi::BIGNUM,
648            e: *mut ffi::BIGNUM,
649            d: *mut ffi::BIGNUM,
650        ) -> c_int {
651            (*r).n = n;
652            (*r).e = e;
653            (*r).d = d;
654            1
655        }
656
657        #[allow(bad_style)]
658        unsafe fn RSA_set0_factors(
659            r: *mut ffi::RSA,
660            p: *mut ffi::BIGNUM,
661            q: *mut ffi::BIGNUM,
662        ) -> c_int {
663            (*r).p = p;
664            (*r).q = q;
665            1
666        }
667
668        #[allow(bad_style)]
669        unsafe fn RSA_set0_crt_params(
670            r: *mut ffi::RSA,
671            dmp1: *mut ffi::BIGNUM,
672            dmq1: *mut ffi::BIGNUM,
673            iqmp: *mut ffi::BIGNUM,
674        ) -> c_int {
675            (*r).dmp1 = dmp1;
676            (*r).dmq1 = dmq1;
677            (*r).iqmp = iqmp;
678            1
679        }
680    }
681}
682
683#[cfg(test)]
684mod test {
685    use crate::symm::Cipher;
686
687    use super::*;
688
689    #[test]
690    fn test_from_password() {
691        let key = include_bytes!("../test/rsa-encrypted.pem");
692        Rsa::private_key_from_pem_passphrase(key, b"mypass").unwrap();
693    }
694
695    #[test]
696    fn test_from_password_callback() {
697        let mut password_queried = false;
698        let key = include_bytes!("../test/rsa-encrypted.pem");
699        Rsa::private_key_from_pem_callback(key, |password| {
700            password_queried = true;
701            password[..6].copy_from_slice(b"mypass");
702            Ok(6)
703        })
704        .unwrap();
705
706        assert!(password_queried);
707    }
708
709    #[test]
710    fn test_to_password() {
711        let key = Rsa::generate(2048).unwrap();
712        let pem = key
713            .private_key_to_pem_passphrase(Cipher::aes_128_cbc(), b"foobar")
714            .unwrap();
715        Rsa::private_key_from_pem_passphrase(&pem, b"foobar").unwrap();
716        assert!(Rsa::private_key_from_pem_passphrase(&pem, b"fizzbuzz").is_err());
717    }
718
719    #[test]
720    fn test_public_encrypt_private_decrypt_with_padding() {
721        let key = include_bytes!("../test/rsa.pem.pub");
722        let public_key = Rsa::public_key_from_pem(key).unwrap();
723
724        let mut result = vec![0; public_key.size() as usize];
725        let original_data = b"This is test";
726        let len = public_key
727            .public_encrypt(original_data, &mut result, Padding::PKCS1)
728            .unwrap();
729        assert_eq!(len, 256);
730
731        let pkey = include_bytes!("../test/rsa.pem");
732        let private_key = Rsa::private_key_from_pem(pkey).unwrap();
733        let mut dec_result = vec![0; private_key.size() as usize];
734        let len = private_key
735            .private_decrypt(&result, &mut dec_result, Padding::PKCS1)
736            .unwrap();
737
738        assert_eq!(&dec_result[..len], original_data);
739    }
740
741    #[test]
742    fn test_private_encrypt() {
743        let k0 = super::Rsa::generate(512).unwrap();
744        let k0pkey = k0.public_key_to_pem().unwrap();
745        let k1 = super::Rsa::public_key_from_pem(&k0pkey).unwrap();
746
747        let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
748
749        let mut emesg = vec![0; k0.size() as usize];
750        k0.private_encrypt(&msg, &mut emesg, Padding::PKCS1)
751            .unwrap();
752        let mut dmesg = vec![0; k1.size() as usize];
753        let len = k1
754            .public_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
755            .unwrap();
756        assert_eq!(msg, &dmesg[..len]);
757    }
758
759    #[test]
760    fn test_public_encrypt() {
761        let k0 = super::Rsa::generate(512).unwrap();
762        let k0pkey = k0.private_key_to_pem().unwrap();
763        let k1 = super::Rsa::private_key_from_pem(&k0pkey).unwrap();
764
765        let msg = vec![0xdeu8, 0xadu8, 0xd0u8, 0x0du8];
766
767        let mut emesg = vec![0; k0.size() as usize];
768        k0.public_encrypt(&msg, &mut emesg, Padding::PKCS1).unwrap();
769        let mut dmesg = vec![0; k1.size() as usize];
770        let len = k1
771            .private_decrypt(&emesg, &mut dmesg, Padding::PKCS1)
772            .unwrap();
773        assert_eq!(msg, &dmesg[..len]);
774    }
775
776    #[test]
777    fn test_public_key_from_pem_pkcs1() {
778        let key = include_bytes!("../test/pkcs1.pem.pub");
779        Rsa::public_key_from_pem_pkcs1(key).unwrap();
780    }
781
782    #[test]
783    #[should_panic]
784    fn test_public_key_from_pem_pkcs1_file_panic() {
785        let key = include_bytes!("../test/key.pem.pub");
786        Rsa::public_key_from_pem_pkcs1(key).unwrap();
787    }
788
789    #[test]
790    fn test_public_key_to_pem_pkcs1() {
791        let keypair = super::Rsa::generate(512).unwrap();
792        let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
793        super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
794    }
795
796    #[test]
797    #[should_panic]
798    fn test_public_key_from_pem_pkcs1_generate_panic() {
799        let keypair = super::Rsa::generate(512).unwrap();
800        let pubkey_pem = keypair.public_key_to_pem().unwrap();
801        super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
802    }
803
804    #[test]
805    fn test_pem_pkcs1_encrypt() {
806        let keypair = super::Rsa::generate(2048).unwrap();
807        let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
808        let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
809        let msg = b"Hello, world!";
810
811        let mut encrypted = vec![0; pubkey.size() as usize];
812        let len = pubkey
813            .public_encrypt(msg, &mut encrypted, Padding::PKCS1)
814            .unwrap();
815        assert!(len > msg.len());
816        let mut decrypted = vec![0; keypair.size() as usize];
817        let len = keypair
818            .private_decrypt(&encrypted, &mut decrypted, Padding::PKCS1)
819            .unwrap();
820        assert_eq!(len, msg.len());
821        assert_eq!(&decrypted[..len], msg);
822    }
823
824    #[test]
825    fn test_pem_pkcs1_padding() {
826        let keypair = super::Rsa::generate(2048).unwrap();
827        let pubkey_pem = keypair.public_key_to_pem_pkcs1().unwrap();
828        let pubkey = super::Rsa::public_key_from_pem_pkcs1(&pubkey_pem).unwrap();
829        let msg = b"foo";
830
831        let mut encrypted1 = vec![0; pubkey.size() as usize];
832        let mut encrypted2 = vec![0; pubkey.size() as usize];
833        let len1 = pubkey
834            .public_encrypt(msg, &mut encrypted1, Padding::PKCS1)
835            .unwrap();
836        let len2 = pubkey
837            .public_encrypt(msg, &mut encrypted2, Padding::PKCS1)
838            .unwrap();
839        assert!(len1 > (msg.len() + 1));
840        assert_eq!(len1, len2);
841        assert_ne!(encrypted1, encrypted2);
842    }
843
844    #[test]
845    #[allow(clippy::redundant_clone)]
846    fn clone() {
847        let key = Rsa::generate(2048).unwrap();
848        drop(key.clone());
849    }
850
851    #[test]
852    fn generate_with_e() {
853        let e = BigNum::from_u32(0x10001).unwrap();
854        Rsa::generate_with_e(2048, &e).unwrap();
855    }
856
857    #[test]
858    fn test_check_key() {
859        let k = Rsa::private_key_from_pem_passphrase(
860            include_bytes!("../test/rsa-encrypted.pem"),
861            b"mypass",
862        )
863        .unwrap();
864        assert!(matches!(k.check_key(), Ok(true)));
865        assert!(ErrorStack::get().errors().is_empty());
866
867        // BoringSSL simply rejects this key, because its corrupted!
868        if let Ok(k) = Rsa::private_key_from_pem(include_bytes!("../test/corrupted-rsa.pem")) {
869            assert!(matches!(k.check_key(), Ok(false) | Err(_)));
870            assert!(ErrorStack::get().errors().is_empty());
871        }
872    }
873}