Loading openssl/src/cipher_ctx.rs +79 −1 Original line number Diff line number Diff line use crate::error::ErrorStack; use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef}; use crate::symm::{Cipher, Mode}; use crate::{cvt, cvt_p}; use cfg_if::cfg_if; Loading Loading @@ -35,7 +36,7 @@ impl CipherCtx { } impl CipherCtxRef { pub fn init( pub fn cipher_init( &mut self, // FIXME CipherRef type_: Option<&Cipher>, Loading Loading @@ -74,6 +75,83 @@ impl CipherCtxRef { Ok(()) } pub fn seal_init<T>( &mut self, // FIXME CipherRef type_: Option<&Cipher>, pub_keys: &[PKey<T>], encrypted_keys: &mut [Vec<u8>], iv: Option<&mut [u8]>, ) -> Result<(), ErrorStack> where T: HasPublic, { assert_eq!(pub_keys.len(), encrypted_keys.len()); let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_len()); if let Some(iv_len) = iv_len { assert!(iv.as_ref().map_or(0, |b| b.len()) >= iv_len); } for (pub_key, buf) in pub_keys.iter().zip(&mut *encrypted_keys) { buf.resize(pub_key.size(), 0); } let mut keys = encrypted_keys .iter_mut() .map(|b| b.as_mut_ptr()) .collect::<Vec<_>>(); let mut key_lengths = vec![0; pub_keys.len()]; let pub_keys_len = i32::try_from(pub_keys.len()).unwrap(); unsafe { cvt(ffi::EVP_SealInit( self.as_ptr(), type_.map_or(ptr::null(), Cipher::as_ptr), keys.as_mut_ptr(), key_lengths.as_mut_ptr(), iv.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), pub_keys.as_ptr() as *mut _, pub_keys_len, ))?; } for (buf, len) in encrypted_keys.iter_mut().zip(key_lengths) { buf.truncate(len as usize); } Ok(()) } pub fn open_init<T>( &mut self, type_: Option<&Cipher>, encrypted_key: &[u8], iv: Option<&[u8]>, priv_key: Option<&PKeyRef<T>>, ) -> Result<(), ErrorStack> where T: HasPrivate, { let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_len()); if let Some(iv_len) = iv_len { assert!(iv.map_or(0, |b| b.len()) >= iv_len); } let len = c_int::try_from(encrypted_key.len()).unwrap(); unsafe { cvt(ffi::EVP_OpenInit( self.as_ptr(), type_.map_or(ptr::null(), Cipher::as_ptr), encrypted_key.as_ptr(), len, iv.map_or(ptr::null(), |b| b.as_ptr()), priv_key.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr), ))?; } Ok(()) } fn assert_cipher(&self) { unsafe { assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null()); Loading openssl/src/envelope.rs +15 −128 Original line number Diff line number Diff line Loading @@ -21,19 +21,14 @@ //! enc_len += seal.finalize(&mut encrypted[enc_len..]).unwrap(); //! encrypted.truncate(enc_len); //! ``` 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; /// 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>>, } Loading @@ -44,45 +39,13 @@ 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()]; 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 enc_keys = vec![vec![]; pub_keys.len()]; for (buf, len) in enc_keys.iter_mut().zip(&enc_key_lens) { buf.truncate(*len as usize); } let mut ctx = CipherCtx::new()?; ctx.seal_init(Some(&cipher), pub_keys, &mut enc_keys, iv.as_deref_mut())?; 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. Loading @@ -107,20 +70,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.update(input, Some(output)) } /// Finishes the encryption process, writing any remaining data to `output`. Loading @@ -133,29 +83,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.finalize(output) } } /// Represents an EVP_Open context. pub struct Open { ctx: *mut ffi::EVP_CIPHER_CTX, block_size: usize, ctx: CipherCtx, } impl Open { Loading @@ -169,29 +103,10 @@ 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(&cipher), 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`. Loading @@ -205,20 +120,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.update(input, Some(output)) } /// Finishes the decryption process, writing any remaining data to `output`. Loading @@ -231,22 +133,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.finalize(output) } } Loading openssl/src/symm.rs +2 −2 Original line number Diff line number Diff line Loading @@ -451,7 +451,7 @@ impl Crypter { iv: Option<&[u8]>, ) -> Result<Crypter, ErrorStack> { let mut ctx = CipherCtx::new()?; ctx.init(Some(&t), None, None, mode)?; ctx.cipher_init(Some(&t), None, None, mode)?; ctx.set_key_length(key.len())?; Loading @@ -459,7 +459,7 @@ impl Crypter { ctx.set_iv_length(iv.len())?; } ctx.init(None, Some(key), iv, mode)?; ctx.cipher_init(None, Some(key), iv, mode)?; Ok(Crypter { ctx }) } Loading Loading
openssl/src/cipher_ctx.rs +79 −1 Original line number Diff line number Diff line use crate::error::ErrorStack; use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef}; use crate::symm::{Cipher, Mode}; use crate::{cvt, cvt_p}; use cfg_if::cfg_if; Loading Loading @@ -35,7 +36,7 @@ impl CipherCtx { } impl CipherCtxRef { pub fn init( pub fn cipher_init( &mut self, // FIXME CipherRef type_: Option<&Cipher>, Loading Loading @@ -74,6 +75,83 @@ impl CipherCtxRef { Ok(()) } pub fn seal_init<T>( &mut self, // FIXME CipherRef type_: Option<&Cipher>, pub_keys: &[PKey<T>], encrypted_keys: &mut [Vec<u8>], iv: Option<&mut [u8]>, ) -> Result<(), ErrorStack> where T: HasPublic, { assert_eq!(pub_keys.len(), encrypted_keys.len()); let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_len()); if let Some(iv_len) = iv_len { assert!(iv.as_ref().map_or(0, |b| b.len()) >= iv_len); } for (pub_key, buf) in pub_keys.iter().zip(&mut *encrypted_keys) { buf.resize(pub_key.size(), 0); } let mut keys = encrypted_keys .iter_mut() .map(|b| b.as_mut_ptr()) .collect::<Vec<_>>(); let mut key_lengths = vec![0; pub_keys.len()]; let pub_keys_len = i32::try_from(pub_keys.len()).unwrap(); unsafe { cvt(ffi::EVP_SealInit( self.as_ptr(), type_.map_or(ptr::null(), Cipher::as_ptr), keys.as_mut_ptr(), key_lengths.as_mut_ptr(), iv.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), pub_keys.as_ptr() as *mut _, pub_keys_len, ))?; } for (buf, len) in encrypted_keys.iter_mut().zip(key_lengths) { buf.truncate(len as usize); } Ok(()) } pub fn open_init<T>( &mut self, type_: Option<&Cipher>, encrypted_key: &[u8], iv: Option<&[u8]>, priv_key: Option<&PKeyRef<T>>, ) -> Result<(), ErrorStack> where T: HasPrivate, { let iv_len = type_.map_or_else(|| self.iv_length(), |c| c.iv_len()); if let Some(iv_len) = iv_len { assert!(iv.map_or(0, |b| b.len()) >= iv_len); } let len = c_int::try_from(encrypted_key.len()).unwrap(); unsafe { cvt(ffi::EVP_OpenInit( self.as_ptr(), type_.map_or(ptr::null(), Cipher::as_ptr), encrypted_key.as_ptr(), len, iv.map_or(ptr::null(), |b| b.as_ptr()), priv_key.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr), ))?; } Ok(()) } fn assert_cipher(&self) { unsafe { assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null()); Loading
openssl/src/envelope.rs +15 −128 Original line number Diff line number Diff line Loading @@ -21,19 +21,14 @@ //! enc_len += seal.finalize(&mut encrypted[enc_len..]).unwrap(); //! encrypted.truncate(enc_len); //! ``` 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; /// 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>>, } Loading @@ -44,45 +39,13 @@ 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()]; 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 enc_keys = vec![vec![]; pub_keys.len()]; for (buf, len) in enc_keys.iter_mut().zip(&enc_key_lens) { buf.truncate(*len as usize); } let mut ctx = CipherCtx::new()?; ctx.seal_init(Some(&cipher), pub_keys, &mut enc_keys, iv.as_deref_mut())?; 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. Loading @@ -107,20 +70,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.update(input, Some(output)) } /// Finishes the encryption process, writing any remaining data to `output`. Loading @@ -133,29 +83,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.finalize(output) } } /// Represents an EVP_Open context. pub struct Open { ctx: *mut ffi::EVP_CIPHER_CTX, block_size: usize, ctx: CipherCtx, } impl Open { Loading @@ -169,29 +103,10 @@ 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(&cipher), 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`. Loading @@ -205,20 +120,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.update(input, Some(output)) } /// Finishes the decryption process, writing any remaining data to `output`. Loading @@ -231,22 +133,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.finalize(output) } } Loading
openssl/src/symm.rs +2 −2 Original line number Diff line number Diff line Loading @@ -451,7 +451,7 @@ impl Crypter { iv: Option<&[u8]>, ) -> Result<Crypter, ErrorStack> { let mut ctx = CipherCtx::new()?; ctx.init(Some(&t), None, None, mode)?; ctx.cipher_init(Some(&t), None, None, mode)?; ctx.set_key_length(key.len())?; Loading @@ -459,7 +459,7 @@ impl Crypter { ctx.set_iv_length(iv.len())?; } ctx.init(None, Some(key), iv, mode)?; ctx.cipher_init(None, Some(key), iv, mode)?; Ok(Crypter { ctx }) } Loading