Coverage Report

Created: 2025-12-12 07:07

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/openssl-0.10.62/src/hash.rs
Line
Count
Source
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, libressl382))] {
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.
63
0
    pub unsafe fn from_ptr(x: *const ffi::EVP_MD) -> Self {
64
0
        MessageDigest(x)
65
0
    }
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
72
0
    pub fn from_nid(type_: Nid) -> Option<MessageDigest> {
73
        unsafe {
74
0
            let ptr = ffi::EVP_get_digestbynid(type_.as_raw());
75
0
            if ptr.is_null() {
76
0
                None
77
            } else {
78
0
                Some(MessageDigest(ptr))
79
            }
80
        }
81
0
    }
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
88
0
    pub fn from_name(name: &str) -> Option<MessageDigest> {
89
0
        ffi::init();
90
0
        let name = CString::new(name).ok()?;
91
        unsafe {
92
0
            let ptr = ffi::EVP_get_digestbyname(name.as_ptr());
93
0
            if ptr.is_null() {
94
0
                None
95
            } else {
96
0
                Some(MessageDigest(ptr))
97
            }
98
        }
99
0
    }
100
101
    #[cfg(not(boringssl))]
102
0
    pub fn null() -> MessageDigest {
103
0
        unsafe { MessageDigest(ffi::EVP_md_null()) }
104
0
    }
105
106
0
    pub fn md5() -> MessageDigest {
107
0
        unsafe { MessageDigest(ffi::EVP_md5()) }
108
0
    }
109
110
0
    pub fn sha1() -> MessageDigest {
111
0
        unsafe { MessageDigest(ffi::EVP_sha1()) }
112
0
    }
113
114
0
    pub fn sha224() -> MessageDigest {
115
0
        unsafe { MessageDigest(ffi::EVP_sha224()) }
116
0
    }
117
118
0
    pub fn sha256() -> MessageDigest {
119
0
        unsafe { MessageDigest(ffi::EVP_sha256()) }
120
0
    }
121
122
0
    pub fn sha384() -> MessageDigest {
123
0
        unsafe { MessageDigest(ffi::EVP_sha384()) }
124
0
    }
125
126
0
    pub fn sha512() -> MessageDigest {
127
0
        unsafe { MessageDigest(ffi::EVP_sha512()) }
128
0
    }
129
130
    #[cfg(any(ossl111, libressl380))]
131
0
    pub fn sha3_224() -> MessageDigest {
132
0
        unsafe { MessageDigest(ffi::EVP_sha3_224()) }
133
0
    }
134
135
    #[cfg(any(ossl111, libressl380))]
136
0
    pub fn sha3_256() -> MessageDigest {
137
0
        unsafe { MessageDigest(ffi::EVP_sha3_256()) }
138
0
    }
139
140
    #[cfg(any(ossl111, libressl380))]
141
0
    pub fn sha3_384() -> MessageDigest {
142
0
        unsafe { MessageDigest(ffi::EVP_sha3_384()) }
143
0
    }
144
145
    #[cfg(any(ossl111, libressl380))]
146
0
    pub fn sha3_512() -> MessageDigest {
147
0
        unsafe { MessageDigest(ffi::EVP_sha3_512()) }
148
0
    }
149
150
    #[cfg(ossl111)]
151
0
    pub fn shake_128() -> MessageDigest {
152
0
        unsafe { MessageDigest(ffi::EVP_shake128()) }
153
0
    }
154
155
    #[cfg(ossl111)]
156
0
    pub fn shake_256() -> MessageDigest {
157
0
        unsafe { MessageDigest(ffi::EVP_shake256()) }
158
0
    }
159
160
    #[cfg(not(osslconf = "OPENSSL_NO_RMD160"))]
161
0
    pub fn ripemd160() -> MessageDigest {
162
0
        unsafe { MessageDigest(ffi::EVP_ripemd160()) }
163
0
    }
164
165
    #[cfg(all(any(ossl111, libressl291), not(osslconf = "OPENSSL_NO_SM3")))]
166
0
    pub fn sm3() -> MessageDigest {
167
0
        unsafe { MessageDigest(ffi::EVP_sm3()) }
168
0
    }
169
170
    #[allow(clippy::trivially_copy_pass_by_ref)]
171
0
    pub fn as_ptr(&self) -> *const ffi::EVP_MD {
172
0
        self.0
173
0
    }
174
175
    /// The block size of the digest in bytes.
176
    #[allow(clippy::trivially_copy_pass_by_ref)]
177
0
    pub fn block_size(&self) -> usize {
178
0
        unsafe { ffi::EVP_MD_block_size(self.0) as usize }
179
0
    }
180
181
    /// The size of the digest in bytes.
182
    #[allow(clippy::trivially_copy_pass_by_ref)]
183
0
    pub fn size(&self) -> usize {
184
0
        unsafe { ffi::EVP_MD_size(self.0) as usize }
185
0
    }
186
187
    /// The name of the digest.
188
    #[allow(clippy::trivially_copy_pass_by_ref)]
189
0
    pub fn type_(&self) -> Nid {
190
0
        Nid::from_raw(unsafe { ffi::EVP_MD_type(self.0) })
191
0
    }
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.
246
0
    pub fn new(ty: MessageDigest) -> Result<Hasher, ErrorStack> {
247
0
        ffi::init();
248
249
0
        let ctx = unsafe { cvt_p(EVP_MD_CTX_new())? };
250
251
0
        let mut h = Hasher {
252
0
            ctx,
253
0
            md: ty.as_ptr(),
254
0
            type_: ty,
255
0
            state: Finalized,
256
0
        };
257
0
        h.init()?;
258
0
        Ok(h)
259
0
    }
260
261
0
    fn init(&mut self) -> Result<(), ErrorStack> {
262
0
        match self.state {
263
0
            Reset => return Ok(()),
264
            Updated => {
265
0
                self.finish()?;
266
            }
267
0
            Finalized => (),
268
        }
269
        unsafe {
270
0
            cvt(ffi::EVP_DigestInit_ex(self.ctx, self.md, ptr::null_mut()))?;
271
        }
272
0
        self.state = Reset;
273
0
        Ok(())
274
0
    }
275
276
    /// Feeds data into the hasher.
277
0
    pub fn update(&mut self, data: &[u8]) -> Result<(), ErrorStack> {
278
0
        if self.state == Finalized {
279
0
            self.init()?;
280
0
        }
281
        unsafe {
282
0
            cvt(ffi::EVP_DigestUpdate(
283
0
                self.ctx,
284
0
                data.as_ptr() as *mut _,
285
0
                data.len(),
286
0
            ))?;
287
        }
288
0
        self.state = Updated;
289
0
        Ok(())
290
0
    }
291
292
    /// Returns the hash of the data written and resets the non-XOF hasher.
293
0
    pub fn finish(&mut self) -> Result<DigestBytes, ErrorStack> {
294
0
        if self.state == Finalized {
295
0
            self.init()?;
296
0
        }
297
        unsafe {
298
            #[cfg(not(boringssl))]
299
0
            let mut len = ffi::EVP_MAX_MD_SIZE;
300
            #[cfg(boringssl)]
301
            let mut len = ffi::EVP_MAX_MD_SIZE as u32;
302
0
            let mut buf = [0; ffi::EVP_MAX_MD_SIZE as usize];
303
0
            cvt(ffi::EVP_DigestFinal_ex(
304
0
                self.ctx,
305
0
                buf.as_mut_ptr(),
306
0
                &mut len,
307
0
            ))?;
308
0
            self.state = Finalized;
309
0
            Ok(DigestBytes {
310
0
                buf,
311
0
                len: len as usize,
312
0
            })
313
        }
314
0
    }
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)]
319
0
    pub fn finish_xof(&mut self, buf: &mut [u8]) -> Result<(), ErrorStack> {
320
0
        if self.state == Finalized {
321
0
            self.init()?;
322
0
        }
323
        unsafe {
324
0
            cvt(ffi::EVP_DigestFinalXOF(
325
0
                self.ctx,
326
0
                buf.as_mut_ptr(),
327
0
                buf.len(),
328
0
            ))?;
329
0
            self.state = Finalized;
330
0
            Ok(())
331
        }
332
0
    }
