192f3ab15Sopenharmony_ci//! Message digest (hash) computation support.
292f3ab15Sopenharmony_ci//!
392f3ab15Sopenharmony_ci//! # Examples
492f3ab15Sopenharmony_ci//!
592f3ab15Sopenharmony_ci//! Calculate a hash in one go:
692f3ab15Sopenharmony_ci//!
792f3ab15Sopenharmony_ci//! ```
892f3ab15Sopenharmony_ci//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
992f3ab15Sopenharmony_ci//! use openssl::hash::{hash, MessageDigest};
1092f3ab15Sopenharmony_ci//!
1192f3ab15Sopenharmony_ci//! let data = b"\x42\xF4\x97\xE0";
1292f3ab15Sopenharmony_ci//! let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
1392f3ab15Sopenharmony_ci//! let res = hash(MessageDigest::md5(), data)?;
1492f3ab15Sopenharmony_ci//! assert_eq!(&*res, spec);
1592f3ab15Sopenharmony_ci//! # Ok(()) }
1692f3ab15Sopenharmony_ci//! ```
1792f3ab15Sopenharmony_ci//!
1892f3ab15Sopenharmony_ci//! Supply the input in chunks:
1992f3ab15Sopenharmony_ci//!
2092f3ab15Sopenharmony_ci//! ```
2192f3ab15Sopenharmony_ci//! use openssl::hash::{Hasher, MessageDigest};
2292f3ab15Sopenharmony_ci//!
2392f3ab15Sopenharmony_ci//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
2492f3ab15Sopenharmony_ci//! let mut hasher = Hasher::new(MessageDigest::sha256())?;
2592f3ab15Sopenharmony_ci//! hasher.update(b"test")?;
2692f3ab15Sopenharmony_ci//! hasher.update(b"this")?;
2792f3ab15Sopenharmony_ci//! let digest: &[u8] = &hasher.finish()?;
2892f3ab15Sopenharmony_ci//!
2992f3ab15Sopenharmony_ci//! let expected = hex::decode("9740e652ab5b4acd997a7cca13d6696702ccb2d441cca59fc6e285127f28cfe6")?;
3092f3ab15Sopenharmony_ci//! assert_eq!(digest, expected);
3192f3ab15Sopenharmony_ci//! # Ok(()) }
3292f3ab15Sopenharmony_ci//! ```
3392f3ab15Sopenharmony_ciuse cfg_if::cfg_if;
3492f3ab15Sopenharmony_ciuse std::ffi::CString;
3592f3ab15Sopenharmony_ciuse std::fmt;
3692f3ab15Sopenharmony_ciuse std::io;
3792f3ab15Sopenharmony_ciuse std::io::prelude::*;
3892f3ab15Sopenharmony_ciuse std::ops::{Deref, DerefMut};
3992f3ab15Sopenharmony_ciuse std::ptr;
4092f3ab15Sopenharmony_ci
4192f3ab15Sopenharmony_ciuse crate::error::ErrorStack;
4292f3ab15Sopenharmony_ciuse crate::nid::Nid;
4392f3ab15Sopenharmony_ciuse crate::{cvt, cvt_p};
4492f3ab15Sopenharmony_ci
4592f3ab15Sopenharmony_cicfg_if! {
4692f3ab15Sopenharmony_ci    if #[cfg(any(ossl110, boringssl))] {
4792f3ab15Sopenharmony_ci        use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
4892f3ab15Sopenharmony_ci    } else {
4992f3ab15Sopenharmony_ci        use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
5092f3ab15Sopenharmony_ci    }
5192f3ab15Sopenharmony_ci}
5292f3ab15Sopenharmony_ci
5392f3ab15Sopenharmony_ci/// A message digest algorithm.
5492f3ab15Sopenharmony_ci#[derive(Copy, Clone, PartialEq, Eq)]
5592f3ab15Sopenharmony_cipub struct MessageDigest(*const ffi::EVP_MD);
5692f3ab15Sopenharmony_ci
5792f3ab15Sopenharmony_ciimpl MessageDigest {
5892f3ab15Sopenharmony_ci    /// Creates a `MessageDigest` from a raw OpenSSL pointer.
5992f3ab15Sopenharmony_ci    ///
6092f3ab15Sopenharmony_ci    /// # Safety
6192f3ab15Sopenharmony_ci    ///
6292f3ab15Sopenharmony_ci    /// The caller must ensure the pointer is valid.
6392f3ab15Sopenharmony_ci    pub unsafe fn from_ptr(x: *const ffi::EVP_MD) -> Self {
6492f3ab15Sopenharmony_ci        MessageDigest(x)
6592f3ab15Sopenharmony_ci    }
6692f3ab15Sopenharmony_ci
6792f3ab15Sopenharmony_ci    /// Returns the `MessageDigest` corresponding to an `Nid`.
6892f3ab15Sopenharmony_ci    ///
6992f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_get_digestbynid`].
7092f3ab15Sopenharmony_ci    ///
7192f3ab15Sopenharmony_ci    /// [`EVP_get_digestbynid`]: https://www.openssl.org/docs/manmaster/crypto/EVP_DigestInit.html
7292f3ab15Sopenharmony_ci    pub fn from_nid(type_: Nid) -> Option<MessageDigest> {
7392f3ab15Sopenharmony_ci        unsafe {
7492f3ab15Sopenharmony_ci            let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
7592f3ab15Sopenharmony_ci            if ptr.is_null() {
7692f3ab15Sopenharmony_ci                None
7792f3ab15Sopenharmony_ci            } else {
7892f3ab15Sopenharmony_ci                Some(MessageDigest(ptr))
7992f3ab15Sopenharmony_ci            }
8092f3ab15Sopenharmony_ci        }
8192f3ab15Sopenharmony_ci    }
8292f3ab15Sopenharmony_ci
8392f3ab15Sopenharmony_ci    /// Returns the `MessageDigest` corresponding to an algorithm name.
8492f3ab15Sopenharmony_ci    ///
8592f3ab15Sopenharmony_ci    /// This corresponds to [`EVP_get_digestbyname`].
8692f3ab15Sopenharmony_ci    ///
8792f3ab15Sopenharmony_ci    /// [`EVP_get_digestbyname`]: https://www.openssl.org/docs/manmaster/crypto/EVP_DigestInit.html
8892f3ab15Sopenharmony_ci    pub fn from_name(name: &str) -> Option<MessageDigest> {
8992f3ab15Sopenharmony_ci        ffi::init();
9092f3ab15Sopenharmony_ci        let name = CString::new(name).ok()?;
9192f3ab15Sopenharmony_ci        unsafe {
9292f3ab15Sopenharmony_ci            let ptr = ffi::EVP_get_digestbyname(name.as_ptr());
9392f3ab15Sopenharmony_ci            if ptr.is_null() {
9492f3ab15Sopenharmony_ci                None
9592f3ab15Sopenharmony_ci            } else {
9692f3ab15Sopenharmony_ci                Some(MessageDigest(ptr))
9792f3ab15Sopenharmony_ci            }
9892f3ab15Sopenharmony_ci        }
9992f3ab15Sopenharmony_ci    }
10092f3ab15Sopenharmony_ci
10192f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
10292f3ab15Sopenharmony_ci    pub fn null() -> MessageDigest {
10392f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_md_null()) }
10492f3ab15Sopenharmony_ci    }
10592f3ab15Sopenharmony_ci
10692f3ab15Sopenharmony_ci    pub fn md5() -> MessageDigest {
10792f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_md5()) }
10892f3ab15Sopenharmony_ci    }
10992f3ab15Sopenharmony_ci
11092f3ab15Sopenharmony_ci    pub fn sha1() -> MessageDigest {
11192f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_sha1()) }
11292f3ab15Sopenharmony_ci    }
11392f3ab15Sopenharmony_ci
11492f3ab15Sopenharmony_ci    pub fn sha224() -> MessageDigest {
11592f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_sha224()) }
11692f3ab15Sopenharmony_ci    }
11792f3ab15Sopenharmony_ci
11892f3ab15Sopenharmony_ci    pub fn sha256() -> MessageDigest {
11992f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_sha256()) }
12092f3ab15Sopenharmony_ci    }
12192f3ab15Sopenharmony_ci
12292f3ab15Sopenharmony_ci    pub fn sha384() -> MessageDigest {
12392f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_sha384()) }
12492f3ab15Sopenharmony_ci    }
12592f3ab15Sopenharmony_ci
12692f3ab15Sopenharmony_ci    pub fn sha512() -> MessageDigest {
12792f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_sha512()) }
12892f3ab15Sopenharmony_ci    }
12992f3ab15Sopenharmony_ci
13092f3ab15Sopenharmony_ci    #[cfg(ossl111)]
13192f3ab15Sopenharmony_ci    pub fn sha3_224() -> MessageDigest {
13292f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_sha3_224()) }
13392f3ab15Sopenharmony_ci    }
13492f3ab15Sopenharmony_ci
13592f3ab15Sopenharmony_ci    #[cfg(ossl111)]
13692f3ab15Sopenharmony_ci    pub fn sha3_256() -> MessageDigest {
13792f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_sha3_256()) }
13892f3ab15Sopenharmony_ci    }
13992f3ab15Sopenharmony_ci
14092f3ab15Sopenharmony_ci    #[cfg(ossl111)]
14192f3ab15Sopenharmony_ci    pub fn sha3_384() -> MessageDigest {
14292f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_sha3_384()) }
14392f3ab15Sopenharmony_ci    }
14492f3ab15Sopenharmony_ci
14592f3ab15Sopenharmony_ci    #[cfg(ossl111)]
14692f3ab15Sopenharmony_ci    pub fn sha3_512() -> MessageDigest {
14792f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_sha3_512()) }
14892f3ab15Sopenharmony_ci    }
14992f3ab15Sopenharmony_ci
15092f3ab15Sopenharmony_ci    #[cfg(ossl111)]
15192f3ab15Sopenharmony_ci    pub fn shake_128() -> MessageDigest {
15292f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_shake128()) }
15392f3ab15Sopenharmony_ci    }
15492f3ab15Sopenharmony_ci
15592f3ab15Sopenharmony_ci    #[cfg(ossl111)]
15692f3ab15Sopenharmony_ci    pub fn shake_256() -> MessageDigest {
15792f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_shake256()) }
15892f3ab15Sopenharmony_ci    }
15992f3ab15Sopenharmony_ci
16092f3ab15Sopenharmony_ci    #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_RMD160")))]
16192f3ab15Sopenharmony_ci    pub fn ripemd160() -> MessageDigest {
16292f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_ripemd160()) }
16392f3ab15Sopenharmony_ci    }
16492f3ab15Sopenharmony_ci
16592f3ab15Sopenharmony_ci    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
16692f3ab15Sopenharmony_ci    pub fn sm3() -> MessageDigest {
16792f3ab15Sopenharmony_ci        unsafe { MessageDigest(ffi::EVP_sm3()) }
16892f3ab15Sopenharmony_ci    }
16992f3ab15Sopenharmony_ci
17092f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
17192f3ab15Sopenharmony_ci    pub fn as_ptr(&self) -> *const ffi::EVP_MD {
17292f3ab15Sopenharmony_ci        self.0
17392f3ab15Sopenharmony_ci    }
17492f3ab15Sopenharmony_ci
17592f3ab15Sopenharmony_ci    /// The block size of the digest in bytes.
17692f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
17792f3ab15Sopenharmony_ci    pub fn block_size(&self) -> usize {
17892f3ab15Sopenharmony_ci        unsafe { ffi::EVP_MD_block_size(self.0) as usize }
17992f3ab15Sopenharmony_ci    }
18092f3ab15Sopenharmony_ci
18192f3ab15Sopenharmony_ci    /// The size of the digest in bytes.
18292f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
18392f3ab15Sopenharmony_ci    pub fn size(&self) -> usize {
18492f3ab15Sopenharmony_ci        unsafe { ffi::EVP_MD_size(self.0) as usize }
18592f3ab15Sopenharmony_ci    }
18692f3ab15Sopenharmony_ci
18792f3ab15Sopenharmony_ci    /// The name of the digest.
18892f3ab15Sopenharmony_ci    #[allow(clippy::trivially_copy_pass_by_ref)]
18992f3ab15Sopenharmony_ci    pub fn type_(&self) -> Nid {
19092f3ab15Sopenharmony_ci        Nid::from_raw(unsafe { ffi::EVP_MD_type(self.0) })
19192f3ab15Sopenharmony_ci    }
19292f3ab15Sopenharmony_ci}
19392f3ab15Sopenharmony_ci
19492f3ab15Sopenharmony_ciunsafe impl Sync for MessageDigest {}
19592f3ab15Sopenharmony_ciunsafe impl Send for MessageDigest {}
19692f3ab15Sopenharmony_ci
19792f3ab15Sopenharmony_ci#[derive(PartialEq, Copy, Clone)]
19892f3ab15Sopenharmony_cienum State {
19992f3ab15Sopenharmony_ci    Reset,
20092f3ab15Sopenharmony_ci    Updated,
20192f3ab15Sopenharmony_ci    Finalized,
20292f3ab15Sopenharmony_ci}
20392f3ab15Sopenharmony_ci
20492f3ab15Sopenharmony_ciuse self::State::*;
20592f3ab15Sopenharmony_ci
20692f3ab15Sopenharmony_ci/// Provides message digest (hash) computation.
20792f3ab15Sopenharmony_ci///
20892f3ab15Sopenharmony_ci/// # Examples
20992f3ab15Sopenharmony_ci///
21092f3ab15Sopenharmony_ci/// ```
21192f3ab15Sopenharmony_ci/// use openssl::hash::{Hasher, MessageDigest};
21292f3ab15Sopenharmony_ci///
21392f3ab15Sopenharmony_ci/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
21492f3ab15Sopenharmony_ci/// let data = [b"\x42\xF4", b"\x97\xE0"];
21592f3ab15Sopenharmony_ci/// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
21692f3ab15Sopenharmony_ci/// let mut h = Hasher::new(MessageDigest::md5())?;
21792f3ab15Sopenharmony_ci/// h.update(data[0])?;
21892f3ab15Sopenharmony_ci/// h.update(data[1])?;
21992f3ab15Sopenharmony_ci/// let res = h.finish()?;
22092f3ab15Sopenharmony_ci/// assert_eq!(&*res, spec);
22192f3ab15Sopenharmony_ci/// # Ok(()) }
22292f3ab15Sopenharmony_ci/// ```
22392f3ab15Sopenharmony_ci///
22492f3ab15Sopenharmony_ci/// # Warning
22592f3ab15Sopenharmony_ci///
22692f3ab15Sopenharmony_ci/// Don't actually use MD5 and SHA-1 hashes, they're not secure anymore.
22792f3ab15Sopenharmony_ci///
22892f3ab15Sopenharmony_ci/// Don't ever hash passwords, use the functions in the `pkcs5` module or bcrypt/scrypt instead.
22992f3ab15Sopenharmony_ci///
23092f3ab15Sopenharmony_ci/// For extendable output functions (XOFs, i.e. SHAKE128/SHAKE256),
23192f3ab15Sopenharmony_ci/// you must use [`Hasher::finish_xof`] instead of [`Hasher::finish`]
23292f3ab15Sopenharmony_ci/// and provide a `buf` to store the hash. The hash will be as long as
23392f3ab15Sopenharmony_ci/// the `buf`.
23492f3ab15Sopenharmony_cipub struct Hasher {
23592f3ab15Sopenharmony_ci    ctx: *mut ffi::EVP_MD_CTX,
23692f3ab15Sopenharmony_ci    md: *const ffi::EVP_MD,
23792f3ab15Sopenharmony_ci    type_: MessageDigest,
23892f3ab15Sopenharmony_ci    state: State,
23992f3ab15Sopenharmony_ci}
24092f3ab15Sopenharmony_ci
24192f3ab15Sopenharmony_ciunsafe impl Sync for Hasher {}
24292f3ab15Sopenharmony_ciunsafe impl Send for Hasher {}
24392f3ab15Sopenharmony_ci
24492f3ab15Sopenharmony_ciimpl Hasher {
24592f3ab15Sopenharmony_ci    /// Creates a new `Hasher` with the specified hash type.
24692f3ab15Sopenharmony_ci    pub fn new(ty: MessageDigest) -> Result<Hasher, ErrorStack> {
24792f3ab15Sopenharmony_ci        ffi::init();
24892f3ab15Sopenharmony_ci
24992f3ab15Sopenharmony_ci        let ctx = unsafe { cvt_p(EVP_MD_CTX_new())? };
25092f3ab15Sopenharmony_ci
25192f3ab15Sopenharmony_ci        let mut h = Hasher {
25292f3ab15Sopenharmony_ci            ctx,
25392f3ab15Sopenharmony_ci            md: ty.as_ptr(),
25492f3ab15Sopenharmony_ci            type_: ty,
25592f3ab15Sopenharmony_ci            state: Finalized,
25692f3ab15Sopenharmony_ci        };
25792f3ab15Sopenharmony_ci        h.init()?;
25892f3ab15Sopenharmony_ci        Ok(h)
25992f3ab15Sopenharmony_ci    }
26092f3ab15Sopenharmony_ci
26192f3ab15Sopenharmony_ci    fn init(&mut self) -> Result<(), ErrorStack> {
26292f3ab15Sopenharmony_ci        match self.state {
26392f3ab15Sopenharmony_ci            Reset => return Ok(()),
26492f3ab15Sopenharmony_ci            Updated => {
26592f3ab15Sopenharmony_ci                self.finish()?;
26692f3ab15Sopenharmony_ci            }
26792f3ab15Sopenharmony_ci            Finalized => (),
26892f3ab15Sopenharmony_ci        }
26992f3ab15Sopenharmony_ci        unsafe {
27092f3ab15Sopenharmony_ci            cvt(ffi::EVP_DigestInit_ex(self.ctx, self.md, ptr::null_mut()))?;
27192f3ab15Sopenharmony_ci        }
27292f3ab15Sopenharmony_ci        self.state = Reset;
27392f3ab15Sopenharmony_ci        Ok(())
27492f3ab15Sopenharmony_ci    }
27592f3ab15Sopenharmony_ci
27692f3ab15Sopenharmony_ci    /// Feeds data into the hasher.
27792f3ab15Sopenharmony_ci    pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
27892f3ab15Sopenharmony_ci        if self.state == Finalized {
27992f3ab15Sopenharmony_ci            self.init()?;
28092f3ab15Sopenharmony_ci        }
28192f3ab15Sopenharmony_ci        unsafe {
28292f3ab15Sopenharmony_ci            cvt(ffi::EVP_DigestUpdate(
28392f3ab15Sopenharmony_ci                self.ctx,
28492f3ab15Sopenharmony_ci                data.as_ptr() as *mut _,
28592f3ab15Sopenharmony_ci                data.len(),
28692f3ab15Sopenharmony_ci            ))?;
28792f3ab15Sopenharmony_ci        }
28892f3ab15Sopenharmony_ci        self.state = Updated;
28992f3ab15Sopenharmony_ci        Ok(())
29092f3ab15Sopenharmony_ci    }
29192f3ab15Sopenharmony_ci
29292f3ab15Sopenharmony_ci    /// Returns the hash of the data written and resets the non-XOF hasher.
29392f3ab15Sopenharmony_ci    pub fn finish(&mut self) -> Result<DigestBytes, ErrorStack> {
29492f3ab15Sopenharmony_ci        if self.state == Finalized {
29592f3ab15Sopenharmony_ci            self.init()?;
29692f3ab15Sopenharmony_ci        }
29792f3ab15Sopenharmony_ci        unsafe {
29892f3ab15Sopenharmony_ci            #[cfg(not(boringssl))]
29992f3ab15Sopenharmony_ci            let mut len = ffi::EVP_MAX_MD_SIZE;
30092f3ab15Sopenharmony_ci            #[cfg(boringssl)]
30192f3ab15Sopenharmony_ci            let mut len = ffi::EVP_MAX_MD_SIZE as u32;
30292f3ab15Sopenharmony_ci            let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize];
30392f3ab15Sopenharmony_ci            cvt(ffi::EVP_DigestFinal_ex(
30492f3ab15Sopenharmony_ci                self.ctx,
30592f3ab15Sopenharmony_ci                buf.as_mut_ptr(),
30692f3ab15Sopenharmony_ci                &mut len,
30792f3ab15Sopenharmony_ci            ))?;
30892f3ab15Sopenharmony_ci            self.state = Finalized;
30992f3ab15Sopenharmony_ci            Ok(DigestBytes {
31092f3ab15Sopenharmony_ci                buf,
31192f3ab15Sopenharmony_ci                len: len as usize,
31292f3ab15Sopenharmony_ci            })
31392f3ab15Sopenharmony_ci        }
31492f3ab15Sopenharmony_ci    }
31592f3ab15Sopenharmony_ci
31692f3ab15Sopenharmony_ci    /// Writes the hash of the data into the supplied buf and resets the XOF hasher.
31792f3ab15Sopenharmony_ci    /// The hash will be as long as the buf.
31892f3ab15Sopenharmony_ci    #[cfg(ossl111)]
31992f3ab15Sopenharmony_ci    pub fn finish_xof(&mut self, buf: &mut [u8]) -> Result<(), ErrorStack> {
32092f3ab15Sopenharmony_ci        if self.state == Finalized {
32192f3ab15Sopenharmony_ci            self.init()?;
32292f3ab15Sopenharmony_ci        }
32392f3ab15Sopenharmony_ci        unsafe {
32492f3ab15Sopenharmony_ci            cvt(ffi::EVP_DigestFinalXOF(
32592f3ab15Sopenharmony_ci                self.ctx,
32692f3ab15Sopenharmony_ci                buf.as_mut_ptr(),
32792f3ab15Sopenharmony_ci                buf.len(),
32892f3ab15Sopenharmony_ci            ))?;
32992f3ab15Sopenharmony_ci            self.state = Finalized;
33092f3ab15Sopenharmony_ci            Ok(())
33192f3ab15Sopenharmony_ci        }
33292f3ab15Sopenharmony_ci    }
33392f3ab15Sopenharmony_ci}
33492f3ab15Sopenharmony_ci
33592f3ab15Sopenharmony_ciimpl Write for Hasher {
33692f3ab15Sopenharmony_ci    #[inline]
33792f3ab15Sopenharmony_ci    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
33892f3ab15Sopenharmony_ci        self.update(buf)?;
33992f3ab15Sopenharmony_ci        Ok(buf.len())
34092f3ab15Sopenharmony_ci    }
34192f3ab15Sopenharmony_ci
34292f3ab15Sopenharmony_ci    fn flush(&mut self) -> io::Result<()> {
34392f3ab15Sopenharmony_ci        Ok(())
34492f3ab15Sopenharmony_ci    }
34592f3ab15Sopenharmony_ci}
34692f3ab15Sopenharmony_ci
34792f3ab15Sopenharmony_ciimpl Clone for Hasher {
34892f3ab15Sopenharmony_ci    fn clone(&self) -> Hasher {
34992f3ab15Sopenharmony_ci        let ctx = unsafe {
35092f3ab15Sopenharmony_ci            let ctx = EVP_MD_CTX_new();
35192f3ab15Sopenharmony_ci            assert!(!ctx.is_null());
35292f3ab15Sopenharmony_ci            let r = ffi::EVP_MD_CTX_copy_ex(ctx, self.ctx);
35392f3ab15Sopenharmony_ci            assert_eq!(r, 1);
35492f3ab15Sopenharmony_ci            ctx
35592f3ab15Sopenharmony_ci        };
35692f3ab15Sopenharmony_ci        Hasher {
35792f3ab15Sopenharmony_ci            ctx,
35892f3ab15Sopenharmony_ci            md: self.md,
35992f3ab15Sopenharmony_ci            type_: self.type_,
36092f3ab15Sopenharmony_ci            state: self.state,
36192f3ab15Sopenharmony_ci        }
36292f3ab15Sopenharmony_ci    }
36392f3ab15Sopenharmony_ci}
36492f3ab15Sopenharmony_ci
36592f3ab15Sopenharmony_ciimpl Drop for Hasher {
36692f3ab15Sopenharmony_ci    fn drop(&mut self) {
36792f3ab15Sopenharmony_ci        unsafe {
36892f3ab15Sopenharmony_ci            if self.state != Finalized {
36992f3ab15Sopenharmony_ci                drop(self.finish());
37092f3ab15Sopenharmony_ci            }
37192f3ab15Sopenharmony_ci            EVP_MD_CTX_free(self.ctx);
37292f3ab15Sopenharmony_ci        }
37392f3ab15Sopenharmony_ci    }
37492f3ab15Sopenharmony_ci}
37592f3ab15Sopenharmony_ci
37692f3ab15Sopenharmony_ci/// The resulting bytes of a digest.
37792f3ab15Sopenharmony_ci///
37892f3ab15Sopenharmony_ci/// This type derefs to a byte slice - it exists to avoid allocating memory to
37992f3ab15Sopenharmony_ci/// store the digest data.
38092f3ab15Sopenharmony_ci#[derive(Copy)]
38192f3ab15Sopenharmony_cipub struct DigestBytes {
38292f3ab15Sopenharmony_ci    pub(crate) buf: [u8; ffi::EVP_MAX_MD_SIZE as usize],
38392f3ab15Sopenharmony_ci    pub(crate) len: usize,
38492f3ab15Sopenharmony_ci}
38592f3ab15Sopenharmony_ci
38692f3ab15Sopenharmony_ciimpl Clone for DigestBytes {
38792f3ab15Sopenharmony_ci    #[inline]
38892f3ab15Sopenharmony_ci    fn clone(&self) -> DigestBytes {
38992f3ab15Sopenharmony_ci        *self
39092f3ab15Sopenharmony_ci    }
39192f3ab15Sopenharmony_ci}
39292f3ab15Sopenharmony_ci
39392f3ab15Sopenharmony_ciimpl Deref for DigestBytes {
39492f3ab15Sopenharmony_ci    type Target = [u8];
39592f3ab15Sopenharmony_ci
39692f3ab15Sopenharmony_ci    #[inline]
39792f3ab15Sopenharmony_ci    fn deref(&self) -> &[u8] {
39892f3ab15Sopenharmony_ci        &self.buf[..self.len]
39992f3ab15Sopenharmony_ci    }
40092f3ab15Sopenharmony_ci}
40192f3ab15Sopenharmony_ci
40292f3ab15Sopenharmony_ciimpl DerefMut for DigestBytes {
40392f3ab15Sopenharmony_ci    #[inline]
40492f3ab15Sopenharmony_ci    fn deref_mut(&mut self) -> &mut [u8] {
40592f3ab15Sopenharmony_ci        &mut self.buf[..self.len]
40692f3ab15Sopenharmony_ci    }
40792f3ab15Sopenharmony_ci}
40892f3ab15Sopenharmony_ci
40992f3ab15Sopenharmony_ciimpl AsRef<[u8]> for DigestBytes {
41092f3ab15Sopenharmony_ci    #[inline]
41192f3ab15Sopenharmony_ci    fn as_ref(&self) -> &[u8] {
41292f3ab15Sopenharmony_ci        self.deref()
41392f3ab15Sopenharmony_ci    }
41492f3ab15Sopenharmony_ci}
41592f3ab15Sopenharmony_ci
41692f3ab15Sopenharmony_ciimpl fmt::Debug for DigestBytes {
41792f3ab15Sopenharmony_ci    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
41892f3ab15Sopenharmony_ci        fmt::Debug::fmt(&**self, fmt)
41992f3ab15Sopenharmony_ci    }
42092f3ab15Sopenharmony_ci}
42192f3ab15Sopenharmony_ci
42292f3ab15Sopenharmony_ci/// Computes the hash of the `data` with the non-XOF hasher `t`.
42392f3ab15Sopenharmony_ci///
42492f3ab15Sopenharmony_ci/// # Examples
42592f3ab15Sopenharmony_ci///
42692f3ab15Sopenharmony_ci/// ```
42792f3ab15Sopenharmony_ci/// # fn main() -> Result<(), Box<dyn std::error::Error>> {
42892f3ab15Sopenharmony_ci/// use openssl::hash::{hash, MessageDigest};
42992f3ab15Sopenharmony_ci///
43092f3ab15Sopenharmony_ci/// let data = b"\x42\xF4\x97\xE0";
43192f3ab15Sopenharmony_ci/// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
43292f3ab15Sopenharmony_ci/// let res = hash(MessageDigest::md5(), data)?;
43392f3ab15Sopenharmony_ci/// assert_eq!(&*res, spec);
43492f3ab15Sopenharmony_ci/// # Ok(()) }
43592f3ab15Sopenharmony_ci/// ```
43692f3ab15Sopenharmony_cipub fn hash(t: MessageDigest, data: &[u8]) -> Result<DigestBytes, ErrorStack> {
43792f3ab15Sopenharmony_ci    let mut h = Hasher::new(t)?;
43892f3ab15Sopenharmony_ci    h.update(data)?;
43992f3ab15Sopenharmony_ci    h.finish()
44092f3ab15Sopenharmony_ci}
44192f3ab15Sopenharmony_ci
44292f3ab15Sopenharmony_ci/// Computes the hash of the `data` with the XOF hasher `t` and stores it in `buf`.
44392f3ab15Sopenharmony_ci///
44492f3ab15Sopenharmony_ci/// # Examples
44592f3ab15Sopenharmony_ci///
44692f3ab15Sopenharmony_ci/// ```
44792f3ab15Sopenharmony_ci/// use openssl::hash::{hash_xof, MessageDigest};
44892f3ab15Sopenharmony_ci///
44992f3ab15Sopenharmony_ci/// let data = b"\x41\x6c\x6c\x20\x79\x6f\x75\x72\x20\x62\x61\x73\x65\x20\x61\x72\x65\x20\x62\x65\x6c\x6f\x6e\x67\x20\x74\x6f\x20\x75\x73";
45092f3ab15Sopenharmony_ci/// let spec = b"\x49\xd0\x69\x7f\xf5\x08\x11\x1d\x8b\x84\xf1\x5e\x46\xda\xf1\x35";
45192f3ab15Sopenharmony_ci/// let mut buf = vec![0; 16];
45292f3ab15Sopenharmony_ci/// hash_xof(MessageDigest::shake_128(), data, buf.as_mut_slice()).unwrap();
45392f3ab15Sopenharmony_ci/// assert_eq!(buf, spec);
45492f3ab15Sopenharmony_ci/// ```
45592f3ab15Sopenharmony_ci///
45692f3ab15Sopenharmony_ci#[cfg(ossl111)]
45792f3ab15Sopenharmony_cipub fn hash_xof(t: MessageDigest, data: &[u8], buf: &mut [u8]) -> Result<(), ErrorStack> {
45892f3ab15Sopenharmony_ci    let mut h = Hasher::new(t)?;
45992f3ab15Sopenharmony_ci    h.update(data)?;
46092f3ab15Sopenharmony_ci    h.finish_xof(buf)
46192f3ab15Sopenharmony_ci}
46292f3ab15Sopenharmony_ci
46392f3ab15Sopenharmony_ci#[cfg(test)]
46492f3ab15Sopenharmony_cimod tests {
46592f3ab15Sopenharmony_ci    use hex::{self, FromHex};
46692f3ab15Sopenharmony_ci    use std::io::prelude::*;
46792f3ab15Sopenharmony_ci
46892f3ab15Sopenharmony_ci    use super::*;
46992f3ab15Sopenharmony_ci
47092f3ab15Sopenharmony_ci    fn hash_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
47192f3ab15Sopenharmony_ci        let res = hash(hashtype, &Vec::from_hex(hashtest.0).unwrap()).unwrap();
47292f3ab15Sopenharmony_ci        assert_eq!(hex::encode(res), hashtest.1);
47392f3ab15Sopenharmony_ci    }
47492f3ab15Sopenharmony_ci
47592f3ab15Sopenharmony_ci    #[cfg(ossl111)]
47692f3ab15Sopenharmony_ci    fn hash_xof_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
47792f3ab15Sopenharmony_ci        let expected = Vec::from_hex(hashtest.1).unwrap();
47892f3ab15Sopenharmony_ci        let mut buf = vec![0; expected.len()];
47992f3ab15Sopenharmony_ci        hash_xof(
48092f3ab15Sopenharmony_ci            hashtype,
48192f3ab15Sopenharmony_ci            &Vec::from_hex(hashtest.0).unwrap(),
48292f3ab15Sopenharmony_ci            buf.as_mut_slice(),
48392f3ab15Sopenharmony_ci        )
48492f3ab15Sopenharmony_ci        .unwrap();
48592f3ab15Sopenharmony_ci        assert_eq!(buf, expected);
48692f3ab15Sopenharmony_ci    }
48792f3ab15Sopenharmony_ci
48892f3ab15Sopenharmony_ci    fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) {
48992f3ab15Sopenharmony_ci        h.write_all(&Vec::from_hex(hashtest.0).unwrap()).unwrap();
49092f3ab15Sopenharmony_ci        let res = h.finish().unwrap();
49192f3ab15Sopenharmony_ci        assert_eq!(hex::encode(res), hashtest.1);
49292f3ab15Sopenharmony_ci    }
49392f3ab15Sopenharmony_ci
49492f3ab15Sopenharmony_ci    // Test vectors from http://www.nsrl.nist.gov/testdata/
49592f3ab15Sopenharmony_ci    const MD5_TESTS: [(&str, &str); 13] = [
49692f3ab15Sopenharmony_ci        ("", "d41d8cd98f00b204e9800998ecf8427e"),
49792f3ab15Sopenharmony_ci        ("7F", "83acb6e67e50e31db6ed341dd2de1595"),
49892f3ab15Sopenharmony_ci        ("EC9C", "0b07f0d4ca797d8ac58874f887cb0b68"),
49992f3ab15Sopenharmony_ci        ("FEE57A", "e0d583171eb06d56198fc0ef22173907"),
50092f3ab15Sopenharmony_ci        ("42F497E0", "7c430f178aefdf1487fee7144e9641e2"),
50192f3ab15Sopenharmony_ci        ("C53B777F1C", "75ef141d64cb37ec423da2d9d440c925"),
50292f3ab15Sopenharmony_ci        ("89D5B576327B", "ebbaf15eb0ed784c6faa9dc32831bf33"),
50392f3ab15Sopenharmony_ci        ("5D4CCE781EB190", "ce175c4b08172019f05e6b5279889f2c"),
50492f3ab15Sopenharmony_ci        ("81901FE94932D7B9", "cd4d2f62b8cdb3a0cf968a735a239281"),
50592f3ab15Sopenharmony_ci        ("C9FFDEE7788EFB4EC9", "e0841a231ab698db30c6c0f3f246c014"),
50692f3ab15Sopenharmony_ci        ("66AC4B7EBA95E53DC10B", "a3b3cea71910d9af56742aa0bb2fe329"),
50792f3ab15Sopenharmony_ci        ("A510CD18F7A56852EB0319", "577e216843dd11573574d3fb209b97d8"),
50892f3ab15Sopenharmony_ci        (
50992f3ab15Sopenharmony_ci            "AAED18DBE8938C19ED734A8D",
51092f3ab15Sopenharmony_ci            "6f80fb775f27e0a4ce5c2f42fc72c5f1",
51192f3ab15Sopenharmony_ci        ),
51292f3ab15Sopenharmony_ci    ];
51392f3ab15Sopenharmony_ci
51492f3ab15Sopenharmony_ci    #[test]
51592f3ab15Sopenharmony_ci    fn test_md5() {
51692f3ab15Sopenharmony_ci        for test in MD5_TESTS.iter() {
51792f3ab15Sopenharmony_ci            hash_test(MessageDigest::md5(), test);
51892f3ab15Sopenharmony_ci        }
51992f3ab15Sopenharmony_ci
52092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::md5().block_size(), 64);
52192f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::md5().size(), 16);
52292f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::md5().type_().as_raw(), Nid::MD5.as_raw());
52392f3ab15Sopenharmony_ci    }
52492f3ab15Sopenharmony_ci
52592f3ab15Sopenharmony_ci    #[test]
52692f3ab15Sopenharmony_ci    fn test_md5_recycle() {
52792f3ab15Sopenharmony_ci        let mut h = Hasher::new(MessageDigest::md5()).unwrap();
52892f3ab15Sopenharmony_ci        for test in MD5_TESTS.iter() {
52992f3ab15Sopenharmony_ci            hash_recycle_test(&mut h, test);
53092f3ab15Sopenharmony_ci        }
53192f3ab15Sopenharmony_ci    }
53292f3ab15Sopenharmony_ci
53392f3ab15Sopenharmony_ci    #[test]
53492f3ab15Sopenharmony_ci    fn test_finish_twice() {
53592f3ab15Sopenharmony_ci        let mut h = Hasher::new(MessageDigest::md5()).unwrap();
53692f3ab15Sopenharmony_ci        h.write_all(&Vec::from_hex(MD5_TESTS[6].0).unwrap())
53792f3ab15Sopenharmony_ci            .unwrap();
53892f3ab15Sopenharmony_ci        h.finish().unwrap();
53992f3ab15Sopenharmony_ci        let res = h.finish().unwrap();
54092f3ab15Sopenharmony_ci        let null = hash(MessageDigest::md5(), &[]).unwrap();
54192f3ab15Sopenharmony_ci        assert_eq!(&*res, &*null);
54292f3ab15Sopenharmony_ci    }
54392f3ab15Sopenharmony_ci
54492f3ab15Sopenharmony_ci    #[test]
54592f3ab15Sopenharmony_ci    #[allow(clippy::redundant_clone)]
54692f3ab15Sopenharmony_ci    fn test_clone() {
54792f3ab15Sopenharmony_ci        let i = 7;
54892f3ab15Sopenharmony_ci        let inp = Vec::from_hex(MD5_TESTS[i].0).unwrap();
54992f3ab15Sopenharmony_ci        assert!(inp.len() > 2);
55092f3ab15Sopenharmony_ci        let p = inp.len() / 2;
55192f3ab15Sopenharmony_ci        let h0 = Hasher::new(MessageDigest::md5()).unwrap();
55292f3ab15Sopenharmony_ci
55392f3ab15Sopenharmony_ci        println!("Clone a new hasher");
55492f3ab15Sopenharmony_ci        let mut h1 = h0.clone();
55592f3ab15Sopenharmony_ci        h1.write_all(&inp[..p]).unwrap();
55692f3ab15Sopenharmony_ci        {
55792f3ab15Sopenharmony_ci            println!("Clone an updated hasher");
55892f3ab15Sopenharmony_ci            let mut h2 = h1.clone();
55992f3ab15Sopenharmony_ci            h2.write_all(&inp[p..]).unwrap();
56092f3ab15Sopenharmony_ci            let res = h2.finish().unwrap();
56192f3ab15Sopenharmony_ci            assert_eq!(hex::encode(res), MD5_TESTS[i].1);
56292f3ab15Sopenharmony_ci        }
56392f3ab15Sopenharmony_ci        h1.write_all(&inp[p..]).unwrap();
56492f3ab15Sopenharmony_ci        let res = h1.finish().unwrap();
56592f3ab15Sopenharmony_ci        assert_eq!(hex::encode(res), MD5_TESTS[i].1);
56692f3ab15Sopenharmony_ci
56792f3ab15Sopenharmony_ci        println!("Clone a finished hasher");
56892f3ab15Sopenharmony_ci        let mut h3 = h1.clone();
56992f3ab15Sopenharmony_ci        h3.write_all(&Vec::from_hex(MD5_TESTS[i + 1].0).unwrap())
57092f3ab15Sopenharmony_ci            .unwrap();
57192f3ab15Sopenharmony_ci        let res = h3.finish().unwrap();
57292f3ab15Sopenharmony_ci        assert_eq!(hex::encode(res), MD5_TESTS[i + 1].1);
57392f3ab15Sopenharmony_ci    }
57492f3ab15Sopenharmony_ci
57592f3ab15Sopenharmony_ci    #[test]
57692f3ab15Sopenharmony_ci    fn test_sha1() {
57792f3ab15Sopenharmony_ci        let tests = [("616263", "a9993e364706816aba3e25717850c26c9cd0d89d")];
57892f3ab15Sopenharmony_ci
57992f3ab15Sopenharmony_ci        for test in tests.iter() {
58092f3ab15Sopenharmony_ci            hash_test(MessageDigest::sha1(), test);
58192f3ab15Sopenharmony_ci        }
58292f3ab15Sopenharmony_ci
58392f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha1().block_size(), 64);
58492f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha1().size(), 20);
58592f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha1().type_().as_raw(), Nid::SHA1.as_raw());
58692f3ab15Sopenharmony_ci    }
58792f3ab15Sopenharmony_ci
58892f3ab15Sopenharmony_ci    #[test]
58992f3ab15Sopenharmony_ci    fn test_sha256() {
59092f3ab15Sopenharmony_ci        let tests = [(
59192f3ab15Sopenharmony_ci            "616263",
59292f3ab15Sopenharmony_ci            "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
59392f3ab15Sopenharmony_ci        )];
59492f3ab15Sopenharmony_ci
59592f3ab15Sopenharmony_ci        for test in tests.iter() {
59692f3ab15Sopenharmony_ci            hash_test(MessageDigest::sha256(), test);
59792f3ab15Sopenharmony_ci        }
59892f3ab15Sopenharmony_ci
59992f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha256().block_size(), 64);
60092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha256().size(), 32);
60192f3ab15Sopenharmony_ci        assert_eq!(
60292f3ab15Sopenharmony_ci            MessageDigest::sha256().type_().as_raw(),
60392f3ab15Sopenharmony_ci            Nid::SHA256.as_raw()
60492f3ab15Sopenharmony_ci        );
60592f3ab15Sopenharmony_ci    }
60692f3ab15Sopenharmony_ci
60792f3ab15Sopenharmony_ci    #[test]
60892f3ab15Sopenharmony_ci    fn test_sha512() {
60992f3ab15Sopenharmony_ci        let tests = [(
61092f3ab15Sopenharmony_ci            "737465766566696e647365766572797468696e67",
61192f3ab15Sopenharmony_ci            "ba61d1f1af0f2dd80729f6cc900f19c0966bd38ba5c75e4471ef11b771dfe7551afab7fcbd300fdc4418f2\
61292f3ab15Sopenharmony_ci            b07a028fcd99e7b6446a566f2d9bcd7c604a1ea801",
61392f3ab15Sopenharmony_ci        )];
61492f3ab15Sopenharmony_ci
61592f3ab15Sopenharmony_ci        for test in tests.iter() {
61692f3ab15Sopenharmony_ci            hash_test(MessageDigest::sha512(), test);
61792f3ab15Sopenharmony_ci        }
61892f3ab15Sopenharmony_ci
61992f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha512().block_size(), 128);
62092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha512().size(), 64);
62192f3ab15Sopenharmony_ci        assert_eq!(
62292f3ab15Sopenharmony_ci            MessageDigest::sha512().type_().as_raw(),
62392f3ab15Sopenharmony_ci            Nid::SHA512.as_raw()
62492f3ab15Sopenharmony_ci        );
62592f3ab15Sopenharmony_ci    }
62692f3ab15Sopenharmony_ci
62792f3ab15Sopenharmony_ci    #[cfg(ossl111)]
62892f3ab15Sopenharmony_ci    #[test]
62992f3ab15Sopenharmony_ci    fn test_sha3_224() {
63092f3ab15Sopenharmony_ci        let tests = [(
63192f3ab15Sopenharmony_ci            "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
63292f3ab15Sopenharmony_ci            "1de092dd9fbcbbf450f26264f4778abd48af851f2832924554c56913",
63392f3ab15Sopenharmony_ci        )];
63492f3ab15Sopenharmony_ci
63592f3ab15Sopenharmony_ci        for test in tests.iter() {
63692f3ab15Sopenharmony_ci            hash_test(MessageDigest::sha3_224(), test);
63792f3ab15Sopenharmony_ci        }
63892f3ab15Sopenharmony_ci
63992f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha3_224().block_size(), 144);
64092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha3_224().size(), 28);
64192f3ab15Sopenharmony_ci        assert_eq!(
64292f3ab15Sopenharmony_ci            MessageDigest::sha3_224().type_().as_raw(),
64392f3ab15Sopenharmony_ci            Nid::SHA3_224.as_raw()
64492f3ab15Sopenharmony_ci        );
64592f3ab15Sopenharmony_ci    }
64692f3ab15Sopenharmony_ci
64792f3ab15Sopenharmony_ci    #[cfg(ossl111)]
64892f3ab15Sopenharmony_ci    #[test]
64992f3ab15Sopenharmony_ci    fn test_sha3_256() {
65092f3ab15Sopenharmony_ci        let tests = [(
65192f3ab15Sopenharmony_ci            "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
65292f3ab15Sopenharmony_ci            "b38e38f08bc1c0091ed4b5f060fe13e86aa4179578513ad11a6e3abba0062f61",
65392f3ab15Sopenharmony_ci        )];
65492f3ab15Sopenharmony_ci
65592f3ab15Sopenharmony_ci        for test in tests.iter() {
65692f3ab15Sopenharmony_ci            hash_test(MessageDigest::sha3_256(), test);
65792f3ab15Sopenharmony_ci        }
65892f3ab15Sopenharmony_ci
65992f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha3_256().block_size(), 136);
66092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha3_256().size(), 32);
66192f3ab15Sopenharmony_ci        assert_eq!(
66292f3ab15Sopenharmony_ci            MessageDigest::sha3_256().type_().as_raw(),
66392f3ab15Sopenharmony_ci            Nid::SHA3_256.as_raw()
66492f3ab15Sopenharmony_ci        );
66592f3ab15Sopenharmony_ci    }
66692f3ab15Sopenharmony_ci
66792f3ab15Sopenharmony_ci    #[cfg(ossl111)]
66892f3ab15Sopenharmony_ci    #[test]
66992f3ab15Sopenharmony_ci    fn test_sha3_384() {
67092f3ab15Sopenharmony_ci        let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
67192f3ab15Sopenharmony_ci            "966ee786ab3482dd811bf7c8fa8db79aa1f52f6c3c369942ef14240ebd857c6ff626ec35d9e131ff64d328\
67292f3ab15Sopenharmony_ci            ef2008ff16"
67392f3ab15Sopenharmony_ci        )];
67492f3ab15Sopenharmony_ci
67592f3ab15Sopenharmony_ci        for test in tests.iter() {
67692f3ab15Sopenharmony_ci            hash_test(MessageDigest::sha3_384(), test);
67792f3ab15Sopenharmony_ci        }
67892f3ab15Sopenharmony_ci
67992f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha3_384().block_size(), 104);
68092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha3_384().size(), 48);
68192f3ab15Sopenharmony_ci        assert_eq!(
68292f3ab15Sopenharmony_ci            MessageDigest::sha3_384().type_().as_raw(),
68392f3ab15Sopenharmony_ci            Nid::SHA3_384.as_raw()
68492f3ab15Sopenharmony_ci        );
68592f3ab15Sopenharmony_ci    }
68692f3ab15Sopenharmony_ci
68792f3ab15Sopenharmony_ci    #[cfg(ossl111)]
68892f3ab15Sopenharmony_ci    #[test]
68992f3ab15Sopenharmony_ci    fn test_sha3_512() {
69092f3ab15Sopenharmony_ci        let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
69192f3ab15Sopenharmony_ci            "c072288ef728cd53a029c47687960b9225893532f42b923156e37020bdc1eda753aafbf30af859d4f4c3a1\
69292f3ab15Sopenharmony_ci            807caee3a79f8eb02dcd61589fbbdf5f40c8787a72"
69392f3ab15Sopenharmony_ci        )];
69492f3ab15Sopenharmony_ci
69592f3ab15Sopenharmony_ci        for test in tests.iter() {
69692f3ab15Sopenharmony_ci            hash_test(MessageDigest::sha3_512(), test);
69792f3ab15Sopenharmony_ci        }
69892f3ab15Sopenharmony_ci
69992f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha3_512().block_size(), 72);
70092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sha3_512().size(), 64);
70192f3ab15Sopenharmony_ci        assert_eq!(
70292f3ab15Sopenharmony_ci            MessageDigest::sha3_512().type_().as_raw(),
70392f3ab15Sopenharmony_ci            Nid::SHA3_512.as_raw()
70492f3ab15Sopenharmony_ci        );
70592f3ab15Sopenharmony_ci    }
70692f3ab15Sopenharmony_ci
70792f3ab15Sopenharmony_ci    #[cfg(ossl111)]
70892f3ab15Sopenharmony_ci    #[test]
70992f3ab15Sopenharmony_ci    fn test_shake_128() {
71092f3ab15Sopenharmony_ci        let tests = [(
71192f3ab15Sopenharmony_ci            "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
71292f3ab15Sopenharmony_ci            "49d0697ff508111d8b84f15e46daf135",
71392f3ab15Sopenharmony_ci        )];
71492f3ab15Sopenharmony_ci
71592f3ab15Sopenharmony_ci        for test in tests.iter() {
71692f3ab15Sopenharmony_ci            hash_xof_test(MessageDigest::shake_128(), test);
71792f3ab15Sopenharmony_ci        }
71892f3ab15Sopenharmony_ci
71992f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::shake_128().block_size(), 168);
72092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::shake_128().size(), 16);
72192f3ab15Sopenharmony_ci        assert_eq!(
72292f3ab15Sopenharmony_ci            MessageDigest::shake_128().type_().as_raw(),
72392f3ab15Sopenharmony_ci            Nid::SHAKE128.as_raw()
72492f3ab15Sopenharmony_ci        );
72592f3ab15Sopenharmony_ci    }
72692f3ab15Sopenharmony_ci
72792f3ab15Sopenharmony_ci    #[cfg(ossl111)]
72892f3ab15Sopenharmony_ci    #[test]
72992f3ab15Sopenharmony_ci    fn test_shake_256() {
73092f3ab15Sopenharmony_ci        let tests = [(
73192f3ab15Sopenharmony_ci            "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
73292f3ab15Sopenharmony_ci            "4e2dfdaa75d1e049d0eaeffe28e76b17cea47b650fb8826fe48b94664326a697",
73392f3ab15Sopenharmony_ci        )];
73492f3ab15Sopenharmony_ci
73592f3ab15Sopenharmony_ci        for test in tests.iter() {
73692f3ab15Sopenharmony_ci            hash_xof_test(MessageDigest::shake_256(), test);
73792f3ab15Sopenharmony_ci        }
73892f3ab15Sopenharmony_ci
73992f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::shake_256().block_size(), 136);
74092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::shake_256().size(), 32);
74192f3ab15Sopenharmony_ci        assert_eq!(
74292f3ab15Sopenharmony_ci            MessageDigest::shake_256().type_().as_raw(),
74392f3ab15Sopenharmony_ci            Nid::SHAKE256.as_raw()
74492f3ab15Sopenharmony_ci        );
74592f3ab15Sopenharmony_ci    }
74692f3ab15Sopenharmony_ci
74792f3ab15Sopenharmony_ci    #[test]
74892f3ab15Sopenharmony_ci    #[cfg(not(boringssl))]
74992f3ab15Sopenharmony_ci    #[cfg_attr(ossl300, ignore)]
75092f3ab15Sopenharmony_ci    fn test_ripemd160() {
75192f3ab15Sopenharmony_ci        #[cfg(ossl300)]
75292f3ab15Sopenharmony_ci        let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
75392f3ab15Sopenharmony_ci
75492f3ab15Sopenharmony_ci        let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")];
75592f3ab15Sopenharmony_ci
75692f3ab15Sopenharmony_ci        for test in tests.iter() {
75792f3ab15Sopenharmony_ci            hash_test(MessageDigest::ripemd160(), test);
75892f3ab15Sopenharmony_ci        }
75992f3ab15Sopenharmony_ci
76092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::ripemd160().block_size(), 64);
76192f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::ripemd160().size(), 20);
76292f3ab15Sopenharmony_ci        assert_eq!(
76392f3ab15Sopenharmony_ci            MessageDigest::ripemd160().type_().as_raw(),
76492f3ab15Sopenharmony_ci            Nid::RIPEMD160.as_raw()
76592f3ab15Sopenharmony_ci        );
76692f3ab15Sopenharmony_ci    }
76792f3ab15Sopenharmony_ci
76892f3ab15Sopenharmony_ci    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
76992f3ab15Sopenharmony_ci    #[test]
77092f3ab15Sopenharmony_ci    fn test_sm3() {
77192f3ab15Sopenharmony_ci        let tests = [(
77292f3ab15Sopenharmony_ci            "616263",
77392f3ab15Sopenharmony_ci            "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
77492f3ab15Sopenharmony_ci        )];
77592f3ab15Sopenharmony_ci
77692f3ab15Sopenharmony_ci        for test in tests.iter() {
77792f3ab15Sopenharmony_ci            hash_test(MessageDigest::sm3(), test);
77892f3ab15Sopenharmony_ci        }
77992f3ab15Sopenharmony_ci
78092f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sm3().block_size(), 64);
78192f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sm3().size(), 32);
78292f3ab15Sopenharmony_ci        assert_eq!(MessageDigest::sm3().type_().as_raw(), Nid::SM3.as_raw());
78392f3ab15Sopenharmony_ci    }
78492f3ab15Sopenharmony_ci
78592f3ab15Sopenharmony_ci    #[test]
78692f3ab15Sopenharmony_ci    fn from_nid() {
78792f3ab15Sopenharmony_ci        assert_eq!(
78892f3ab15Sopenharmony_ci            MessageDigest::from_nid(Nid::SHA256).unwrap().as_ptr(),
78992f3ab15Sopenharmony_ci            MessageDigest::sha256().as_ptr()
79092f3ab15Sopenharmony_ci        );
79192f3ab15Sopenharmony_ci    }
79292f3ab15Sopenharmony_ci
79392f3ab15Sopenharmony_ci    #[test]
79492f3ab15Sopenharmony_ci    fn from_name() {
79592f3ab15Sopenharmony_ci        assert_eq!(
79692f3ab15Sopenharmony_ci            MessageDigest::from_name("SHA256").unwrap().as_ptr(),
79792f3ab15Sopenharmony_ci            MessageDigest::sha256().as_ptr()
79892f3ab15Sopenharmony_ci        )
79992f3ab15Sopenharmony_ci    }
80092f3ab15Sopenharmony_ci}
801