Search code examples
microsoft-information-protection

MIP SDK fails to use DKE sensitivity label


I'm trying to create a Windows application that uses C# MIP SDK (NuGet Microsoft.InformationProtection.File, version 1.13.161) to work with files protected by a Double Key Encryption.

I followed this guide to setup MIP SDK and enabled DKE by adding DoubleKeyProtection and DoubleKeyUserDefinedProtection keys to the FileEngineSettings.ConfiguredFunctionality dictionary.

Using the IFileEngine, I can retrieve all sensitivity labels (including DKE labels) and work with files protected by single key encryption ("Confidential" labels). But whenever I try to use sensitivity label with DKE, I receive a NotSupportedError: Double key protection is disabled. Exception with this error is thrown when committing a file handle after setting the label and when trying to initialize a file handle from a file protected by the DKE label.

According to MIP log, the source of the error is some inner HTTPS request that receives HTTP status 400:

MIP [Info] - message: Received HTTP response: ID: aa43de0d-3a0a-44d4-8499-83fd0de7d1c2, Status: 400, Time: 2023-06-07T20:20:04Z, Body: {"Code":"Microsoft.RightsManagement.Exceptions.BadInputException","InnerError":{"Resource":"[dke_service_url]","Code":"DoubleKeyEncryptionParametersMissing","Message":""},"Message":"Parameter DoubleKeyEncryptionPolicy is invalid."}, Headers['Date'] = 'Wed, 07 Jun 2023 20:20:03 GMT', Headers['Pragma'] = 'no-cache', Headers['Expires'] = '-1', Headers['X-Cache'] = 'CONFIG_NOCACHE', Headers['Content-Type'] = 'application/json; charset=utf-8', Headers['X-MSEdge-Ref'] = 'Ref A: 99DEEE7B27304EDC97E061BC77E9808F Ref B: AMS231032601031 Ref C: 2023-06-07T20:20:03Z', Headers['X-Powered-By'] = 'ASP.NET', Headers['Cache-Control'] = 'no-cache', Headers['CorrelationId'] = 'aa43de0d-3a0a-44d4-8499-83fd0de7d1c2', Headers['Content-Length'] = '250', Headers['X-AspNet-Version'] = '4.0.30319', Headers['client-request-id'] = 'aa43de0d-3a0a-44d4-8499-83fd0de7d1c2', Headers['Strict-Transport-Security'] = 'max-age=31536000; includeSubDomains', func: 'anonymous-namespace'::LogHttpOperationDetails at src\core\api_impl\http\http_director_impl.cpp (38)

I have tried to:

  • enable Double key encryption on both FileEngine and PolicyEngine
  • setting different cache storage types on engines
  • clear MIP cache between attempts
  • use different user accounts

The result was always the same - NotSupportedError: Double key protection is disabled.

I was testing with PC and account both configured for DKE. The same sensitivity label that fails in MIP SDK can be normally used in MS Office apps and AIP client. The DKE label was configured following the Microsoft guide. The DKE service is the sample DoubleKeyEncryptionService downloaded from GitHub.

Am I missing something in the configuration, or is it just a bug in the MIP SDK?


Sample codes (the project is just a POC for now, some values are hardcoded)

MIP initialization:

MIP.Initialize(MipComponent.File);

ApplicationInfo appInfo = new()
{
    ApplicationId = _userIdentity.ClientId,
    ApplicationName = "MIP tester",
    ApplicationVersion = "1.0.0",
};

MipConfiguration mipConfiguration = new(appInfo, path, Microsoft.InformationProtection.LogLevel.Trace, false);
mipConfiguration.LoggerDelegateOverride = this;

_mipContext = MIP.CreateMipContext(mipConfiguration);

File engine initialization:

FileProfileSettings profileSettings = new(
    _mipContext,
    CacheStorageType.InMemory,
    new ConsentDelegate()
);

_fileProfile = await Task.Run(async () => await MIP.LoadFileProfileAsync(profileSettings).ConfigureAwait(false));

if (_fileProfile is null)
{
    throw new MipServiceException("Loaded file profile is null!");
}

FileEngineSettings engineSetings = new($"file_engine_{_userIdentity.UserName}", this, string.Empty, "en-US");
engineSetings.Identity = new Identity(_userIdentity.UserName);

// Enable DKE
var functionsDict = engineSetings.ConfiguredFunctionality ?? new Dictionary<FunctionalityFilterType, bool>();
functionsDict[FunctionalityFilterType.DoubleKeyProtection] = true;
functionsDict[FunctionalityFilterType.DoubleKeyUserDefinedProtection] = true;
engineSetings.ConfiguredFunctionality = functionsDict;

_fileEngine = await Task.Run(async () => await _fileProfile.AddEngineAsync(engineSetings).ConfigureAwait(false));

Setting a sensitivity label:

public async Task<string> SetLabel(Stream fileStream, string fileName, string labelId, string userName)
{
    if (_fileEngine is not null)
    {
        try
        {
            Label newLabel = _fileEngine.GetLabelById(labelId);

            IFileHandler fileHandler = await _fileEngine.CreateFileHandlerAsync(fileStream, fileName, true);

            fileHandler.SetLabel(newLabel, new LabelingOptions
            {
                AssignmentMethod = AssignmentMethod.Auto,
                IsDowngradeJustified = true,
                JustificationMessage = "I just want to do it :-)",
            },
            new ProtectionSettings
            {
                DelegatedUserEmail = userName,
                PFileExtensionBehavior = PFileExtensionBehavior.Default,
            });

            MemoryStream protectedStream = new MemoryStream();
            bool success = await fileHandler.CommitAsync(protectedStream); //This line throws an exception when setting DKE label

            return System.Convert.ToBase64String(protectedStream.ToArray());
        }
        catch (Exception e)
        {
            return $"Exception setting sensitivity label: {e}";
        }
    }
    return "Failure";
}

Reading content of a protected file:

IFileHandler fileHandler = await _fileEngine.CreateFileHandlerAsync(fileStream, fileName, true); //This line throws an exception when opening DKE protected file

Solution

  • MS Support helped me to solve the issue. The DKE feature has to be enabled also in the MipConfiguration.FeatureSettingsOverride when initializing MIP SDK:

    MIP.Initialize(MipComponent.File);
    
    ApplicationInfo appInfo = new()
    {
        ApplicationId = _userIdentity.ClientId,
        ApplicationName = "MIP tester",
        ApplicationVersion = "1.0.0",
    };
    
    MipConfiguration mipConfiguration = new(appInfo, path, Microsoft.InformationProtection.LogLevel.Trace, false);
    mipConfiguration.LoggerDelegateOverride = this;
    
    //Enable DKE
    Dictionary<FlightingFeature, bool> featureSettings = mipConfiguration.FeatureSettingsOverride ?? new Dictionary<FlightingFeature, bool>();
    featureSettings[FlightingFeature.DoubleKey] = true;
    mipConfiguration.FeatureSettingsOverride = featureSettings; 
    
    _mipContext = MIP.CreateMipContext(mipConfiguration);