diff --git a/openssl/src/md.rs b/openssl/src/md.rs index a9df31140..9589b21bd 100644 --- a/openssl/src/md.rs +++ b/openssl/src/md.rs @@ -8,20 +8,17 @@ 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, DerefMut}; #[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; - impl Drop for Md { #[inline] fn drop(&mut self) { @@ -30,52 +27,52 @@ cfg_if! { } } } + } +} - impl ForeignType for Md { - type CType = ffi::EVP_MD; - type Ref = MdRef; +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] + unsafe fn from_ptr(ptr: *mut Self::CType) -> Self { + Md(ptr) + } - #[inline] - fn as_ptr(&self) -> *mut Self::CType { - self.0 - } - } + #[inline] + fn as_ptr(&self) -> *mut Self::CType { + self.0 + } +} - impl Deref for Md { - type Target = MdRef; +impl Deref for Md { + type Target = MdRef; - #[inline] - fn deref(&self) -> &Self::Target { - unsafe { - MdRef::from_ptr(self.as_ptr()) - } - } - } + #[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 { - unsafe { - MdRef::from_ptr_mut(self.as_ptr()) - } - } - } - } else { - enum Inner {} +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(Inner); +pub struct Md(*mut ffi::EVP_MD); 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); + } }