Autopsy  4.0
Graphical digital forensics platform for The Sleuth Kit and other tools.
E01VerifyIngestModule.java
Go to the documentation of this file.
1 /*
2  * Autopsy Forensic Browser
3  *
4  * Copyright 2013-2014 Basis Technology Corp.
5  * Contact: carrier <at> sleuthkit <dot> org
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 package org.sleuthkit.autopsy.modules.e01verify;
20 
21 import java.security.MessageDigest;
22 import java.security.NoSuchAlgorithmException;
23 import java.util.logging.Level;
24 import javax.xml.bind.DatatypeConverter;
25 import org.openide.util.NbBundle;
26 import org.python.bouncycastle.util.Arrays;
34 import org.sleuthkit.datamodel.Content;
35 import org.sleuthkit.datamodel.Image;
36 import org.sleuthkit.datamodel.TskCoreException;
37 import org.sleuthkit.datamodel.TskData;
38 
45 
46  private static final Logger logger = Logger.getLogger(E01VerifyIngestModule.class.getName());
47  private static final long DEFAULT_CHUNK_SIZE = 32 * 1024;
49 
50  private MessageDigest messageDigest;
51  private boolean verified = false;
52  private String calculatedHash = "";
53  private String storedHash = "";
55 
57  }
58 
59  @Override
60  public void startUp(IngestJobContext context) throws IngestModuleException {
61  this.context = context;
62  verified = false;
63  storedHash = "";
64  calculatedHash = "";
65 
66  try {
67  messageDigest = MessageDigest.getInstance("MD5"); //NON-NLS
68  } catch (NoSuchAlgorithmException ex) {
69  logger.log(Level.WARNING, "Error getting md5 algorithm", ex); //NON-NLS
70  throw new RuntimeException(
71  NbBundle.getMessage(this.getClass(), "EwfVerifyIngestModule.startUp.exception.failGetMd5"));
72  }
73  }
74 
75  @Override
76  public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper) {
77  String imgName = dataSource.getName();
78 
79  // Skip non-images
80  if (!(dataSource instanceof Image)) {
81  logger.log(Level.INFO, "Skipping non-image {0}", imgName); //NON-NLS
83  NbBundle.getMessage(this.getClass(),
84  "EwfVerifyIngestModule.process.skipNonEwf",
85  imgName)));
86  return ProcessResult.OK;
87  }
88  Image img = (Image) dataSource;
89 
90  // Skip images that are not E01
91  if (img.getType() != TskData.TSK_IMG_TYPE_ENUM.TSK_IMG_TYPE_EWF_EWF) {
92  logger.log(Level.INFO, "Skipping non-ewf image {0}", imgName); //NON-NLS
94  NbBundle.getMessage(this.getClass(),
95  "EwfVerifyIngestModule.process.skipNonEwf",
96  imgName)));
97  return ProcessResult.OK;
98  }
99 
100  // Report an error for null or empty MD5
101  if ((img.getMd5() == null) || img.getMd5().isEmpty()) {
103  NbBundle.getMessage(this.getClass(),
104  "EwfVerifyIngestModule.process.noStoredHash",
105  imgName)));
106  return ProcessResult.ERROR;
107  }
108 
109  storedHash = img.getMd5().toLowerCase();
110  logger.log(Level.INFO, "Hash value stored in {0}: {1}", new Object[]{imgName, storedHash}); //NON-NLS
111 
112  logger.log(Level.INFO, "Starting hash verification of {0}", img.getName()); //NON-NLS
114  NbBundle.getMessage(this.getClass(),
115  "EwfVerifyIngestModule.process.startingImg",
116  imgName)));
117 
118  long size = img.getSize();
119  if (size == 0) {
120  logger.log(Level.WARNING, "Size of image {0} was 0 when queried.", imgName); //NON-NLS
122  NbBundle.getMessage(this.getClass(),
123  "EwfVerifyIngestModule.process.errGetSizeOfImg",
124  imgName)));
125  }
126 
127  // Libewf uses a sector size of 64 times the sector size, which is the
128  // motivation for using it here.
129  long chunkSize = 64 * img.getSsize();
130  chunkSize = (chunkSize == 0) ? DEFAULT_CHUNK_SIZE : chunkSize;
131 
132  // Casting to double to capture decimals
133  int totalChunks = (int) Math.ceil((double)size / (double)chunkSize);
134  logger.log(Level.INFO, "Total chunks = {0}", totalChunks); //NON-NLS
135  int read;
136 
137  byte[] data = new byte[(int) chunkSize];
138  statusHelper.switchToDeterminate(totalChunks);
139 
140  // Read in byte size chunks and update the hash value with the data.
141  for (int i = 0; i < totalChunks; i++) {
142  if (context.dataSourceIngestIsCancelled()) {
143  return ProcessResult.OK;
144  }
145  try {
146  read = img.read(data, i * chunkSize, chunkSize);
147  } catch (TskCoreException ex) {
148  String msg = NbBundle.getMessage(this.getClass(),
149  "EwfVerifyIngestModule.process.errReadImgAtChunk", imgName, i);
151  logger.log(Level.SEVERE, msg, ex);
152  return ProcessResult.ERROR;
153  }
154 
155  // Only update with the read bytes.
156  if(read == chunkSize) {
157  messageDigest.update(data);
158  } else {
159  byte[] subData = Arrays.copyOfRange(data, 0, read);
160  messageDigest.update(subData);
161  }
162  statusHelper.progress(i);
163  }
164 
165  // Finish generating the hash and get it as a string value
166  calculatedHash = DatatypeConverter.printHexBinary(messageDigest.digest()).toLowerCase();
167  verified = calculatedHash.equals(storedHash);
168  logger.log(Level.INFO, "Hash calculated from {0}: {1}", new Object[]{imgName, calculatedHash}); //NON-NLS
169 
170  logger.log(Level.INFO, "complete() {0}", E01VerifierModuleFactory.getModuleName()); //NON-NLS
171  String msg;
172  if (verified) {
173  msg = NbBundle.getMessage(this.getClass(), "EwfVerifyIngestModule.shutDown.verified");
174  } else {
175  msg = NbBundle.getMessage(this.getClass(), "EwfVerifyIngestModule.shutDown.notVerified");
176  }
177  String extra = NbBundle
178  .getMessage(this.getClass(), "EwfVerifyIngestModule.shutDown.verifyResultsHeader", imgName);
179  extra += NbBundle.getMessage(this.getClass(), "EwfVerifyIngestModule.shutDown.resultLi", msg);
180  extra += NbBundle.getMessage(this.getClass(), "EwfVerifyIngestModule.shutDown.calcHashLi", calculatedHash);
181  extra += NbBundle.getMessage(this.getClass(), "EwfVerifyIngestModule.shutDown.storedHashLi", storedHash);
182  services.postMessage(IngestMessage.createMessage(MessageType.INFO, E01VerifierModuleFactory.getModuleName(), imgName + msg, extra));
183  logger.log(Level.INFO, "{0}{1}", new Object[]{imgName, msg});
184 
185  return ProcessResult.OK;
186  }
187 }
static IngestMessage createMessage(MessageType messageType, String source, String subject, String detailsHtml)
void postMessage(final IngestMessage message)
ProcessResult process(Content dataSource, DataSourceIngestModuleProgress statusHelper)
synchronized static Logger getLogger(String name)
Definition: Logger.java:166
static synchronized IngestServices getInstance()

Copyright © 2012-2015 Basis Technology. Generated on: Wed Apr 6 2016
This work is licensed under a Creative Commons Attribution-Share Alike 3.0 United States License.