Skip to main content

ewf_forensic/
repair.rs

1use crate::integrity::{adler32, EwfIntegrity, EwfIntegrityAnomaly, SECTION_DESCRIPTOR_SIZE};
2
3pub struct EwfRepair {
4    segments: Vec<Vec<u8>>,
5}
6
7pub struct RepairReport {
8    pub segments: Vec<Vec<u8>>,
9    pub repairs: Vec<Repaired>,
10    pub cannot_repair: Vec<CannotRepair>,
11}
12
13#[derive(Debug, Clone)]
14pub enum Repaired {
15    SectionDescriptorCrc { offset: u64, section_type: String },
16}
17
18#[derive(Debug, Clone)]
19pub enum CannotRepair {
20    HashMismatch {
21        computed: [u8; 16],
22        stored: [u8; 16],
23    },
24}
25
26impl EwfRepair {
27    pub fn new(data: Vec<u8>) -> Self {
28        Self { segments: vec![data] }
29    }
30
31    pub fn from_segments(segments: Vec<Vec<u8>>) -> Self {
32        Self { segments }
33    }
34
35    pub fn repair(mut self) -> RepairReport {
36        let mut repairs = Vec::new();
37        let mut cannot_repair = Vec::new();
38
39        let seg_refs: Vec<&[u8]> = self.segments.iter().map(|s| s.as_slice()).collect();
40        let anomalies = EwfIntegrity::from_segments(&seg_refs).analyse();
41
42        for anomaly in anomalies {
43            match anomaly {
44                EwfIntegrityAnomaly::SectionDescriptorCrcMismatch {
45                    offset,
46                    section_type,
47                    ..
48                } => {
49                    // Locate which segment contains this offset and apply the fix.
50                    let mut abs = offset as usize;
51                    for seg in &mut self.segments {
52                        if abs < seg.len() {
53                            let off = abs;
54                            if off + SECTION_DESCRIPTOR_SIZE <= seg.len() {
55                                let correct = adler32(&seg[off..off + 72]);
56                                seg[off + 72..off + 76]
57                                    .copy_from_slice(&correct.to_le_bytes());
58                                repairs.push(Repaired::SectionDescriptorCrc {
59                                    offset,
60                                    section_type,
61                                });
62                            }
63                            break;
64                        }
65                        abs -= seg.len();
66                    }
67                }
68                EwfIntegrityAnomaly::HashMismatch { computed, stored } => {
69                    cannot_repair.push(CannotRepair::HashMismatch { computed, stored });
70                }
71                _ => {}
72            }
73        }
74
75        RepairReport {
76            segments: self.segments,
77            repairs,
78            cannot_repair,
79        }
80    }
81}