192f3ab15Sopenharmony_ci//! Message encryption.
292f3ab15Sopenharmony_ci//!
392f3ab15Sopenharmony_ci//! The [`Encrypter`] allows for encryption of data given a public key. The [`Decrypter`] can be
492f3ab15Sopenharmony_ci//! used with the corresponding private key to decrypt the data.
592f3ab15Sopenharmony_ci//!
692f3ab15Sopenharmony_ci//! # Examples
792f3ab15Sopenharmony_ci//!
892f3ab15Sopenharmony_ci//! Encrypt and decrypt data given an RSA keypair:
992f3ab15Sopenharmony_ci//!
1092f3ab15Sopenharmony_ci//! ```rust
1192f3ab15Sopenharmony_ci//! use openssl::encrypt::{Encrypter, Decrypter};
1292f3ab15Sopenharmony_ci//! use openssl::rsa::{Rsa, Padding};
1392f3ab15Sopenharmony_ci//! use openssl::pkey::PKey;
1492f3ab15Sopenharmony_ci//!
1592f3ab15Sopenharmony_ci//! // Generate a keypair
1692f3ab15Sopenharmony_ci//! let keypair = Rsa::generate(2048).unwrap();
1792f3ab15Sopenharmony_ci//! let keypair = PKey::from_rsa(keypair).unwrap();
1892f3ab15Sopenharmony_ci//!
1992f3ab15Sopenharmony_ci//! let data = b"hello, world!";
2092f3ab15Sopenharmony_ci//!
2192f3ab15Sopenharmony_ci//! // Encrypt the data with RSA PKCS1
2292f3ab15Sopenharmony_ci//! let mut encrypter = Encrypter::new(&keypair).unwrap();
2392f3ab15Sopenharmony_ci//! encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
2492f3ab15Sopenharmony_ci//! // Create an output buffer
2592f3ab15Sopenharmony_ci//! let buffer_len = encrypter.encrypt_len(data).unwrap();
2692f3ab15Sopenharmony_ci//! let mut encrypted = vec![0; buffer_len];
2792f3ab15Sopenharmony_ci//! // Encrypt and truncate the buffer
2892f3ab15Sopenharmony_ci//! let encrypted_len = encrypter.encrypt(data, &mut encrypted).unwrap();
2992f3ab15Sopenharmony_ci//! encrypted.truncate(encrypted_len);
3092f3ab15Sopenharmony_ci//!
3192f3ab15Sopenharmony_ci//! // Decrypt the data
3292f3ab15Sopenharmony_ci//! let mut decrypter = Decrypter::new(&keypair).unwrap();
3392f3ab15Sopenharmony_ci//! decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
3492f3ab15Sopenharmony_ci//! // Create an output buffer
3592f3ab15Sopenharmony_ci//! let buffer_len = decrypter.decrypt_len(&encrypted).unwrap();
3692f3ab15Sopenharmony_ci//! let mut decrypted = vec![0; buffer_len];
3792f3ab15Sopenharmony_ci//! // Encrypt and truncate the buffer
3892f3ab15Sopenharmony_ci//! let decrypted_len = decrypter.decrypt(&encrypted, &mut decrypted).unwrap();
3992f3ab15Sopenharmony_ci//! decrypted.truncate(decrypted_len);
4092f3ab15Sopenharmony_ci//! assert_eq!(&*decrypted, data);
4192f3ab15Sopenharmony_ci//! ```
4292f3ab15Sopenharmony_ci#[cfg(any(ossl102, libressl310))]
4392f3ab15Sopenharmony_ciuse libc::{c_int, c_void};
4492f3ab15Sopenharmony_ciuse std::{marker::PhantomData, ptr};
4592f3ab15Sopenharmony_ci
4692f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
4792f3ab15Sopenharmony_ciuse crate::hash::MessageDigest;
4892f3ab15Sopenharmony_ciuse crate::pkey::{HasPrivate, HasPublic, PKeyRef};
4992f3ab15Sopenharmony_ciuse crate::rsa::Padding;
5092f3ab15Sopenharmony_ciuse crate::{cvt, cvt_p};
5192f3ab15Sopenharmony_ciuse foreign_types::ForeignTypeRef;
5292f3ab15Sopenharmony_ci
5392f3ab15Sopenharmony_ci/// A type which encrypts data.
5492f3ab15Sopenharmony_cipub struct Encrypter<'a> {
5592f3ab15Sopenharmony_ci    pctx: *mut ffi::EVP_PKEY_CTX,
5692f3ab15Sopenharmony_ci    _p: PhantomData<&'a ()>,
5792f3ab15Sopenharmony_ci}
5892f3ab15Sopenharmony_ci
5992f3ab15Sopenharmony_ciunsafe impl<'a> Sync for Encrypter<'a> {}
6092f3ab15Sopenharmony_ciunsafe impl<'a> Send for Encrypter<'a> {}
6192f3ab15Sopenharmony_ci
6292f3ab15Sopenharmony_ciimpl<'a> Drop for Encrypter<'a> {
6392f3ab15Sopenharmony_ci    fn drop(&mut self) {
6492f3ab15Sopenharmony_ci        unsafe {
6592f3ab15Sopenharmony_ci            ffi::EVP_PKEY_CTX_free(self.pctx);
6692f3ab15Sopenharmony_ci        }
6792f3ab15Sopenharmony_ci    }
6892f3ab15Sopenharmony_ci}
6992f3ab15Sopenharmony_ci
7092f3ab15Sopenharmony_ciimpl<'a> Encrypter<'a> {
7192f3ab15Sopenharmony_ci    /// Creates a new `Encrypter`.
7292f3ab15Sopenharmony_ci    ///
7392f3ab15Sopenharmony_ci    /// OpenSSL documentation at [`EVP_PKEY_encrypt_init`].
7492f3ab15Sopenharmony_ci    ///
7592f3ab15Sopenharmony_ci    /// [`EVP_PKEY_encrypt_init`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt_init.html
7692f3ab15Sopenharmony_ci    pub fn new<T>(pkey: &'a PKeyRef<T>) -> Result<Encrypter<'a>, ErrorStack>
7792f3ab15Sopenharmony_ci    where
7892f3ab15Sopenharmony_ci        T: HasPublic,
7992f3ab15Sopenharmony_ci    {
8092f3ab15Sopenharmony_ci        unsafe {
8192f3ab15Sopenharmony_ci            ffi::init();
8292f3ab15Sopenharmony_ci
8392f3ab15Sopenharmony_ci            let pctx = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
8492f3ab15Sopenharmony_ci            let r = ffi::EVP_PKEY_encrypt_init(pctx);
8592f3ab15Sopenharmony_ci            if r != 1 {
8692f3ab15Sopenharmony_ci                ffi::EVP_PKEY_CTX_free(pctx);
8792f3ab15Sopenharmony_ci                return Err(ErrorStack::get());
8892f3ab15Sopenharmony_ci            }
8992f3ab15Sopenharmony_ci
9092f3ab15Sopenharmony_ci            Ok(Encrypter {
9192f3ab15Sopenharmony_ci                pctx,
9292f3ab15Sopenharmony_ci                _p: PhantomData,
9392f3ab15Sopenharmony_ci            })
9492f3ab15Sopenharmony_ci        }
9592f3ab15Sopenharmony_ci    }
9692f3ab15Sopenharmony_ci
9792f3ab15Sopenharmony_ci    /// Returns the RSA padding mode in use.
9892f3ab15Sopenharmony_ci    ///
9992f3ab15Sopenharmony_ci    /// This is only useful for RSA keys.
10092f3ab15Sopenharmony_ci    ///
10192f3ab15Sopenharmony_ci    /// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
10292f3ab15Sopenharmony_ci    pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
10392f3ab15Sopenharmony_ci        unsafe {
10492f3ab15Sopenharmony_ci            let mut pad = 0;
10592f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
10692f3ab15Sopenharmony_ci                .map(|_| Padding::from_raw(pad))
10792f3ab15Sopenharmony_ci        }
10892f3ab15Sopenharmony_ci    }
10992f3ab15Sopenharmony_ci
11092f3ab15Sopenharmony_ci    /// Sets the RSA padding mode.
11192f3ab15Sopenharmony_ci    ///
11292f3ab15Sopenharmony_ci    /// This is only useful for RSA keys.
11392f3ab15Sopenharmony_ci    ///
11492f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`].
11592f3ab15Sopenharmony_ci    ///
11692f3ab15Sopenharmony_ci    /// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_CTX_set_rsa_padding.html
11792f3ab15Sopenharmony_ci    pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
11892f3ab15Sopenharmony_ci        unsafe {
11992f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
12092f3ab15Sopenharmony_ci                self.pctx,
12192f3ab15Sopenharmony_ci                padding.as_raw(),
12292f3ab15Sopenharmony_ci            ))
12392f3ab15Sopenharmony_ci            .map(|_| ())
12492f3ab15Sopenharmony_ci        }
12592f3ab15Sopenharmony_ci    }
12692f3ab15Sopenharmony_ci
12792f3ab15Sopenharmony_ci    /// Sets the RSA MGF1 algorithm.
12892f3ab15Sopenharmony_ci    ///
12992f3ab15Sopenharmony_ci    /// This is only useful for RSA keys.
13092f3ab15Sopenharmony_ci    ///
13192f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
13292f3ab15Sopenharmony_ci    ///
13392f3ab15Sopenharmony_ci    /// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
13492f3ab15Sopenharmony_ci    pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
13592f3ab15Sopenharmony_ci        unsafe {
13692f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
13792f3ab15Sopenharmony_ci                self.pctx,
13892f3ab15Sopenharmony_ci                md.as_ptr() as *mut _,
13992f3ab15Sopenharmony_ci            ))
14092f3ab15Sopenharmony_ci            .map(|_| ())
14192f3ab15Sopenharmony_ci        }
14292f3ab15Sopenharmony_ci    }
14392f3ab15Sopenharmony_ci
14492f3ab15Sopenharmony_ci    /// Sets the RSA OAEP algorithm.
14592f3ab15Sopenharmony_ci    ///
14692f3ab15Sopenharmony_ci    /// This is only useful for RSA keys.
14792f3ab15Sopenharmony_ci    ///
14892f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`].
14992f3ab15Sopenharmony_ci    ///
15092f3ab15Sopenharmony_ci    /// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html
15192f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl310))]
15292f3ab15Sopenharmony_ci    pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
15392f3ab15Sopenharmony_ci        unsafe {
15492f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
15592f3ab15Sopenharmony_ci                self.pctx,
15692f3ab15Sopenharmony_ci                md.as_ptr() as *mut _,
15792f3ab15Sopenharmony_ci            ))
15892f3ab15Sopenharmony_ci            .map(|_| ())
15992f3ab15Sopenharmony_ci        }
16092f3ab15Sopenharmony_ci    }
16192f3ab15Sopenharmony_ci
16292f3ab15Sopenharmony_ci    /// Sets the RSA OAEP label.
16392f3ab15Sopenharmony_ci    ///
16492f3ab15Sopenharmony_ci    /// This is only useful for RSA keys.
16592f3ab15Sopenharmony_ci    ///
16692f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_CTX_set0_rsa_oaep_label`].
16792f3ab15Sopenharmony_ci    ///
16892f3ab15Sopenharmony_ci    /// [`EVP_PKEY_CTX_set0_rsa_oaep_label`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set0_rsa_oaep_label.html
16992f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl310))]
17092f3ab15Sopenharmony_ci    pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
17192f3ab15Sopenharmony_ci        unsafe {
17292f3ab15Sopenharmony_ci            let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
17392f3ab15Sopenharmony_ci            ptr::copy_nonoverlapping(label.as_ptr(), p as *mut u8, label.len());
17492f3ab15Sopenharmony_ci
17592f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
17692f3ab15Sopenharmony_ci                self.pctx,
17792f3ab15Sopenharmony_ci                p as *mut c_void,
17892f3ab15Sopenharmony_ci                label.len() as c_int,
17992f3ab15Sopenharmony_ci            ))
18092f3ab15Sopenharmony_ci            .map(|_| ())
18192f3ab15Sopenharmony_ci            .map_err(|e| {
18292f3ab15Sopenharmony_ci                ffi::OPENSSL_free(p);
18392f3ab15Sopenharmony_ci                e
18492f3ab15Sopenharmony_ci            })
18592f3ab15Sopenharmony_ci        }
18692f3ab15Sopenharmony_ci    }
18792f3ab15Sopenharmony_ci
18892f3ab15Sopenharmony_ci    /// Performs public key encryption.
18992f3ab15Sopenharmony_ci    ///
19092f3ab15Sopenharmony_ci    /// In order to know the size needed for the output buffer, use [`encrypt_len`](Encrypter::encrypt_len).
19192f3ab15Sopenharmony_ci    /// Note that the length of the output buffer can be greater of the length of the encoded data.
19292f3ab15Sopenharmony_ci    /// ```
19392f3ab15Sopenharmony_ci    /// # use openssl::{
19492f3ab15Sopenharmony_ci    /// #   encrypt::Encrypter,
19592f3ab15Sopenharmony_ci    /// #   pkey::PKey,
19692f3ab15Sopenharmony_ci    /// #   rsa::{Rsa, Padding},
19792f3ab15Sopenharmony_ci    /// # };
19892f3ab15Sopenharmony_ci    /// #
19992f3ab15Sopenharmony_ci    /// # let key = include_bytes!("../test/rsa.pem");
20092f3ab15Sopenharmony_ci    /// # let private_key = Rsa::private_key_from_pem(key).unwrap();
20192f3ab15Sopenharmony_ci    /// # let pkey = PKey::from_rsa(private_key).unwrap();
20292f3ab15Sopenharmony_ci    /// # let input = b"hello world".to_vec();
20392f3ab15Sopenharmony_ci    /// #
20492f3ab15Sopenharmony_ci    /// let mut encrypter = Encrypter::new(&pkey).unwrap();
20592f3ab15Sopenharmony_ci    /// encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
20692f3ab15Sopenharmony_ci    ///
20792f3ab15Sopenharmony_ci    /// // Get the length of the output buffer
20892f3ab15Sopenharmony_ci    /// let buffer_len = encrypter.encrypt_len(&input).unwrap();
20992f3ab15Sopenharmony_ci    /// let mut encoded = vec![0u8; buffer_len];
21092f3ab15Sopenharmony_ci    ///
21192f3ab15Sopenharmony_ci    /// // Encode the data and get its length
21292f3ab15Sopenharmony_ci    /// let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
21392f3ab15Sopenharmony_ci    ///
21492f3ab15Sopenharmony_ci    /// // Use only the part of the buffer with the encoded data
21592f3ab15Sopenharmony_ci    /// let encoded = &encoded[..encoded_len];
21692f3ab15Sopenharmony_ci    /// ```
21792f3ab15Sopenharmony_ci    ///
21892f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_encrypt`].
21992f3ab15Sopenharmony_ci    ///
22092f3ab15Sopenharmony_ci    /// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html
22192f3ab15Sopenharmony_ci    pub fn encrypt(&self, from: &[u8], to: &mut [u8]) -> Result<usize, ErrorStack> {
22292f3ab15Sopenharmony_ci        let mut written = to.len();
22392f3ab15Sopenharmony_ci        unsafe {
22492f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_encrypt(
22592f3ab15Sopenharmony_ci                self.pctx,
22692f3ab15Sopenharmony_ci                to.as_mut_ptr(),
22792f3ab15Sopenharmony_ci                &mut written,
22892f3ab15Sopenharmony_ci                from.as_ptr(),
22992f3ab15Sopenharmony_ci                from.len(),
23092f3ab15Sopenharmony_ci            ))?;
23192f3ab15Sopenharmony_ci        }
23292f3ab15Sopenharmony_ci
23392f3ab15Sopenharmony_ci        Ok(written)
23492f3ab15Sopenharmony_ci    }
23592f3ab15Sopenharmony_ci
23692f3ab15Sopenharmony_ci    /// Gets the size of the buffer needed to encrypt the input data.
23792f3ab15Sopenharmony_ci    ///
23892f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_encrypt`] called with a null pointer as output argument.
23992f3ab15Sopenharmony_ci    ///
24092f3ab15Sopenharmony_ci    /// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html
24192f3ab15Sopenharmony_ci    pub fn encrypt_len(&self, from: &[u8]) -> Result<usize, ErrorStack> {
24292f3ab15Sopenharmony_ci        let mut written = 0;
24392f3ab15Sopenharmony_ci        unsafe {
24492f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_encrypt(
24592f3ab15Sopenharmony_ci                self.pctx,
24692f3ab15Sopenharmony_ci                ptr::null_mut(),
24792f3ab15Sopenharmony_ci                &mut written,
24892f3ab15Sopenharmony_ci                from.as_ptr(),
24992f3ab15Sopenharmony_ci                from.len(),
25092f3ab15Sopenharmony_ci            ))?;
25192f3ab15Sopenharmony_ci        }
25292f3ab15Sopenharmony_ci
25392f3ab15Sopenharmony_ci        Ok(written)
25492f3ab15Sopenharmony_ci    }
25592f3ab15Sopenharmony_ci}
25692f3ab15Sopenharmony_ci
25792f3ab15Sopenharmony_ci/// A type which decrypts data.
25892f3ab15Sopenharmony_cipub struct Decrypter<'a> {
25992f3ab15Sopenharmony_ci    pctx: *mut ffi::EVP_PKEY_CTX,
26092f3ab15Sopenharmony_ci    _p: PhantomData<&'a ()>,
26192f3ab15Sopenharmony_ci}
26292f3ab15Sopenharmony_ci
26392f3ab15Sopenharmony_ciunsafe impl<'a> Sync for Decrypter<'a> {}
26492f3ab15Sopenharmony_ciunsafe impl<'a> Send for Decrypter<'a> {}
26592f3ab15Sopenharmony_ci
26692f3ab15Sopenharmony_ciimpl<'a> Drop for Decrypter<'a> {
26792f3ab15Sopenharmony_ci    fn drop(&mut self) {
26892f3ab15Sopenharmony_ci        unsafe {
26992f3ab15Sopenharmony_ci            ffi::EVP_PKEY_CTX_free(self.pctx);
27092f3ab15Sopenharmony_ci        }
27192f3ab15Sopenharmony_ci    }
27292f3ab15Sopenharmony_ci}
27392f3ab15Sopenharmony_ci
27492f3ab15Sopenharmony_ciimpl<'a> Decrypter<'a> {
27592f3ab15Sopenharmony_ci    /// Creates a new `Decrypter`.
27692f3ab15Sopenharmony_ci    ///
27792f3ab15Sopenharmony_ci    /// OpenSSL documentation at [`EVP_PKEY_decrypt_init`].
27892f3ab15Sopenharmony_ci    ///
27992f3ab15Sopenharmony_ci    /// [`EVP_PKEY_decrypt_init`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt_init.html
28092f3ab15Sopenharmony_ci    pub fn new<T>(pkey: &'a PKeyRef<T>) -> Result<Decrypter<'a>, ErrorStack>
28192f3ab15Sopenharmony_ci    where
28292f3ab15Sopenharmony_ci        T: HasPrivate,
28392f3ab15Sopenharmony_ci    {
28492f3ab15Sopenharmony_ci        unsafe {
28592f3ab15Sopenharmony_ci            ffi::init();
28692f3ab15Sopenharmony_ci
28792f3ab15Sopenharmony_ci            let pctx = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
28892f3ab15Sopenharmony_ci            let r = ffi::EVP_PKEY_decrypt_init(pctx);
28992f3ab15Sopenharmony_ci            if r != 1 {
29092f3ab15Sopenharmony_ci                ffi::EVP_PKEY_CTX_free(pctx);
29192f3ab15Sopenharmony_ci                return Err(ErrorStack::get());
29292f3ab15Sopenharmony_ci            }
29392f3ab15Sopenharmony_ci
29492f3ab15Sopenharmony_ci            Ok(Decrypter {
29592f3ab15Sopenharmony_ci                pctx,
29692f3ab15Sopenharmony_ci                _p: PhantomData,
29792f3ab15Sopenharmony_ci            })
29892f3ab15Sopenharmony_ci        }
29992f3ab15Sopenharmony_ci    }
30092f3ab15Sopenharmony_ci
30192f3ab15Sopenharmony_ci    /// Returns the RSA padding mode in use.
30292f3ab15Sopenharmony_ci    ///
30392f3ab15Sopenharmony_ci    /// This is only useful for RSA keys.
30492f3ab15Sopenharmony_ci    ///
30592f3ab15Sopenharmony_ci    /// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
30692f3ab15Sopenharmony_ci    pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
30792f3ab15Sopenharmony_ci        unsafe {
30892f3ab15Sopenharmony_ci            let mut pad = 0;
30992f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
31092f3ab15Sopenharmony_ci                .map(|_| Padding::from_raw(pad))
31192f3ab15Sopenharmony_ci        }
31292f3ab15Sopenharmony_ci    }
31392f3ab15Sopenharmony_ci
31492f3ab15Sopenharmony_ci    /// Sets the RSA padding mode.
31592f3ab15Sopenharmony_ci    ///
31692f3ab15Sopenharmony_ci    /// This is only useful for RSA keys.
31792f3ab15Sopenharmony_ci    ///
31892f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`].
31992f3ab15Sopenharmony_ci    ///
32092f3ab15Sopenharmony_ci    /// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/manmaster/crypto/EVP_PKEY_CTX_set_rsa_padding.html
32192f3ab15Sopenharmony_ci    pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
32292f3ab15Sopenharmony_ci        unsafe {
32392f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
32492f3ab15Sopenharmony_ci                self.pctx,
32592f3ab15Sopenharmony_ci                padding.as_raw(),
32692f3ab15Sopenharmony_ci            ))
32792f3ab15Sopenharmony_ci            .map(|_| ())
32892f3ab15Sopenharmony_ci        }
32992f3ab15Sopenharmony_ci    }
33092f3ab15Sopenharmony_ci
33192f3ab15Sopenharmony_ci    /// Sets the RSA MGF1 algorithm.
33292f3ab15Sopenharmony_ci    ///
33392f3ab15Sopenharmony_ci    /// This is only useful for RSA keys.
33492f3ab15Sopenharmony_ci    ///
33592f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
33692f3ab15Sopenharmony_ci    ///
33792f3ab15Sopenharmony_ci    /// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
33892f3ab15Sopenharmony_ci    pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
33992f3ab15Sopenharmony_ci        unsafe {
34092f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
34192f3ab15Sopenharmony_ci                self.pctx,
34292f3ab15Sopenharmony_ci                md.as_ptr() as *mut _,
34392f3ab15Sopenharmony_ci            ))
34492f3ab15Sopenharmony_ci            .map(|_| ())
34592f3ab15Sopenharmony_ci        }
34692f3ab15Sopenharmony_ci    }
34792f3ab15Sopenharmony_ci
34892f3ab15Sopenharmony_ci    /// Sets the RSA OAEP algorithm.
34992f3ab15Sopenharmony_ci    ///
35092f3ab15Sopenharmony_ci    /// This is only useful for RSA keys.
35192f3ab15Sopenharmony_ci    ///
35292f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`].
35392f3ab15Sopenharmony_ci    ///
35492f3ab15Sopenharmony_ci    /// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html
35592f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl310))]
35692f3ab15Sopenharmony_ci    pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
35792f3ab15Sopenharmony_ci        unsafe {
35892f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
35992f3ab15Sopenharmony_ci                self.pctx,
36092f3ab15Sopenharmony_ci                md.as_ptr() as *mut _,
36192f3ab15Sopenharmony_ci            ))
36292f3ab15Sopenharmony_ci            .map(|_| ())
36392f3ab15Sopenharmony_ci        }
36492f3ab15Sopenharmony_ci    }
36592f3ab15Sopenharmony_ci
36692f3ab15Sopenharmony_ci    /// Sets the RSA OAEP label.
36792f3ab15Sopenharmony_ci    ///
36892f3ab15Sopenharmony_ci    /// This is only useful for RSA keys.
36992f3ab15Sopenharmony_ci    ///
37092f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_CTX_set0_rsa_oaep_label`].
37192f3ab15Sopenharmony_ci    ///
37292f3ab15Sopenharmony_ci    /// [`EVP_PKEY_CTX_set0_rsa_oaep_label`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set0_rsa_oaep_label.html
37392f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl310))]
37492f3ab15Sopenharmony_ci    pub fn set_rsa_oaep_label(&mut self, label: &[u8]) -> Result<(), ErrorStack> {
37592f3ab15Sopenharmony_ci        unsafe {
37692f3ab15Sopenharmony_ci            let p = cvt_p(ffi::OPENSSL_malloc(label.len() as _))?;
37792f3ab15Sopenharmony_ci            ptr::copy_nonoverlapping(label.as_ptr(), p as *mut u8, label.len());
37892f3ab15Sopenharmony_ci
37992f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_CTX_set0_rsa_oaep_label(
38092f3ab15Sopenharmony_ci                self.pctx,
38192f3ab15Sopenharmony_ci                p as *mut c_void,
38292f3ab15Sopenharmony_ci                label.len() as c_int,
38392f3ab15Sopenharmony_ci            ))
38492f3ab15Sopenharmony_ci            .map(|_| ())
38592f3ab15Sopenharmony_ci            .map_err(|e| {
38692f3ab15Sopenharmony_ci                ffi::OPENSSL_free(p);
38792f3ab15Sopenharmony_ci                e
38892f3ab15Sopenharmony_ci            })
38992f3ab15Sopenharmony_ci        }
39092f3ab15Sopenharmony_ci    }
39192f3ab15Sopenharmony_ci
39292f3ab15Sopenharmony_ci    /// Performs public key decryption.
39392f3ab15Sopenharmony_ci    ///
39492f3ab15Sopenharmony_ci    /// In order to know the size needed for the output buffer, use [`decrypt_len`](Decrypter::decrypt_len).
39592f3ab15Sopenharmony_ci    /// Note that the length of the output buffer can be greater of the length of the decoded data.
39692f3ab15Sopenharmony_ci    /// ```
39792f3ab15Sopenharmony_ci    /// # use openssl::{
39892f3ab15Sopenharmony_ci    /// #   encrypt::Decrypter,
39992f3ab15Sopenharmony_ci    /// #   pkey::PKey,
40092f3ab15Sopenharmony_ci    /// #   rsa::{Rsa, Padding},
40192f3ab15Sopenharmony_ci    /// # };
40292f3ab15Sopenharmony_ci    /// #
40392f3ab15Sopenharmony_ci    /// # const INPUT: &[u8] = b"\
40492f3ab15Sopenharmony_ci    /// #     \x26\xa1\xc1\x13\xc5\x7f\xb4\x9f\xa0\xb4\xde\x61\x5e\x2e\xc6\xfb\x76\x5c\xd1\x2b\x5f\
40592f3ab15Sopenharmony_ci    /// #     \x1d\x36\x60\xfa\xf8\xe8\xb3\x21\xf4\x9c\x70\xbc\x03\xea\xea\xac\xce\x4b\xb3\xf6\x45\
40692f3ab15Sopenharmony_ci    /// #     \xcc\xb3\x80\x9e\xa8\xf7\xc3\x5d\x06\x12\x7a\xa3\x0c\x30\x67\xf1\xe7\x94\x6c\xf6\x26\
40792f3ab15Sopenharmony_ci    /// #     \xac\x28\x17\x59\x69\xe1\xdc\xed\x7e\xc0\xe9\x62\x57\x49\xce\xdd\x13\x07\xde\x18\x03\
40892f3ab15Sopenharmony_ci    /// #     \x0f\x9d\x61\x65\xb9\x23\x8c\x78\x4b\xad\x23\x49\x75\x47\x64\xa0\xa0\xa2\x90\xc1\x49\
40992f3ab15Sopenharmony_ci    /// #     \x1b\x05\x24\xc2\xe9\x2c\x0d\x49\x78\x72\x61\x72\xed\x8b\x6f\x8a\xe8\xca\x05\x5c\x58\
41092f3ab15Sopenharmony_ci    /// #     \xd6\x95\xd6\x7b\xe3\x2d\x0d\xaa\x3e\x6d\x3c\x9a\x1c\x1d\xb4\x6c\x42\x9d\x9a\x82\x55\
41192f3ab15Sopenharmony_ci    /// #     \xd9\xde\xc8\x08\x7b\x17\xac\xd7\xaf\x86\x7b\x69\x9e\x3c\xf4\x5e\x1c\x39\x52\x6d\x62\
41292f3ab15Sopenharmony_ci    /// #     \x50\x51\xbd\xa6\xc8\x4e\xe9\x34\xf0\x37\x0d\xa9\xa9\x77\xe6\xf5\xc2\x47\x2d\xa8\xee\
41392f3ab15Sopenharmony_ci    /// #     \x3f\x69\x78\xff\xa9\xdc\x70\x22\x20\x9a\x5c\x9b\x70\x15\x90\xd3\xb4\x0e\x54\x9e\x48\
41492f3ab15Sopenharmony_ci    /// #     \xed\xb6\x2c\x88\xfc\xb4\xa9\x37\x10\xfa\x71\xb2\xec\x75\xe7\xe7\x0e\xf4\x60\x2c\x7b\
41592f3ab15Sopenharmony_ci    /// #     \x58\xaf\xa0\x53\xbd\x24\xf1\x12\xe3\x2e\x99\x25\x0a\x54\x54\x9d\xa1\xdb\xca\x41\x85\
41692f3ab15Sopenharmony_ci    /// #     \xf4\x62\x78\x64";
41792f3ab15Sopenharmony_ci    /// #
41892f3ab15Sopenharmony_ci    /// # let key = include_bytes!("../test/rsa.pem");
41992f3ab15Sopenharmony_ci    /// # let private_key = Rsa::private_key_from_pem(key).unwrap();
42092f3ab15Sopenharmony_ci    /// # let pkey = PKey::from_rsa(private_key).unwrap();
42192f3ab15Sopenharmony_ci    /// # let input = INPUT.to_vec();
42292f3ab15Sopenharmony_ci    /// #
42392f3ab15Sopenharmony_ci    /// let mut decrypter = Decrypter::new(&pkey).unwrap();
42492f3ab15Sopenharmony_ci    /// decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
42592f3ab15Sopenharmony_ci    ///
42692f3ab15Sopenharmony_ci    /// // Get the length of the output buffer
42792f3ab15Sopenharmony_ci    /// let buffer_len = decrypter.decrypt_len(&input).unwrap();
42892f3ab15Sopenharmony_ci    /// let mut decoded = vec![0u8; buffer_len];
42992f3ab15Sopenharmony_ci    ///
43092f3ab15Sopenharmony_ci    /// // Decrypt the data and get its length
43192f3ab15Sopenharmony_ci    /// let decoded_len = decrypter.decrypt(&input, &mut decoded).unwrap();
43292f3ab15Sopenharmony_ci    ///
43392f3ab15Sopenharmony_ci    /// // Use only the part of the buffer with the decrypted data
43492f3ab15Sopenharmony_ci    /// let decoded = &decoded[..decoded_len];
43592f3ab15Sopenharmony_ci    /// ```
43692f3ab15Sopenharmony_ci    ///
43792f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_decrypt`].
43892f3ab15Sopenharmony_ci    ///
43992f3ab15Sopenharmony_ci    /// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt.html
44092f3ab15Sopenharmony_ci    pub fn decrypt(&self, from: &[u8], to: &mut [u8]) -> Result<usize, ErrorStack> {
44192f3ab15Sopenharmony_ci        let mut written = to.len();
44292f3ab15Sopenharmony_ci        unsafe {
44392f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_decrypt(
44492f3ab15Sopenharmony_ci                self.pctx,
44592f3ab15Sopenharmony_ci                to.as_mut_ptr(),
44692f3ab15Sopenharmony_ci                &mut written,
44792f3ab15Sopenharmony_ci                from.as_ptr(),
44892f3ab15Sopenharmony_ci                from.len(),
44992f3ab15Sopenharmony_ci            ))?;
45092f3ab15Sopenharmony_ci        }
45192f3ab15Sopenharmony_ci
45292f3ab15Sopenharmony_ci        Ok(written)
45392f3ab15Sopenharmony_ci    }
45492f3ab15Sopenharmony_ci
45592f3ab15Sopenharmony_ci    /// Gets the size of the buffer needed to decrypt the input data.
45692f3ab15Sopenharmony_ci    ///
45792f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_PKEY_decrypt`] called with a null pointer as output argument.
45892f3ab15Sopenharmony_ci    ///
45992f3ab15Sopenharmony_ci    /// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt.html
46092f3ab15Sopenharmony_ci    pub fn decrypt_len(&self, from: &[u8]) -> Result<usize, ErrorStack> {
46192f3ab15Sopenharmony_ci        let mut written = 0;
46292f3ab15Sopenharmony_ci        unsafe {
46392f3ab15Sopenharmony_ci            cvt(ffi::EVP_PKEY_decrypt(
46492f3ab15Sopenharmony_ci                self.pctx,
46592f3ab15Sopenharmony_ci                ptr::null_mut(),
46692f3ab15Sopenharmony_ci                &mut written,
46792f3ab15Sopenharmony_ci                from.as_ptr(),
46892f3ab15Sopenharmony_ci                from.len(),
46992f3ab15Sopenharmony_ci            ))?;
47092f3ab15Sopenharmony_ci        }
47192f3ab15Sopenharmony_ci
47292f3ab15Sopenharmony_ci        Ok(written)
47392f3ab15Sopenharmony_ci    }
47492f3ab15Sopenharmony_ci}
47592f3ab15Sopenharmony_ci
47692f3ab15Sopenharmony_ci#[cfg(test)]
47792f3ab15Sopenharmony_cimod test {
47892f3ab15Sopenharmony_ci    use hex::FromHex;
47992f3ab15Sopenharmony_ci
48092f3ab15Sopenharmony_ci    use crate::encrypt::{Decrypter, Encrypter};
48192f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl310))]
48292f3ab15Sopenharmony_ci    use crate::hash::MessageDigest;
48392f3ab15Sopenharmony_ci    use crate::pkey::PKey;
48492f3ab15Sopenharmony_ci    use crate::rsa::{Padding, Rsa};
48592f3ab15Sopenharmony_ci
48692f3ab15Sopenharmony_ci    const INPUT: &str =
48792f3ab15Sopenharmony_ci        "65794a68624763694f694a53557a49314e694a392e65794a7063334d694f694a71623255694c41304b49434a6c\
48892f3ab15Sopenharmony_ci         654841694f6a457a4d4441344d546b7a4f44417344516f67496d6830644841364c79396c654746746347786c4c\
48992f3ab15Sopenharmony_ci         6d4e76625339706331397962323930496a7030636e566c6651";
49092f3ab15Sopenharmony_ci
49192f3ab15Sopenharmony_ci    #[test]
49292f3ab15Sopenharmony_ci    fn rsa_encrypt_decrypt() {
49392f3ab15Sopenharmony_ci        let key = include_bytes!("../test/rsa.pem");
49492f3ab15Sopenharmony_ci        let private_key = Rsa::private_key_from_pem(key).unwrap();
49592f3ab15Sopenharmony_ci        let pkey = PKey::from_rsa(private_key).unwrap();
49692f3ab15Sopenharmony_ci
49792f3ab15Sopenharmony_ci        let mut encrypter = Encrypter::new(&pkey).unwrap();
49892f3ab15Sopenharmony_ci        encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
49992f3ab15Sopenharmony_ci        let input = Vec::from_hex(INPUT).unwrap();
50092f3ab15Sopenharmony_ci        let buffer_len = encrypter.encrypt_len(&input).unwrap();
50192f3ab15Sopenharmony_ci        let mut encoded = vec![0u8; buffer_len];
50292f3ab15Sopenharmony_ci        let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
50392f3ab15Sopenharmony_ci        let encoded = &encoded[..encoded_len];
50492f3ab15Sopenharmony_ci
50592f3ab15Sopenharmony_ci        let mut decrypter = Decrypter::new(&pkey).unwrap();
50692f3ab15Sopenharmony_ci        decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
50792f3ab15Sopenharmony_ci        let buffer_len = decrypter.decrypt_len(encoded).unwrap();
50892f3ab15Sopenharmony_ci        let mut decoded = vec![0u8; buffer_len];
50992f3ab15Sopenharmony_ci        let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
51092f3ab15Sopenharmony_ci        let decoded = &decoded[..decoded_len];
51192f3ab15Sopenharmony_ci
51292f3ab15Sopenharmony_ci        assert_eq!(decoded, &*input);
51392f3ab15Sopenharmony_ci    }
51492f3ab15Sopenharmony_ci
51592f3ab15Sopenharmony_ci    #[test]
51692f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl310))]
51792f3ab15Sopenharmony_ci    fn rsa_encrypt_decrypt_with_sha256() {
51892f3ab15Sopenharmony_ci        let key = include_bytes!("../test/rsa.pem");
51992f3ab15Sopenharmony_ci        let private_key = Rsa::private_key_from_pem(key).unwrap();
52092f3ab15Sopenharmony_ci        let pkey = PKey::from_rsa(private_key).unwrap();
52192f3ab15Sopenharmony_ci
52292f3ab15Sopenharmony_ci        let md = MessageDigest::sha256();
52392f3ab15Sopenharmony_ci
52492f3ab15Sopenharmony_ci        let mut encrypter = Encrypter::new(&pkey).unwrap();
52592f3ab15Sopenharmony_ci        encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
52692f3ab15Sopenharmony_ci        encrypter.set_rsa_oaep_md(md).unwrap();
52792f3ab15Sopenharmony_ci        encrypter.set_rsa_mgf1_md(md).unwrap();
52892f3ab15Sopenharmony_ci        let input = Vec::from_hex(INPUT).unwrap();
52992f3ab15Sopenharmony_ci        let buffer_len = encrypter.encrypt_len(&input).unwrap();
53092f3ab15Sopenharmony_ci        let mut encoded = vec![0u8; buffer_len];
53192f3ab15Sopenharmony_ci        let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
53292f3ab15Sopenharmony_ci        let encoded = &encoded[..encoded_len];
53392f3ab15Sopenharmony_ci
53492f3ab15Sopenharmony_ci        let mut decrypter = Decrypter::new(&pkey).unwrap();
53592f3ab15Sopenharmony_ci        decrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
53692f3ab15Sopenharmony_ci        decrypter.set_rsa_oaep_md(md).unwrap();
53792f3ab15Sopenharmony_ci        decrypter.set_rsa_mgf1_md(md).unwrap();
53892f3ab15Sopenharmony_ci        let buffer_len = decrypter.decrypt_len(encoded).unwrap();
53992f3ab15Sopenharmony_ci        let mut decoded = vec![0u8; buffer_len];
54092f3ab15Sopenharmony_ci        let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
54192f3ab15Sopenharmony_ci        let decoded = &decoded[..decoded_len];
54292f3ab15Sopenharmony_ci
54392f3ab15Sopenharmony_ci        assert_eq!(decoded, &*input);
54492f3ab15Sopenharmony_ci    }
54592f3ab15Sopenharmony_ci
54692f3ab15Sopenharmony_ci    #[test]
54792f3ab15Sopenharmony_ci    #[cfg(any(ossl102, libressl310))]
54892f3ab15Sopenharmony_ci    fn rsa_encrypt_decrypt_oaep_label() {
54992f3ab15Sopenharmony_ci        let key = include_bytes!("../test/rsa.pem");
55092f3ab15Sopenharmony_ci        let private_key = Rsa::private_key_from_pem(key).unwrap();
55192f3ab15Sopenharmony_ci        let pkey = PKey::from_rsa(private_key).unwrap();
55292f3ab15Sopenharmony_ci
55392f3ab15Sopenharmony_ci        let mut encrypter = Encrypter::new(&pkey).unwrap();
55492f3ab15Sopenharmony_ci        encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
55592f3ab15Sopenharmony_ci        encrypter.set_rsa_oaep_label(b"test_oaep_label").unwrap();
55692f3ab15Sopenharmony_ci        let input = Vec::from_hex(INPUT).unwrap();
55792f3ab15Sopenharmony_ci        let buffer_len = encrypter.encrypt_len(&input).unwrap();
55892f3ab15Sopenharmony_ci        let mut encoded = vec![0u8; buffer_len];
55992f3ab15Sopenharmony_ci        let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
56092f3ab15Sopenharmony_ci        let encoded = &encoded[..encoded_len];
56192f3ab15Sopenharmony_ci
56292f3ab15Sopenharmony_ci        let mut decrypter = Decrypter::new(&pkey).unwrap();
56392f3ab15Sopenharmony_ci        decrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
56492f3ab15Sopenharmony_ci        decrypter.set_rsa_oaep_label(b"test_oaep_label").unwrap();
56592f3ab15Sopenharmony_ci        let buffer_len = decrypter.decrypt_len(encoded).unwrap();
56692f3ab15Sopenharmony_ci        let mut decoded = vec![0u8; buffer_len];
56792f3ab15Sopenharmony_ci        let decoded_len = decrypter.decrypt(encoded, &mut decoded).unwrap();
56892f3ab15Sopenharmony_ci        let decoded = &decoded[..decoded_len];
56992f3ab15Sopenharmony_ci
57092f3ab15Sopenharmony_ci        assert_eq!(decoded, &*input);
57192f3ab15Sopenharmony_ci
57292f3ab15Sopenharmony_ci        decrypter.set_rsa_oaep_label(b"wrong_oaep_label").unwrap();
57392f3ab15Sopenharmony_ci        let buffer_len = decrypter.decrypt_len(encoded).unwrap();
57492f3ab15Sopenharmony_ci        let mut decoded = vec![0u8; buffer_len];
57592f3ab15Sopenharmony_ci
57692f3ab15Sopenharmony_ci        assert!(decrypter.decrypt(encoded, &mut decoded).is_err());
57792f3ab15Sopenharmony_ci    }
57892f3ab15Sopenharmony_ci}
579