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, all(awslc, not(awslc_fips))))]
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
495 use super::*;
496
497 fn hash_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
498 let res = hash(hashtype, &Vec::from_hex(hashtest.0).unwrap()).unwrap();
499 assert_eq!(hex::encode(res), hashtest.1);
500 }
501
502 #[cfg(any(ossl111, awslc))]
503 fn hash_xof_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
504 let expected = Vec::from_hex(hashtest.1).unwrap();
505 let mut buf = vec![0; expected.len()];
506 hash_xof(
507 hashtype,
508 &Vec::from_hex(hashtest.0).unwrap(),
509 buf.as_mut_slice(),
510 )
511 .unwrap();
512 assert_eq!(buf, expected);
513 }
514
515 #[cfg(any(ossl330, all(awslc, not(awslc_fips))))]
517 fn hash_xof_squeeze_test(hashtype: MessageDigest, hashtest: &(&str, &str)) {
518 let data = Vec::from_hex(hashtest.0).unwrap();
519 let mut h = Hasher::new(hashtype).unwrap();
520 h.update(&data).unwrap();
521
522 let expected = Vec::from_hex(hashtest.1).unwrap();
523 let mut buf = vec![0; expected.len()];
524 assert!(expected.len() > 10);
525 h.squeeze_xof(&mut buf[..10]).unwrap();
526 h.squeeze_xof(&mut buf[10..]).unwrap();
527 assert_eq!(buf, expected);
528 }
529
530 fn hash_recycle_test(h: &mut Hasher, hashtest: &(&str, &str)) {
531 h.write_all(&Vec::from_hex(hashtest.0).unwrap()).unwrap();
532 let res = h.finish().unwrap();
533 assert_eq!(hex::encode(res), hashtest.1);
534 }
535
536 const MD5_TESTS: [(&str, &str); 13] = [
538 ("", "d41d8cd98f00b204e9800998ecf8427e"),
539 ("7F", "83acb6e67e50e31db6ed341dd2de1595"),
540 ("EC9C", "0b07f0d4ca797d8ac58874f887cb0b68"),
541 ("FEE57A", "e0d583171eb06d56198fc0ef22173907"),
542 ("42F497E0", "7c430f178aefdf1487fee7144e9641e2"),
543 ("C53B777F1C", "75ef141d64cb37ec423da2d9d440c925"),
544 ("89D5B576327B", "ebbaf15eb0ed784c6faa9dc32831bf33"),
545 ("5D4CCE781EB190", "ce175c4b08172019f05e6b5279889f2c"),
546 ("81901FE94932D7B9", "cd4d2f62b8cdb3a0cf968a735a239281"),
547 ("C9FFDEE7788EFB4EC9", "e0841a231ab698db30c6c0f3f246c014"),
548 ("66AC4B7EBA95E53DC10B", "a3b3cea71910d9af56742aa0bb2fe329"),
549 ("A510CD18F7A56852EB0319", "577e216843dd11573574d3fb209b97d8"),
550 (
551 "AAED18DBE8938C19ED734A8D",
552 "6f80fb775f27e0a4ce5c2f42fc72c5f1",
553 ),
554 ];
555
556 #[test]
557 fn test_md5() {
558 for test in MD5_TESTS.iter() {
559 hash_test(MessageDigest::md5(), test);
560 }
561
562 assert_eq!(MessageDigest::md5().block_size(), 64);
563 assert_eq!(MessageDigest::md5().size(), 16);
564 assert_eq!(MessageDigest::md5().type_().as_raw(), Nid::MD5.as_raw());
565 }
566
567 #[test]
568 fn test_md5_recycle() {
569 let mut h = Hasher::new(MessageDigest::md5()).unwrap();
570 for test in MD5_TESTS.iter() {
571 hash_recycle_test(&mut h, test);
572 }
573 }
574
575 #[test]
576 fn test_finish_twice() {
577 let mut h = Hasher::new(MessageDigest::md5()).unwrap();
578 h.write_all(&Vec::from_hex(MD5_TESTS[6].0).unwrap())
579 .unwrap();
580 h.finish().unwrap();
581 let res = h.finish().unwrap();
582 let null = hash(MessageDigest::md5(), &[]).unwrap();
583 assert_eq!(&*res, &*null);
584 }
585
586 #[cfg(any(ossl330, all(awslc, not(awslc_fips))))]
587 #[test]
588 fn test_finish_then_squeeze() {
589 let digest = MessageDigest::shake_128();
590 let mut h = Hasher::new(digest).unwrap();
591 let mut buf = vec![0; digest.size()];
592 h.finish_xof(&mut buf).unwrap();
593 h.squeeze_xof(&mut buf)
594 .expect_err("squeezing after finalize should fail");
595 }
596
597 #[cfg(any(ossl330, all(awslc, not(awslc_fips))))]
598 #[test]
599 fn test_squeeze_then_update() {
600 let digest = MessageDigest::shake_128();
601 let data = Vec::from_hex(MD5_TESTS[6].0).unwrap();
602 let mut h = Hasher::new(digest).unwrap();
603 let mut buf = vec![0; digest.size()];
604 h.squeeze_xof(&mut buf).unwrap();
605 h.update(&data)
606 .expect_err("updating after squeeze should fail");
607 }
608
609 #[cfg(any(ossl330, all(awslc, not(awslc_fips))))]
610 #[test]
611 fn test_squeeze_then_finalize() {
612 let digest = MessageDigest::shake_128();
613 let mut h = Hasher::new(digest).unwrap();
614 let mut buf = vec![0; digest.size()];
615 h.squeeze_xof(&mut buf).unwrap();
616 if cfg!(ossl330) {
617 h.finish_xof(&mut buf)
618 .expect_err("finalize after squeeze should fail");
619 } else if cfg!(awslc) {
620 h.finish_xof(&mut buf).unwrap();
621 }
622 }
623
624 #[test]
625 #[allow(clippy::redundant_clone)]
626 fn test_clone() {
627 let i = 7;
628 let inp = Vec::from_hex(MD5_TESTS[i].0).unwrap();
629 assert!(inp.len() > 2);
630 let p = inp.len() / 2;
631 let h0 = Hasher::new(MessageDigest::md5()).unwrap();
632
633 println!("Clone a new hasher");
634 let mut h1 = h0.clone();
635 h1.write_all(&inp[..p]).unwrap();
636 {
637 println!("Clone an updated hasher");
638 let mut h2 = h1.clone();
639 h2.write_all(&inp[p..]).unwrap();
640 let res = h2.finish().unwrap();
641 assert_eq!(hex::encode(res), MD5_TESTS[i].1);
642 }
643 h1.write_all(&inp[p..]).unwrap();
644 let res = h1.finish().unwrap();
645 assert_eq!(hex::encode(res), MD5_TESTS[i].1);
646
647 println!("Clone a finished hasher");
648 let mut h3 = h1.clone();
649 h3.write_all(&Vec::from_hex(MD5_TESTS[i + 1].0).unwrap())
650 .unwrap();
651 let res = h3.finish().unwrap();
652 assert_eq!(hex::encode(res), MD5_TESTS[i + 1].1);
653 }
654
655 #[test]
656 fn test_sha1() {
657 let tests = [("616263", "a9993e364706816aba3e25717850c26c9cd0d89d")];
658
659 for test in tests.iter() {
660 hash_test(MessageDigest::sha1(), test);
661 }
662
663 assert_eq!(MessageDigest::sha1().block_size(), 64);
664 assert_eq!(MessageDigest::sha1().size(), 20);
665 assert_eq!(MessageDigest::sha1().type_().as_raw(), Nid::SHA1.as_raw());
666 }
667
668 #[test]
669 fn test_sha256() {
670 let tests = [(
671 "616263",
672 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
673 )];
674
675 for test in tests.iter() {
676 hash_test(MessageDigest::sha256(), test);
677 }
678
679 assert_eq!(MessageDigest::sha256().block_size(), 64);
680 assert_eq!(MessageDigest::sha256().size(), 32);
681 assert_eq!(
682 MessageDigest::sha256().type_().as_raw(),
683 Nid::SHA256.as_raw()
684 );
685 }
686
687 #[test]
688 fn test_sha512() {
689 let tests = [(
690 "737465766566696e647365766572797468696e67",
691 "ba61d1f1af0f2dd80729f6cc900f19c0966bd38ba5c75e4471ef11b771dfe7551afab7fcbd300fdc4418f2\
692 b07a028fcd99e7b6446a566f2d9bcd7c604a1ea801",
693 )];
694
695 for test in tests.iter() {
696 hash_test(MessageDigest::sha512(), test);
697 }
698
699 assert_eq!(MessageDigest::sha512().block_size(), 128);
700 assert_eq!(MessageDigest::sha512().size(), 64);
701 assert_eq!(
702 MessageDigest::sha512().type_().as_raw(),
703 Nid::SHA512.as_raw()
704 );
705 }
706
707 #[cfg(any(ossl111, libressl380, awslc))]
708 #[test]
709 fn test_sha3_224() {
710 let tests = [(
711 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
712 "1de092dd9fbcbbf450f26264f4778abd48af851f2832924554c56913",
713 )];
714
715 for test in tests.iter() {
716 hash_test(MessageDigest::sha3_224(), test);
717 }
718
719 assert_eq!(MessageDigest::sha3_224().block_size(), 144);
720 assert_eq!(MessageDigest::sha3_224().size(), 28);
721 assert_eq!(
722 MessageDigest::sha3_224().type_().as_raw(),
723 Nid::SHA3_224.as_raw()
724 );
725 }
726
727 #[cfg(any(ossl111, libressl380, awslc))]
728 #[test]
729 fn test_sha3_256() {
730 let tests = [(
731 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
732 "b38e38f08bc1c0091ed4b5f060fe13e86aa4179578513ad11a6e3abba0062f61",
733 )];
734
735 for test in tests.iter() {
736 hash_test(MessageDigest::sha3_256(), test);
737 }
738
739 assert_eq!(MessageDigest::sha3_256().block_size(), 136);
740 assert_eq!(MessageDigest::sha3_256().size(), 32);
741 assert_eq!(
742 MessageDigest::sha3_256().type_().as_raw(),
743 Nid::SHA3_256.as_raw()
744 );
745 }
746
747 #[cfg(any(ossl111, libressl380, awslc))]
748 #[test]
749 fn test_sha3_384() {
750 let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
751 "966ee786ab3482dd811bf7c8fa8db79aa1f52f6c3c369942ef14240ebd857c6ff626ec35d9e131ff64d328\
752 ef2008ff16"
753 )];
754
755 for test in tests.iter() {
756 hash_test(MessageDigest::sha3_384(), test);
757 }
758
759 assert_eq!(MessageDigest::sha3_384().block_size(), 104);
760 assert_eq!(MessageDigest::sha3_384().size(), 48);
761 assert_eq!(
762 MessageDigest::sha3_384().type_().as_raw(),
763 Nid::SHA3_384.as_raw()
764 );
765 }
766
767 #[cfg(any(ossl111, libressl380, awslc))]
768 #[test]
769 fn test_sha3_512() {
770 let tests = [("416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
771 "c072288ef728cd53a029c47687960b9225893532f42b923156e37020bdc1eda753aafbf30af859d4f4c3a1\
772 807caee3a79f8eb02dcd61589fbbdf5f40c8787a72"
773 )];
774
775 for test in tests.iter() {
776 hash_test(MessageDigest::sha3_512(), test);
777 }
778
779 assert_eq!(MessageDigest::sha3_512().block_size(), 72);
780 assert_eq!(MessageDigest::sha3_512().size(), 64);
781 assert_eq!(
782 MessageDigest::sha3_512().type_().as_raw(),
783 Nid::SHA3_512.as_raw()
784 );
785 }
786
787 #[cfg(any(ossl111, awslc))]
788 #[test]
789 fn test_shake_128() {
790 let tests = [(
791 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
792 "49d0697ff508111d8b84f15e46daf135",
793 )];
794
795 for test in tests.iter() {
796 hash_xof_test(MessageDigest::shake_128(), test);
797 #[cfg(any(ossl330, all(awslc, not(awslc_fips))))]
798 hash_xof_squeeze_test(MessageDigest::shake_128(), test);
799 }
800
801 assert_eq!(MessageDigest::shake_128().block_size(), 168);
802 #[cfg(ossl111)]
803 assert_eq!(MessageDigest::shake_128().size(), 16);
804 #[cfg(awslc)]
805 assert_eq!(MessageDigest::shake_128().size(), 0);
806 assert_eq!(
807 MessageDigest::shake_128().type_().as_raw(),
808 Nid::SHAKE128.as_raw()
809 );
810 }
811
812 #[cfg(any(ossl111, awslc))]
813 #[test]
814 fn test_shake_256() {
815 let tests = [(
816 "416c6c20796f75722062617365206172652062656c6f6e6720746f207573",
817 "4e2dfdaa75d1e049d0eaeffe28e76b17cea47b650fb8826fe48b94664326a697",
818 )];
819
820 for test in tests.iter() {
821 hash_xof_test(MessageDigest::shake_256(), test);
822 #[cfg(any(ossl330, all(awslc, not(awslc_fips))))]
823 hash_xof_squeeze_test(MessageDigest::shake_256(), test);
824 }
825
826 assert_eq!(MessageDigest::shake_256().block_size(), 136);
827 #[cfg(ossl111)]
828 assert_eq!(MessageDigest::shake_256().size(), 32);
829 #[cfg(awslc)]
830 assert_eq!(MessageDigest::shake_256().size(), 0);
831 assert_eq!(
832 MessageDigest::shake_256().type_().as_raw(),
833 Nid::SHAKE256.as_raw()
834 );
835 }
836
837 #[test]
838 #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
839 #[cfg_attr(ossl300, ignore)]
840 fn test_ripemd160() {
841 #[cfg(ossl300)]
842 let _provider = crate::provider::Provider::try_load(None, "legacy", true).unwrap();
843
844 let tests = [("616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc")];
845
846 for test in tests.iter() {
847 hash_test(MessageDigest::ripemd160(), test);
848 }
849
850 assert_eq!(MessageDigest::ripemd160().block_size(), 64);
851 assert_eq!(MessageDigest::ripemd160().size(), 20);
852 assert_eq!(
853 MessageDigest::ripemd160().type_().as_raw(),
854 Nid::RIPEMD160.as_raw()
855 );
856 }
857
858 #[cfg(all(any(ossl111, libressl), not(osslconf = "OPENSSL_NO_SM3")))]
859 #[test]
860 fn test_sm3() {
861 let tests = [(
862 "616263",
863 "66c7f0f462eeedd9d1f2d46bdc10e4e24167c4875cf2f7a2297da02b8f4ba8e0",
864 )];
865
866 for test in tests.iter() {
867 hash_test(MessageDigest::sm3(), test);
868 }
869
870 assert_eq!(MessageDigest::sm3().block_size(), 64);
871 assert_eq!(MessageDigest::sm3().size(), 32);
872 assert_eq!(MessageDigest::sm3().type_().as_raw(), Nid::SM3.as_raw());
873 }
874
875 #[test]
876 fn from_nid() {
877 assert_eq!(
878 MessageDigest::from_nid(Nid::SHA256).unwrap().as_ptr(),
879 MessageDigest::sha256().as_ptr()
880 );
881 }
882
883 #[test]
884 fn from_name() {
885 assert_eq!(
886 MessageDigest::from_name("SHA256").unwrap().as_ptr(),
887 MessageDigest::sha256().as_ptr()
888 )
889 }
890}