blob: 4ade8e870da2348d5c877db073d331f64c39e5ea [file] [log] [blame]
//! 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())) }
}
}