Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

allow conversion from MessageDigest to Md #2292

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 34 additions & 37 deletions openssl/src/md.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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 {}
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit suspicious that this is a safe change. I vaguely remember that the new OpenSSL 3 dynamic lookup APIs were the reason I had to make the new types in the first place.

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<crate::hash::MessageDigest> 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)]
Expand Down
18 changes: 18 additions & 0 deletions openssl/src/md_ctx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}