Unverified Commit 72d84b0c authored by Steven Fackler's avatar Steven Fackler Committed by GitHub
Browse files

Merge pull request #1561 from sfackler/cipher-ctx

Add CipherCtx
parents 66635f10 ee05a837
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -127,4 +127,9 @@ extern "C" {
    pub fn FIPS_mode_set(onoff: c_int) -> c_int;

    pub fn CRYPTO_memcmp(a: *const c_void, b: *const c_void, len: size_t) -> c_int;

    #[cfg(ossl300)]
    pub fn OSSL_LIB_CTX_new() -> *mut OSSL_LIB_CTX;
    #[cfg(ossl300)]
    pub fn OSSL_LIB_CTX_free(libcts: *mut OSSL_LIB_CTX);
}
+33 −1
Original line number Diff line number Diff line
@@ -39,6 +39,18 @@ cfg_if! {
            pub fn EVP_CIPHER_get_block_size(cipher: *const EVP_CIPHER) -> c_int;
            pub fn EVP_CIPHER_get_iv_length(cipher: *const EVP_CIPHER) -> c_int;
            pub fn EVP_CIPHER_get_nid(cipher: *const EVP_CIPHER) -> c_int;
            pub fn EVP_CIPHER_fetch(
                ctx: *mut OSSL_LIB_CTX,
                algorithm: *const c_char,
                properties: *const c_char,
            ) -> *mut EVP_CIPHER;
            pub fn EVP_CIPHER_free(cipher: *mut EVP_CIPHER);

            pub fn EVP_CIPHER_CTX_get0_cipher(ctx: *const EVP_CIPHER_CTX) -> *const EVP_CIPHER;
            pub fn EVP_CIPHER_CTX_get_block_size(ctx: *const EVP_CIPHER_CTX) -> c_int;
            pub fn EVP_CIPHER_CTX_get_key_length(ctx: *const EVP_CIPHER_CTX) -> c_int;
            pub fn EVP_CIPHER_CTX_get_iv_length(ctx: *const EVP_CIPHER_CTX) -> c_int;
            pub fn EVP_CIPHER_CTX_get_tag_length(ctx: *const EVP_CIPHER_CTX) -> c_int;
        }

        #[inline]
@@ -70,6 +82,21 @@ cfg_if! {
        pub unsafe fn EVP_CIPHER_nid(cipher: *const EVP_CIPHER) -> c_int {
            EVP_CIPHER_get_nid(cipher)
        }

        #[inline]
        pub unsafe fn EVP_CIPHER_CTX_block_size(ctx: *const EVP_CIPHER_CTX) -> c_int {
            EVP_CIPHER_CTX_get_block_size(ctx)
        }

        #[inline]
        pub unsafe fn EVP_CIPHER_CTX_key_length(ctx: *const EVP_CIPHER_CTX) -> c_int {
            EVP_CIPHER_CTX_get_key_length(ctx)
        }

        #[inline]
        pub unsafe fn EVP_CIPHER_CTX_iv_length(ctx: *const EVP_CIPHER_CTX) -> c_int {
            EVP_CIPHER_CTX_get_iv_length(ctx)
        }
    } else {
        extern "C" {
            pub fn EVP_MD_size(md: *const EVP_MD) -> c_int;
@@ -79,10 +106,14 @@ cfg_if! {
            pub fn EVP_CIPHER_block_size(cipher: *const EVP_CIPHER) -> c_int;
            pub fn EVP_CIPHER_iv_length(cipher: *const EVP_CIPHER) -> c_int;
            pub fn EVP_CIPHER_nid(cipher: *const EVP_CIPHER) -> c_int;

            pub fn EVP_CIPHER_CTX_cipher(ctx: *const EVP_CIPHER_CTX) -> *const EVP_CIPHER;
            pub fn EVP_CIPHER_CTX_block_size(ctx: *const EVP_CIPHER_CTX) -> c_int;
            pub fn EVP_CIPHER_CTX_key_length(ctx: *const EVP_CIPHER_CTX) -> c_int;
            pub fn EVP_CIPHER_CTX_iv_length(ctx: *const EVP_CIPHER_CTX) -> c_int;
        }
    }
}
extern "C" {}

