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 javax.xml.bind.DatatypeConverter;
 
   27 import java.util.Arrays;
 
   39 import org.openide.util.NbBundle;
 
   65         computeHashes = settings.shouldComputeHashes();
 
   66         verifyHashes = settings.shouldVerifyHashes();
 
   70         "DataSourceIntegrityIngestModule.startup.noCheckboxesSelected=At least one of the checkboxes must be selected" 
   77         if (!(computeHashes || verifyHashes)) {
 
   78             throw new IngestModuleException(Bundle.DataSourceIntegrityIngestModule_startup_noCheckboxesSelected());
 
   84         "DataSourceIntegrityIngestModule.process.skipCompute=Not computing new hashes for {0} since the option was disabled",
 
   86         "DataSourceIntegrityIngestModule.process.skipVerify=Not verifying existing hashes for {0} since the option was disabled",
 
   88         "DataSourceIntegrityIngestModule.process.hashAlgorithmError=Error creating message digest for {0} algorithm",
 
   90         "DataSourceIntegrityIngestModule.process.hashMatch=<li>{0} hash verified </li>",
 
   92         "DataSourceIntegrityIngestModule.process.hashNonMatch=<li>{0} hash not verified </li>",
 
   93         "# {0} - calculatedHashValue",
 
   94         "# {1} - storedHashValue",
 
   95         "DataSourceIntegrityIngestModule.process.hashList=<ul><li>Calculated hash: {0} </li><li>Stored hash: {1} </li></ul>",
 
   97         "# {1} - calculatedHashValue",
 
   98         "DataSourceIntegrityIngestModule.process.calcHashWithType=<li>Calculated {0} hash: {1} </li>",
 
  100         "DataSourceIntegrityIngestModule.process.calculateHashDone=<p>Data Source Hash Calculation Results for {0} </p>", 
 
  101         "DataSourceIntegrityIngestModule.process.hashesCalculated= hashes calculated", 
 
  103         "DataSourceIntegrityIngestModule.process.errorSavingHashes= Error saving hashes for image {0} to the database", 
 
  105         "DataSourceIntegrityIngestModule.process.errorLoadingHashes= Error loading hashes for image {0} from the database", 
 
  106         "# {0} - hashAlgorithm",
 
  107         "# {1} - calculatedHashValue",
 
  108         "# {2} - storedHashValue",
 
  109         "DataSourceIntegrityIngestModule.process.hashFailedForArtifact={0} hash verification failed:\n  Calculated hash: {1}\n  Stored hash: {2}\n",  
 
  111         "DataSourceIntegrityIngestModule.process.verificationSuccess=Integrity of {0} verified",
 
  113         "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;
 
  131         long size = img.getSize();
 
  133             logger.log(Level.WARNING, 
"Size of image {0} was 0 when queried.", imgName); 
 
  142             if (img.getMd5() != null && ! img.getMd5().isEmpty()) {
 
  145             if (img.getSha1() != null && ! img.getSha1().isEmpty()) {
 
  148             if (img.getSha256() != null && ! img.getSha256().isEmpty()) {
 
  151         } 
catch (TskCoreException ex) {
 
  152                 String msg = Bundle.DataSourceIntegrityIngestModule_process_errorLoadingHashes(imgName);
 
  154                 logger.log(Level.SEVERE, msg, ex);
 
  160         if (hashDataList.isEmpty()) {
 
  168             logger.log(Level.INFO, 
"Not computing hashes for {0} since the option was disabled", imgName); 
 
  170                     Bundle.DataSourceIntegrityIngestModule_process_skipCompute(imgName)));
 
  173             logger.log(Level.INFO, 
"Not verifying hashes for {0} since the option was disabled", imgName); 
 
  175                     Bundle.DataSourceIntegrityIngestModule_process_skipVerify(imgName)));
 
  183                 hashDataList.add(
new HashData(type, 
""));
 
  188         for (
HashData hashData:hashDataList) {
 
  190                 hashData.digest = MessageDigest.getInstance(hashData.type.getName());
 
  191             } 
catch (NoSuchAlgorithmException ex) {
 
  192                 String msg = Bundle.DataSourceIntegrityIngestModule_process_hashAlgorithmError(hashData.type.getName());
 
  194                 logger.log(Level.SEVERE, msg, ex);
 
  202         long chunkSize = 64 * img.getSsize();
 
  203         chunkSize = (chunkSize == 0) ? DEFAULT_CHUNK_SIZE : chunkSize;
 
  206         int totalChunks = (int) Math.ceil((
double) size / (
double) chunkSize);
 
  207         logger.log(Level.INFO, 
"Total chunks = {0}", totalChunks); 
 
  210             logger.log(Level.INFO, 
"Starting hash verification of {0}", img.getName()); 
 
  212             logger.log(Level.INFO, 
"Starting hash calculation for {0}", img.getName()); 
 
  215         NbBundle.getMessage(this.getClass(),
 
  216                 "DataSourceIntegrityIngestModule.process.startingImg",
 
  223         byte[] data = 
new byte[(int) chunkSize];
 
  225         for (
int i = 0; i < totalChunks; i++) {
 
  230                 read = img.read(data, i * chunkSize, chunkSize);
 
  231             } 
catch (TskCoreException ex) {
 
  232                 String msg = NbBundle.getMessage(this.getClass(),
 
  233                         "DataSourceIntegrityIngestModule.process.errReadImgAtChunk", imgName, i);
 
  235                 logger.log(Level.SEVERE, msg, ex);
 
  240             if (read == chunkSize) {
 
  241                 for (
HashData struct:hashDataList) {
 
  242                     struct.digest.update(data);
 
  245                 byte[] subData = Arrays.copyOfRange(data, 0, read);
 
  246                 for (
HashData struct:hashDataList) {
 
  247                     struct.digest.update(subData);
 
  254         for(
HashData hashData:hashDataList) {
 
  255             hashData.calculatedHash = DatatypeConverter.printHexBinary(hashData.digest.digest()).toLowerCase();
 
  256             logger.log(Level.INFO, 
"Hash calculated from {0}: {1}", 
new Object[]{imgName, hashData.calculatedHash}); 
 
  261             boolean verified = 
true;
 
  262             String detailedResults = NbBundle
 
  263                 .getMessage(this.getClass(), 
"DataSourceIntegrityIngestModule.shutDown.verifyResultsHeader", imgName);
 
  264             String hashResults = 
"";
 
  265             String artifactComment = 
"";
 
  267             for (
HashData hashData:hashDataList) {
 
  268                 if (hashData.storedHash.equals(hashData.calculatedHash)) {
 
  269                     hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashMatch(hashData.type.name) + 
" ";
 
  272                     hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashNonMatch(hashData.type.name) + 
" ";
 
  273                     artifactComment += Bundle.DataSourceIntegrityIngestModule_process_hashFailedForArtifact(hashData.type.name,
 
  274                             hashData.calculatedHash, hashData.storedHash) + 
" ";
 
  276                 hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashList(hashData.calculatedHash, hashData.storedHash);
 
  279             String verificationResultStr;
 
  280             String messageResultStr;
 
  284                 verificationResultStr = NbBundle.getMessage(this.getClass(), 
"DataSourceIntegrityIngestModule.shutDown.verified");
 
  285                 messageResultStr = Bundle.DataSourceIntegrityIngestModule_process_verificationSuccess(imgName);
 
  288                 verificationResultStr = NbBundle.getMessage(this.getClass(), 
"DataSourceIntegrityIngestModule.shutDown.notVerified");
 
  289                 messageResultStr = Bundle.DataSourceIntegrityIngestModule_process_verificationFailure(imgName);
 
  292             detailedResults += NbBundle.getMessage(this.getClass(), 
"DataSourceIntegrityIngestModule.shutDown.resultLi", verificationResultStr);
 
  293             detailedResults += hashResults;
 
  297                     BlackboardArtifact verificationFailedArtifact = 
Case.
getCurrentCase().
getSleuthkitCase().newBlackboardArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_VERIFICATION_FAILED, img.getId());
 
  298                     verificationFailedArtifact.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT,
 
  301                         BlackboardArtifact.ARTIFACT_TYPE.TSK_VERIFICATION_FAILED));
 
  302                 } 
catch (TskCoreException ex) {
 
  303                     logger.log(Level.SEVERE, 
"Error creating verification failed artifact", ex);
 
  308                     messageResultStr, detailedResults));
 
  313                 String results = Bundle.DataSourceIntegrityIngestModule_process_calculateHashDone(imgName);
 
  315                 for (
HashData hashData:hashDataList) {
 
  316                     switch (hashData.type) {
 
  319                                 img.setMD5(hashData.calculatedHash);
 
  320                             } 
catch (TskDataException ex) {
 
  321                                 logger.log(Level.SEVERE, 
"Error setting calculated hash", ex);
 
  326                                 img.setSha1(hashData.calculatedHash);
 
  327                             } 
catch (TskDataException ex) {
 
  328                                 logger.log(Level.SEVERE, 
"Error setting calculated hash", ex);
 
  333                                 img.setSha256(hashData.calculatedHash);
 
  334                             } 
catch (TskDataException ex) {
 
  335                                 logger.log(Level.SEVERE, 
"Error setting calculated hash", ex);
 
  341                     results += Bundle.DataSourceIntegrityIngestModule_process_calcHashWithType(hashData.type.name, hashData.calculatedHash);
 
  346                         imgName + Bundle.DataSourceIntegrityIngestModule_process_hashesCalculated(), results));
 
  348             } 
catch (TskCoreException ex) {
 
  349                 String msg = Bundle.DataSourceIntegrityIngestModule_process_errorSavingHashes(imgName);
 
  351                 logger.log(Level.SEVERE, 
"Error saving hash for image " + imgName + 
" to database", ex);
 
static final IngestServices services
static final Logger logger
static IngestMessage createMessage(MessageType messageType, String source, String subject, String detailsHtml)
final List< HashData > hashDataList
void postMessage(final IngestMessage message)
final boolean verifyHashes
void fireModuleDataEvent(ModuleDataEvent moduleDataEvent)
SleuthkitCase getSleuthkitCase()
static final long DEFAULT_CHUNK_SIZE
boolean dataSourceIngestIsCancelled()
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()