333
}
334
335
impl Write for Hasher {
336
    #[inline]
337
0
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
338
0
        self.update(buf)?;
339
0
        Ok(buf.len())
340
0
    }
341
342
0
    fn flush(&mut self) -> io::Result<()> {
343
0
        Ok(())
344
0
    }
345
}
346
347
impl Clone for Hasher {
348
0
    fn clone(&self) -> Hasher {
349
0
        let ctx = unsafe {
350
0
            let ctx = EVP_MD_CTX_new();
351
0
            assert!(!ctx.is_null());
352
0
            let r = ffi::EVP_MD_CTX_copy_ex(ctx, self.ctx);
353
0
            assert_eq!(r, 1);
354
0
            ctx
355
        };
356
0
        Hasher {
357
0
            ctx,
358
0
            md: self.md,
359
0
            type_: self.type_,
360
0
            state: self.state,
361
0
        }
362
0
    }
363
}
364
365
impl Drop for Hasher {
366
0
    fn drop(&mut self) {
367
        unsafe {
368
0
            if self.state != Finalized {
369
0
                drop(self.finish());
370
0
            }
371
0
            EVP_MD_CTX_free(self.ctx);
372
        }
373
0
    }
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]
388
0
    fn clone(&self) -> DigestBytes {
389
0
        *self
390
0
    }
