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