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