authenticode/
authenticode_digest.rs1use crate::usize_from_u32;
10use crate::{PeOffsetError, PeTrait};
11use alloc::vec::Vec;
12use digest::Update;
13
14fn authenticode_digest_impl(
15 pe: &dyn PeTrait,
16 digest: &mut dyn Update,
17) -> Option<()> {
18 let offsets = pe.offsets().ok()?;
19
20 let bytes = &pe.data().get(..offsets.check_sum)?;
22 digest.update(bytes);
23
24 let bytes = &pe
26 .data()
27 .get(offsets.after_check_sum..offsets.security_data_dir)?;
28 digest.update(bytes);
29
30 let bytes = &pe
32 .data()
33 .get(offsets.after_security_data_dir..offsets.after_header)?;
34 digest.update(bytes);
35
36 let mut sum_of_bytes_hashed = usize_from_u32(offsets.after_header as u32);
39
40 let mut sections = (1..=pe.num_sections())
42 .map(|i| pe.section_data_range(i))
43 .collect::<Result<Vec<_>, PeOffsetError>>()
44 .ok()?;
45 sections.sort_unstable_by_key(|r| r.start);
46
47 for section_range in sections {
49 let bytes = &pe.data().get(section_range)?;
50
51 digest.update(bytes);
52 sum_of_bytes_hashed = sum_of_bytes_hashed.checked_add(bytes.len())?;
53 }
54
55 let mut extra_hash_len =
56 pe.data().len().checked_sub(sum_of_bytes_hashed)?;
57
58 if let Some(security_data_dir) = pe.certificate_table_range().ok()? {
60 let size =
61 security_data_dir.end.checked_sub(security_data_dir.start)?;
62 extra_hash_len = extra_hash_len.checked_sub(size)?;
63 }
64
65 digest.update(pe.data().get(
66 sum_of_bytes_hashed..sum_of_bytes_hashed.checked_add(extra_hash_len)?,
67 )?);
68
69 Some(())
70}
71
72pub fn authenticode_digest(
74 pe: &dyn PeTrait,
75 digest: &mut dyn Update,
76) -> Result<(), PeOffsetError> {
77 authenticode_digest_impl(pe, digest).ok_or(PeOffsetError)
78}