cfg_if! {
    if #[cfg(ossl110)] {
@@ -291,6 +322,7 @@ extern "C" {
        arg: c_int,
        ptr: *mut c_void,
    ) -> c_int;
    pub fn EVP_CIPHER_CTX_rand_key(ctx: *mut EVP_CIPHER_CTX, key: *mut c_uchar) -> c_int;

    pub fn EVP_md_null() -> *const EVP_MD;
    pub fn EVP_md5() -> *const EVP_MD;

openssl/src/cipher.rs

0 → 100644
+393 −0
Original line number Diff line number Diff line
//! Symmetric ciphers.

#[cfg(ossl300)]
use crate::cvt_p;
#[cfg(ossl300)]
use crate::error::ErrorStack;
#[cfg(ossl300)]
use crate::lib_ctx::LibCtxRef;
use crate::nid::Nid;
use cfg_if::cfg_if;
use foreign_types::{ForeignTypeRef, Opaque};
#[cfg(ossl300)]
use std::ffi::CString;
#[cfg(ossl300)]
use std::ptr;

cfg_if! {
    if #[cfg(any(ossl110, libressl273))] {
        use ffi::{EVP_CIPHER_block_size, EVP_CIPHER_iv_length, EVP_CIPHER_key_length};
    } else {
        use libc::c_int;

        #[allow(bad_style)]
        pub unsafe fn EVP_CIPHER_iv_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
            (*ptr).iv_len
        }

        #[allow(bad_style)]
        pub unsafe fn EVP_CIPHER_block_size(ptr: *const ffi::EVP_CIPHER) -> c_int {
            (*ptr).block_size
        }

        #[allow(bad_style)]
        pub unsafe fn EVP_CIPHER_key_length(ptr: *const ffi::EVP_CIPHER) -> c_int {
            (*ptr).key_len
        }
    }
}

cfg_if! {
    if #[cfg(ossl300)] {
        use foreign_types::ForeignType;
        use std::ops::{Deref, DerefMut};

        type Inner = *mut ffi::EVP_CIPHER;

        impl Drop for Cipher {
            #[inline]
            fn drop(&mut self) {
                unsafe {
                    ffi::EVP_CIPHER_free(self.as_ptr());
                }
            }
        }

        impl ForeignType for Cipher {
            type CType = ffi::EVP_CIPHER;
            type Ref = CipherRef;

            #[inline]
            unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
                Cipher(ptr)
            }

            #[inline]
            fn as_ptr(&self) -> *mut Self::CType {
                self.0
            }
        }

        impl Deref for Cipher {
            type Target = CipherRef;

            #[inline]
            fn deref(&self) -> &Self::Target {
                unsafe {
                    CipherRef::from_ptr(self.as_ptr())
                }
            }
        }

        impl DerefMut for Cipher {
            #[inline]
            fn deref_mut(&mut self) -> &mut Self::Target {
                unsafe {
                    CipherRef::from_ptr_mut(self.as_ptr())
                }
            }
        }
    } else {
        enum Inner {}
    }
}

/// A symmetric cipher.
pub struct Cipher(Inner);

unsafe impl Sync for Cipher {}
unsafe impl Send for Cipher {}