391
}
392
393
impl Deref for DigestBytes {
394
    type Target = [u8];
395
396
    #[inline]
397
0
    fn deref(&self) -> &[u8] {
398
0
        &self.buf[..self.len]
399
0
    }
400
}
401
402
impl DerefMut for DigestBytes {
403
    #[inline]
404
0
    fn deref_mut(&mut self) -> &mut [u8] {
405
0
        &mut self.buf[..self.len]
406
0
    }
407
}
408
409
impl AsRef<[u8]> for DigestBytes {
410
    #[inline]
411
0
    fn as_ref(&self) -> &[u8] {
412
0
        self.deref()
413
0
    }
414
}
415
416
impl fmt::Debug for DigestBytes {
417
0
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
418
0
        fmt::Debug::fmt(&**self, fmt)
419
0
    }
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
0
pub fn hash(t: MessageDigest, data: &[u8]) -> Result<DigestBytes, ErrorStack> {
437
0
    let mut h = Hasher::new(t)?;
438
0
    h.update(data)?;
439
0
    h.finish()
440
0
}
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)]
457
0
pub fn hash_xof(t: MessageDigest, data: &[u8], buf: &mut [u8]) -> Result<(), ErrorStack> {
458
0
    let mut h = Hasher::new(t)?;
459
0
    h.update(data)?;
460
0
    h.finish_xof(buf)
461
0
}
462
463
#[cfg(test)]
464
mod tests {
465
    use hex::{self, FromHex};
466
    use std::io::prelude::*;
467
468
    use super::*;
469
470
    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)]
476
    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
488
    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]
515
    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]
526
    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]
534
    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)]
546
    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]
576
    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]
589
    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]
608
    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(any(ossl111, libressl380))]
628
    #[test]
629
    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(any(ossl111, libressl380))]
648
    #[test]
649
    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(any(ossl111, libressl380))]
668
    #[test]
669
    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(any(ossl111, libressl380))]
688
    #[test]
689
    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]
709
    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]
729
    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(osslconf = "OPENSSL_NO_RMD160"))]
749
    #[cfg_attr(ossl300, ignore)]
750
    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]
770
    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]
786
    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]
794
    fn from_name() {
795
        assert_eq!(
796
            MessageDigest::from_name("SHA256").unwrap().as_ptr(),
797
            MessageDigest::sha256().as_ptr()
798
        )
799
    }
800
}