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, libressl), 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(any(ossl330, awslc))]
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(any(ossl330, awslc))]
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(any(ossl330, awslc))]
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(any(ossl330, awslc))]
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(any(ossl330, awslc))]
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(any(ossl330, awslc))]
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(any(ossl330, awslc))]
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(any(ossl330, awslc))]
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 if cfg!(ossl330) {
618 h.finish_xof(&mut buf)
619 .expect_err("finalize after squeeze should fail");
620 } else if cfg!(awslc) {
621 h.finish_xof(&mut buf).unwrap();
622 }
623 }
624
625 #[test]
626 #[allow(clippy::redundant_clone)]
627 fn test_clone() {
628 let i = 7;
629 let inp = Vec::from_hex(MD5_TESTS[i].0).unwrap();
630 assert!(inp.len() > 2);
631 let p = inp.len() / 2;
632 let h0 = Hasher::new(MessageDigest::md5()).unwrap();
633
634 println!("Clone a new hasher");
635 let mut h1 = h0.clone();
636 h1.write_all(&inp[..p]).unwrap();
637 {
638 println!("Clone an updated hasher");
639 let mut h2 = h1.clone();
640 h2.write_all(&inp[p..]).unwrap();
641 let res = h2.finish().unwrap();
642 assert_eq!(hex::encode(res), MD5_TESTS[i].1);
643 }
644 h1.write_all(&inp[p..]).unwrap();
645 let res = h1.finish().unwrap();
646 assert_eq!(hex::encode(res), MD5_TESTS[i].1);
647
648 println!("Clone a finished hasher");
649 let mut h3 = h1.clone();
650 h3.write_all(&Vec::from_hex(MD5_TESTS[i + 1].0).unwrap())
651 .unwrap();
652 let res = h3.finish().unwrap();
653 assert_eq!(hex::encode(res), MD5_TESTS[i + 1].1);
654 }
655
656 #[test]
657 fn test_sha1() {
658 let tests = [("616263", "a9993e364706816aba3e25717850c26c9cd0d89d")];
659
660 for test in tests.iter() {
661 hash_test(MessageDigest::sha1(), test);
662 }
663
664 assert_eq!(MessageDigest::sha1().block_size(), 64);
665 assert_eq!(MessageDigest::sha1().size(), 20);
666 assert_eq!(MessageDigest::sha1().type_().as_raw(), Nid::SHA1.as_raw());
667 }
668
669 #[test]
670 fn test_sha256() {
671 let tests = [(
672 "616263",
673 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
674 )];
675
676 for test in tests.iter() {
677 hash_test(MessageDigest::sha256(), test);
678 }
679
680 assert_eq!(MessageDigest::sha256().block_size(), 64);
681 assert_eq!(MessageDigest::sha256().size(), 32);
682 assert_eq!(
683 MessageDigest::sha256().type_().as_raw(),
684 Nid::SHA256.as_raw()
685 );
686 }
687
688 #[test]
689 fn test_sha512() {
690 let tests = [(
691 "737465766566696e647365766572797468696e67",
692 "ba61d1f1af0f2dd80729f6cc900f19c0966bd38ba5c75e4471ef11b771dfe7551afab7fcbd300fdc4418f2\
693 b07a028fcd99e7b6446a566f2d9bcd7c604a1ea801",
694 )];
695
696 for test in tests.iter() {
697 hash_test(MessageDigest::sha512(), test);
698 }
699
700 assert_eq!(MessageDigest::sha512().block_size(), 128);
701 assert_eq!(MessageDigest::sha512().size(), 64);
702 assert_eq!(
703 MessageDigest::sha512().type_().as_raw(),
704 Nid::SHA512.as_raw()
705 );
706 }
707
708 #[cfg(any(ossl111, libressl380, awslc))]
709 #[test]
710 fn test_sha3_224() {
711 let tests = [(
712 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
713 "1de092dd9fbcbbf450f26264f4778abd48af851f2832924554c56913",
714 )];
715
716 for test in tests.iter() {
717 hash_test(MessageDigest::sha3_224(), test);
718 }
719
720 assert_eq!(MessageDigest::sha3_224().block_size(), 144);
721 assert_eq!(MessageDigest::sha3_224().size(), 28);
722 assert_eq!(
723 MessageDigest::sha3_224().type_().as_raw(),
724 Nid::SHA3_224.as_raw()
725 );
726 }
727
728 #[cfg(any(ossl111, libressl380, awslc))]
729 #[test]
730 fn test_sha3_256() {
731 let tests = [(
732 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
733 "b38e38f08bc1c0091ed4b5f060fe13e86aa4179578513ad11a6e3abba0062f61",
734 )];
735
736 for test in tests.iter() {
737 hash_test(MessageDigest::sha3_256(), test);
738 }
739
740 assert_eq!(MessageDigest::sha3_256().block_size(), 136);
741 assert_eq!(MessageDigest::sha3_256().size(), 32);
742 assert_eq!(
743 MessageDigest::sha3_256().type_().as_raw(),
744 Nid::SHA3_256.as_raw()
745 );
746 }
747
748 #[cfg(any(ossl111, libressl380, awslc))]
749 #[test]
750 fn test_sha3_384() {
751 let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
752 "966ee786ab3482dd811bf7c8fa8db79aa1f52f6c3c369942ef14240ebd857c6ff626ec35d9e131ff64d328\
753 ef2008ff16"
754 )];
755
756 for test in tests.iter() {
757 hash_test(MessageDigest::sha3_384(), test);
758 }
759
760 assert_eq!(MessageDigest::sha3_384().block_size(), 104);
761 assert_eq!(MessageDigest::sha3_384().size(), 48);
762 assert_eq!(
763 MessageDigest::sha3_384().type_().as_raw(),
764 Nid::SHA3_384.as_raw()
765 );
766 }
767
768 #[cfg(any(ossl111, libressl380, awslc))]
769 #[test]
770 fn test_sha3_512() {
771 let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
772 "c072288ef728cd53a029c47687960b9225893532f42b923156e37020bdc1eda753aafbf30af859d4f4c3a1\
773 807caee3a79f8eb02dcd61589fbbdf5f40c8787a72"
774 )];
775
776 for test in tests.iter() {
777 hash_test(MessageDigest::sha3_512(), test);
778 }
779
780 assert_eq!(MessageDigest::sha3_512().block_size(), 72);
781 assert_eq!(MessageDigest::sha3_512().size(), 64);
782 assert_eq!(
783 MessageDigest::sha3_512().type_().as_raw(),
784 Nid::SHA3_512.as_raw()
785 );
786 }
787
788 #[cfg(any(ossl111, awslc))]
789 #[test]
790 fn test_shake_128() {
791 let tests = [(
792 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
793 "49d0697ff508111d8b84f15e46daf135",
794 )];
795
796 for test in tests.iter() {
797 hash_xof_test(MessageDigest::shake_128(), test);
798 #[cfg(any(ossl330, awslc))]
799 hash_xof_squeeze_test(MessageDigest::shake_128(), test);
800 }
801
802 assert_eq!(MessageDigest::shake_128().block_size(), 168);
803 #[cfg(ossl111)]
804 assert_eq!(MessageDigest::shake_128().size(), 16);
805 #[cfg(awslc)]
806 assert_eq!(MessageDigest::shake_128().size(), 0);
807 assert_eq!(
808 MessageDigest::shake_128().type_().as_raw(),
809 Nid::SHAKE128.as_raw()
810 );
811 }
812
813 #[cfg(any(ossl111, awslc))]
814 #[test]
815 fn test_shake_256() {
816 let tests = [(
817 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
818 "4e2dfdaa75d1e049d0eaeffe28e76b17cea47b650fb8826fe48b94664326a697",
819 )];
820
821 for test in tests.iter() {
822 hash_xof_test(MessageDigest::shake_256(), test);
823 #[cfg(any(ossl330, awslc))]
824 hash_xof_squeeze_test(MessageDigest::shake_256(), test);
825 }
826
827 assert_eq!(MessageDigest::shake_256().block_size(), 136);
828 #[cfg(ossl111)]
829 assert_eq!(MessageDigest::shake_256().size(), 32);
830 #[cfg(awslc)]
831 assert_eq!(MessageDigest::shake_256().size(), 0);
832 assert_eq!(
833 MessageDigest::shake_256().type_().as_raw(),
834 Nid::SHAKE256.as_raw()
835 );
836 }
837
838 #[test]
839 #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
840 #[cfg_attr(ossl300, ignore)]
841 fn test_ripemd160() {
842 #[cfg(ossl300)]
843 let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
844
845 let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")];
846
847 for test in tests.iter() {
848 hash_test(MessageDigest::ripemd160(), test);
849 }
850
851 assert_eq!(MessageDigest::ripemd160().block_size(), 64);
852 assert_eq!(MessageDigest::ripemd160().size(), 20);
853 assert_eq!(
854 MessageDigest::ripemd160().type_().as_raw(),
855 Nid::RIPEMD160.as_raw()
856 );
857 }
858
859 #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM3")))]
860 #[test]
861 fn test_sm3() {
862 let tests = [(
863 "616263",
864 "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
865 )];
866
867 for test in tests.iter() {
868 hash_test(MessageDigest::sm3(), test);
869 }
870
871 assert_eq!(MessageDigest::sm3().block_size(), 64);
872 assert_eq!(MessageDigest::sm3().size(), 32);
873 assert_eq!(MessageDigest::sm3().type_().as_raw(), Nid::SM3.as_raw());
874 }
875
876 #[test]
877 fn from_nid() {
878 assert_eq!(
879 MessageDigest::from_nid(Nid::SHA256).unwrap().as_ptr(),
880 MessageDigest::sha256().as_ptr()
881 );
882 }
883
884 #[test]
885 fn from_name() {
886 assert_eq!(
887 MessageDigest::from_name("SHA256").unwrap().as_ptr(),
888 MessageDigest::sha256().as_ptr()
889 )
890 }
891}