1use cfg_if::cfg_if;
34use std::ffi::CString;
35use std::fmt;
36use std::io;
37use std::io::prelude::*;
38use std::ops::{Deref, DerefMut};
39use std::ptr;
40
41use crate::error::ErrorStack;
42use crate::nid::Nid;
43use crate::{cvt, cvt_p};
44use openssl_macros::corresponds;
45
46cfg_if! {
47 if #[cfg(any(ossl110, boringssl, libressl382, awslc))] {
48 use ffi::{EVP_MD_CTX_free, EVP_MD_CTX_new};
49 } else {
50 use ffi::{EVP_MD_CTX_create as EVP_MD_CTX_new, EVP_MD_CTX_destroy as EVP_MD_CTX_free};
51 }
52}
53
54#[derive(Copy, Clone, PartialEq, Eq)]
56pub struct MessageDigest(*const ffi::EVP_MD);
57
58impl MessageDigest {
59 pub unsafe fn from_ptr(x: *const ffi::EVP_MD) -> Self {
65 MessageDigest(x)
66 }
67
68 #[corresponds(EVP_get_digestbynid)]
70 pub fn from_nid(type_: Nid) -> Option<MessageDigest> {
71 ffi::init();
72 unsafe {
73 let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
74 if ptr.is_null() {
75 None
76 } else {
77 Some(MessageDigest(ptr))
78 }
79 }
80 }
81
82 #[corresponds(EVP_get_digestbyname)]
84 pub fn from_name(name: &str) -> Option<MessageDigest> {
85 ffi::init();
86 let name = CString::new(name).ok()?;
87 unsafe {
88 let ptr = ffi::EVP_get_digestbyname(name.as_ptr());
89 if ptr.is_null() {
90 None
91 } else {
92 Some(MessageDigest(ptr))
93 }
94 }
95 }
96
97 #[cfg(not(boringssl))]
98 pub fn null() -> MessageDigest {
99 unsafe { MessageDigest(ffi::EVP_md_null()) }
100 }
101
102 pub fn md5() -> MessageDigest {
103 unsafe { MessageDigest(ffi::EVP_md5()) }
104 }
105
106 pub fn sha1() -> MessageDigest {
107 unsafe { MessageDigest(ffi::EVP_sha1()) }
108 }
109
110 pub fn sha224() -> MessageDigest {
111 unsafe { MessageDigest(ffi::EVP_sha224()) }
112 }
113
114 pub fn sha256() -> MessageDigest {
115 unsafe { MessageDigest(ffi::EVP_sha256()) }
116 }
117
118 pub fn sha384() -> MessageDigest {
119 unsafe { MessageDigest(ffi::EVP_sha384()) }
120 }
121
122 pub fn sha512() -> MessageDigest {
123 unsafe { MessageDigest(ffi::EVP_sha512()) }
124 }
125
126 #[cfg(any(ossl111, libressl380, awslc))]
127 pub fn sha3_224() -> MessageDigest {
128 unsafe { MessageDigest(ffi::EVP_sha3_224()) }
129 }
130
131 #[cfg(any(ossl111, libressl380, awslc))]
132 pub fn sha3_256() -> MessageDigest {
133 unsafe { MessageDigest(ffi::EVP_sha3_256()) }
134 }
135
136 #[cfg(any(ossl111, libressl380, awslc))]
137 pub fn sha3_384() -> MessageDigest {
138 unsafe { MessageDigest(ffi::EVP_sha3_384()) }
139 }
140
141 #[cfg(any(ossl111, libressl380, awslc))]
142 pub fn sha3_512() -> MessageDigest {
143 unsafe { MessageDigest(ffi::EVP_sha3_512()) }
144 }
145
146 #[cfg(any(ossl111, awslc))]
147 pub fn shake_128() -> MessageDigest {
148 unsafe { MessageDigest(ffi::EVP_shake128()) }
149 }
150
151 #[cfg(any(ossl111, awslc))]
152 pub fn shake_256() -> MessageDigest {
153 unsafe { MessageDigest(ffi::EVP_shake256()) }
154 }
155
156 #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
157 pub fn ripemd160() -> MessageDigest {
158 unsafe { MessageDigest(ffi::EVP_ripemd160()) }
159 }
160
161 #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
162 pub fn sm3() -> MessageDigest {
163 unsafe { MessageDigest(ffi::EVP_sm3()) }
164 }
165
166 #[allow(clippy::trivially_copy_pass_by_ref)]
167 pub fn as_ptr(&self) -> *const ffi::EVP_MD {
168 self.0
169 }
170
171 #[allow(clippy::trivially_copy_pass_by_ref)]
173 pub fn block_size(&self) -> usize {
174 unsafe { ffi::EVP_MD_block_size(self.0) as usize }
175 }
176
177 #[allow(clippy::trivially_copy_pass_by_ref)]
179 pub fn size(&self) -> usize {
180 unsafe { ffi::EVP_MD_size(self.0) as usize }
181 }
182
183 #[allow(clippy::trivially_copy_pass_by_ref)]
185 pub fn type_(&self) -> Nid {
186 Nid::from_raw(unsafe { ffi::EVP_MD_type(self.0) })
187 }
188}
189
190unsafe impl Sync for MessageDigest {}
191unsafe impl Send for MessageDigest {}
192
193#[derive(PartialEq, Copy, Clone)]
194enum State {
195 Reset,
196 Updated,
197 #[cfg(ossl330)]
198 Squeeze,
199 Finalized,
200}
201
202use self::State::*;
203
204pub struct Hasher {
233 ctx: *mut ffi::EVP_MD_CTX,
234 md: *const ffi::EVP_MD,
235 type_: MessageDigest,
236 state: State,
237}
238
239unsafe impl Sync for Hasher {}
240unsafe impl Send for Hasher {}
241
242impl Hasher {
243 pub fn new(ty: MessageDigest) -> Result<Hasher, ErrorStack> {
245 ffi::init();
246
247 let ctx = unsafe { cvt_p(EVP_MD_CTX_new())? };
248
249 let mut h = Hasher {
250 ctx,
251 md: ty.as_ptr(),
252 type_: ty,
253 state: Finalized,
254 };
255 h.init()?;
256 Ok(h)
257 }
258
259 fn init(&mut self) -> Result<(), ErrorStack> {
260 match self.state {
261 Reset => return Ok(()),
262 Updated => {
263 self.finish()?;
264 }
265 #[cfg(ossl330)]
266 Squeeze => (),
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 pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
278 if self.state == Finalized {
279 self.init()?;
280 }
281 #[cfg(ossl330)]
282 if self.state == Squeeze {
283 let errors = ErrorStack::get();
292 return Err(errors);
293 }
294 unsafe {
295 cvt(ffi::EVP_DigestUpdate(
296 self.ctx,
297 data.as_ptr() as *mut _,
298 data.len(),
299 ))?;
300 }
301 self.state = Updated;
302 Ok(())
303 }
304
305 #[cfg(ossl330)]
308 pub fn squeeze_xof(&mut self, buf: &mut [u8]) -> Result<(), ErrorStack> {
309 unsafe {
310 cvt(ffi::EVP_DigestSqueeze(
311 self.ctx,
312 buf.as_mut_ptr(),
313 buf.len(),
314 ))?;
315 self.state = Squeeze;
316 Ok(())
317 }
318 }
319
320 pub fn finish(&mut self) -> Result<DigestBytes, ErrorStack> {
322 if self.state == Finalized {
323 self.init()?;
324 }
325 unsafe {
326 #[cfg(not(any(boringssl, awslc)))]
327 let mut len = ffi::EVP_MAX_MD_SIZE;
328 #[cfg(any(boringssl, awslc))]
329 let mut len = ffi::EVP_MAX_MD_SIZE as u32;
330 let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize];
331 cvt(ffi::EVP_DigestFinal_ex(
332 self.ctx,
333 buf.as_mut_ptr(),
334 &mut len,
335 ))?;
336 self.state = Finalized;
337 Ok(DigestBytes {
338 buf,
339 len: len as usize,
340 })
341 }
342 }
343
344 #[cfg(any(ossl111, awslc))]
347 pub fn finish_xof(&mut self, buf: &mut [u8]) -> Result<(), ErrorStack> {
348 if self.state == Finalized {
349 self.init()?;
350 }
351 unsafe {
352 cvt(ffi::EVP_DigestFinalXOF(
353 self.ctx,
354 buf.as_mut_ptr(),
355 buf.len(),
356 ))?;
357 self.state = Finalized;
358 Ok(())
359 }
360 }
361}
362
363impl Write for Hasher {
364 #[inline]
365 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
366 self.update(buf)?;
367 Ok(buf.len())
368 }
369
370 fn flush(&mut self) -> io::Result<()> {
371 Ok(())
372 }
373}
374
375impl Clone for Hasher {
376 fn clone(&self) -> Hasher {
377 let ctx = unsafe {
378 let ctx = EVP_MD_CTX_new();
379 assert!(!ctx.is_null());
380 let r = ffi::EVP_MD_CTX_copy_ex(ctx, self.ctx);
381 assert_eq!(r, 1);
382 ctx
383 };
384 Hasher {
385 ctx,
386 md: self.md,
387 type_: self.type_,
388 state: self.state,
389 }
390 }
391}
392
393impl Drop for Hasher {
394 fn drop(&mut self) {
395 unsafe {
396 if self.state != Finalized {
397 drop(self.finish());
398 }
399 EVP_MD_CTX_free(self.ctx);
400 }
401 }
402}
403
404#[derive(Copy)]
409pub struct DigestBytes {
410 pub(crate) buf: [u8; ffi::EVP_MAX_MD_SIZE as usize],
411 pub(crate) len: usize,
412}
413
414impl Clone for DigestBytes {
415 #[inline]
416 fn clone(&self) -> DigestBytes {
417 *self
418 }
419}
420
421impl Deref for DigestBytes {
422 type Target = [u8];
423
424 #[inline]
425 fn deref(&self) -> &[u8] {
426 &self.buf[..self.len]
427 }
428}
429
430impl DerefMut for DigestBytes {
431 #[inline]
432 fn deref_mut(&mut self) -> &mut [u8] {
433 &mut self.buf[..self.len]
434 }
435}
436
437impl AsRef<[u8]> for DigestBytes {
438 #[inline]
439 fn as_ref(&self) -> &[u8] {
440 self.deref()
441 }
442}
443
444impl fmt::Debug for DigestBytes {
445 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
446 fmt::Debug::fmt(&**self, fmt)
447 }
448}
449
450pub fn hash(t: MessageDigest, data: &[u8]) -> Result<DigestBytes, ErrorStack> {
465 let mut h = Hasher::new(t)?;
466 h.update(data)?;
467 h.finish()
468}
469
470#[cfg(any(ossl111, awslc))]
485pub fn hash_xof(t: MessageDigest, data: &[u8], buf: &mut [u8]) -> Result<(), ErrorStack> {
486 let mut h = Hasher::new(t)?;
487 h.update(data)?;
488 h.finish_xof(buf)
489}
490
491#[cfg(test)]
492mod tests {
493 use hex::{self, FromHex};
494 use std::io::prelude::*;
495
496 use super::*;
497
498 fn hash_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
499 let res = hash(hashtype, &Vec::from_hex(hashtest.0).unwrap()).unwrap();
500 assert_eq!(hex::encode(res), hashtest.1);
501 }
502
503 #[cfg(any(ossl111, awslc))]
504 fn hash_xof_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
505 let expected = Vec::from_hex(hashtest.1).unwrap();
506 let mut buf = vec![0; expected.len()];
507 hash_xof(
508 hashtype,
509 &Vec::from_hex(hashtest.0).unwrap(),
510 buf.as_mut_slice(),
511 )
512 .unwrap();
513 assert_eq!(buf, expected);
514 }
515
516 #[cfg(ossl330)]
518 fn hash_xof_squeeze_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
519 let data = Vec::from_hex(hashtest.0).unwrap();
520 let mut h = Hasher::new(hashtype).unwrap();
521 h.update(&data).unwrap();
522
523 let expected = Vec::from_hex(hashtest.1).unwrap();
524 let mut buf = vec![0; expected.len()];
525 assert!(expected.len() > 10);
526 h.squeeze_xof(&mut buf[..10]).unwrap();
527 h.squeeze_xof(&mut buf[10..]).unwrap();
528 assert_eq!(buf, expected);
529 }
530
531 fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) {
532 h.write_all(&Vec::from_hex(hashtest.0).unwrap()).unwrap();
533 let res = h.finish().unwrap();
534 assert_eq!(hex::encode(res), hashtest.1);
535 }
536
537 const MD5_TESTS: [(&str, &str); 13] = [
539 ("", "d41d8cd98f00b204e9800998ecf8427e"),
540 ("7F", "83acb6e67e50e31db6ed341dd2de1595"),
541 ("EC9C", "0b07f0d4ca797d8ac58874f887cb0b68"),
542 ("FEE57A", "e0d583171eb06d56198fc0ef22173907"),
543 ("42F497E0", "7c430f178aefdf1487fee7144e9641e2"),
544 ("C53B777F1C", "75ef141d64cb37ec423da2d9d440c925"),
545 ("89D5B576327B", "ebbaf15eb0ed784c6faa9dc32831bf33"),
546 ("5D4CCE781EB190", "ce175c4b08172019f05e6b5279889f2c"),
547 ("81901FE94932D7B9", "cd4d2f62b8cdb3a0cf968a735a239281"),
548 ("C9FFDEE7788EFB4EC9", "e0841a231ab698db30c6c0f3f246c014"),
549 ("66AC4B7EBA95E53DC10B", "a3b3cea71910d9af56742aa0bb2fe329"),
550 ("A510CD18F7A56852EB0319", "577e216843dd11573574d3fb209b97d8"),
551 (
552 "AAED18DBE8938C19ED734A8D",
553 "6f80fb775f27e0a4ce5c2f42fc72c5f1",
554 ),
555 ];
556
557 #[test]
558 fn test_md5() {
559 for test in MD5_TESTS.iter() {
560 hash_test(MessageDigest::md5(), test);
561 }
562
563 assert_eq!(MessageDigest::md5().block_size(), 64);
564 assert_eq!(MessageDigest::md5().size(), 16);
565 assert_eq!(MessageDigest::md5().type_().as_raw(), Nid::MD5.as_raw());
566 }
567
568 #[test]
569 fn test_md5_recycle() {
570 let mut h = Hasher::new(MessageDigest::md5()).unwrap();
571 for test in MD5_TESTS.iter() {
572 hash_recycle_test(&mut h, test);
573 }
574 }
575
576 #[test]
577 fn test_finish_twice() {
578 let mut h = Hasher::new(MessageDigest::md5()).unwrap();
579 h.write_all(&Vec::from_hex(MD5_TESTS[6].0).unwrap())
580 .unwrap();
581 h.finish().unwrap();
582 let res = h.finish().unwrap();
583 let null = hash(MessageDigest::md5(), &[]).unwrap();
584 assert_eq!(&*res, &*null);
585 }
586
587 #[cfg(ossl330)]
588 #[test]
589 fn test_finish_then_squeeze() {
590 let digest = MessageDigest::shake_128();
591 let mut h = Hasher::new(digest).unwrap();
592 let mut buf = vec![0; digest.size()];
593 h.finish_xof(&mut buf).unwrap();
594 h.squeeze_xof(&mut buf)
595 .expect_err("squeezing after finalize should fail");
596 }
597
598 #[cfg(ossl330)]
599 #[test]
600 fn test_squeeze_then_update() {
601 let digest = MessageDigest::shake_128();
602 let data = Vec::from_hex(MD5_TESTS[6].0).unwrap();
603 let mut h = Hasher::new(digest).unwrap();
604 let mut buf = vec![0; digest.size()];
605 h.squeeze_xof(&mut buf).unwrap();
606 h.update(&data)
607 .expect_err("updating after squeeze should fail");
608 }
609
610 #[cfg(ossl330)]
611 #[test]
612 fn test_squeeze_then_finalize() {
613 let digest = MessageDigest::shake_128();
614 let mut h = Hasher::new(digest).unwrap();
615 let mut buf = vec![0; digest.size()];
616 h.squeeze_xof(&mut buf).unwrap();
617 h.finish_xof(&mut buf)
618 .expect_err("finalize after squeeze should fail");
619 }
620
621 #[test]
622 #[allow(clippy::redundant_clone)]
623 fn test_clone() {
624 let i = 7;
625 let inp = Vec::from_hex(MD5_TESTS[i].0).unwrap();
626 assert!(inp.len() > 2);
627 let p = inp.len() / 2;
628 let h0 = Hasher::new(MessageDigest::md5()).unwrap();
629
630 println!("Clone a new hasher");
631 let mut h1 = h0.clone();
632 h1.write_all(&inp[..p]).unwrap();
633 {
634 println!("Clone an updated hasher");
635 let mut h2 = h1.clone();
636 h2.write_all(&inp[p..]).unwrap();
637 let res = h2.finish().unwrap();
638 assert_eq!(hex::encode(res), MD5_TESTS[i].1);
639 }
640 h1.write_all(&inp[p..]).unwrap();
641 let res = h1.finish().unwrap();
642 assert_eq!(hex::encode(res), MD5_TESTS[i].1);
643
644 println!("Clone a finished hasher");
645 let mut h3 = h1.clone();
646 h3.write_all(&Vec::from_hex(MD5_TESTS[i + 1].0).unwrap())
647 .unwrap();
648 let res = h3.finish().unwrap();
649 assert_eq!(hex::encode(res), MD5_TESTS[i + 1].1);
650 }
651
652 #[test]
653 fn test_sha1() {
654 let tests = [("616263", "a9993e364706816aba3e25717850c26c9cd0d89d")];
655
656 for test in tests.iter() {
657 hash_test(MessageDigest::sha1(), test);
658 }
659
660 assert_eq!(MessageDigest::sha1().block_size(), 64);
661 assert_eq!(MessageDigest::sha1().size(), 20);
662 assert_eq!(MessageDigest::sha1().type_().as_raw(), Nid::SHA1.as_raw());
663 }
664
665 #[test]
666 fn test_sha256() {
667 let tests = [(
668 "616263",
669 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
670 )];
671
672 for test in tests.iter() {
673 hash_test(MessageDigest::sha256(), test);
674 }
675
676 assert_eq!(MessageDigest::sha256().block_size(), 64);
677 assert_eq!(MessageDigest::sha256().size(), 32);
678 assert_eq!(
679 MessageDigest::sha256().type_().as_raw(),
680 Nid::SHA256.as_raw()
681 );
682 }
683
684 #[test]
685 fn test_sha512() {
686 let tests = [(
687 "737465766566696e647365766572797468696e67",
688 "ba61d1f1af0f2dd80729f6cc900f19c0966bd38ba5c75e4471ef11b771dfe7551afab7fcbd300fdc4418f2\
689 b07a028fcd99e7b6446a566f2d9bcd7c604a1ea801",
690 )];
691
692 for test in tests.iter() {
693 hash_test(MessageDigest::sha512(), test);
694 }
695
696 assert_eq!(MessageDigest::sha512().block_size(), 128);
697 assert_eq!(MessageDigest::sha512().size(), 64);
698 assert_eq!(
699 MessageDigest::sha512().type_().as_raw(),
700 Nid::SHA512.as_raw()
701 );
702 }
703
704 #[cfg(any(ossl111, libressl380, awslc))]
705 #[test]
706 fn test_sha3_224() {
707 let tests = [(
708 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
709 "1de092dd9fbcbbf450f26264f4778abd48af851f2832924554c56913",
710 )];
711
712 for test in tests.iter() {
713 hash_test(MessageDigest::sha3_224(), test);
714 }
715
716 assert_eq!(MessageDigest::sha3_224().block_size(), 144);
717 assert_eq!(MessageDigest::sha3_224().size(), 28);
718 assert_eq!(
719 MessageDigest::sha3_224().type_().as_raw(),
720 Nid::SHA3_224.as_raw()
721 );
722 }
723
724 #[cfg(any(ossl111, libressl380, awslc))]
725 #[test]
726 fn test_sha3_256() {
727 let tests = [(
728 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
729 "b38e38f08bc1c0091ed4b5f060fe13e86aa4179578513ad11a6e3abba0062f61",
730 )];
731
732 for test in tests.iter() {
733 hash_test(MessageDigest::sha3_256(), test);
734 }
735
736 assert_eq!(MessageDigest::sha3_256().block_size(), 136);
737 assert_eq!(MessageDigest::sha3_256().size(), 32);
738 assert_eq!(
739 MessageDigest::sha3_256().type_().as_raw(),
740 Nid::SHA3_256.as_raw()
741 );
742 }
743
744 #[cfg(any(ossl111, libressl380, awslc))]
745 #[test]
746 fn test_sha3_384() {
747 let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
748 "966ee786ab3482dd811bf7c8fa8db79aa1f52f6c3c369942ef14240ebd857c6ff626ec35d9e131ff64d328\
749 ef2008ff16"
750 )];
751
752 for test in tests.iter() {
753 hash_test(MessageDigest::sha3_384(), test);
754 }
755
756 assert_eq!(MessageDigest::sha3_384().block_size(), 104);
757 assert_eq!(MessageDigest::sha3_384().size(), 48);
758 assert_eq!(
759 MessageDigest::sha3_384().type_().as_raw(),
760 Nid::SHA3_384.as_raw()
761 );
762 }
763
764 #[cfg(any(ossl111, libressl380, awslc))]
765 #[test]
766 fn test_sha3_512() {
767 let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
768 "c072288ef728cd53a029c47687960b9225893532f42b923156e37020bdc1eda753aafbf30af859d4f4c3a1\
769 807caee3a79f8eb02dcd61589fbbdf5f40c8787a72"
770 )];
771
772 for test in tests.iter() {
773 hash_test(MessageDigest::sha3_512(), test);
774 }
775
776 assert_eq!(MessageDigest::sha3_512().block_size(), 72);
777 assert_eq!(MessageDigest::sha3_512().size(), 64);
778 assert_eq!(
779 MessageDigest::sha3_512().type_().as_raw(),
780 Nid::SHA3_512.as_raw()
781 );
782 }
783
784 #[cfg(any(ossl111, awslc))]
785 #[test]
786 fn test_shake_128() {
787 let tests = [(
788 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
789 "49d0697ff508111d8b84f15e46daf135",
790 )];
791
792 for test in tests.iter() {
793 hash_xof_test(MessageDigest::shake_128(), test);
794 #[cfg(ossl330)]
795 hash_xof_squeeze_test(MessageDigest::shake_128(), test);
796 }
797
798 assert_eq!(MessageDigest::shake_128().block_size(), 168);
799 #[cfg(ossl111)]
800 assert_eq!(MessageDigest::shake_128().size(), 16);
801 #[cfg(awslc)]
802 assert_eq!(MessageDigest::shake_128().size(), 0);
803 assert_eq!(
804 MessageDigest::shake_128().type_().as_raw(),
805 Nid::SHAKE128.as_raw()
806 );
807 }
808
809 #[cfg(any(ossl111, awslc))]
810 #[test]
811 fn test_shake_256() {
812 let tests = [(
813 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
814 "4e2dfdaa75d1e049d0eaeffe28e76b17cea47b650fb8826fe48b94664326a697",
815 )];
816
817 for test in tests.iter() {
818 hash_xof_test(MessageDigest::shake_256(), test);
819 #[cfg(ossl330)]
820 hash_xof_squeeze_test(MessageDigest::shake_256(), test);
821 }
822
823 assert_eq!(MessageDigest::shake_256().block_size(), 136);
824 #[cfg(ossl111)]
825 assert_eq!(MessageDigest::shake_256().size(), 32);
826 #[cfg(awslc)]
827 assert_eq!(MessageDigest::shake_256().size(), 0);
828 assert_eq!(
829 MessageDigest::shake_256().type_().as_raw(),
830 Nid::SHAKE256.as_raw()
831 );
832 }
833
834 #[test]
835 #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
836 #[cfg_attr(ossl300, ignore)]
837 fn test_ripemd160() {
838 #[cfg(ossl300)]
839 let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
840
841 let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")];
842
843 for test in tests.iter() {
844 hash_test(MessageDigest::ripemd160(), test);
845 }
846
847 assert_eq!(MessageDigest::ripemd160().block_size(), 64);
848 assert_eq!(MessageDigest::ripemd160().size(), 20);
849 assert_eq!(
850 MessageDigest::ripemd160().type_().as_raw(),
851 Nid::RIPEMD160.as_raw()
852 );
853 }
854
855 #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
856 #[test]
857 fn test_sm3() {
858 let tests = [(
859 "616263",
860 "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
861 )];
862
863 for test in tests.iter() {
864 hash_test(MessageDigest::sm3(), test);
865 }
866
867 assert_eq!(MessageDigest::sm3().block_size(), 64);
868 assert_eq!(MessageDigest::sm3().size(), 32);
869 assert_eq!(MessageDigest::sm3().type_().as_raw(), Nid::SM3.as_raw());
870 }
871
872 #[test]
873 fn from_nid() {
874 assert_eq!(
875 MessageDigest::from_nid(Nid::SHA256).unwrap().as_ptr(),
876 MessageDigest::sha256().as_ptr()
877 );
878 }
879
880 #[test]
881 fn from_name() {
882 assert_eq!(
883 MessageDigest::from_name("SHA256").unwrap().as_ptr(),
884 MessageDigest::sha256().as_ptr()
885 )
886 }
887}