From b404efb9f5a18d93fffcc22964e7e2aaab0c10de Mon Sep 17 00:00:00 2001 From: Steven Fackler Date: Sat, 13 Nov 2021 16:01:18 -0500 Subject: [PATCH] Cipher::fetch --- openssl-sys/src/crypto.rs | 5 +++++ openssl-sys/src/evp.rs | 5 +++++ openssl/src/cipher.rs | 37 ++++++++++++++++++++++++++++++++ openssl/src/cipher_ctx.rs | 44 +++++++++++++++++++++++++++++++++++++++ openssl/src/lib.rs | 2 ++ openssl/src/lib_ctx.rs | 20 ++++++++++++++++++ 6 files changed, 113 insertions(+) create mode 100644 openssl/src/lib_ctx.rs diff --git a/openssl-sys/src/crypto.rs b/openssl-sys/src/crypto.rs index 63a95a289..b5b6f351e 100644 --- a/openssl-sys/src/crypto.rs +++ b/openssl-sys/src/crypto.rs @@ -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); } diff --git a/openssl-sys/src/evp.rs b/openssl-sys/src/evp.rs index 71a8d4fff..3872ed922 100644 --- a/openssl-sys/src/evp.rs +++ b/openssl-sys/src/evp.rs @@ -39,6 +39,11 @@ 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; diff --git a/openssl/src/cipher.rs b/openssl/src/cipher.rs index dfed73b37..bae08d091 100644 --- a/openssl/src/cipher.rs +++ b/openssl/src/cipher.rs @@ -1,8 +1,18 @@ //! 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))] { @@ -105,6 +115,33 @@ impl Cipher { } } + /// 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 { + 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 _) } } diff --git a/openssl/src/cipher_ctx.rs b/openssl/src/cipher_ctx.rs index 99efd43d4..081e79a94 100644 --- a/openssl/src/cipher_ctx.rs +++ b/openssl/src/cipher_ctx.rs @@ -669,4 +669,48 @@ mod test { assert_eq!(secret, &decrypted[..]); } + + fn aes_128_cbc(cipher: &CipherRef) { + // from https://nvlpubs.nist.gov/nistpubs/Legacy/SP/nistspecialpublication800-38a.pdf + let key = hex::decode("2b7e151628aed2a6abf7158809cf4f3c").unwrap(); + let iv = hex::decode("000102030405060708090a0b0c0d0e0f").unwrap(); + let pt = hex::decode("6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e51") + .unwrap(); + let ct = hex::decode("7649abac8119b246cee98e9b12e9197d5086cb9b507219ee95db113a917678b2") + .unwrap(); + + let mut ctx = CipherCtx::new().unwrap(); + ctx.set_padding(false); + + ctx.encrypt_init(Some(cipher), Some(&key), Some(&iv)) + .unwrap(); + + let mut buf = vec![]; + ctx.cipher_update_vec(&pt, &mut buf).unwrap(); + ctx.cipher_final_vec(&mut buf).unwrap(); + + assert_eq!(buf, ct); + + ctx.decrypt_init(Some(cipher), Some(&key), Some(&iv)) + .unwrap(); + + let mut buf = vec![]; + ctx.cipher_update_vec(&ct, &mut buf).unwrap(); + ctx.cipher_final_vec(&mut buf).unwrap(); + + assert_eq!(buf, pt); + } + + #[test] + #[cfg(ossl300)] + fn fetched_aes_128_cbc() { + let cipher = Cipher::fetch(None, "AES-128-CBC", None).unwrap(); + aes_128_cbc(&cipher); + } + + #[test] + fn default_aes_128_cbc() { + let cipher = Cipher::aes_128_cbc(); + aes_128_cbc(cipher); + } } diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index 47ed98c69..091ba0f6e 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -151,6 +151,8 @@ pub mod ex_data; #[cfg(not(any(libressl, ossl300)))] pub mod fips; pub mod hash; +#[cfg(ossl300)] +pub mod lib_ctx; pub mod memcmp; pub mod nid; #[cfg(not(osslconf = "OPENSSL_NO_OCSP"))] diff --git a/openssl/src/lib_ctx.rs b/openssl/src/lib_ctx.rs new file mode 100644 index 000000000..7bfc79121 --- /dev/null +++ b/openssl/src/lib_ctx.rs @@ -0,0 +1,20 @@ +use crate::cvt_p; +use crate::error::ErrorStack; +use foreign_types::ForeignType; + +foreign_type_and_impl_send_sync! { + type CType = ffi::OSSL_LIB_CTX; + fn drop = ffi::OSSL_LIB_CTX_free; + + pub struct LibCtx; + pub struct LibCtxRef; +} + +impl LibCtx { + pub fn new() -> Result { + unsafe { + let ptr = cvt_p(ffi::OSSL_LIB_CTX_new())?; + Ok(LibCtx::from_ptr(ptr)) + } + } +} -- GitLab