Loading openssl-sys/src/evp.rs +32 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,12 @@ 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_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] Loading Loading @@ -70,6 +76,26 @@ 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) } #[inline] pub unsafe fn EVP_CIPHER_CTX_tag_length(ctx: *const EVP_CIPHER_CTX) -> c_int { EVP_CIPHER_CTX_get_tag_length(ctx) } } else { extern "C" { pub fn EVP_MD_size(md: *const EVP_MD) -> c_int; Loading @@ -79,10 +105,15 @@ 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; pub fn EVP_CIPHER_CTX_tag_length(ctx: *const EVP_CIPHER_CTX) -> c_int; } } } extern "C" {} cfg_if! { if #[cfg(ossl110)] { Loading openssl/src/cipher_ctx.rs 0 → 100644 +273 −0 Original line number Diff line number Diff line use crate::error::ErrorStack; use crate::symm::{Cipher, Mode}; use crate::{cvt, cvt_p}; use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef}; use libc::c_int; use std::convert::TryFrom; use std::ptr; cfg_if! { if #[cfg(ossl300)] { use ffi::EVP_CIPHER_CTX_get0_cipher; } else { use ffi::EVP_CIPHER_CTX_cipher as EVP_CIPHER_CTX_get0_cipher; } } foreign_type_and_impl_send_sync! { type CType = ffi::EVP_CIPHER_CTX; fn drop = ffi::EVP_CIPHER_CTX_free; pub struct CipherCtx; pub struct CipherCtxRef; } impl CipherCtx { pub fn new() -> Result<Self, ErrorStack> { ffi::init(); unsafe { let ptr = cvt_p(ffi::EVP_CIPHER_CTX_new())?; Ok(CipherCtx::from_ptr(ptr)) } } } impl CipherCtxRef { pub fn init( &mut self, // FIXME CipherRef type_: Option<&Cipher>, key: Option<&[u8]>, iv: Option<&[u8]>, mode: Mode, ) -> Result<(), ErrorStack> { if let Some(key) = key { if let Some(len) = self.key_length() { assert_eq!(len, key.len()); } } if let Some(iv) = iv { if let Some(len) = self.iv_length() { assert_eq!(len, iv.len()); } } let mode = match mode { Mode::Encrypt => 1, Mode::Decrypt => 0, }; unsafe { cvt(ffi::EVP_CipherInit_ex( self.as_ptr(), type_.map_or(ptr::null(), Cipher::as_ptr), ptr::null_mut(), key.map_or(ptr::null(), |k| k.as_ptr()), iv.map_or(ptr::null(), |iv| iv.as_ptr()), mode, ))?; } Ok(()) } fn assert_cipher(&self) { unsafe { assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null()); } } pub fn block_size(&self) -> Option<usize> { self.assert_cipher(); unsafe { let r = ffi::EVP_CIPHER_CTX_block_size(self.as_ptr()); if r > 0 { Some(r as usize) } else { None } } } pub fn key_length(&self) -> Option<usize> { self.assert_cipher(); unsafe { let r = ffi::EVP_CIPHER_CTX_key_length(self.as_ptr()); if r > 0 { Some(r as usize) } else { None } } } pub fn set_key_length(&mut self, len: usize) -> Result<(), ErrorStack> { self.assert_cipher(); let len = c_int::try_from(len).unwrap(); unsafe { cvt(ffi::EVP_CIPHER_CTX_set_key_length(self.as_ptr(), len))?; } Ok(()) } pub fn iv_length(&self) -> Option<usize> { self.assert_cipher(); unsafe { let r = ffi::EVP_CIPHER_CTX_iv_length(self.as_ptr()); if r > 0 { Some(r as usize) } else { None } } } pub fn set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack> { self.assert_cipher(); let len = c_int::try_from(len).unwrap(); unsafe { cvt(ffi::EVP_CIPHER_CTX_ctrl( self.as_ptr(), ffi::EVP_CTRL_GCM_SET_IVLEN, len, ptr::null_mut(), ))?; } Ok(()) } pub fn tag_length(&self) -> Option<usize> { self.assert_cipher(); unsafe { let r = ffi::EVP_CIPHER_CTX_tag_length(self.as_ptr()); if r > 0 { Some(r as usize) } else { None } } } pub fn tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(tag.len()).unwrap(); unsafe { cvt(ffi::EVP_CIPHER_CTX_ctrl( self.as_ptr(), ffi::EVP_CTRL_GCM_GET_TAG, len, tag.as_mut_ptr() as *mut _, ))?; } Ok(()) } pub fn set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack> { let len = c_int::try_from(len).unwrap(); unsafe { cvt(ffi::EVP_CIPHER_CTX_ctrl( self.as_ptr(), ffi::EVP_CTRL_GCM_SET_TAG, len, ptr::null_mut(), ))?; } Ok(()) } pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(tag.len()).unwrap(); unsafe { cvt(ffi::EVP_CIPHER_CTX_ctrl( self.as_ptr(), ffi::EVP_CTRL_GCM_SET_TAG, len, tag.as_ptr() as *mut _, ))?; } Ok(()) } pub fn set_padding(&mut self, padding: bool) { unsafe { ffi::EVP_CIPHER_CTX_set_padding(self.as_ptr(), padding as c_int); } } pub fn set_data_len(&mut self, len: usize) -> Result<(), ErrorStack> { let len = c_int::try_from(len).unwrap(); unsafe { cvt(ffi::EVP_CipherUpdate( self.as_ptr(), ptr::null_mut(), &mut 0, ptr::null(), len, ))?; } Ok(()) } pub fn update(&mut self, input: &[u8], output: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let inlen = c_int::try_from(input.len()).unwrap(); if let (Some(mut block_size), Some(output)) = (self.block_size(), &output) { if block_size == 1 { block_size = 0; } assert!(output.len() >= input.len() + block_size); } let mut outlen = 0; unsafe { cvt(ffi::EVP_CipherUpdate( self.as_ptr(), output.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut outlen, input.as_ptr(), inlen, ))?; } Ok(outlen as usize) } pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> { if let Some(block_size) = self.block_size() { if block_size > 1 { assert!(output.len() >= block_size); } } let mut outl = 0; unsafe { cvt(ffi::EVP_CipherFinal( self.as_ptr(), output.as_mut_ptr(), &mut outl, ))?; } Ok(outl as usize) } } openssl/src/lib.rs +1 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,7 @@ pub mod aes; pub mod asn1; pub mod base64; pub mod bn; pub mod cipher_ctx; #[cfg(all(not(libressl), not(osslconf = "OPENSSL_NO_CMS")))] pub mod cms; pub mod conf; Loading openssl/src/symm.rs +22 −169 Original line number Diff line number Diff line Loading @@ -51,15 +51,10 @@ //! assert_eq!("Foo bar", output_string); //! println!("Decrypted: '{}'", output_string); //! ``` use cfg_if::cfg_if; use libc::c_int; use std::cmp; use std::ptr; use crate::cipher_ctx::CipherCtx; use crate::error::ErrorStack; use crate::nid::Nid; use crate::{cvt, cvt_p}; use cfg_if::cfg_if; #[derive(Copy, Clone)] pub enum Mode { Loading Loading @@ -438,13 +433,9 @@ unsafe impl Send for Cipher {} /// assert_eq!(b"Some Stream of Crypto Text", &plaintext[..]); /// ``` pub struct Crypter { ctx: *mut ffi::EVP_CIPHER_CTX, block_size: usize, ctx: CipherCtx, } unsafe impl Sync for Crypter {} unsafe impl Send for Crypter {} impl Crypter { /// Creates a new `Crypter`. The initialisation vector, `iv`, is not necessary for certain /// types of `Cipher`. Loading @@ -459,63 +450,18 @@ impl Crypter { key: &[u8], iv: Option<&[u8]>, ) -> Result<Crypter, ErrorStack> { ffi::init(); let mut ctx = CipherCtx::new()?; ctx.init(Some(&t), None, None, mode)?; unsafe { let ctx = cvt_p(ffi::EVP_CIPHER_CTX_new())?; let crypter = Crypter { ctx, block_size: t.block_size(), }; ctx.set_key_length(key.len())?; let mode = match mode { Mode::Encrypt => 1, Mode::Decrypt => 0, }; if let Some(iv) = iv { ctx.set_iv_length(iv.len())?; } cvt(ffi::EVP_CipherInit_ex( crypter.ctx, t.as_ptr(), ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), mode, ))?; assert!(key.len() <= c_int::max_value() as usize); cvt(ffi::EVP_CIPHER_CTX_set_key_length( crypter.ctx, key.len() as c_int, ))?; let key = key.as_ptr() as *mut _; let iv = match (iv, t.iv_len()) { (Some(iv), Some(len)) => { if iv.len() != len { assert!(iv.len() <= c_int::max_value() as usize); cvt(ffi::EVP_CIPHER_CTX_ctrl( crypter.ctx, ffi::EVP_CTRL_GCM_SET_IVLEN, iv.len() as c_int, ptr::null_mut(), ))?; } iv.as_ptr() as *mut _ } (Some(_), None) | (None, None) => ptr::null_mut(), (None, Some(_)) => panic!("an IV is required for this cipher"), }; cvt(ffi::EVP_CipherInit_ex( crypter.ctx, ptr::null(), ptr::null_mut(), key, iv, mode, ))?; ctx.init(None, Some(key), iv, mode)?; Ok(crypter) } Ok(Crypter { ctx }) } /// Enables or disables padding. Loading @@ -523,26 +469,14 @@ impl Crypter { /// If padding is disabled, total amount of data encrypted/decrypted must /// be a multiple of the cipher's block size. pub fn pad(&mut self, padding: bool) { unsafe { ffi::EVP_CIPHER_CTX_set_padding(self.ctx, padding as c_int); } self.ctx.set_padding(padding) } /// Sets the tag used to authenticate ciphertext in AEAD ciphers such as AES GCM. /// /// When decrypting cipher text using an AEAD cipher, this must be called before `finalize`. pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> { unsafe { assert!(tag.len() <= c_int::max_value() as usize); // NB: this constant is actually more general than just GCM. cvt(ffi::EVP_CIPHER_CTX_ctrl( self.ctx, ffi::EVP_CTRL_GCM_SET_TAG, tag.len() as c_int, tag.as_ptr() as *mut _, )) .map(|_| ()) } self.ctx.set_tag(tag) } /// Sets the length of the authentication tag to generate in AES CCM. Loading @@ -550,17 +484,7 @@ impl Crypter { /// When encrypting with AES CCM, the tag length needs to be explicitly set in order /// to use a value different than the default 12 bytes. pub fn set_tag_len(&mut self, tag_len: usize) -> Result<(), ErrorStack> { unsafe { assert!(tag_len <= c_int::max_value() as usize); // NB: this constant is actually more general than just GCM. cvt(ffi::EVP_CIPHER_CTX_ctrl( self.ctx, ffi::EVP_CTRL_GCM_SET_TAG, tag_len as c_int, ptr::null_mut(), )) .map(|_| ()) } self.ctx.set_tag_length(tag_len) } /// Feeds total plaintext length to the cipher. Loading @@ -568,18 +492,7 @@ impl Crypter { /// The total plaintext or ciphertext length MUST be passed to the cipher when it operates in /// CCM mode. pub fn set_data_len(&mut self, data_len: usize) -> Result<(), ErrorStack> { unsafe { assert!(data_len <= c_int::max_value() as usize); let mut len = 0; cvt(ffi::EVP_CipherUpdate( self.ctx, ptr::null_mut(), &mut len, ptr::null_mut(), data_len as c_int, )) .map(|_| ()) } self.ctx.set_data_len(data_len) } /// Feeds Additional Authenticated Data (AAD) through the cipher. Loading @@ -588,18 +501,8 @@ impl Crypter { /// is factored into the authentication tag. It must be called before the first call to /// `update`. pub fn aad_update(&mut self, input: &[u8]) -> Result<(), ErrorStack> { unsafe { assert!(input.len() <= c_int::max_value() as usize); let mut len = 0; cvt(ffi::EVP_CipherUpdate( self.ctx, ptr::null_mut(), &mut len, input.as_ptr(), input.len() as c_int, )) .map(|_| ()) } self.ctx.update(input, None)?; Ok(()) } /// Feeds data from `input` through the cipher, writing encrypted/decrypted Loading @@ -617,27 +520,7 @@ impl Crypter { /// /// Panics if `output.len() > c_int::max_value()`. pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack> { unsafe { let block_size = if self.block_size > 1 { self.block_size } else { 0 }; assert!(output.len() >= input.len() + 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_CipherUpdate( 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/decryption process, writing any remaining data Loading @@ -652,20 +535,7 @@ impl Crypter { /// Panics for block ciphers if `output.len() < block_size`, /// where `block_size` is the block size of the cipher (see `Cipher::block_size`). pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> { unsafe { if self.block_size > 1 { 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_CipherFinal( self.ctx, output.as_mut_ptr(), &mut outl, ))?; Ok(outl as usize) } self.ctx.finalize(output) } /// Retrieves the authentication tag used to authenticate ciphertext in AEAD ciphers such Loading @@ -677,24 +547,7 @@ impl Crypter { /// range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16 /// bytes, for example. pub fn get_tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> { unsafe { assert!(tag.len() <= c_int::max_value() as usize); cvt(ffi::EVP_CIPHER_CTX_ctrl( self.ctx, ffi::EVP_CTRL_GCM_GET_TAG, tag.len() as c_int, tag.as_mut_ptr() as *mut _, )) .map(|_| ()) } } } impl Drop for Crypter { fn drop(&mut self) { unsafe { ffi::EVP_CIPHER_CTX_free(self.ctx); } self.ctx.tag(tag) } } Loading Loading
openssl-sys/src/evp.rs +32 −1 Original line number Diff line number Diff line Loading @@ -39,6 +39,12 @@ 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_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] Loading Loading @@ -70,6 +76,26 @@ 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) } #[inline] pub unsafe fn EVP_CIPHER_CTX_tag_length(ctx: *const EVP_CIPHER_CTX) -> c_int { EVP_CIPHER_CTX_get_tag_length(ctx) } } else { extern "C" { pub fn EVP_MD_size(md: *const EVP_MD) -> c_int; Loading @@ -79,10 +105,15 @@ 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; pub fn EVP_CIPHER_CTX_tag_length(ctx: *const EVP_CIPHER_CTX) -> c_int; } } } extern "C" {} cfg_if! { if #[cfg(ossl110)] { Loading
openssl/src/cipher_ctx.rs 0 → 100644 +273 −0 Original line number Diff line number Diff line use crate::error::ErrorStack; use crate::symm::{Cipher, Mode}; use crate::{cvt, cvt_p}; use cfg_if::cfg_if; use foreign_types::{ForeignType, ForeignTypeRef}; use libc::c_int; use std::convert::TryFrom; use std::ptr; cfg_if! { if #[cfg(ossl300)] { use ffi::EVP_CIPHER_CTX_get0_cipher; } else { use ffi::EVP_CIPHER_CTX_cipher as EVP_CIPHER_CTX_get0_cipher; } } foreign_type_and_impl_send_sync! { type CType = ffi::EVP_CIPHER_CTX; fn drop = ffi::EVP_CIPHER_CTX_free; pub struct CipherCtx; pub struct CipherCtxRef; } impl CipherCtx { pub fn new() -> Result<Self, ErrorStack> { ffi::init(); unsafe { let ptr = cvt_p(ffi::EVP_CIPHER_CTX_new())?; Ok(CipherCtx::from_ptr(ptr)) } } } impl CipherCtxRef { pub fn init( &mut self, // FIXME CipherRef type_: Option<&Cipher>, key: Option<&[u8]>, iv: Option<&[u8]>, mode: Mode, ) -> Result<(), ErrorStack> { if let Some(key) = key { if let Some(len) = self.key_length() { assert_eq!(len, key.len()); } } if let Some(iv) = iv { if let Some(len) = self.iv_length() { assert_eq!(len, iv.len()); } } let mode = match mode { Mode::Encrypt => 1, Mode::Decrypt => 0, }; unsafe { cvt(ffi::EVP_CipherInit_ex( self.as_ptr(), type_.map_or(ptr::null(), Cipher::as_ptr), ptr::null_mut(), key.map_or(ptr::null(), |k| k.as_ptr()), iv.map_or(ptr::null(), |iv| iv.as_ptr()), mode, ))?; } Ok(()) } fn assert_cipher(&self) { unsafe { assert!(!EVP_CIPHER_CTX_get0_cipher(self.as_ptr()).is_null()); } } pub fn block_size(&self) -> Option<usize> { self.assert_cipher(); unsafe { let r = ffi::EVP_CIPHER_CTX_block_size(self.as_ptr()); if r > 0 { Some(r as usize) } else { None } } } pub fn key_length(&self) -> Option<usize> { self.assert_cipher(); unsafe { let r = ffi::EVP_CIPHER_CTX_key_length(self.as_ptr()); if r > 0 { Some(r as usize) } else { None } } } pub fn set_key_length(&mut self, len: usize) -> Result<(), ErrorStack> { self.assert_cipher(); let len = c_int::try_from(len).unwrap(); unsafe { cvt(ffi::EVP_CIPHER_CTX_set_key_length(self.as_ptr(), len))?; } Ok(()) } pub fn iv_length(&self) -> Option<usize> { self.assert_cipher(); unsafe { let r = ffi::EVP_CIPHER_CTX_iv_length(self.as_ptr()); if r > 0 { Some(r as usize) } else { None } } } pub fn set_iv_length(&mut self, len: usize) -> Result<(), ErrorStack> { self.assert_cipher(); let len = c_int::try_from(len).unwrap(); unsafe { cvt(ffi::EVP_CIPHER_CTX_ctrl( self.as_ptr(), ffi::EVP_CTRL_GCM_SET_IVLEN, len, ptr::null_mut(), ))?; } Ok(()) } pub fn tag_length(&self) -> Option<usize> { self.assert_cipher(); unsafe { let r = ffi::EVP_CIPHER_CTX_tag_length(self.as_ptr()); if r > 0 { Some(r as usize) } else { None } } } pub fn tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(tag.len()).unwrap(); unsafe { cvt(ffi::EVP_CIPHER_CTX_ctrl( self.as_ptr(), ffi::EVP_CTRL_GCM_GET_TAG, len, tag.as_mut_ptr() as *mut _, ))?; } Ok(()) } pub fn set_tag_length(&mut self, len: usize) -> Result<(), ErrorStack> { let len = c_int::try_from(len).unwrap(); unsafe { cvt(ffi::EVP_CIPHER_CTX_ctrl( self.as_ptr(), ffi::EVP_CTRL_GCM_SET_TAG, len, ptr::null_mut(), ))?; } Ok(()) } pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> { let len = c_int::try_from(tag.len()).unwrap(); unsafe { cvt(ffi::EVP_CIPHER_CTX_ctrl( self.as_ptr(), ffi::EVP_CTRL_GCM_SET_TAG, len, tag.as_ptr() as *mut _, ))?; } Ok(()) } pub fn set_padding(&mut self, padding: bool) { unsafe { ffi::EVP_CIPHER_CTX_set_padding(self.as_ptr(), padding as c_int); } } pub fn set_data_len(&mut self, len: usize) -> Result<(), ErrorStack> { let len = c_int::try_from(len).unwrap(); unsafe { cvt(ffi::EVP_CipherUpdate( self.as_ptr(), ptr::null_mut(), &mut 0, ptr::null(), len, ))?; } Ok(()) } pub fn update(&mut self, input: &[u8], output: Option<&mut [u8]>) -> Result<usize, ErrorStack> { let inlen = c_int::try_from(input.len()).unwrap(); if let (Some(mut block_size), Some(output)) = (self.block_size(), &output) { if block_size == 1 { block_size = 0; } assert!(output.len() >= input.len() + block_size); } let mut outlen = 0; unsafe { cvt(ffi::EVP_CipherUpdate( self.as_ptr(), output.map_or(ptr::null_mut(), |b| b.as_mut_ptr()), &mut outlen, input.as_ptr(), inlen, ))?; } Ok(outlen as usize) } pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> { if let Some(block_size) = self.block_size() { if block_size > 1 { assert!(output.len() >= block_size); } } let mut outl = 0; unsafe { cvt(ffi::EVP_CipherFinal( self.as_ptr(), output.as_mut_ptr(), &mut outl, ))?; } Ok(outl as usize) } }
openssl/src/lib.rs +1 −0 Original line number Diff line number Diff line Loading @@ -134,6 +134,7 @@ pub mod aes; pub mod asn1; pub mod base64; pub mod bn; pub mod cipher_ctx; #[cfg(all(not(libressl), not(osslconf = "OPENSSL_NO_CMS")))] pub mod cms; pub mod conf; Loading
openssl/src/symm.rs +22 −169 Original line number Diff line number Diff line Loading @@ -51,15 +51,10 @@ //! assert_eq!("Foo bar", output_string); //! println!("Decrypted: '{}'", output_string); //! ``` use cfg_if::cfg_if; use libc::c_int; use std::cmp; use std::ptr; use crate::cipher_ctx::CipherCtx; use crate::error::ErrorStack; use crate::nid::Nid; use crate::{cvt, cvt_p}; use cfg_if::cfg_if; #[derive(Copy, Clone)] pub enum Mode { Loading Loading @@ -438,13 +433,9 @@ unsafe impl Send for Cipher {} /// assert_eq!(b"Some Stream of Crypto Text", &plaintext[..]); /// ``` pub struct Crypter { ctx: *mut ffi::EVP_CIPHER_CTX, block_size: usize, ctx: CipherCtx, } unsafe impl Sync for Crypter {} unsafe impl Send for Crypter {} impl Crypter { /// Creates a new `Crypter`. The initialisation vector, `iv`, is not necessary for certain /// types of `Cipher`. Loading @@ -459,63 +450,18 @@ impl Crypter { key: &[u8], iv: Option<&[u8]>, ) -> Result<Crypter, ErrorStack> { ffi::init(); let mut ctx = CipherCtx::new()?; ctx.init(Some(&t), None, None, mode)?; unsafe { let ctx = cvt_p(ffi::EVP_CIPHER_CTX_new())?; let crypter = Crypter { ctx, block_size: t.block_size(), }; ctx.set_key_length(key.len())?; let mode = match mode { Mode::Encrypt => 1, Mode::Decrypt => 0, }; if let Some(iv) = iv { ctx.set_iv_length(iv.len())?; } cvt(ffi::EVP_CipherInit_ex( crypter.ctx, t.as_ptr(), ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), mode, ))?; assert!(key.len() <= c_int::max_value() as usize); cvt(ffi::EVP_CIPHER_CTX_set_key_length( crypter.ctx, key.len() as c_int, ))?; let key = key.as_ptr() as *mut _; let iv = match (iv, t.iv_len()) { (Some(iv), Some(len)) => { if iv.len() != len { assert!(iv.len() <= c_int::max_value() as usize); cvt(ffi::EVP_CIPHER_CTX_ctrl( crypter.ctx, ffi::EVP_CTRL_GCM_SET_IVLEN, iv.len() as c_int, ptr::null_mut(), ))?; } iv.as_ptr() as *mut _ } (Some(_), None) | (None, None) => ptr::null_mut(), (None, Some(_)) => panic!("an IV is required for this cipher"), }; cvt(ffi::EVP_CipherInit_ex( crypter.ctx, ptr::null(), ptr::null_mut(), key, iv, mode, ))?; ctx.init(None, Some(key), iv, mode)?; Ok(crypter) } Ok(Crypter { ctx }) } /// Enables or disables padding. Loading @@ -523,26 +469,14 @@ impl Crypter { /// If padding is disabled, total amount of data encrypted/decrypted must /// be a multiple of the cipher's block size. pub fn pad(&mut self, padding: bool) { unsafe { ffi::EVP_CIPHER_CTX_set_padding(self.ctx, padding as c_int); } self.ctx.set_padding(padding) } /// Sets the tag used to authenticate ciphertext in AEAD ciphers such as AES GCM. /// /// When decrypting cipher text using an AEAD cipher, this must be called before `finalize`. pub fn set_tag(&mut self, tag: &[u8]) -> Result<(), ErrorStack> { unsafe { assert!(tag.len() <= c_int::max_value() as usize); // NB: this constant is actually more general than just GCM. cvt(ffi::EVP_CIPHER_CTX_ctrl( self.ctx, ffi::EVP_CTRL_GCM_SET_TAG, tag.len() as c_int, tag.as_ptr() as *mut _, )) .map(|_| ()) } self.ctx.set_tag(tag) } /// Sets the length of the authentication tag to generate in AES CCM. Loading @@ -550,17 +484,7 @@ impl Crypter { /// When encrypting with AES CCM, the tag length needs to be explicitly set in order /// to use a value different than the default 12 bytes. pub fn set_tag_len(&mut self, tag_len: usize) -> Result<(), ErrorStack> { unsafe { assert!(tag_len <= c_int::max_value() as usize); // NB: this constant is actually more general than just GCM. cvt(ffi::EVP_CIPHER_CTX_ctrl( self.ctx, ffi::EVP_CTRL_GCM_SET_TAG, tag_len as c_int, ptr::null_mut(), )) .map(|_| ()) } self.ctx.set_tag_length(tag_len) } /// Feeds total plaintext length to the cipher. Loading @@ -568,18 +492,7 @@ impl Crypter { /// The total plaintext or ciphertext length MUST be passed to the cipher when it operates in /// CCM mode. pub fn set_data_len(&mut self, data_len: usize) -> Result<(), ErrorStack> { unsafe { assert!(data_len <= c_int::max_value() as usize); let mut len = 0; cvt(ffi::EVP_CipherUpdate( self.ctx, ptr::null_mut(), &mut len, ptr::null_mut(), data_len as c_int, )) .map(|_| ()) } self.ctx.set_data_len(data_len) } /// Feeds Additional Authenticated Data (AAD) through the cipher. Loading @@ -588,18 +501,8 @@ impl Crypter { /// is factored into the authentication tag. It must be called before the first call to /// `update`. pub fn aad_update(&mut self, input: &[u8]) -> Result<(), ErrorStack> { unsafe { assert!(input.len() <= c_int::max_value() as usize); let mut len = 0; cvt(ffi::EVP_CipherUpdate( self.ctx, ptr::null_mut(), &mut len, input.as_ptr(), input.len() as c_int, )) .map(|_| ()) } self.ctx.update(input, None)?; Ok(()) } /// Feeds data from `input` through the cipher, writing encrypted/decrypted Loading @@ -617,27 +520,7 @@ impl Crypter { /// /// Panics if `output.len() > c_int::max_value()`. pub fn update(&mut self, input: &[u8], output: &mut [u8]) -> Result<usize, ErrorStack> { unsafe { let block_size = if self.block_size > 1 { self.block_size } else { 0 }; assert!(output.len() >= input.len() + 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_CipherUpdate( 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/decryption process, writing any remaining data Loading @@ -652,20 +535,7 @@ impl Crypter { /// Panics for block ciphers if `output.len() < block_size`, /// where `block_size` is the block size of the cipher (see `Cipher::block_size`). pub fn finalize(&mut self, output: &mut [u8]) -> Result<usize, ErrorStack> { unsafe { if self.block_size > 1 { 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_CipherFinal( self.ctx, output.as_mut_ptr(), &mut outl, ))?; Ok(outl as usize) } self.ctx.finalize(output) } /// Retrieves the authentication tag used to authenticate ciphertext in AEAD ciphers such Loading @@ -677,24 +547,7 @@ impl Crypter { /// range of tag sizes, it is recommended to pick the maximum size. For AES GCM, this is 16 /// bytes, for example. pub fn get_tag(&self, tag: &mut [u8]) -> Result<(), ErrorStack> { unsafe { assert!(tag.len() <= c_int::max_value() as usize); cvt(ffi::EVP_CIPHER_CTX_ctrl( self.ctx, ffi::EVP_CTRL_GCM_GET_TAG, tag.len() as c_int, tag.as_mut_ptr() as *mut _, )) .map(|_| ()) } } } impl Drop for Crypter { fn drop(&mut self) { unsafe { ffi::EVP_CIPHER_CTX_free(self.ctx); } self.ctx.tag(tag) } } Loading