summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteven Fackler <sfackler@gmail.com>2020-12-13 18:06:13 -0500
committerGitHub <noreply@github.com>2020-12-13 18:06:13 -0500
commit74f380ec534ac6b892fc07a4bf7e3c38fdf74048 (patch)
tree176fcd43652bcd8c586c57bc3d48dd30b28f7ba0
parent7254b603c8266f9913d48c531e68c1306c8ccc2f (diff)
parentc4b3f591054b34b7a63945d0682e8767ecfbc83d (diff)
downloadrust-openssl-74f380ec534ac6b892fc07a4bf7e3c38fdf74048.zip
Merge pull request #1384 from dodomorandi/rsa-oaep
Add encrypt module and RSA OAEP support
-rw-r--r--openssl-sys/src/rsa.rs15
-rw-r--r--openssl/src/encrypt.rs490
-rw-r--r--openssl/src/lib.rs1
3 files changed, 506 insertions, 0 deletions
diff --git a/openssl-sys/src/rsa.rs b/openssl-sys/src/rsa.rs
index 9b6ab82f..dd7cab95 100644
--- a/openssl-sys/src/rsa.rs
+++ b/openssl-sys/src/rsa.rs
@@ -49,6 +49,18 @@ pub unsafe fn EVP_PKEY_CTX_set_rsa_mgf1_md(ctx: *mut EVP_PKEY_CTX, md: *mut EVP_
)
}
+#[cfg(any(ossl102, libressl310))]
+pub unsafe fn EVP_PKEY_CTX_set_rsa_oaep_md(ctx: *mut EVP_PKEY_CTX, md: *mut EVP_MD) -> c_int {
+ EVP_PKEY_CTX_ctrl(
+ ctx,
+ EVP_PKEY_RSA,
+ EVP_PKEY_OP_TYPE_CRYPT,
+ EVP_PKEY_CTRL_RSA_OAEP_MD,
+ 0,
+ md as *mut c_void,
+ )
+}
+
pub const EVP_PKEY_CTRL_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 1;
pub const EVP_PKEY_CTRL_RSA_PSS_SALTLEN: c_int = EVP_PKEY_ALG_CTRL + 2;
@@ -56,6 +68,9 @@ pub const EVP_PKEY_CTRL_RSA_MGF1_MD: c_int = EVP_PKEY_ALG_CTRL + 5;
pub const EVP_PKEY_CTRL_GET_RSA_PADDING: c_int = EVP_PKEY_ALG_CTRL + 6;
+#[cfg(any(ossl102, libressl310))]
+pub const EVP_PKEY_CTRL_RSA_OAEP_MD: c_int = EVP_PKEY_ALG_CTRL + 9;
+
pub const RSA_PKCS1_PADDING: c_int = 1;
pub const RSA_SSLV23_PADDING: c_int = 2;
pub const RSA_NO_PADDING: c_int = 3;
diff --git a/openssl/src/encrypt.rs b/openssl/src/encrypt.rs
new file mode 100644
index 00000000..0d28ac9e
--- /dev/null
+++ b/openssl/src/encrypt.rs
@@ -0,0 +1,490 @@
+//! Message encryption.
+//!
+//! The [`Encrypter`] allows for encryption of data given a public key. The [`Decrypter`] can be
+//! used with the corresponding private key to decrypt the data.
+//!
+//! # Examples
+//!
+//! Encrypt and decrypt data given an RSA keypair:
+//!
+//! ```rust
+//! use openssl::encrypt::{Encrypter, Decrypter};
+//! use openssl::rsa::{Rsa, Padding};
+//! use openssl::pkey::PKey;
+//!
+//! // Generate a keypair
+//! let keypair = Rsa::generate(2048).unwrap();
+//! let keypair = PKey::from_rsa(keypair).unwrap();
+//!
+//! let data = b"hello, world!";
+//!
+//! // Encrypt the data with RSA PKCS1
+//! let mut encrypter = Encrypter::new(&keypair).unwrap();
+//! encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
+//! // Create an output buffer
+//! let buffer_len = encrypter.encrypt_len(data).unwrap();
+//! let mut encrypted = vec![0; buffer_len];
+//! // Encrypt and truncate the buffer
+//! let encrypted_len = encrypter.encrypt(data, &mut encrypted).unwrap();
+//! encrypted.truncate(encrypted_len);
+//!
+//! // Decrypt the data
+//! let mut decrypter = Decrypter::new(&keypair).unwrap();
+//! decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
+//! // Create an output buffer
+//! let buffer_len = decrypter.decrypt_len(&encrypted).unwrap();
+//! let mut decrypted = vec![0; buffer_len];
+//! // Encrypt and truncate the buffer
+//! let decrypted_len = decrypter.decrypt(&encrypted, &mut decrypted).unwrap();
+//! decrypted.truncate(decrypted_len);
+//! assert_eq!(&*decrypted, data);
+//! ```
+use std::{marker::PhantomData, ptr};
+
+use error::ErrorStack;
+use foreign_types::ForeignTypeRef;
+use hash::MessageDigest;
+use pkey::{HasPrivate, HasPublic, PKeyRef};
+use rsa::Padding;
+use {cvt, cvt_p};
+
+/// A type which encrypts data.
+pub struct Encrypter<'a> {
+ pctx: *mut ffi::EVP_PKEY_CTX,
+ _p: PhantomData<&'a ()>,
+}
+
+unsafe impl<'a> Sync for Encrypter<'a> {}
+unsafe impl<'a> Send for Encrypter<'a> {}
+
+impl<'a> Drop for Encrypter<'a> {
+ fn drop(&mut self) {
+ unsafe {
+ ffi::EVP_PKEY_CTX_free(self.pctx);
+ }
+ }
+}
+
+impl<'a> Encrypter<'a> {
+ /// Creates a new `Encrypter`.
+ ///
+ /// OpenSSL documentation at [`EVP_PKEY_encrypt_init`].
+ ///
+ /// [`EVP_PKEY_encrypt_init`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt_init.html
+ pub fn new<T>(pkey: &'a PKeyRef<T>) -> Result<Encrypter<'a>, ErrorStack>
+ where
+ T: HasPublic,
+ {
+ unsafe {
+ ffi::init();
+
+ let pctx = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
+ let r = ffi::EVP_PKEY_encrypt_init(pctx);
+ if r != 1 {
+ ffi::EVP_PKEY_CTX_free(pctx);
+ return Err(ErrorStack::get());
+ }
+
+ Ok(Encrypter {
+ pctx,
+ _p: PhantomData,
+ })
+ }
+ }
+
+ /// Returns the RSA padding mode in use.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
+ pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
+ unsafe {
+ let mut pad = 0;
+ cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
+ .map(|_| Padding::from_raw(pad))
+ }
+ }
+
+ /// Sets the RSA padding mode.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`].
+ ///
+ /// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_padding.html
+ pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
+ self.pctx,
+ padding.as_raw(),
+ ))
+ .map(|_| ())
+ }
+ }
+
+ /// Sets the RSA MGF1 algorithm.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
+ ///
+ /// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
+ pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
+ self.pctx,
+ md.as_ptr() as *mut _,
+ ))
+ .map(|_| ())
+ }
+ }
+
+ /// Sets the RSA OAEP algorithm.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`].
+ ///
+ /// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html
+ #[cfg(any(ossl102, libressl310))]
+ pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
+ self.pctx,
+ md.as_ptr() as *mut _,
+ ))
+ .map(|_| ())
+ }
+ }
+
+ /// Performs public key encryption.
+ ///
+ /// In order to know the size needed for the output buffer, use [`encrypt_len`](Encrypter::encrypt_len).
+ /// Note that the length of the output buffer can be greater of the length of the encoded data.
+ /// ```
+ /// # use openssl::{
+ /// # encrypt::Encrypter,
+ /// # pkey::PKey,
+ /// # rsa::{Rsa, Padding},
+ /// # };
+ /// #
+ /// # let key = include_bytes!("../test/rsa.pem");
+ /// # let private_key = Rsa::private_key_from_pem(key).unwrap();
+ /// # let pkey = PKey::from_rsa(private_key).unwrap();
+ /// # let input = b"hello world".to_vec();
+ /// #
+ /// let mut encrypter = Encrypter::new(&pkey).unwrap();
+ /// encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
+ ///
+ /// // Get the length of the output buffer
+ /// let buffer_len = encrypter.encrypt_len(&input).unwrap();
+ /// let mut encoded = vec![0u8; buffer_len];
+ ///
+ /// // Encode the data and get its length
+ /// let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
+ ///
+ /// // Use only the part of the buffer with the encoded data
+ /// let encoded = &encoded[..encoded_len];
+ /// ```
+ ///
+ /// This corresponds to [`EVP_PKEY_encrypt`].
+ ///
+ /// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html
+ pub fn encrypt(&self, from: &[u8], to: &mut [u8]) -> Result<usize, ErrorStack> {
+ let mut written = to.len();
+ unsafe {
+ cvt(ffi::EVP_PKEY_encrypt(
+ self.pctx,
+ to.as_mut_ptr(),
+ &mut written,
+ from.as_ptr(),
+ from.len(),
+ ))?;
+ }
+
+ Ok(written)
+ }
+
+ /// Gets the size of the buffer needed to encrypt the input data.
+ ///
+ /// This corresponds to [`EVP_PKEY_encrypt`] called with a null pointer as output argument.
+ ///
+ /// [`EVP_PKEY_encrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_encrypt.html
+ pub fn encrypt_len(&self, from: &[u8]) -> Result<usize, ErrorStack> {
+ let mut written = 0;
+ unsafe {
+ cvt(ffi::EVP_PKEY_encrypt(
+ self.pctx,
+ ptr::null_mut(),
+ &mut written,
+ from.as_ptr(),
+ from.len(),
+ ))?;
+ }
+
+ Ok(written)
+ }
+}
+
+/// A type which decrypts data.
+pub struct Decrypter<'a> {
+ pctx: *mut ffi::EVP_PKEY_CTX,
+ _p: PhantomData<&'a ()>,
+}
+
+unsafe impl<'a> Sync for Decrypter<'a> {}
+unsafe impl<'a> Send for Decrypter<'a> {}
+
+impl<'a> Drop for Decrypter<'a> {
+ fn drop(&mut self) {
+ unsafe {
+ ffi::EVP_PKEY_CTX_free(self.pctx);
+ }
+ }
+}
+
+impl<'a> Decrypter<'a> {
+ /// Creates a new `Decrypter`.
+ ///
+ /// OpenSSL documentation at [`EVP_PKEY_decrypt_init`].
+ ///
+ /// [`EVP_PKEY_decrypt_init`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt_init.html
+ pub fn new<T>(pkey: &'a PKeyRef<T>) -> Result<Decrypter<'a>, ErrorStack>
+ where
+ T: HasPrivate,
+ {
+ unsafe {
+ ffi::init();
+
+ let pctx = cvt_p(ffi::EVP_PKEY_CTX_new(pkey.as_ptr(), ptr::null_mut()))?;
+ let r = ffi::EVP_PKEY_decrypt_init(pctx);
+ if r != 1 {
+ ffi::EVP_PKEY_CTX_free(pctx);
+ return Err(ErrorStack::get());
+ }
+
+ Ok(Decrypter {
+ pctx,
+ _p: PhantomData,
+ })
+ }
+ }
+
+ /// Returns the RSA padding mode in use.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to `EVP_PKEY_CTX_get_rsa_padding`.
+ pub fn rsa_padding(&self) -> Result<Padding, ErrorStack> {
+ unsafe {
+ let mut pad = 0;
+ cvt(ffi::EVP_PKEY_CTX_get_rsa_padding(self.pctx, &mut pad))
+ .map(|_| Padding::from_raw(pad))
+ }
+ }
+
+ /// Sets the RSA padding mode.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to [`EVP_PKEY_CTX_set_rsa_padding`].
+ ///
+ /// [`EVP_PKEY_CTX_set_rsa_padding`]: https://www.openssl.org/docs/man1.1.0/crypto/EVP_PKEY_CTX_set_rsa_padding.html
+ pub fn set_rsa_padding(&mut self, padding: Padding) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::EVP_PKEY_CTX_set_rsa_padding(
+ self.pctx,
+ padding.as_raw(),
+ ))
+ .map(|_| ())
+ }
+ }
+
+ /// Sets the RSA MGF1 algorithm.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to [`EVP_PKEY_CTX_set_rsa_mgf1_md`].
+ ///
+ /// [`EVP_PKEY_CTX_set_rsa_mgf1_md`]: https://www.openssl.org/docs/manmaster/man7/RSA-PSS.html
+ pub fn set_rsa_mgf1_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::EVP_PKEY_CTX_set_rsa_mgf1_md(
+ self.pctx,
+ md.as_ptr() as *mut _,
+ ))
+ .map(|_| ())
+ }
+ }
+
+ /// Sets the RSA OAEP algorithm.
+ ///
+ /// This is only useful for RSA keys.
+ ///
+ /// This corresponds to [`EVP_PKEY_CTX_set_rsa_oaep_md`].
+ ///
+ /// [`EVP_PKEY_CTX_set_rsa_oaep_md`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_CTX_set_rsa_oaep_md.html
+ #[cfg(any(ossl102, libressl310))]
+ pub fn set_rsa_oaep_md(&mut self, md: MessageDigest) -> Result<(), ErrorStack> {
+ unsafe {
+ cvt(ffi::EVP_PKEY_CTX_set_rsa_oaep_md(
+ self.pctx,
+ md.as_ptr() as *mut _,
+ ))
+ .map(|_| ())
+ }
+ }
+
+ /// Performs public key decryption.
+ ///
+ /// In order to know the size needed for the output buffer, use [`decrypt_len`](Decrypter::decrypt_len).
+ /// Note that the length of the output buffer can be greater of the length of the decoded data.
+ /// ```
+ /// # use openssl::{
+ /// # encrypt::Decrypter,
+ /// # pkey::PKey,
+ /// # rsa::{Rsa, Padding},
+ /// # };
+ /// #
+ /// # const INPUT: &[u8] = b"\
+ /// # \x26\xa1\xc1\x13\xc5\x7f\xb4\x9f\xa0\xb4\xde\x61\x5e\x2e\xc6\xfb\x76\x5c\xd1\x2b\x5f\
+ /// # \x1d\x36\x60\xfa\xf8\xe8\xb3\x21\xf4\x9c\x70\xbc\x03\xea\xea\xac\xce\x4b\xb3\xf6\x45\
+ /// # \xcc\xb3\x80\x9e\xa8\xf7\xc3\x5d\x06\x12\x7a\xa3\x0c\x30\x67\xf1\xe7\x94\x6c\xf6\x26\
+ /// # \xac\x28\x17\x59\x69\xe1\xdc\xed\x7e\xc0\xe9\x62\x57\x49\xce\xdd\x13\x07\xde\x18\x03\
+ /// # \x0f\x9d\x61\x65\xb9\x23\x8c\x78\x4b\xad\x23\x49\x75\x47\x64\xa0\xa0\xa2\x90\xc1\x49\
+ /// # \x1b\x05\x24\xc2\xe9\x2c\x0d\x49\x78\x72\x61\x72\xed\x8b\x6f\x8a\xe8\xca\x05\x5c\x58\
+ /// # \xd6\x95\xd6\x7b\xe3\x2d\x0d\xaa\x3e\x6d\x3c\x9a\x1c\x1d\xb4\x6c\x42\x9d\x9a\x82\x55\
+ /// # \xd9\xde\xc8\x08\x7b\x17\xac\xd7\xaf\x86\x7b\x69\x9e\x3c\xf4\x5e\x1c\x39\x52\x6d\x62\
+ /// # \x50\x51\xbd\xa6\xc8\x4e\xe9\x34\xf0\x37\x0d\xa9\xa9\x77\xe6\xf5\xc2\x47\x2d\xa8\xee\
+ /// # \x3f\x69\x78\xff\xa9\xdc\x70\x22\x20\x9a\x5c\x9b\x70\x15\x90\xd3\xb4\x0e\x54\x9e\x48\
+ /// # \xed\xb6\x2c\x88\xfc\xb4\xa9\x37\x10\xfa\x71\xb2\xec\x75\xe7\xe7\x0e\xf4\x60\x2c\x7b\
+ /// # \x58\xaf\xa0\x53\xbd\x24\xf1\x12\xe3\x2e\x99\x25\x0a\x54\x54\x9d\xa1\xdb\xca\x41\x85\
+ /// # \xf4\x62\x78\x64";
+ /// #
+ /// # let key = include_bytes!("../test/rsa.pem");
+ /// # let private_key = Rsa::private_key_from_pem(key).unwrap();
+ /// # let pkey = PKey::from_rsa(private_key).unwrap();
+ /// # let input = INPUT.to_vec();
+ /// #
+ /// let mut decrypter = Decrypter::new(&pkey).unwrap();
+ /// decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
+ ///
+ /// // Get the length of the output buffer
+ /// let buffer_len = decrypter.decrypt_len(&input).unwrap();
+ /// let mut decoded = vec![0u8; buffer_len];
+ ///
+ /// // Decrypt the data and get its length
+ /// let decoded_len = decrypter.decrypt(&input, &mut decoded).unwrap();
+ ///
+ /// // Use only the part of the buffer with the decrypted data
+ /// let decoded = &decoded[..decoded_len];
+ /// ```
+ ///
+ /// This corresponds to [`EVP_PKEY_decrypt`].
+ ///
+ /// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt.html
+ pub fn decrypt(&self, from: &[u8], to: &mut [u8]) -> Result<usize, ErrorStack> {
+ let mut written = to.len();
+ unsafe {
+ cvt(ffi::EVP_PKEY_decrypt(
+ self.pctx,
+ to.as_mut_ptr(),
+ &mut written,
+ from.as_ptr(),
+ from.len(),
+ ))?;
+ }
+
+ Ok(written)
+ }
+
+ /// Gets the size of the buffer needed to decrypt the input data.
+ ///
+ /// This corresponds to [`EVP_PKEY_decrypt`] called with a null pointer as output argument.
+ ///
+ /// [`EVP_PKEY_decrypt`]: https://www.openssl.org/docs/manmaster/man3/EVP_PKEY_decrypt.html
+ pub fn decrypt_len(&self, from: &[u8]) -> Result<usize, ErrorStack> {
+ let mut written = 0;
+ unsafe {
+ cvt(ffi::EVP_PKEY_decrypt(
+ self.pctx,
+ ptr::null_mut(),
+ &mut written,
+ from.as_ptr(),
+ from.len(),
+ ))?;
+ }
+
+ Ok(written)
+ }
+}
+
+#[cfg(test)]
+mod test {
+ use hex::FromHex;
+
+ use encrypt::{Decrypter, Encrypter};
+ use hash::MessageDigest;
+ use pkey::PKey;
+ use rsa::{Padding, Rsa};
+
+ const INPUT: &str =
+ "65794a68624763694f694a53557a49314e694a392e65794a7063334d694f694a71623255694c41304b49434a6c\
+ 654841694f6a457a4d4441344d546b7a4f44417344516f67496d6830644841364c79396c654746746347786c4c\
+ 6d4e76625339706331397962323930496a7030636e566c6651";
+
+ #[test]
+ fn rsa_encrypt_decrypt() {
+ let key = include_bytes!("../test/rsa.pem");
+ let private_key = Rsa::private_key_from_pem(key).unwrap();
+ let pkey = PKey::from_rsa(private_key).unwrap();
+
+ let mut encrypter = Encrypter::new(&pkey).unwrap();
+ encrypter.set_rsa_padding(Padding::PKCS1).unwrap();
+ let input = Vec::from_hex(INPUT).unwrap();
+ let buffer_len = encrypter.encrypt_len(&input).unwrap();
+ let mut encoded = vec![0u8; buffer_len];
+ let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
+ let encoded = &encoded[..encoded_len];
+
+ let mut decrypter = Decrypter::new(&pkey).unwrap();
+ decrypter.set_rsa_padding(Padding::PKCS1).unwrap();
+ let buffer_len = decrypter.decrypt_len(&encoded).unwrap();
+ let mut decoded = vec![0u8; buffer_len];
+ let decoded_len = decrypter.decrypt(&encoded, &mut decoded).unwrap();
+ let decoded = &decoded[..decoded_len];
+
+ assert_eq!(decoded, &*input);
+ }
+
+ #[test]
+ #[cfg(any(ossl102, libressl310))]
+ fn rsa_encrypt_decrypt_with_sha256() {
+ let key = include_bytes!("../test/rsa.pem");
+ let private_key = Rsa::private_key_from_pem(key).unwrap();
+ let pkey = PKey::from_rsa(private_key).unwrap();
+
+ let md = MessageDigest::sha256();
+
+ let mut encrypter = Encrypter::new(&pkey).unwrap();
+ encrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
+ encrypter.set_rsa_oaep_md(md).unwrap();
+ encrypter.set_rsa_mgf1_md(md).unwrap();
+ let input = Vec::from_hex(INPUT).unwrap();
+ let buffer_len = encrypter.encrypt_len(&input).unwrap();
+ let mut encoded = vec![0u8; buffer_len];
+ let encoded_len = encrypter.encrypt(&input, &mut encoded).unwrap();
+ let encoded = &encoded[..encoded_len];
+
+ let mut decrypter = Decrypter::new(&pkey).unwrap();
+ decrypter.set_rsa_padding(Padding::PKCS1_OAEP).unwrap();
+ decrypter.set_rsa_oaep_md(md).unwrap();
+ decrypter.set_rsa_mgf1_md(md).unwrap();
+ let buffer_len = decrypter.decrypt_len(&encoded).unwrap();
+ let mut decoded = vec![0u8; buffer_len];
+ let decoded_len = decrypter.decrypt(&encoded, &mut decoded).unwrap();
+ let decoded = &decoded[..decoded_len];
+
+ assert_eq!(decoded, &*input);
+ }
+}
diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs
index 07ec23c9..1027eb52 100644
--- a/openssl/src/lib.rs
+++ b/openssl/src/lib.rs
@@ -151,6 +151,7 @@ pub mod dh;
pub mod dsa;
pub mod ec;
pub mod ecdsa;
+pub mod encrypt;
pub mod envelope;
pub mod error;
pub mod ex_data;