impl Cipher {
    /// Looks up the cipher for a certain nid.
    ///
    /// This corresponds to [`EVP_get_cipherbynid`]
    ///
    /// [`EVP_get_cipherbynid`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_get_cipherbyname.html
    pub fn from_nid(nid: Nid) -> Option<&'static CipherRef> {
        unsafe {
            let ptr = ffi::EVP_get_cipherbyname(ffi::OBJ_nid2sn(nid.as_raw()));
            if ptr.is_null() {
                None
            } else {
                Some(CipherRef::from_ptr(ptr as *mut _))
            }
        }
    }

    /// Fetches a cipher object corresponding to the specified algorithm name and properties.
    ///
    /// This corresponds to [`EVP_CIPHER_fetch`].
    ///
    /// Requires OpenSSL 3.0.0 or newer.
    ///
    /// [`EVP_CIPHER_fetch`]: https://www.openssl.org/docs/manmaster/man3/EVP_CIPHER_fetch.html
    #[cfg(ossl300)]
    pub fn fetch(
        ctx: Option<&LibCtxRef>,
        algorithm: &str,
        properties: Option<&str>,
    ) -> Result<Self, ErrorStack> {
        let algorithm = CString::new(algorithm).unwrap();
        let properties = properties.map(|s| CString::new(s).unwrap());

        unsafe {
            let ptr = cvt_p(ffi::EVP_CIPHER_fetch(
                ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
                algorithm.as_ptr(),
                properties.map_or(ptr::null_mut(), |s| s.as_ptr()),
            ))?;

            Ok(Cipher::from_ptr(ptr))
        }
    }

    pub fn aes_128_ecb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ecb() as *mut _) }
    }

    pub fn aes_128_cbc() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cbc() as *mut _) }
    }

    pub fn aes_128_xts() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_xts() as *mut _) }
    }

    pub fn aes_128_ctr() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ctr() as *mut _) }
    }

    pub fn aes_128_cfb1() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb1() as *mut _) }
    }

    pub fn aes_128_cfb128() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb128() as *mut _) }
    }

    pub fn aes_128_cfb8() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_cfb8() as *mut _) }
    }

    pub fn aes_128_gcm() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_gcm() as *mut _) }
    }

    pub fn aes_128_ccm() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ccm() as *mut _) }
    }

    pub fn aes_128_ofb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ofb() as *mut _) }
    }

    /// Requires OpenSSL 1.1.0 or newer.
    #[cfg(ossl110)]
    pub fn aes_128_ocb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_128_ocb() as *mut _) }
    }

    pub fn aes_192_ecb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ecb() as *mut _) }
    }

    pub fn aes_192_cbc() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cbc() as *mut _) }
    }

    pub fn aes_192_ctr() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ctr() as *mut _) }
    }

    pub fn aes_192_cfb1() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb1() as *mut _) }
    }

    pub fn aes_192_cfb128() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb128() as *mut _) }
    }

    pub fn aes_192_cfb8() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_cfb8() as *mut _) }
    }

    pub fn aes_192_gcm() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_gcm() as *mut _) }
    }

    pub fn aes_192_ccm() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ccm() as *mut _) }
    }

    pub fn aes_192_ofb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ofb() as *mut _) }
    }

    /// Requires OpenSSL 1.1.0 or newer.
    #[cfg(ossl110)]
    pub fn aes_192_ocb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_192_ocb() as *mut _) }
    }

    pub fn aes_256_ecb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ecb() as *mut _) }
    }

    pub fn aes_256_cbc() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cbc() as *mut _) }
    }

    pub fn aes_256_ctr() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ctr() as *mut _) }
    }

    pub fn aes_256_cfb1() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb1() as *mut _) }
    }

    pub fn aes_256_cfb128() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb128() as *mut _) }
    }

    pub fn aes_256_cfb8() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_cfb8() as *mut _) }
    }

    pub fn aes_256_gcm() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_gcm() as *mut _) }
    }

    pub fn aes_256_ccm() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ccm() as *mut _) }
    }

    pub fn aes_256_ofb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ofb() as *mut _) }
    }

    /// Requires OpenSSL 1.1.0 or newer.
    #[cfg(ossl110)]
    pub fn aes_256_ocb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_aes_256_ocb() as *mut _) }
    }

    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
    pub fn bf_cbc() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_bf_cbc() as *mut _) }
    }

    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
    pub fn bf_ecb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_bf_ecb() as *mut _) }
    }

    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
    pub fn bf_cfb64() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_bf_cfb64() as *mut _) }
    }

    #[cfg(not(osslconf = "OPENSSL_NO_BF"))]
    pub fn bf_ofb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_bf_ofb() as *mut _) }
    }

    pub fn des_cbc() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_des_cbc() as *mut _) }
    }

    pub fn des_ecb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_des_ecb() as *mut _) }
    }

    pub fn des_ede3() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3() as *mut _) }
    }

    pub fn des_ede3_cbc() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cbc() as *mut _) }
    }

    pub fn des_ede3_cfb64() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_des_ede3_cfb64() as *mut _) }
    }

    pub fn rc4() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_rc4() as *mut _) }
    }

    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_CHACHA")))]
    pub fn chacha20() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_chacha20() as *mut _) }
    }

    #[cfg(all(ossl110, not(osslconf = "OPENSSL_NO_CHACHA")))]
    pub fn chacha20_poly1305() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_chacha20_poly1305() as *mut _) }
    }

    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
    pub fn seed_cbc() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_seed_cbc() as *mut _) }
    }

    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
    pub fn seed_cfb128() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_seed_cfb128() as *mut _) }
    }

    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
    pub fn seed_ecb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_seed_ecb() as *mut _) }
    }

    #[cfg(not(osslconf = "OPENSSL_NO_SEED"))]
    pub fn seed_ofb() -> &'static CipherRef {
        unsafe { CipherRef::from_ptr(ffi::EVP_seed_ofb() as *mut _) }
    }
}

