192f3ab15Sopenharmony_ci//! Message digest algorithms.
292f3ab15Sopenharmony_ci
392f3ab15Sopenharmony_ci#[cfg(ossl300)]
492f3ab15Sopenharmony_ciuse crate::cvt_p;
592f3ab15Sopenharmony_ci#[cfg(ossl300)]
692f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
792f3ab15Sopenharmony_ci#[cfg(ossl300)]
892f3ab15Sopenharmony_ciuse crate::lib_ctx::LibCtxRef;
992f3ab15Sopenharmony_ciuse crate::nid::Nid;
1092f3ab15Sopenharmony_ciuse cfg_if::cfg_if;
1192f3ab15Sopenharmony_ciuse foreign_types::{ForeignTypeRef, Opaque};
1292f3ab15Sopenharmony_ciuse openssl_macros::corresponds;
1392f3ab15Sopenharmony_ci#[cfg(ossl300)]
1492f3ab15Sopenharmony_ciuse std::ffi::CString;
1592f3ab15Sopenharmony_ci#[cfg(ossl300)]
1692f3ab15Sopenharmony_ciuse std::ptr;
1792f3ab15Sopenharmony_ci
1892f3ab15Sopenharmony_cicfg_if! {
1992f3ab15Sopenharmony_ci    if #[cfg(ossl300)] {
2092f3ab15Sopenharmony_ci        use foreign_types::ForeignType;
2192f3ab15Sopenharmony_ci        use std::ops::{Deref, DerefMut};
2292f3ab15Sopenharmony_ci
2392f3ab15Sopenharmony_ci        type Inner = *mut ffi::EVP_MD;
2492f3ab15Sopenharmony_ci
2592f3ab15Sopenharmony_ci        impl Drop for Md {
2692f3ab15Sopenharmony_ci            #[inline]
2792f3ab15Sopenharmony_ci            fn drop(&mut self) {
2892f3ab15Sopenharmony_ci                unsafe {
2992f3ab15Sopenharmony_ci                    ffi::EVP_MD_free(self.as_ptr());
3092f3ab15Sopenharmony_ci                }
3192f3ab15Sopenharmony_ci            }
3292f3ab15Sopenharmony_ci        }
3392f3ab15Sopenharmony_ci
3492f3ab15Sopenharmony_ci        impl ForeignType for Md {
3592f3ab15Sopenharmony_ci            type CType = ffi::EVP_MD;
3692f3ab15Sopenharmony_ci            type Ref = MdRef;
3792f3ab15Sopenharmony_ci
3892f3ab15Sopenharmony_ci            #[inline]
3992f3ab15Sopenharmony_ci            unsafe fn from_ptr(ptr: *mut Self::CType) -> Self {
4092f3ab15Sopenharmony_ci                Md(ptr)
4192f3ab15Sopenharmony_ci            }
4292f3ab15Sopenharmony_ci
4392f3ab15Sopenharmony_ci            #[inline]
4492f3ab15Sopenharmony_ci            fn as_ptr(&self) -> *mut Self::CType {
4592f3ab15Sopenharmony_ci                self.0
4692f3ab15Sopenharmony_ci            }
4792f3ab15Sopenharmony_ci        }
4892f3ab15Sopenharmony_ci
4992f3ab15Sopenharmony_ci        impl Deref for Md {
5092f3ab15Sopenharmony_ci            type Target = MdRef;
5192f3ab15Sopenharmony_ci
5292f3ab15Sopenharmony_ci            #[inline]
5392f3ab15Sopenharmony_ci            fn deref(&self) -> &Self::Target {
5492f3ab15Sopenharmony_ci                unsafe {
5592f3ab15Sopenharmony_ci                    MdRef::from_ptr(self.as_ptr())
5692f3ab15Sopenharmony_ci                }
5792f3ab15Sopenharmony_ci            }
5892f3ab15Sopenharmony_ci        }
5992f3ab15Sopenharmony_ci
6092f3ab15Sopenharmony_ci        impl DerefMut for Md {
6192f3ab15Sopenharmony_ci            #[inline]
6292f3ab15Sopenharmony_ci            fn deref_mut(&mut self) -> &mut Self::Target {
6392f3ab15Sopenharmony_ci                unsafe {
6492f3ab15Sopenharmony_ci                    MdRef::from_ptr_mut(self.as_ptr())
6592f3ab15Sopenharmony_ci                }
6692f3ab15Sopenharmony_ci            }
6792f3ab15Sopenharmony_ci        }
6892f3ab15Sopenharmony_ci    } else {
6992f3ab15Sopenharmony_ci        enum Inner {}
7092f3ab15Sopenharmony_ci    }
7192f3ab15Sopenharmony_ci}
7292f3ab15Sopenharmony_ci
7392f3ab15Sopenharmony_ci/// A message digest algorithm.
7492f3ab15Sopenharmony_cipub struct Md(Inner);
7592f3ab15Sopenharmony_ci
7692f3ab15Sopenharmony_ciunsafe impl Sync for Md {}
7792f3ab15Sopenharmony_ciunsafe impl Send for Md {}
7892f3ab15Sopenharmony_ci
7992f3ab15Sopenharmony_ciimpl Md {
8092f3ab15Sopenharmony_ci    /// Returns the `Md` corresponding to an [`Nid`].
8192f3ab15Sopenharmony_ci    #[corresponds(EVP_get_digestbynid)]
8292f3ab15Sopenharmony_ci    pub fn from_nid(type_: Nid) -> Option<&'static MdRef> {
8392f3ab15Sopenharmony_ci        unsafe {
8492f3ab15Sopenharmony_ci            let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
8592f3ab15Sopenharmony_ci            if ptr.is_null() {
8692f3ab15Sopenharmony_ci                None
8792f3ab15Sopenharmony_ci            } else {
8892f3ab15Sopenharmony_ci                Some(MdRef::from_ptr(ptr as *mut _))
8992f3ab15Sopenharmony_ci            }
9092f3ab15Sopenharmony_ci        }
9192f3ab15Sopenharmony_ci    }
9292f3ab15Sopenharmony_ci
9392f3ab15Sopenharmony_ci    /// Fetches an `Md` object corresponding to the specified algorithm name and properties.
9492f3ab15Sopenharmony_ci    ///
9592f3ab15Sopenharmony_ci    /// Requires OpenSSL 3.0.0 or newer.
9692f3ab15Sopenharmony_ci    #[corresponds(EVP_MD_fetch)]
9792f3ab15Sopenharmony_ci    #[cfg(ossl300)]
9892f3ab15Sopenharmony_ci    pub fn fetch(
9992f3ab15Sopenharmony_ci        ctx: Option<&LibCtxRef>,
10092f3ab15Sopenharmony_ci        algorithm: &str,
10192f3ab15Sopenharmony_ci        properties: Option<&str>,
10292f3ab15Sopenharmony_ci    ) -> Result<Self, ErrorStack> {
10392f3ab15Sopenharmony_ci        let algorithm = CString::new(algorithm).unwrap();
10492f3ab15Sopenharmony_ci        let properties = properties.map(|s| CString::new(s).unwrap());
10592f3ab15Sopenharmony_ci
10692f3ab15Sopenharmony_ci        unsafe {
10792f3ab15Sopenharmony_ci            let ptr = cvt_p(ffi::EVP_MD_fetch(
10892f3ab15Sopenharmony_ci                ctx.map_or(ptr::null_mut(), ForeignTypeRef::as_ptr),
10992f3ab15Sopenharmony_ci                algorithm.as_ptr(),
11092f3ab15Sopenharmony_ci                properties.map_or(ptr::null_mut(), |s| s.as_ptr()),
11192f3ab15Sopenharmony_ci            ))?;
11292f3ab15Sopenharmony_ci
11392f3ab15Sopenharmony_ci            Ok(Md::from_ptr(ptr))
11492f3ab15Sopenharmony_ci        }
11592f3ab15Sopenharmony_ci    }
11692f3ab15Sopenharmony_ci
11792f3ab15Sopenharmony_ci    #[inline]
11892f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
11992f3ab15Sopenharmony_ci    pub fn null() -> &'static MdRef {
12092f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_md_null() as *mut _) }
12192f3ab15Sopenharmony_ci    }
12292f3ab15Sopenharmony_ci
12392f3ab15Sopenharmony_ci    #[inline]
12492f3ab15Sopenharmony_ci    pub fn md5() -> &'static MdRef {
12592f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_md5() as *mut _) }
12692f3ab15Sopenharmony_ci    }
12792f3ab15Sopenharmony_ci
12892f3ab15Sopenharmony_ci    #[inline]
12992f3ab15Sopenharmony_ci    pub fn sha1() -> &'static MdRef {
13092f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_sha1() as *mut _) }
13192f3ab15Sopenharmony_ci    }
13292f3ab15Sopenharmony_ci
13392f3ab15Sopenharmony_ci    #[inline]
13492f3ab15Sopenharmony_ci    pub fn sha224() -> &'static MdRef {
13592f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_sha224() as *mut _) }
13692f3ab15Sopenharmony_ci    }
13792f3ab15Sopenharmony_ci
13892f3ab15Sopenharmony_ci    #[inline]
13992f3ab15Sopenharmony_ci    pub fn sha256() -> &'static MdRef {
14092f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_sha256() as *mut _) }
14192f3ab15Sopenharmony_ci    }
14292f3ab15Sopenharmony_ci
14392f3ab15Sopenharmony_ci    #[inline]
14492f3ab15Sopenharmony_ci    pub fn sha384() -> &'static MdRef {
14592f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_sha384() as *mut _) }
14692f3ab15Sopenharmony_ci    }
14792f3ab15Sopenharmony_ci
14892f3ab15Sopenharmony_ci    #[inline]
14992f3ab15Sopenharmony_ci    pub fn sha512() -> &'static MdRef {
15092f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_sha512() as *mut _) }
15192f3ab15Sopenharmony_ci    }
15292f3ab15Sopenharmony_ci
15392f3ab15Sopenharmony_ci    #[cfg(ossl111)]
15492f3ab15Sopenharmony_ci    #[inline]
15592f3ab15Sopenharmony_ci    pub fn sha3_224() -> &'static MdRef {
15692f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_sha3_224() as *mut _) }
15792f3ab15Sopenharmony_ci    }
15892f3ab15Sopenharmony_ci
15992f3ab15Sopenharmony_ci    #[cfg(ossl111)]
16092f3ab15Sopenharmony_ci    #[inline]
16192f3ab15Sopenharmony_ci    pub fn sha3_256() -> &'static MdRef {
16292f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_sha3_256() as *mut _) }
16392f3ab15Sopenharmony_ci    }
16492f3ab15Sopenharmony_ci
16592f3ab15Sopenharmony_ci    #[cfg(ossl111)]
16692f3ab15Sopenharmony_ci    #[inline]
16792f3ab15Sopenharmony_ci    pub fn sha3_384() -> &'static MdRef {
16892f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_sha3_384() as *mut _) }
16992f3ab15Sopenharmony_ci    }
17092f3ab15Sopenharmony_ci
17192f3ab15Sopenharmony_ci    #[cfg(ossl111)]
17292f3ab15Sopenharmony_ci    #[inline]
17392f3ab15Sopenharmony_ci    pub fn sha3_512() -> &'static MdRef {
17492f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_sha3_512() as *mut _) }
17592f3ab15Sopenharmony_ci    }
17692f3ab15Sopenharmony_ci
17792f3ab15Sopenharmony_ci    #[cfg(ossl111)]
17892f3ab15Sopenharmony_ci    #[inline]
17992f3ab15Sopenharmony_ci    pub fn shake128() -> &'static MdRef {
18092f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_shake128() as *mut _) }
18192f3ab15Sopenharmony_ci    }
18292f3ab15Sopenharmony_ci
18392f3ab15Sopenharmony_ci    #[cfg(ossl111)]
18492f3ab15Sopenharmony_ci    #[inline]
18592f3ab15Sopenharmony_ci    pub fn shake256() -> &'static MdRef {
18692f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_shake256() as *mut _) }
18792f3ab15Sopenharmony_ci    }
18892f3ab15Sopenharmony_ci
18992f3ab15Sopenharmony_ci    #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
19092f3ab15Sopenharmony_ci    #[inline]
19192f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
19292f3ab15Sopenharmony_ci    pub fn ripemd160() -> &'static MdRef {
19392f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_ripemd160() as *mut _) }
19492f3ab15Sopenharmony_ci    }
19592f3ab15Sopenharmony_ci
19692f3ab15Sopenharmony_ci    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
19792f3ab15Sopenharmony_ci    #[inline]
19892f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
19992f3ab15Sopenharmony_ci    pub fn sm3() -> &'static MdRef {
20092f3ab15Sopenharmony_ci        unsafe { MdRef::from_ptr(ffi::EVP_sm3() as *mut _) }
20192f3ab15Sopenharmony_ci    }
20292f3ab15Sopenharmony_ci}
20392f3ab15Sopenharmony_ci
20492f3ab15Sopenharmony_ci/// A reference to an [`Md`].
20592f3ab15Sopenharmony_cipub struct MdRef(Opaque);
20692f3ab15Sopenharmony_ci
20792f3ab15Sopenharmony_ciimpl ForeignTypeRef for MdRef {
20892f3ab15Sopenharmony_ci    type CType = ffi::EVP_MD;
20992f3ab15Sopenharmony_ci}
21092f3ab15Sopenharmony_ci
21192f3ab15Sopenharmony_ciunsafe impl Sync for MdRef {}
21292f3ab15Sopenharmony_ciunsafe impl Send for MdRef {}
21392f3ab15Sopenharmony_ci
21492f3ab15Sopenharmony_ciimpl MdRef {
21592f3ab15Sopenharmony_ci    /// Returns the block size of the digest in bytes.
21692f3ab15Sopenharmony_ci    #[corresponds(EVP_MD_block_size)]
21792f3ab15Sopenharmony_ci    #[inline]
21892f3ab15Sopenharmony_ci    pub fn block_size(&self) -> usize {
21992f3ab15Sopenharmony_ci        unsafe { ffi::EVP_MD_block_size(self.as_ptr()) as usize }
22092f3ab15Sopenharmony_ci    }
22192f3ab15Sopenharmony_ci
22292f3ab15Sopenharmony_ci    /// Returns the size of the digest in bytes.
22392f3ab15Sopenharmony_ci    #[corresponds(EVP_MD_size)]
22492f3ab15Sopenharmony_ci    #[inline]
22592f3ab15Sopenharmony_ci    pub fn size(&self) -> usize {
22692f3ab15Sopenharmony_ci        unsafe { ffi::EVP_MD_size(self.as_ptr()) as usize }
22792f3ab15Sopenharmony_ci    }
22892f3ab15Sopenharmony_ci
22992f3ab15Sopenharmony_ci    /// Returns the [`Nid`] of the digest.
23092f3ab15Sopenharmony_ci    #[corresponds(EVP_MD_type)]
23192f3ab15Sopenharmony_ci    #[inline]
23292f3ab15Sopenharmony_ci    pub fn type_(&self) -> Nid {
23392f3ab15Sopenharmony_ci        unsafe { Nid::from_raw(ffi::EVP_MD_type(self.as_ptr())) }
23492f3ab15Sopenharmony_ci    }
23592f3ab15Sopenharmony_ci}
236