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;
 
   38 import org.openide.util.NbBundle;
 
   64         computeHashes = settings.shouldComputeHashes();
 
   65         verifyHashes = settings.shouldVerifyHashes();
 
   69         "DataSourceIntegrityIngestModule.startup.noCheckboxesSelected=At least one of the checkboxes must be selected" 
   76         if (!(computeHashes || verifyHashes)) {
 
   77             throw new IngestModuleException(Bundle.DataSourceIntegrityIngestModule_startup_noCheckboxesSelected());
 
   83         "DataSourceIntegrityIngestModule.process.skipCompute=Not computing new hashes for {0} since the option was disabled",
 
   85         "DataSourceIntegrityIngestModule.process.skipVerify=Not verifying existing hashes for {0} since the option was disabled",
 
   87         "DataSourceIntegrityIngestModule.process.hashAlgorithmError=Error creating message digest for {0} algorithm",
 
   89         "DataSourceIntegrityIngestModule.process.hashMatch=<li>{0} hash verified </li>",
 
   91         "DataSourceIntegrityIngestModule.process.hashNonMatch=<li>{0} hash not verified </li>",
 
   92         "# {0} - calculatedHashValue",
 
   93         "# {1} - storedHashValue",
 
   94         "DataSourceIntegrityIngestModule.process.hashList=<ul><li>Calculated hash: {0} </li><li>Stored hash: {1} </li></ul>",
 
   96         "# {1} - calculatedHashValue",
 
   97         "DataSourceIntegrityIngestModule.process.calcHashWithType=<li>Calculated {0} hash: {1} </li>",
 
   99         "DataSourceIntegrityIngestModule.process.calculateHashDone=<p>Data Source Hash Calculation Results for {0} </p>", 
 
  100         "DataSourceIntegrityIngestModule.process.hashesCalculated= hashes calculated", 
 
  102         "DataSourceIntegrityIngestModule.process.errorSavingHashes= Error saving hashes for image {0} to the database", 
 
  104         "DataSourceIntegrityIngestModule.process.errorLoadingHashes= Error loading hashes for image {0} from the database", 
 
  105         "# {0} - hashAlgorithm",
 
  106         "# {1} - calculatedHashValue",
 
  107         "# {2} - storedHashValue",
 
  108         "DataSourceIntegrityIngestModule.process.hashFailedForArtifact={0} hash verification failed:\n  Calculated hash: {1}\n  Stored hash: {2}\n",  
 
  110         "DataSourceIntegrityIngestModule.process.verificationSuccess=Integrity of {0} verified",
 
  112         "DataSourceIntegrityIngestModule.process.verificationFailure={0} failed integrity verification",
 
  116         String imgName = dataSource.getName();
 
  119         if (!(dataSource instanceof Image)) {
 
  120             logger.log(Level.INFO, 
"Skipping non-image {0}", imgName); 
 
  122                     NbBundle.getMessage(this.getClass(),
 
  123                             "DataSourceIntegrityIngestModule.process.skipNonEwf",
 
  127         Image img = (Image) dataSource;
 
  130         long size = img.getSize();
 
  132             logger.log(Level.WARNING, 
"Size of image {0} was 0 when queried.", imgName); 
 
  134                     NbBundle.getMessage(this.getClass(),
 
  135                             "DataSourceIntegrityIngestModule.process.errGetSizeOfImg",
 
  145             if (img.getMd5() != null && ! img.getMd5().isEmpty()) {
 
  148             if (img.getSha1() != null && ! img.getSha1().isEmpty()) {
 
  151             if (img.getSha256() != null && ! img.getSha256().isEmpty()) {
 
  154         } 
catch (TskCoreException ex) {
 
  155                 String msg = Bundle.DataSourceIntegrityIngestModule_process_errorLoadingHashes(imgName);
 
  157                 logger.log(Level.SEVERE, msg, ex);
 
  163         if (hashDataList.isEmpty()) {
 
  171             logger.log(Level.INFO, 
"Not computing hashes for {0} since the option was disabled", imgName); 
 
  173                     Bundle.DataSourceIntegrityIngestModule_process_skipCompute(imgName)));
 
  176             logger.log(Level.INFO, 
"Not verifying hashes for {0} since the option was disabled", imgName); 
 
  178                     Bundle.DataSourceIntegrityIngestModule_process_skipVerify(imgName)));
 
  186                 hashDataList.add(
new HashData(type, 
""));
 
  191         for (
HashData hashData:hashDataList) {
 
  193                 hashData.digest = MessageDigest.getInstance(hashData.type.getName());
 
  194             } 
catch (NoSuchAlgorithmException ex) {
 
  195                 String msg = Bundle.DataSourceIntegrityIngestModule_process_hashAlgorithmError(hashData.type.getName());
 
  197                 logger.log(Level.SEVERE, msg, ex);
 
  205         long chunkSize = 64 * img.getSsize();
 
  206         chunkSize = (chunkSize == 0) ? DEFAULT_CHUNK_SIZE : chunkSize;
 
  209         int totalChunks = (int) Math.ceil((
double) size / (
double) chunkSize);
 
  210         logger.log(Level.INFO, 
"Total chunks = {0}", totalChunks); 
 
  213             logger.log(Level.INFO, 
"Starting hash verification of {0}", img.getName()); 
 
  215             logger.log(Level.INFO, 
"Starting hash calculation for {0}", img.getName()); 
 
  218         NbBundle.getMessage(this.getClass(),
 
  219                 "DataSourceIntegrityIngestModule.process.startingImg",
 
  226         byte[] data = 
new byte[(int) chunkSize];
 
  228         for (
int i = 0; i < totalChunks; i++) {
 
  233                 read = img.read(data, i * chunkSize, chunkSize);
 
  234             } 
catch (TskCoreException ex) {
 
  235                 String msg = NbBundle.getMessage(this.getClass(),
 
  236                         "DataSourceIntegrityIngestModule.process.errReadImgAtChunk", imgName, i);
 
  238                 logger.log(Level.SEVERE, msg, ex);
 
  243             if (read == chunkSize) {
 
  244                 for (
HashData struct:hashDataList) {
 
  245                     struct.digest.update(data);
 
  248                 byte[] subData = Arrays.copyOfRange(data, 0, read);
 
  249                 for (
HashData struct:hashDataList) {
 
  250                     struct.digest.update(subData);
 
  257         for(
HashData hashData:hashDataList) {
 
  258             hashData.calculatedHash = DatatypeConverter.printHexBinary(hashData.digest.digest()).toLowerCase();
 
  259             logger.log(Level.INFO, 
"Hash calculated from {0}: {1}", 
new Object[]{imgName, hashData.calculatedHash}); 
 
  264             boolean verified = 
true;
 
  265             String detailedResults = NbBundle
 
  266                 .getMessage(this.getClass(), 
"DataSourceIntegrityIngestModule.shutDown.verifyResultsHeader", imgName);
 
  267             String hashResults = 
"";
 
  268             String artifactComment = 
"";
 
  270             for (
HashData hashData:hashDataList) {
 
  271                 if (hashData.storedHash.equals(hashData.calculatedHash)) {
 
  272                     hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashMatch(hashData.type.name) + 
" ";
 
  275                     hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashNonMatch(hashData.type.name) + 
" ";
 
  276                     artifactComment += Bundle.DataSourceIntegrityIngestModule_process_hashFailedForArtifact(hashData.type.name,
 
  277                             hashData.calculatedHash, hashData.storedHash) + 
" ";
 
  279                 hashResults += Bundle.DataSourceIntegrityIngestModule_process_hashList(hashData.calculatedHash, hashData.storedHash);
 
  282             String verificationResultStr;
 
  283             String messageResultStr;
 
  287                 verificationResultStr = NbBundle.getMessage(this.getClass(), 
"DataSourceIntegrityIngestModule.shutDown.verified");
 
  288                 messageResultStr = Bundle.DataSourceIntegrityIngestModule_process_verificationSuccess(imgName);
 
  291                 verificationResultStr = NbBundle.getMessage(this.getClass(), 
"DataSourceIntegrityIngestModule.shutDown.notVerified");
 
  292                 messageResultStr = Bundle.DataSourceIntegrityIngestModule_process_verificationFailure(imgName);
 
  295             detailedResults += NbBundle.getMessage(this.getClass(), 
"DataSourceIntegrityIngestModule.shutDown.resultLi", verificationResultStr);
 
  296             detailedResults += hashResults;
 
  300                     BlackboardArtifact verificationFailedArtifact = 
Case.
getCurrentCase().
getSleuthkitCase().newBlackboardArtifact(BlackboardArtifact.ARTIFACT_TYPE.TSK_VERIFICATION_FAILED, img.getId());
 
  301                     verificationFailedArtifact.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT,
 
  303                 } 
catch (TskCoreException ex) {
 
  304                     logger.log(Level.SEVERE, 
"Error creating verification failed artifact", ex);
 
  309                     messageResultStr, detailedResults));
 
  314                 String results = Bundle.DataSourceIntegrityIngestModule_process_calculateHashDone(imgName);
 
  316                 for (
HashData hashData:hashDataList) {
 
  317                     switch (hashData.type) {
 
  320                                 img.setMD5(hashData.calculatedHash);
 
  321                             } 
catch (TskDataException ex) {
 
  322                                 logger.log(Level.SEVERE, 
"Error setting calculated hash", ex);
 
  327                                 img.setSha1(hashData.calculatedHash);
 
  328                             } 
catch (TskDataException ex) {
 
  329                                 logger.log(Level.SEVERE, 
"Error setting calculated hash", ex);
 
  334                                 img.setSha256(hashData.calculatedHash);
 
  335                             } 
catch (TskDataException ex) {
 
  336                                 logger.log(Level.SEVERE, 
"Error setting calculated hash", ex);
 
  342                     results += Bundle.DataSourceIntegrityIngestModule_process_calcHashWithType(hashData.type.name, hashData.calculatedHash);
 
  347                         imgName + Bundle.DataSourceIntegrityIngestModule_process_hashesCalculated(), results));
 
  349             } 
catch (TskCoreException ex) {
 
  350                 String msg = Bundle.DataSourceIntegrityIngestModule_process_errorSavingHashes(imgName);
 
  352                 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
 
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()