19 package org.sleuthkit.autopsy.modules.encryptiondetection;
 
   21 import java.io.IOException;
 
   22 import java.util.Collections;
 
   23 import java.util.List;
 
   24 import java.util.logging.Level;
 
   25 import org.openide.util.NbBundle.Messages;
 
   48 final class EncryptionDetectionDataSourceIngestModule 
implements DataSourceIngestModule {
 
   50     private final IngestServices services = IngestServices.getInstance();
 
   51     private final Logger logger = services.getLogger(EncryptionDetectionModuleFactory.getModuleName());
 
   52     private Blackboard blackboard;
 
   53     private double calculatedEntropy;
 
   54     private final double minimumEntropy;
 
   62     EncryptionDetectionDataSourceIngestModule(EncryptionDetectionIngestJobSettings settings) {
 
   63         minimumEntropy = settings.getMinimumEntropy();
 
   67     public void startUp(IngestJobContext context) 
throws IngestModule.IngestModuleException {
 
   69         blackboard = Case.getCurrentCase().getServices().getBlackboard();
 
   73         "EncryptionDetectionDataSourceIngestModule.artifactComment.bitlocker=Bitlocker encryption detected.",
 
   74         "EncryptionDetectionDataSourceIngestModule.artifactComment.suspected=Suspected encryption due to high entropy (%f)." 
   77     public ProcessResult process(Content dataSource, DataSourceIngestModuleProgress progressBar) {
 
   80             if (dataSource instanceof Image) {
 
   81                 List<VolumeSystem> volumeSystems = ((Image) dataSource).getVolumeSystems();
 
   82                 for (VolumeSystem volumeSystem : volumeSystems) {
 
   83                     for (Volume volume : volumeSystem.getVolumes()) {
 
   84                         if (BitlockerDetection.isBitlockerVolume(volume)) {
 
   85                             return flagVolume(volume, BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_DETECTED, Bundle.EncryptionDetectionDataSourceIngestModule_artifactComment_bitlocker());
 
   87                         if (isVolumeEncrypted(volume)) {
 
   88                             return flagVolume(volume, BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED, String.format(Bundle.EncryptionDetectionDataSourceIngestModule_artifactComment_suspected(), calculatedEntropy));
 
   93         } 
catch (ReadContentInputStream.ReadContentInputStreamException ex) {
 
   94             logger.log(Level.WARNING, String.format(
"Unable to read data source '%s'", dataSource.getName()), ex);
 
   95             return IngestModule.ProcessResult.ERROR;
 
   96         } 
catch (IOException | TskCoreException ex) {
 
   97             logger.log(Level.SEVERE, String.format(
"Unable to process data source '%s'", dataSource.getName()), ex);
 
   98             return IngestModule.ProcessResult.ERROR;
 
  101         return IngestModule.ProcessResult.OK;
 
  112     private void validateSettings() throws IngestModule.IngestModuleException {
 
  113         EncryptionDetectionTools.validateMinEntropyValue(minimumEntropy);
 
  126     private IngestModule.ProcessResult flagVolume(Volume volume, BlackboardArtifact.ARTIFACT_TYPE artifactType, String comment) {
 
  128             BlackboardArtifact artifact = volume.newArtifact(artifactType);
 
  129             artifact.addAttribute(
new BlackboardAttribute(BlackboardAttribute.ATTRIBUTE_TYPE.TSK_COMMENT, EncryptionDetectionModuleFactory.getModuleName(), comment));
 
  135                 blackboard.indexArtifact(artifact);
 
  136             } 
catch (Blackboard.BlackboardException ex) {
 
  137                 logger.log(Level.SEVERE, 
"Unable to index blackboard artifact " + artifact.getArtifactID(), ex); 
 
  143             services.fireModuleDataEvent(
new ModuleDataEvent(EncryptionDetectionModuleFactory.getModuleName(), artifactType, Collections.singletonList(artifact)));
 
  148             StringBuilder detailsSb = 
new StringBuilder(
"");
 
  149             detailsSb.append(
"File: ");
 
  150             Content parentFile = volume.getParent();
 
  151             if (parentFile != null) {
 
  152                 detailsSb.append(volume.getParent().getUniquePath());
 
  154             detailsSb.append(volume.getName());
 
  155             if (artifactType.equals(BlackboardArtifact.ARTIFACT_TYPE.TSK_ENCRYPTION_SUSPECTED)) {
 
  156                 detailsSb.append(
"<br/>\nEntropy: ").append(calculatedEntropy);
 
  159             services.postMessage(IngestMessage.createDataMessage(EncryptionDetectionModuleFactory.getModuleName(),
 
  160                     artifactType.getDisplayName() + 
" Match: " + volume.getName(),
 
  161                     detailsSb.toString(),
 
  165             return IngestModule.ProcessResult.OK;
 
  166         } 
catch (TskCoreException ex) {
 
  167             logger.log(Level.SEVERE, String.format(
"Failed to create blackboard artifact for '%s'.", volume.getName()), ex); 
 
  168             return IngestModule.ProcessResult.ERROR;
 
  180     private boolean isVolumeEncrypted(Volume volume) 
throws ReadContentInputStream.ReadContentInputStreamException, IOException, TskCoreException {
 
  185         if (volume.getFileSystems().isEmpty()) {
 
  186             calculatedEntropy = EncryptionDetectionTools.calculateEntropy(volume);
 
  187             if (calculatedEntropy >= minimumEntropy) {