19 package org.sleuthkit.autopsy.modules.dataSourceIntegrity;
21 import java.security.MessageDigest;
22 import java.security.NoSuchAlgorithmException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.logging.Level;
26 import java.util.Arrays;
27 import org.apache.commons.codec.binary.Hex;
38 import org.openide.util.NbBundle;
66 computeHashes = settings.shouldComputeHashes();
67 verifyHashes = settings.shouldVerifyHashes();
71 "DataSourceIntegrityIngestModule.startup.noCheckboxesSelected=At least one of the checkboxes must be selected"
78 if (!(computeHashes || verifyHashes)) {
79 throw new IngestModuleException(Bundle.DataSourceIntegrityIngestModule_startup_noCheckboxesSelected());
85 "DataSourceIntegrityIngestModule.process.skipCompute=Not computing new hashes for {0} since the option was disabled",
87 "DataSourceIntegrityIngestModule.process.skipVerify=Not verifying existing hashes for {0} since the option was disabled",
89 "DataSourceIntegrityIngestModule.process.hashAlgorithmError=Error creating message digest for {0} algorithm",
91 "DataSourceIntegrityIngestModule.process.hashMatch=<li>{0} hash verified </li>",
93 "DataSourceIntegrityIngestModule.process.hashNonMatch=<li>{0} hash not verified </li>",
94 "# {0} - calculatedHashValue",
95 "# {1} - storedHashValue",
96 "DataSourceIntegrityIngestModule.process.hashList=<ul><li>Calculated hash: {0} </li><li>Stored hash: {1} </li></ul>",
98 "# {1} - calculatedHashValue",
99 "DataSourceIntegrityIngestModule.process.calcHashWithType=<li>Calculated {0} hash: {1} </li>",
101 "DataSourceIntegrityIngestModule.process.calculateHashDone=<p>Data Source Hash Calculation Results for {0} </p>",
102 "DataSourceIntegrityIngestModule.process.hashesCalculated= hashes calculated",
104 "DataSourceIntegrityIngestModule.process.errorSavingHashes= Error saving hashes for image {0} to the database",
106 "DataSourceIntegrityIngestModule.process.errorLoadingHashes= Error loading hashes for image {0} from the database",
107 "# {0} - hashAlgorithm",
108 "# {1} - calculatedHashValue",
109 "# {2} - storedHashValue",
110 "DataSourceIntegrityIngestModule.process.hashFailedForArtifact={0} hash verification failed:\n Calculated hash: {1}\n Stored hash: {2}\n",
112 "DataSourceIntegrityIngestModule.process.verificationSuccess=Integrity of {0} verified",
114 "DataSourceIntegrityIngestModule.process.verificationFailure={0} failed integrity verification",})
117 String imgName = dataSource.
getName();
120 if (!(dataSource instanceof
Image)) {
121 logger.log(Level.INFO,
"Skipping non-image {0}", imgName);
123 NbBundle.getMessage(this.getClass(),
124 "DataSourceIntegrityIngestModule.process.skipNonEwf",
128 Image img = (Image) dataSource;
133 logger.log(Level.WARNING,
"Size of image {0} was 0 when queried.", imgName);
151 String msg = Bundle.DataSourceIntegrityIngestModule_process_errorLoadingHashes(imgName);
153 logger.log(Level.SEVERE, msg, ex);
159 if (hashDataList.isEmpty()) {
167 logger.log(Level.INFO,
"Not computing hashes for {0} since the option was disabled", imgName);
169 Bundle.DataSourceIntegrityIngestModule_process_skipCompute(imgName)));
172 logger.log(Level.INFO,
"Not verifying hashes for {0} since the option was disabled", imgName);
174 Bundle.DataSourceIntegrityIngestModule_process_skipVerify(imgName)));
182 hashDataList.add(
new HashData(type,
""));
187 for (
HashData hashData : hashDataList) {
189 hashData.digest = MessageDigest.getInstance(hashData.type.getName());
190 }
catch (NoSuchAlgorithmException ex) {
191 String msg = Bundle.DataSourceIntegrityIngestModule_process_hashAlgorithmError(hashData.type.getName());
193 logger.log(Level.SEVERE, msg, ex);
201 long chunkSize = 64 * img.
getSsize();
202 chunkSize = (chunkSize == 0) ? DEFAULT_CHUNK_SIZE : chunkSize;
205 int totalChunks = (int) Math.ceil((
double) size / (
double) chunkSize);
206 logger.log(Level.INFO,
"Total chunks = {0}", totalChunks);
209 logger.log(Level.INFO,
"Starting hash verification of {0}", img.
getName());
211 logger.log(Level.INFO,
"Starting hash calculation for {0}", img.
getName());
214 NbBundle.getMessage(this.getClass(),
215 "DataSourceIntegrityIngestModule.process.startingImg",
222 byte[] data =
new byte[(int) chunkSize];
224 for (
int i = 0; i < totalChunks; i++) {
229 read = img.
read(data, i * chunkSize, chunkSize);
231 String msg = NbBundle.getMessage(this.getClass(),
232 "DataSourceIntegrityIngestModule.process.errReadImgAtChunk", imgName, i);
234 logger.log(Level.SEVERE, msg, ex);
239 if (read == chunkSize) {
240 for (
HashData struct : hashDataList) {
241 struct.digest.update(data);
244 byte[] subData = Arrays.copyOfRange(data, 0, read);
245 for (
HashData struct : hashDataList) {
246 struct.digest.update(subData);
253 for(
HashData hashData: hashDataList) {
254 hashData.calculatedHash = Hex.encodeHexString(hashData.digest.digest()).toLowerCase();
255 logger.log(Level.INFO,
"Hash calculated from {0}: {1}",
new Object[]{imgName, hashData.calculatedHash});
260 boolean verified =
true;
261 String detailedResults = NbBundle
262 .getMessage(this.getClass(),
"DataSourceIntegrityIngestModule.shutDown.verifyResultsHeader", imgName);
263 String hashResults =
"";
264 String artifactComment =
"";
266 for (
HashData hashData : hashDataList) {
267 if (hashData.storedHash.equals(hashData.calculatedHash)) {
268 hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashMatch(hashData.type.name) +
" ";
271 hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashNonMatch(hashData.type.name) +
" ";
272 artifactComment += Bundle.DataSourceIntegrityIngestModule_process_hashFailedForArtifact(hashData.type.name,
273 hashData.calculatedHash, hashData.storedHash) +
" ";
275 hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashList(hashData.calculatedHash, hashData.storedHash);
278 String verificationResultStr;
279 String messageResultStr;
283 verificationResultStr = NbBundle.getMessage(this.getClass(),
"DataSourceIntegrityIngestModule.shutDown.verified");
284 messageResultStr = Bundle.DataSourceIntegrityIngestModule_process_verificationSuccess(imgName);
287 verificationResultStr = NbBundle.getMessage(this.getClass(),
"DataSourceIntegrityIngestModule.shutDown.notVerified");
288 messageResultStr = Bundle.DataSourceIntegrityIngestModule_process_verificationFailure(imgName);
291 detailedResults += NbBundle.getMessage(this.getClass(),
"DataSourceIntegrityIngestModule.shutDown.resultLi", verificationResultStr);
292 detailedResults += hashResults;
300 null, null, artifactComment,
303 .getAnalysisResult();
308 logger.log(Level.SEVERE,
"Error creating verification failed artifact", ex);
310 logger.log(Level.SEVERE,
"Error posting verification failed artifact", ex);
315 messageResultStr, detailedResults));
320 String results = Bundle.DataSourceIntegrityIngestModule_process_calculateHashDone(imgName);
322 for (
HashData hashData : hashDataList) {
323 switch (hashData.type) {
326 img.
setMD5(hashData.calculatedHash);
328 logger.log(Level.SEVERE,
"Error setting calculated hash", ex);
333 img.
setSha1(hashData.calculatedHash);
335 logger.log(Level.SEVERE,
"Error setting calculated hash", ex);
342 logger.log(Level.SEVERE,
"Error setting calculated hash", ex);
348 results += Bundle.DataSourceIntegrityIngestModule_process_calcHashWithType(hashData.type.name, hashData.calculatedHash);
353 imgName + Bundle.DataSourceIntegrityIngestModule_process_hashesCalculated(), results));
356 String msg = Bundle.DataSourceIntegrityIngestModule_process_errorSavingHashes(imgName);
358 logger.log(Level.SEVERE,
"Error saving hash for image " + imgName +
" to database", ex);
static final IngestServices services
static final Score SCORE_NOTABLE
org.sleuthkit.datamodel.Blackboard getArtifactsBlackboard()
Blackboard getBlackboard()
static final Logger logger
void setSha1(String sha1)
static IngestMessage createMessage(MessageType messageType, String source, String subject, String detailsHtml)
int read(byte[] buf, long offset, long len)
final List< HashData > hashDataList
static final Type TSK_VERIFICATION_FAILED
void postMessage(final IngestMessage message)
final boolean verifyHashes
SleuthkitCase getSleuthkitCase()
static final long DEFAULT_CHUNK_SIZE
void setSha256(String sha256)
boolean dataSourceIngestIsCancelled()
AnalysisResultAdded newAnalysisResult(BlackboardArtifact.Type artifactType, long objId, Long dataSourceObjId, Score score, String conclusion, String configuration, String justification, Collection< BlackboardAttribute > attributesList)
void switchToDeterminate(int workUnits)
static Case getCurrentCase()
synchronized static Logger getLogger(String name)
final boolean computeHashes
ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper)
void progress(int workUnits)
void startUp(IngestJobContext context)
static synchronized IngestServices getInstance()