/// A reference to a [`Cipher`].
pub struct CipherRef(Opaque);

impl ForeignTypeRef for CipherRef {
    type CType = ffi::EVP_CIPHER;
}

unsafe impl Sync for CipherRef {}
unsafe impl Send for CipherRef {}

impl CipherRef {
    /// Returns the cipher's Nid.
    ///
    /// This corresponds to [`EVP_CIPHER_nid`]
    ///
    /// [`EVP_CIPHER_nid`]: https://www.openssl.org/docs/man1.0.2/crypto/EVP_CIPHER_nid.html
    pub fn nid(&self) -> Nid {
        let nid = unsafe { ffi::EVP_CIPHER_nid(self.as_ptr()) };
        Nid::from_raw(nid)
    }

    /// Returns the length of keys used with this cipher.
    pub fn key_length(&self) -> usize {
        unsafe { EVP_CIPHER_key_length(self.as_ptr()) as usize }
    }

    /// Returns the length of the IV used with this cipher.
    ///
    /// # Note
    ///
    /// Ciphers that do not use an IV have an IV length of 0.
    pub fn iv_length(&self) -> usize {
        unsafe { EVP_CIPHER_iv_length(self.as_ptr()) as usize }
    }

    /// Returns the block size of the cipher.
    ///
    /// # Note
    ///
    /// Stream ciphers have a block size of 1.
    pub fn block_size(&self) -> usize {
        unsafe { EVP_CIPHER_block_size(self.as_ptr()) as usize }
    }
}
+717 −0

File added.

Preview size limit exceeded, changes collapsed.

+30 −131
Original line number Diff line number Diff line
@@ -21,19 +21,16 @@
//! enc_len += seal.finalize(&mut encrypted[enc_len..]).unwrap();
//! encrypted.truncate(enc_len);
//! ```
use crate::cipher::CipherRef;
use crate::cipher_ctx::CipherCtx;
use crate::error::ErrorStack;
use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef};
use crate::symm::Cipher;
use crate::{cvt, cvt_p};
use foreign_types::{ForeignType, ForeignTypeRef};
use libc::c_int;
use std::cmp;
use std::ptr;
use foreign_types::ForeignTypeRef;

/// Represents an EVP_Seal context.
pub struct Seal {
    ctx: *mut ffi::EVP_CIPHER_CTX,
    block_size: usize,
    ctx: CipherCtx,
    iv: Option<Vec<u8>>,
    enc_keys: Vec<Vec<u8>>,
}
@@ -44,45 +41,18 @@ impl Seal {
    where
        T: HasPublic,
    {
        unsafe {
            assert!(pub_keys.len() <= c_int::max_value() as usize);

            let ctx = cvt_p(ffi::EVP_CIPHER_CTX_new())?;
            let mut enc_key_ptrs = vec![];
            let mut pub_key_ptrs = vec![];
            let mut enc_keys = vec![];
            for key in pub_keys {
                let mut enc_key = vec![0; key.size()];
                let enc_key_ptr = enc_key.as_mut_ptr();
                enc_keys.push(enc_key);
                enc_key_ptrs.push(enc_key_ptr);
                pub_key_ptrs.push(key.as_ptr());
            }
        let mut iv = cipher.iv_len().map(|len| vec![0; len]);
            let iv_ptr = iv.as_mut().map_or(ptr::null_mut(), |v| v.as_mut_ptr());
            let mut enc_key_lens = vec![0; enc_keys.len()];
        let mut enc_keys = vec![vec![]; pub_keys.len()];

            cvt(ffi::EVP_SealInit(
                ctx,
                cipher.as_ptr(),
                enc_key_ptrs.as_mut_ptr(),
                enc_key_lens.as_mut_ptr(),
                iv_ptr,
                pub_key_ptrs.as_mut_ptr(),
                pub_key_ptrs.len() as c_int,
            ))?;
        let mut ctx = CipherCtx::new()?;
        ctx.seal_init(
            Some(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) }),
            pub_keys,
            &mut enc_keys,
            iv.as_deref_mut(),
        )?;

            for (buf, len) in enc_keys.iter_mut().zip(&enc_key_lens) {
                buf.truncate(*len as usize);
            }

            Ok(Seal {
                ctx,
                block_size: cipher.block_size(),
                iv,
                enc_keys,
            })
        }
        Ok(Seal { ctx, iv, enc_keys })
    }

    /// Returns the initialization vector, if the cipher uses one.
