Search code examples
windows-server-2012-r2dpapicng

DPAPI NG - NCryptProtectSecret returns NTE_ENCRYPTION_FAILURE


I am trying to encrypt data using DPAPI-NG but it fails on execution of NCryptProtectSecret, it returns:

0x80090034 (NTE_ENCRYPTION_FAILURE)

I have created NCryptCreateProtectionDescriptor with local user SID:

"SID=S-1-5-21-2942599413-360359348-3087651068-500"

Then I use this instance of descriptor as input for NCryptProtectSecret, but it does not work.

If I use a protection descriptor of:

"LOCAL=user"

everything seems okay, but it does not work with SID for user or group. I have tested this on Windows Server 2012R2 and Windows Server 2016.

Any idea?

Here is a code sample:

SECURITY_STATUS Status;
PBYTE       ProtectedData = NULL;
ULONG       ProtectedDataLength = 0;
NCRYPT_DESCRIPTOR_HANDLE    DescriptorHandle = NULL;
LPCWSTR ProtectionDescString = L"SID=S-1-5-21-2942599413-360359348-3087651068-500";

Status = NCryptCreateProtectionDescriptor(
                                        ProtectionDescString,
                                        0,
                                        &DescriptorHandle
                                        );      
// Status is ERROR_SUCCESS (zero)


LPCWSTR SecretString = L"Some message to protect";
PBYTE Secret = (PBYTE)SecretString;
DWORD SecretLength = (ULONG)( (wcslen(SecretString)+1)*sizeof(WCHAR) );

Status = NCryptProtectSecret(
                        DescriptorHandle,
                        0,
                        PlainText,
                        PlainTextLength,
                        NULL, // Use default allocations by LocalAlloc/LocalFree
                        NULL, // Use default parent windows handle.
                        &ProtectedData,  // out LocalFree
                        &ProtectedDataLength
                        );

**// Status == NTE_ENCRYPTION_FAILURE**

Solution

  • I ran into this problem and found that the cause was our domain was running at a functional level that was less than 2012. After upgrading the domain to 2012 the problem was resolved.

    A quick and easy way to determine the functional level is the following PowerShell cmdlet

    [system.directoryservices.activedirectory.Forest]::GetCurrentForest().ForestMode