From d6dfbd26d201db85823953d31e6f341d9905ff0a Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 1 Sep 2024 11:40:34 -0700 Subject: [PATCH 1/3] allow conversion from MessageDigest to Md This eases porting from legacy const EVP_MD to dynamic EVP_MD, especially in codebases that need to support boringssl/libressl in addition to OpenSSL 3 --- openssl/src/md.rs | 6 ++++++ openssl/src/md_ctx.rs | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/openssl/src/md.rs b/openssl/src/md.rs index a9df31140..70796759f 100644 --- a/openssl/src/md.rs +++ b/openssl/src/md.rs @@ -76,6 +76,12 @@ pub struct Md(Inner); unsafe impl Sync for Md {} unsafe impl Send for Md {} +impl From for Md { + fn from(value: crate::hash::MessageDigest) -> Self { + unsafe { Md::from_ptr(value.as_ptr() as *mut _) } + } +} + impl Md { /// Returns the `Md` corresponding to an [`Nid`]. #[corresponds(EVP_get_digestbynid)] diff --git a/openssl/src/md_ctx.rs b/openssl/src/md_ctx.rs index 36be3e996..a08214504 100644 --- a/openssl/src/md_ctx.rs +++ b/openssl/src/md_ctx.rs @@ -549,4 +549,22 @@ mod test { // Validate result of digest of "World" assert_eq!(reset_result, world_expected); } + + #[test] + fn from_message_digest() { + let messagedigest = crate::hash::MessageDigest::from_name("sha256").unwrap(); + let md = Md::from(messagedigest); + let mut ctx = MdCtx::new().unwrap(); + ctx.digest_init(&md).unwrap(); + ctx.digest_update(b"test").unwrap(); + let mut digest = [0; 32]; + ctx.digest_final(digest.as_mut_slice()).unwrap(); + // It is safe to call EVP_MD_free on const EVP_MDs from MessageDigest, but + // let's test it anyway before we use the original const EVP_MD in a hasher + drop(md); + let mut h = crate::hash::Hasher::new(messagedigest).unwrap(); + h.update(b"test").unwrap(); + let output = h.finish().unwrap(); + assert_eq!(digest, *output); + } } From ff6dcd964b382913626b65f535c311e113508905 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 1 Sep 2024 11:49:42 -0700 Subject: [PATCH 2/3] implement Md more broadly rather than limiting strictly to ossl 3 mutable MD and needing to free are both ossl 3 constructs though so we'll leave those gated --- openssl/src/md.rs | 61 ++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/openssl/src/md.rs b/openssl/src/md.rs index 70796759f..5332c9a72 100644 --- a/openssl/src/md.rs +++ b/openssl/src/md.rs @@ -8,19 +8,18 @@ use crate::error::ErrorStack; use crate::lib_ctx::LibCtxRef; use crate::nid::Nid; use cfg_if::cfg_if; +use foreign_types::ForeignType; use foreign_types::{ForeignTypeRef, Opaque}; use openssl_macros::corresponds; #[cfg(ossl300)] use std::ffi::CString; +use std::ops::Deref; #[cfg(ossl300)] use std::ptr; cfg_if! { if #[cfg(ossl300)] { - use foreign_types::ForeignType; - use std::ops::{Deref, DerefMut}; - - type Inner = *mut ffi::EVP_MD; + use std::ops::DerefMut; impl Drop for Md { #[inline] @@ -31,32 +30,6 @@ cfg_if! { } } - impl ForeignType for Md { - type CType = ffi::EVP_MD; - type Ref = MdRef; - - #[inline] - unsafe fn from_ptr(ptr: *mut Self::CType) -> Self { - Md(ptr) - } - - #[inline] - fn as_ptr(&self) -> *mut Self::CType { - self.0 - } - } - - impl Deref for Md { - type Target = MdRef; - - #[inline] - fn deref(&self) -> &Self::Target { - unsafe { - MdRef::from_ptr(self.as_ptr()) - } - } - } - impl DerefMut for Md { #[inline] fn deref_mut(&mut self) -> &mut Self::Target { @@ -65,13 +38,35 @@ cfg_if! { } } } - } else { - enum Inner {} + } +} + +impl ForeignType for Md { + type CType = ffi::EVP_MD; + type Ref = MdRef; + + #[inline] + unsafe fn from_ptr(ptr: *mut Self::CType) -> Self { + Md(ptr) + } + + #[inline] + fn as_ptr(&self) -> *mut Self::CType { + self.0 + } +} + +impl Deref for Md { + type Target = MdRef; + + #[inline] + fn deref(&self) -> &Self::Target { + unsafe { MdRef::from_ptr(self.as_ptr()) } } } /// A message digest algorithm. -pub struct Md(Inner); +pub struct Md(*mut ffi::EVP_MD); unsafe impl Sync for Md {} unsafe impl Send for Md {} From 5212bdcabfd1c5ca85124678b9da67faf8c0df33 Mon Sep 17 00:00:00 2001 From: Paul Kehrer Date: Sun, 1 Sep 2024 14:28:51 -0700 Subject: [PATCH 3/3] move derefmut out too --- openssl/src/md.rs | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/openssl/src/md.rs b/openssl/src/md.rs index 5332c9a72..9589b21bd 100644 --- a/openssl/src/md.rs +++ b/openssl/src/md.rs @@ -13,14 +13,12 @@ use foreign_types::{ForeignTypeRef, Opaque}; use openssl_macros::corresponds; #[cfg(ossl300)] use std::ffi::CString; -use std::ops::Deref; +use std::ops::{Deref, DerefMut}; #[cfg(ossl300)] use std::ptr; cfg_if! { if #[cfg(ossl300)] { - use std::ops::DerefMut; - impl Drop for Md { #[inline] fn drop(&mut self) { @@ -29,15 +27,6 @@ cfg_if! { } } } - - impl DerefMut for Md { - #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - unsafe { - MdRef::from_ptr_mut(self.as_ptr()) - } - } - } } } @@ -65,6 +54,13 @@ impl Deref for Md { } } +impl DerefMut for Md { + #[inline] + fn deref_mut(&mut self) -> &mut Self::Target { + unsafe { MdRef::from_ptr_mut(self.as_ptr()) } + } +} + /// A message digest algorithm. pub struct Md(*mut ffi::EVP_MD);