@@ -107,20 +77,7 @@ impl Seal {
    /// the block size of the cipher (see `Cipher::block_size`), or if
    /// `output.len() > c_int::max_value()`.
    pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack> {
        unsafe {
            assert!(output.len() >= input.len() + self.block_size);
            assert!(output.len() <= c_int::max_value() as usize);
            let mut outl = output.len() as c_int;
            let inl = input.len() as c_int;
            cvt(ffi::EVP_EncryptUpdate(
                self.ctx,
                output.as_mut_ptr(),
                &mut outl,
                input.as_ptr(),
                inl,
            ))?;
            Ok(outl as usize)
        }
        self.ctx.cipher_update(input, Some(output))
    }

    /// Finishes the encryption process, writing any remaining data to `output`.
@@ -133,29 +90,13 @@ impl Seal {
    ///
    /// Panics if `output` is less than the cipher's block size.
    pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
        unsafe {
            assert!(output.len() >= self.block_size);
            let mut outl = cmp::min(output.len(), c_int::max_value() as usize) as c_int;

            cvt(ffi::EVP_SealFinal(self.ctx, output.as_mut_ptr(), &mut outl))?;

            Ok(outl as usize)
        }
    }
}

impl Drop for Seal {
    fn drop(&mut self) {
        unsafe {
            ffi::EVP_CIPHER_CTX_free(self.ctx);
        }
        self.ctx.cipher_final(output)
    }
}

/// Represents an EVP_Open context.
pub struct Open {
    ctx: *mut ffi::EVP_CIPHER_CTX,
    block_size: usize,
    ctx: CipherCtx,
}

impl Open {
@@ -169,29 +110,15 @@ impl Open {
    where
        T: HasPrivate,
    {
        unsafe {
            assert!(encrypted_key.len() <= c_int::max_value() as usize);
            match (cipher.iv_len(), iv) {
                (Some(len), Some(iv)) => assert_eq!(len, iv.len(), "IV length mismatch"),
                (None, None) => {}
                (Some(_), None) => panic!("an IV was required but not provided"),
                (None, Some(_)) => panic!("an IV was provided but not required"),
            }
        let mut ctx = CipherCtx::new()?;
        ctx.open_init(
            Some(unsafe { CipherRef::from_ptr(cipher.as_ptr() as *mut _) }),
            encrypted_key,
            iv,
            Some(priv_key),
        )?;

            let ctx = cvt_p(ffi::EVP_CIPHER_CTX_new())?;
            cvt(ffi::EVP_OpenInit(
                ctx,
                cipher.as_ptr(),
                encrypted_key.as_ptr(),
                encrypted_key.len() as c_int,
                iv.map_or(ptr::null(), |v| v.as_ptr()),
                priv_key.as_ptr(),
            ))?;
            Ok(Open {
                ctx,
                block_size: cipher.block_size(),
            })
        }
        Ok(Open { ctx })
    }

    /// Feeds data from `input` through the cipher, writing decrypted bytes into `output`.
@@ -205,20 +132,7 @@ impl Open {
    /// `block_size` is the block size of the cipher (see `Cipher::block_size`),
    /// or if `output.len() > c_int::max_value()`.
    pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack> {
        unsafe {
            assert!(output.len() >= input.len() + self.block_size);
            assert!(output.len() <= c_int::max_value() as usize);
            let mut outl = output.len() as c_int;
            let inl = input.len() as c_int;
            cvt(ffi::EVP_DecryptUpdate(
                self.ctx,
                output.as_mut_ptr(),
                &mut outl,
                input.as_ptr(),
                inl,
            ))?;
            Ok(outl as usize)
        }
        self.ctx.cipher_update(input, Some(output))
    }

    /// Finishes the decryption process, writing any remaining data to `output`.
@@ -231,22 +145,7 @@ impl Open {
    ///
    /// Panics if `output` is less than the cipher's block size.
    pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> {
        unsafe {
            assert!(output.len() >= self.block_size);
            let mut outl = cmp::min(output.len(), c_int::max_value() as usize) as c_int;

            cvt(ffi::EVP_OpenFinal(self.ctx, output.as_mut_ptr(), &mut outl))?;

            Ok(outl as usize)
        }
    }
}

impl Drop for Open {
    fn drop(&mut self) {
        unsafe {
            ffi::EVP_CIPHER_CTX_free(self.ctx);
        }
        self.ctx.cipher_final(output)
    }
}

Loading