//! Message digest algorithms. #[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}; use openssl_macros::corresponds; #[cfg(ossl300)] use std::ffi::CString; #[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) { unsafe { ffi::EVP_MD_free(self.as_ptr()); } } } 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 { unsafe { MdRef::from_ptr_mut(self.as_ptr()) } } } } else { enum Inner {} } } /// A message digest algorithm. pub struct Md(Inner); unsafe impl Sync for Md {} unsafe impl Send for Md {} impl Md { /// Returns the `Md` corresponding to an [`Nid`]. #[corresponds(EVP_get_digestbynid)] pub fn from_nid(type_: Nid) -> Option<&'static MdRef> { unsafe { let ptr = ffi::EVP_get_digestbynid(type_.as_raw()); if ptr.is_null() { None } else { Some(MdRef::from_ptr(ptr as *mut _)) } } } /// Fetches an `Md` object corresponding to the specified algorithm name and properties. /// /// Requires OpenSSL 3.0.0 or newer. #[corresponds(EVP_MD_fetch)] #[cfg(ossl300)] pub fn fetch( ctx: Option<&LibCtxRef>, algorithm: &str, properties: Option<&str>, ) -> Result<Self, ErrorStack> { let algorithm = CString::new(algorithm).unwrap(); let properties = properties.map(|s| CString::new(s).unwrap()); unsafe { let ptr = cvt_p(ffi::EVP_MD_fetch( ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr), algorithm.as_ptr(), properties.map_or(ptr::null_mut(), |s| s.as_ptr()), ))?; Ok(Md::from_ptr(ptr)) } } #[inline] #[cfg(not(boringssl))] pub fn null() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_md_null() as *mut _) } } #[inline] pub fn md5() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_md5() as *mut _) } } #[inline] pub fn sha1() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sha1() as *mut _) } } #[inline] pub fn sha224() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sha224() as *mut _) } } #[inline] pub fn sha256() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sha256() as *mut _) } } #[inline] pub fn sha384() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sha384() as *mut _) } } #[inline] pub fn sha512() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sha512() as *mut _) } } #[cfg(ossl111)] #[inline] pub fn sha3_224() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sha3_224() as *mut _) } } #[cfg(ossl111)] #[inline] pub fn sha3_256() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sha3_256() as *mut _) } } #[cfg(ossl111)] #[inline] pub fn sha3_384() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sha3_384() as *mut _) } } #[cfg(ossl111)] #[inline] pub fn sha3_512() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sha3_512() as *mut _) } } #[cfg(ossl111)] #[inline] pub fn shake128() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_shake128() as *mut _) } } #[cfg(ossl111)] #[inline] pub fn shake256() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_shake256() as *mut _) } } #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))] #[inline] #[cfg(not(boringssl))] pub fn ripemd160() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_ripemd160() as *mut _) } } #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))] #[inline] #[cfg(not(boringssl))] pub fn sm3() -> &'static MdRef { unsafe { MdRef::from_ptr(ffi::EVP_sm3() as *mut _) } } } /// A reference to an [`Md`]. pub struct MdRef(Opaque); impl ForeignTypeRef for MdRef { type CType = ffi::EVP_MD; } unsafe impl Sync for MdRef {} unsafe impl Send for MdRef {} impl MdRef { /// Returns the block size of the digest in bytes. #[corresponds(EVP_MD_block_size)] #[inline] pub fn block_size(&self) -> usize { unsafe { ffi::EVP_MD_block_size(self.as_ptr()) as usize } } /// Returns the size of the digest in bytes. #[corresponds(EVP_MD_size)] #[inline] pub fn size(&self) -> usize { unsafe { ffi::EVP_MD_size(self.as_ptr()) as usize } } /// Returns the [`Nid`] of the digest. #[corresponds(EVP_MD_type)] #[inline] pub fn type_(&self) -> Nid { unsafe { Nid::from_raw(ffi::EVP_MD_type(self.as_ptr())) } } }