1 //! Message digest (hash) computation support.
2 //!
3 //! # Examples
4 //!
5 //! Calculate a hash in one go:
6 //!
7 //! ```
8 //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
9 //! use openssl::hash::{hash, MessageDigest};
10 //!
11 //! let data = b"\x42\xF4\x97\xE0";
12 //! let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
13 //! let res = hash(MessageDigest::md5(), data)?;
14 //! assert_eq!(&*res, spec);
15 //! # Ok(()) }
16 //! ```
17 //!
18 //! Supply the input in chunks:
19 //!
20 //! ```
21 //! use openssl::hash::{Hasher, MessageDigest};
22 //!
23 //! # fn main() -> Result<(), Box<dyn std::error::Error>> {
24 //! let mut hasher = Hasher::new(MessageDigest::sha256())?;
25 //! hasher.update(b"test")?;
26 //! hasher.update(b"this")?;
27 //! let digest: &[u8] = &hasher.finish()?;
28 //!
29 //! let expected = hex::decode("9740e652ab5b4acd997a7cca13d6696702ccb2d441cca59fc6e285127f28cfe6")?;
30 //! assert_eq!(digest, expected);
31 //! # Ok(()) }
32 //! ```
33 use cfg_if::cfg_if;
34 use std::ffi::CString;
35 use std::fmt;
36 use std::io;
37 use std::io::prelude::*;
38 use std::ops::{Deref, DerefMut};
39 use std::ptr;
40 
41 use crate::error::ErrorStack;
42 use crate::nid::Nid;
43 use crate::{cvt, cvt_p};
44 
45 cfg_if! {
46     if #[cfg(any(ossl110, boringssl))] {
47         use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
48     } else {
49         use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
50     }
51 }
52 
53 /// A message digest algorithm.
54 #[derive(Copy, Clone, PartialEq, Eq)]
55 pub struct MessageDigest(*const ffi::EVP_MD);
56 
57 impl MessageDigest {
58     /// Creates a `MessageDigest` from a raw OpenSSL pointer.
59     ///
60     /// # Safety
61     ///
62     /// The caller must ensure the pointer is valid.
from_ptrnull63     pub unsafe fn from_ptr(x: *const ffi::EVP_MD) -> Self {
64         MessageDigest(x)
65     }
66 
67     /// Returns the `MessageDigest` corresponding to an `Nid`.
68     ///
69     /// This corresponds to [`EVP_get_digestbynid`].
70     ///
71     /// [`EVP_get_digestbynid`]: https://www.openssl.org/docs/manmaster/crypto/EVP_DigestInit.html
from_nidnull72     pub fn from_nid(type_: Nid) -> Option<MessageDigest> {
73         unsafe {
74             let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
75             if ptr.is_null() {
76                 None
77             } else {
78                 Some(MessageDigest(ptr))
79             }
80         }
81     }
82 
83     /// Returns the `MessageDigest` corresponding to an algorithm name.
84     ///
85     /// This corresponds to [`EVP_get_digestbyname`].
86     ///
87     /// [`EVP_get_digestbyname`]: https://www.openssl.org/docs/manmaster/crypto/EVP_DigestInit.html
from_namenull88     pub fn from_name(name: &str) -> Option<MessageDigest> {
89         ffi::init();
90         let name = CString::new(name).ok()?;
91         unsafe {
92             let ptr = ffi::EVP_get_digestbyname(name.as_ptr());
93             if ptr.is_null() {
94                 None
95             } else {
96                 Some(MessageDigest(ptr))
97             }
98         }
99     }
100 
101     #[cfg(not(boringssl))]
nullnull102     pub fn null() -> MessageDigest {
103         unsafe { MessageDigest(ffi::EVP_md_null()) }
104     }
105 
md5null106     pub fn md5() -> MessageDigest {
107         unsafe { MessageDigest(ffi::EVP_md5()) }
108     }
109 
sha1null110     pub fn sha1() -> MessageDigest {
111         unsafe { MessageDigest(ffi::EVP_sha1()) }
112     }
113 
sha224null114     pub fn sha224() -> MessageDigest {
115         unsafe { MessageDigest(ffi::EVP_sha224()) }
116     }
117 
sha256null118     pub fn sha256() -> MessageDigest {
119         unsafe { MessageDigest(ffi::EVP_sha256()) }
120     }
121 
sha384null122     pub fn sha384() -> MessageDigest {
123         unsafe { MessageDigest(ffi::EVP_sha384()) }
124     }
125 
sha512null126     pub fn sha512() -> MessageDigest {
127         unsafe { MessageDigest(ffi::EVP_sha512()) }
128     }
129 
130     #[cfg(ossl111)]
sha3_224null131     pub fn sha3_224() -> MessageDigest {
132         unsafe { MessageDigest(ffi::EVP_sha3_224()) }
133     }
134 
135     #[cfg(ossl111)]
sha3_256null136     pub fn sha3_256() -> MessageDigest {
137         unsafe { MessageDigest(ffi::EVP_sha3_256()) }
138     }
139 
140     #[cfg(ossl111)]
sha3_384null141     pub fn sha3_384() -> MessageDigest {
142         unsafe { MessageDigest(ffi::EVP_sha3_384()) }
143     }
144 
145     #[cfg(ossl111)]
sha3_512null146     pub fn sha3_512() -> MessageDigest {
147         unsafe { MessageDigest(ffi::EVP_sha3_512()) }
148     }
149 
150     #[cfg(ossl111)]
shake_128null151     pub fn shake_128() -> MessageDigest {
152         unsafe { MessageDigest(ffi::EVP_shake128()) }
153     }
154 
155     #[cfg(ossl111)]
shake_256null156     pub fn shake_256() -> MessageDigest {
157         unsafe { MessageDigest(ffi::EVP_shake256()) }
158     }
159 
160     #[cfg(not(any(boringssl, osslconf = "OPENSSL_NO_RMD160")))]
ripemd160null161     pub fn ripemd160() -> MessageDigest {
162         unsafe { MessageDigest(ffi::EVP_ripemd160()) }
163     }
164 
165     #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
sm3null166     pub fn sm3() -> MessageDigest {
167         unsafe { MessageDigest(ffi::EVP_sm3()) }
168     }
169 
170     #[allow(clippy::trivially_copy_pass_by_ref)]
as_ptrnull171     pub fn as_ptr(&self) -> *const ffi::EVP_MD {
172         self.0
173     }
174 
175     /// The block size of the digest in bytes.
176     #[allow(clippy::trivially_copy_pass_by_ref)]
block_sizenull177     pub fn block_size(&self) -> usize {
178         unsafe { ffi::EVP_MD_block_size(self.0) as usize }
179     }
180 
181     /// The size of the digest in bytes.
182     #[allow(clippy::trivially_copy_pass_by_ref)]
sizenull183     pub fn size(&self) -> usize {
184         unsafe { ffi::EVP_MD_size(self.0) as usize }
185     }
186 
187     /// The name of the digest.
188     #[allow(clippy::trivially_copy_pass_by_ref)]
type_null189     pub fn type_(&self) -> Nid {
190         Nid::from_raw(unsafe { ffi::EVP_MD_type(self.0) })
191     }
192 }
193 
194 unsafe impl Sync for MessageDigest {}
195 unsafe impl Send for MessageDigest {}
196 
197 #[derive(PartialEq, Copy, Clone)]
198 enum State {
199     Reset,
200     Updated,
201     Finalized,
202 }
203 
204 use self::State::*;
205 
206 /// Provides message digest (hash) computation.
207 ///
208 /// # Examples
209 ///
210 /// ```
211 /// use openssl::hash::{Hasher, MessageDigest};
212 ///
213 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
214 /// let data = [b"\x42\xF4", b"\x97\xE0"];
215 /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
216 /// let mut h = Hasher::new(MessageDigest::md5())?;
217 /// h.update(data[0])?;
218 /// h.update(data[1])?;
219 /// let res = h.finish()?;
220 /// assert_eq!(&*res, spec);
221 /// # Ok(()) }
222 /// ```
223 ///
224 /// # Warning
225 ///
226 /// Don't actually use MD5 and SHA-1 hashes, they're not secure anymore.
227 ///
228 /// Don't ever hash passwords, use the functions in the `pkcs5` module or bcrypt/scrypt instead.
229 ///
230 /// For extendable output functions (XOFs, i.e. SHAKE128/SHAKE256),
231 /// you must use [`Hasher::finish_xof`] instead of [`Hasher::finish`]
232 /// and provide a `buf` to store the hash. The hash will be as long as
233 /// the `buf`.
234 pub struct Hasher {
235     ctx: *mut ffi::EVP_MD_CTX,
236     md: *const ffi::EVP_MD,
237     type_: MessageDigest,
238     state: State,
239 }
240 
241 unsafe impl Sync for Hasher {}
242 unsafe impl Send for Hasher {}
243 
244 impl Hasher {
245     /// Creates a new `Hasher` with the specified hash type.
newnull246     pub fn new(ty: MessageDigest) -> Result<Hasher, ErrorStack> {
247         ffi::init();
248 
249         let ctx = unsafe { cvt_p(EVP_MD_CTX_new())? };
250 
251         let mut h = Hasher {
252             ctx,
253             md: ty.as_ptr(),
254             type_: ty,
255             state: Finalized,
256         };
257         h.init()?;
258         Ok(h)
259     }
260 
initnull261     fn init(&mut self) -> Result<(), ErrorStack> {
262         match self.state {
263             Reset => return Ok(()),
264             Updated => {
265                 self.finish()?;
266             }
267             Finalized => (),
268         }
269         unsafe {
270             cvt(ffi::EVP_DigestInit_ex(self.ctx, self.md, ptr::null_mut()))?;
271         }
272         self.state = Reset;
273         Ok(())
274     }
275 
276     /// Feeds data into the hasher.
updatenull277     pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
278         if self.state == Finalized {
279             self.init()?;
280         }
281         unsafe {
282             cvt(ffi::EVP_DigestUpdate(
283                 self.ctx,
284                 data.as_ptr() as *mut _,
285                 data.len(),
286             ))?;
287         }
288         self.state = Updated;
289         Ok(())
290     }
291 
292     /// Returns the hash of the data written and resets the non-XOF hasher.
finishnull293     pub fn finish(&mut self) -> Result<DigestBytes, ErrorStack> {
294         if self.state == Finalized {
295             self.init()?;
296         }
297         unsafe {
298             #[cfg(not(boringssl))]
299             let mut len = ffi::EVP_MAX_MD_SIZE;
300             #[cfg(boringssl)]
301             let mut len = ffi::EVP_MAX_MD_SIZE as u32;
302             let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize];
303             cvt(ffi::EVP_DigestFinal_ex(
304                 self.ctx,
305                 buf.as_mut_ptr(),
306                 &mut len,
307             ))?;
308             self.state = Finalized;
309             Ok(DigestBytes {
310                 buf,
311                 len: len as usize,
312             })
313         }
314     }
315 
316     /// Writes the hash of the data into the supplied buf and resets the XOF hasher.
317     /// The hash will be as long as the buf.
318     #[cfg(ossl111)]
finish_xofnull319     pub fn finish_xof(&mut self, buf: &mut [u8]) -> Result<(), ErrorStack> {
320         if self.state == Finalized {
321             self.init()?;
322         }
323         unsafe {
324             cvt(ffi::EVP_DigestFinalXOF(
325                 self.ctx,
326                 buf.as_mut_ptr(),
327                 buf.len(),
328             ))?;
329             self.state = Finalized;
330             Ok(())
331         }
332     }
333 }
334 
335 impl Write for Hasher {
336     #[inline]
writenull337     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
338         self.update(buf)?;
339         Ok(buf.len())
340     }
341 
flushnull342     fn flush(&mut self) -> io::Result<()> {
343         Ok(())
344     }
345 }
346 
347 impl Clone for Hasher {
clonenull348     fn clone(&self) -> Hasher {
349         let ctx = unsafe {
350             let ctx = EVP_MD_CTX_new();
351             assert!(!ctx.is_null());
352             let r = ffi::EVP_MD_CTX_copy_ex(ctx, self.ctx);
353             assert_eq!(r, 1);
354             ctx
355         };
356         Hasher {
357             ctx,
358             md: self.md,
359             type_: self.type_,
360             state: self.state,
361         }
362     }
363 }
364 
365 impl Drop for Hasher {
dropnull366     fn drop(&mut self) {
367         unsafe {
368             if self.state != Finalized {
369                 drop(self.finish());
370             }
371             EVP_MD_CTX_free(self.ctx);
372         }
373     }
374 }
375 
376 /// The resulting bytes of a digest.
377 ///
378 /// This type derefs to a byte slice - it exists to avoid allocating memory to
379 /// store the digest data.
380 #[derive(Copy)]
381 pub struct DigestBytes {
382     pub(crate) buf: [u8; ffi::EVP_MAX_MD_SIZE as usize],
383     pub(crate) len: usize,
384 }
385 
386 impl Clone for DigestBytes {
387     #[inline]
clonenull388     fn clone(&self) -> DigestBytes {
389         *self
390     }
391 }
392 
393 impl Deref for DigestBytes {
394     type Target = [u8];
395 
396     #[inline]
derefnull397     fn deref(&self) -> &[u8] {
398         &self.buf[..self.len]
399     }
400 }
401 
402 impl DerefMut for DigestBytes {
403     #[inline]
deref_mutnull404     fn deref_mut(&mut self) -> &mut [u8] {
405         &mut self.buf[..self.len]
406     }
407 }
408 
409 impl AsRef<[u8]> for DigestBytes {
410     #[inline]
as_refnull411     fn as_ref(&self) -> &[u8] {
412         self.deref()
413     }
414 }
415 
416 impl fmt::Debug for DigestBytes {
fmtnull417     fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
418         fmt::Debug::fmt(&**self, fmt)
419     }
420 }
421 
422 /// Computes the hash of the `data` with the non-XOF hasher `t`.
423 ///
424 /// # Examples
425 ///
426 /// ```
427 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
428 /// use openssl::hash::{hash, MessageDigest};
429 ///
430 /// let data = b"\x42\xF4\x97\xE0";
431 /// let spec = b"\x7c\x43\x0f\x17\x8a\xef\xdf\x14\x87\xfe\xe7\x14\x4e\x96\x41\xe2";
432 /// let res = hash(MessageDigest::md5(), data)?;
433 /// assert_eq!(&*res, spec);
434 /// # Ok(()) }
435 /// ```
436 pub fn hash(t: MessageDigest, data: &[u8]) -> Result<DigestBytes, ErrorStack> {
437     let mut h = Hasher::new(t)?;
438     h.update(data)?;
439     h.finish()
440 }
441 
442 /// Computes the hash of the `data` with the XOF hasher `t` and stores it in `buf`.
443 ///
444 /// # Examples
445 ///
446 /// ```
447 /// use openssl::hash::{hash_xof, MessageDigest};
448 ///
449 /// 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";
450 /// let spec = b"\x49\xd0\x69\x7f\xf5\x08\x11\x1d\x8b\x84\xf1\x5e\x46\xda\xf1\x35";
451 /// let mut buf = vec![0; 16];
452 /// hash_xof(MessageDigest::shake_128(), data, buf.as_mut_slice()).unwrap();
453 /// assert_eq!(buf, spec);
454 /// ```
455 ///
456 #[cfg(ossl111)]
hash_xofnull457 pub fn hash_xof(t: MessageDigest, data: &[u8], buf: &mut [u8]) -> Result<(), ErrorStack> {
458     let mut h = Hasher::new(t)?;
459     h.update(data)?;
460     h.finish_xof(buf)
461 }
462 
463 #[cfg(test)]
464 mod tests {
465     use hex::{self, FromHex};
466     use std::io::prelude::*;
467 
468     use super::*;
469 
hash_testnull470     fn hash_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
471         let res = hash(hashtype, &Vec::from_hex(hashtest.0).unwrap()).unwrap();
472         assert_eq!(hex::encode(res), hashtest.1);
473     }
474 
475     #[cfg(ossl111)]
hash_xof_testnull476     fn hash_xof_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
477         let expected = Vec::from_hex(hashtest.1).unwrap();
478         let mut buf = vec![0; expected.len()];
479         hash_xof(
480             hashtype,
481             &Vec::from_hex(hashtest.0).unwrap(),
482             buf.as_mut_slice(),
483         )
484         .unwrap();
485         assert_eq!(buf, expected);
486     }
487 
hash_recycle_testnull488     fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) {
489         h.write_all(&Vec::from_hex(hashtest.0).unwrap()).unwrap();
490         let res = h.finish().unwrap();
491         assert_eq!(hex::encode(res), hashtest.1);
492     }
493 
494     // Test vectors from http://www.nsrl.nist.gov/testdata/
495     const MD5_TESTS: [(&str, &str); 13] = [
496         ("", "d41d8cd98f00b204e9800998ecf8427e"),
497         ("7F", "83acb6e67e50e31db6ed341dd2de1595"),
498         ("EC9C", "0b07f0d4ca797d8ac58874f887cb0b68"),
499         ("FEE57A", "e0d583171eb06d56198fc0ef22173907"),
500         ("42F497E0", "7c430f178aefdf1487fee7144e9641e2"),
501         ("C53B777F1C", "75ef141d64cb37ec423da2d9d440c925"),
502         ("89D5B576327B", "ebbaf15eb0ed784c6faa9dc32831bf33"),
503         ("5D4CCE781EB190", "ce175c4b08172019f05e6b5279889f2c"),
504         ("81901FE94932D7B9", "cd4d2f62b8cdb3a0cf968a735a239281"),
505         ("C9FFDEE7788EFB4EC9", "e0841a231ab698db30c6c0f3f246c014"),
506         ("66AC4B7EBA95E53DC10B", "a3b3cea71910d9af56742aa0bb2fe329"),
507         ("A510CD18F7A56852EB0319", "577e216843dd11573574d3fb209b97d8"),
508         (
509             "AAED18DBE8938C19ED734A8D",
510             "6f80fb775f27e0a4ce5c2f42fc72c5f1",
511         ),
512     ];
513 
514     #[test]
test_md5null515     fn test_md5() {
516         for test in MD5_TESTS.iter() {
517             hash_test(MessageDigest::md5(), test);
518         }
519 
520         assert_eq!(MessageDigest::md5().block_size(), 64);
521         assert_eq!(MessageDigest::md5().size(), 16);
522         assert_eq!(MessageDigest::md5().type_().as_raw(), Nid::MD5.as_raw());
523     }
524 
525     #[test]
test_md5_recyclenull526     fn test_md5_recycle() {
527         let mut h = Hasher::new(MessageDigest::md5()).unwrap();
528         for test in MD5_TESTS.iter() {
529             hash_recycle_test(&mut h, test);
530         }
531     }
532 
533     #[test]
test_finish_twicenull534     fn test_finish_twice() {
535         let mut h = Hasher::new(MessageDigest::md5()).unwrap();
536         h.write_all(&Vec::from_hex(MD5_TESTS[6].0).unwrap())
537             .unwrap();
538         h.finish().unwrap();
539         let res = h.finish().unwrap();
540         let null = hash(MessageDigest::md5(), &[]).unwrap();
541         assert_eq!(&*res, &*null);
542     }
543 
544     #[test]
545     #[allow(clippy::redundant_clone)]
test_clonenull546     fn test_clone() {
547         let i = 7;
548         let inp = Vec::from_hex(MD5_TESTS[i].0).unwrap();
549         assert!(inp.len() > 2);
550         let p = inp.len() / 2;
551         let h0 = Hasher::new(MessageDigest::md5()).unwrap();
552 
553         println!("Clone a new hasher");
554         let mut h1 = h0.clone();
555         h1.write_all(&inp[..p]).unwrap();
556         {
557             println!("Clone an updated hasher");
558             let mut h2 = h1.clone();
559             h2.write_all(&inp[p..]).unwrap();
560             let res = h2.finish().unwrap();
561             assert_eq!(hex::encode(res), MD5_TESTS[i].1);
562         }
563         h1.write_all(&inp[p..]).unwrap();
564         let res = h1.finish().unwrap();
565         assert_eq!(hex::encode(res), MD5_TESTS[i].1);
566 
567         println!("Clone a finished hasher");
568         let mut h3 = h1.clone();
569         h3.write_all(&Vec::from_hex(MD5_TESTS[i + 1].0).unwrap())
570             .unwrap();
571         let res = h3.finish().unwrap();
572         assert_eq!(hex::encode(res), MD5_TESTS[i + 1].1);
573     }
574 
575     #[test]
test_sha1null576     fn test_sha1() {
577         let tests = [("616263", "a9993e364706816aba3e25717850c26c9cd0d89d")];
578 
579         for test in tests.iter() {
580             hash_test(MessageDigest::sha1(), test);
581         }
582 
583         assert_eq!(MessageDigest::sha1().block_size(), 64);
584         assert_eq!(MessageDigest::sha1().size(), 20);
585         assert_eq!(MessageDigest::sha1().type_().as_raw(), Nid::SHA1.as_raw());
586     }
587 
588     #[test]
test_sha256null589     fn test_sha256() {
590         let tests = [(
591             "616263",
592             "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
593         )];
594 
595         for test in tests.iter() {
596             hash_test(MessageDigest::sha256(), test);
597         }
598 
599         assert_eq!(MessageDigest::sha256().block_size(), 64);
600         assert_eq!(MessageDigest::sha256().size(), 32);
601         assert_eq!(
602             MessageDigest::sha256().type_().as_raw(),
603             Nid::SHA256.as_raw()
604         );
605     }
606 
607     #[test]
test_sha512null608     fn test_sha512() {
609         let tests = [(
610             "737465766566696e647365766572797468696e67",
611             "ba61d1f1af0f2dd80729f6cc900f19c0966bd38ba5c75e4471ef11b771dfe7551afab7fcbd300fdc4418f2\
612             b07a028fcd99e7b6446a566f2d9bcd7c604a1ea801",
613         )];
614 
615         for test in tests.iter() {
616             hash_test(MessageDigest::sha512(), test);
617         }
618 
619         assert_eq!(MessageDigest::sha512().block_size(), 128);
620         assert_eq!(MessageDigest::sha512().size(), 64);
621         assert_eq!(
622             MessageDigest::sha512().type_().as_raw(),
623             Nid::SHA512.as_raw()
624         );
625     }
626 
627     #[cfg(ossl111)]
628     #[test]
test_sha3_224null629     fn test_sha3_224() {
630         let tests = [(
631             "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
632             "1de092dd9fbcbbf450f26264f4778abd48af851f2832924554c56913",
633         )];
634 
635         for test in tests.iter() {
636             hash_test(MessageDigest::sha3_224(), test);
637         }
638 
639         assert_eq!(MessageDigest::sha3_224().block_size(), 144);
640         assert_eq!(MessageDigest::sha3_224().size(), 28);
641         assert_eq!(
642             MessageDigest::sha3_224().type_().as_raw(),
643             Nid::SHA3_224.as_raw()
644         );
645     }
646 
647     #[cfg(ossl111)]
648     #[test]
test_sha3_256null649     fn test_sha3_256() {
650         let tests = [(
651             "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
652             "b38e38f08bc1c0091ed4b5f060fe13e86aa4179578513ad11a6e3abba0062f61",
653         )];
654 
655         for test in tests.iter() {
656             hash_test(MessageDigest::sha3_256(), test);
657         }
658 
659         assert_eq!(MessageDigest::sha3_256().block_size(), 136);
660         assert_eq!(MessageDigest::sha3_256().size(), 32);
661         assert_eq!(
662             MessageDigest::sha3_256().type_().as_raw(),
663             Nid::SHA3_256.as_raw()
664         );
665     }
666 
667     #[cfg(ossl111)]
668     #[test]
test_sha3_384null669     fn test_sha3_384() {
670         let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
671             "966ee786ab3482dd811bf7c8fa8db79aa1f52f6c3c369942ef14240ebd857c6ff626ec35d9e131ff64d328\
672             ef2008ff16"
673         )];
674 
675         for test in tests.iter() {
676             hash_test(MessageDigest::sha3_384(), test);
677         }
678 
679         assert_eq!(MessageDigest::sha3_384().block_size(), 104);
680         assert_eq!(MessageDigest::sha3_384().size(), 48);
681         assert_eq!(
682             MessageDigest::sha3_384().type_().as_raw(),
683             Nid::SHA3_384.as_raw()
684         );
685     }
686 
687     #[cfg(ossl111)]
688     #[test]
test_sha3_512null689     fn test_sha3_512() {
690         let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
691             "c072288ef728cd53a029c47687960b9225893532f42b923156e37020bdc1eda753aafbf30af859d4f4c3a1\
692             807caee3a79f8eb02dcd61589fbbdf5f40c8787a72"
693         )];
694 
695         for test in tests.iter() {
696             hash_test(MessageDigest::sha3_512(), test);
697         }
698 
699         assert_eq!(MessageDigest::sha3_512().block_size(), 72);
700         assert_eq!(MessageDigest::sha3_512().size(), 64);
701         assert_eq!(
702             MessageDigest::sha3_512().type_().as_raw(),
703             Nid::SHA3_512.as_raw()
704         );
705     }
706 
707     #[cfg(ossl111)]
708     #[test]
test_shake_128null709     fn test_shake_128() {
710         let tests = [(
711             "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
712             "49d0697ff508111d8b84f15e46daf135",
713         )];
714 
715         for test in tests.iter() {
716             hash_xof_test(MessageDigest::shake_128(), test);
717         }
718 
719         assert_eq!(MessageDigest::shake_128().block_size(), 168);
720         assert_eq!(MessageDigest::shake_128().size(), 16);
721         assert_eq!(
722             MessageDigest::shake_128().type_().as_raw(),
723             Nid::SHAKE128.as_raw()
724         );
725     }
726 
727     #[cfg(ossl111)]
728     #[test]
test_shake_256null729     fn test_shake_256() {
730         let tests = [(
731             "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
732             "4e2dfdaa75d1e049d0eaeffe28e76b17cea47b650fb8826fe48b94664326a697",
733         )];
734 
735         for test in tests.iter() {
736             hash_xof_test(MessageDigest::shake_256(), test);
737         }
738 
739         assert_eq!(MessageDigest::shake_256().block_size(), 136);
740         assert_eq!(MessageDigest::shake_256().size(), 32);
741         assert_eq!(
742             MessageDigest::shake_256().type_().as_raw(),
743             Nid::SHAKE256.as_raw()
744         );
745     }
746 
747     #[test]
748     #[cfg(not(boringssl))]
749     #[cfg_attr(ossl300, ignore)]
test_ripemd160null750     fn test_ripemd160() {
751         #[cfg(ossl300)]
752         let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
753 
754         let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")];
755 
756         for test in tests.iter() {
757             hash_test(MessageDigest::ripemd160(), test);
758         }
759 
760         assert_eq!(MessageDigest::ripemd160().block_size(), 64);
761         assert_eq!(MessageDigest::ripemd160().size(), 20);
762         assert_eq!(
763             MessageDigest::ripemd160().type_().as_raw(),
764             Nid::RIPEMD160.as_raw()
765         );
766     }
767 
768     #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
769     #[test]
test_sm3null770     fn test_sm3() {
771         let tests = [(
772             "616263",
773             "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
774         )];
775 
776         for test in tests.iter() {
777             hash_test(MessageDigest::sm3(), test);
778         }
779 
780         assert_eq!(MessageDigest::sm3().block_size(), 64);
781         assert_eq!(MessageDigest::sm3().size(), 32);
782         assert_eq!(MessageDigest::sm3().type_().as_raw(), Nid::SM3.as_raw());
783     }
784 
785     #[test]
from_nidnull786     fn from_nid() {
787         assert_eq!(
788             MessageDigest::from_nid(Nid::SHA256).unwrap().as_ptr(),
789             MessageDigest::sha256().as_ptr()
790         );
791     }
792 
793     #[test]
from_namenull794     fn from_name() {
795         assert_eq!(
796             MessageDigest::from_name("SHA256").unwrap().as_ptr(),
797             MessageDigest::sha256().as_ptr()
798         )
799     }
800 }
801