mirror of https://github.com/FreeRDP/FreeRDP
libwinpr-crypto: implement CryptProtectMemory/CryptUnprotectMemory
This commit is contained in:
parent
6365880f4d
commit
851ace73ff
|
@ -23,6 +23,8 @@
|
|||
#include <winpr/winpr.h>
|
||||
#include <winpr/wtypes.h>
|
||||
|
||||
#include <winpr/error.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <wincrypt.h>
|
||||
|
@ -492,6 +494,94 @@ DWORD CertGetNameStringA(PCCERT_CONTEXT pCertContext, DWORD dwType,
|
|||
#define CertGetNameString CertGetNameStringA
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Data Protection API (DPAPI)
|
||||
*/
|
||||
|
||||
#define CRYPTPROTECTMEMORY_BLOCK_SIZE 16
|
||||
|
||||
#define CRYPTPROTECTMEMORY_SAME_PROCESS 0x00000000
|
||||
#define CRYPTPROTECTMEMORY_CROSS_PROCESS 0x00000001
|
||||
#define CRYPTPROTECTMEMORY_SAME_LOGON 0x00000002
|
||||
|
||||
#define CRYPTPROTECT_PROMPT_ON_UNPROTECT 0x00000001
|
||||
#define CRYPTPROTECT_PROMPT_ON_PROTECT 0x00000002
|
||||
#define CRYPTPROTECT_PROMPT_RESERVED 0x00000004
|
||||
#define CRYPTPROTECT_PROMPT_STRONG 0x00000008
|
||||
#define CRYPTPROTECT_PROMPT_REQUIRE_STRONG 0x00000010
|
||||
|
||||
#define CRYPTPROTECT_UI_FORBIDDEN 0x1
|
||||
#define CRYPTPROTECT_LOCAL_MACHINE 0x4
|
||||
#define CRYPTPROTECT_CRED_SYNC 0x8
|
||||
#define CRYPTPROTECT_AUDIT 0x10
|
||||
#define CRYPTPROTECT_NO_RECOVERY 0x20
|
||||
#define CRYPTPROTECT_VERIFY_PROTECTION 0x40
|
||||
#define CRYPTPROTECT_CRED_REGENERATE 0x80
|
||||
|
||||
#define CRYPTPROTECT_FIRST_RESERVED_FLAGVAL 0x0FFFFFFF
|
||||
#define CRYPTPROTECT_LAST_RESERVED_FLAGVAL 0xFFFFFFFF
|
||||
|
||||
typedef struct _CRYPTPROTECT_PROMPTSTRUCT
|
||||
{
|
||||
DWORD cbSize;
|
||||
DWORD dwPromptFlags;
|
||||
HWND hwndApp;
|
||||
LPCWSTR szPrompt;
|
||||
} CRYPTPROTECT_PROMPTSTRUCT, *PCRYPTPROTECT_PROMPTSTRUCT;
|
||||
|
||||
#define CRYPTPROTECT_DEFAULT_PROVIDER { 0xdf9d8cd0, 0x1501, 0x11d1, { 0x8c, 0x7a, 0x00, 0xc0, 0x4f, 0xc2, 0x97, 0xeb } }
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WINPR_API BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags);
|
||||
WINPR_API BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags);
|
||||
|
||||
WINPR_API BOOL CryptProtectData(DATA_BLOB* pDataIn, LPCWSTR szDataDescr, DATA_BLOB* pOptionalEntropy,
|
||||
PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags, DATA_BLOB* pDataOut);
|
||||
WINPR_API BOOL CryptUnprotectData(DATA_BLOB* pDataIn, LPWSTR* ppszDataDescr, DATA_BLOB* pOptionalEntropy,
|
||||
PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags, DATA_BLOB* pDataOut);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CRYPT_STRING_BASE64HEADER 0x00000000
|
||||
#define CRYPT_STRING_BASE64 0x00000001
|
||||
#define CRYPT_STRING_BINARY 0x00000002
|
||||
#define CRYPT_STRING_BASE64REQUESTHEADER 0x00000003
|
||||
#define CRYPT_STRING_HEX 0x00000004
|
||||
#define CRYPT_STRING_HEXASCII 0x00000005
|
||||
#define CRYPT_STRING_BASE64_ANY 0x00000006
|
||||
#define CRYPT_STRING_ANY 0x00000007
|
||||
#define CRYPT_STRING_HEX_ANY 0x00000008
|
||||
#define CRYPT_STRING_BASE64X509CRLHEADER 0x00000009
|
||||
#define CRYPT_STRING_HEXADDR 0x0000000A
|
||||
#define CRYPT_STRING_HEXASCIIADDR 0x0000000B
|
||||
#define CRYPT_STRING_HEXRAW 0x0000000C
|
||||
|
||||
#define CRYPT_STRING_HASHDATA 0x10000000
|
||||
#define CRYPT_STRING_STRICT 0x20000000
|
||||
#define CRYPT_STRING_NOCRLF 0x40000000
|
||||
#define CRYPT_STRING_NOCR 0x80000000
|
||||
|
||||
BOOL CryptStringToBinaryW(LPCWSTR pszString, DWORD cchString, DWORD dwFlags, BYTE* pbBinary,
|
||||
DWORD* pcbBinary, DWORD* pdwSkip, DWORD* pdwFlags);
|
||||
BOOL CryptStringToBinaryA(LPCSTR pszString, DWORD cchString, DWORD dwFlags, BYTE* pbBinary,
|
||||
DWORD* pcbBinary, DWORD* pdwSkip, DWORD* pdwFlags);
|
||||
|
||||
BOOL CryptBinaryToStringW(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD* pcchString);
|
||||
BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD* pcchString);
|
||||
|
||||
#ifdef UNICODE
|
||||
#define CryptStringToBinary CryptStringToBinaryW
|
||||
#define CryptBinaryToString CryptBinaryToStringW
|
||||
#else
|
||||
#define CryptStringToBinary CryptStringToBinaryA
|
||||
#define CryptBinaryToString CryptBinaryToStringA
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_CRYPTO_H */
|
||||
|
|
|
@ -35,6 +35,11 @@ if(WIN32)
|
|||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} credui)
|
||||
endif()
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL
|
||||
MODULE winpr
|
||||
MODULES winpr-crt winpr-utils)
|
||||
|
||||
if(MONOLITHIC_BUILD)
|
||||
set(WINPR_LIBS ${WINPR_LIBS} ${${MODULE_PREFIX}_LIBS} PARENT_SCOPE)
|
||||
else()
|
||||
|
|
|
@ -31,8 +31,20 @@ add_complex_library(MODULE ${MODULE_NAME} TYPE "OBJECT"
|
|||
MONOLITHIC ${MONOLITHIC_BUILD}
|
||||
SOURCES ${${MODULE_PREFIX}_SRCS})
|
||||
|
||||
include_directories(${ZLIB_INCLUDE_DIRS})
|
||||
include_directories(${OPENSSL_INCLUDE_DIR})
|
||||
|
||||
set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION_FULL} SOVERSION ${WINPR_VERSION} PREFIX "lib")
|
||||
|
||||
set(${MODULE_PREFIX}_LIBS
|
||||
${ZLIB_LIBRARIES}
|
||||
${OPENSSL_LIBRARIES})
|
||||
|
||||
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
|
||||
MONOLITHIC ${MONOLITHIC_BUILD} INTERNAL
|
||||
MODULE winpr
|
||||
MODULES winpr-crt winpr-utils)
|
||||
|
||||
if(WIN32)
|
||||
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} crypt32)
|
||||
endif()
|
||||
|
|
|
@ -89,8 +89,6 @@
|
|||
* CryptMsgUpdate
|
||||
* CryptMsgVerifyCountersignatureEncoded
|
||||
* CryptMsgVerifyCountersignatureEncodedEx
|
||||
* CryptProtectData
|
||||
* CryptProtectMemory
|
||||
* CryptQueryObject
|
||||
* CryptRegisterDefaultOIDFunction
|
||||
* CryptRegisterOIDFunction
|
||||
|
@ -115,11 +113,7 @@
|
|||
* CryptSIPRetrieveSubjectGuid
|
||||
* CryptSIPRetrieveSubjectGuidForCatalogFile
|
||||
* CryptSIPVerifyIndirectData
|
||||
* CryptStringToBinaryA
|
||||
* CryptStringToBinaryW
|
||||
* CryptUninstallDefaultContext
|
||||
* CryptUnprotectData
|
||||
* CryptUnprotectMemory
|
||||
* CryptUnregisterDefaultOIDFunction
|
||||
* CryptUnregisterOIDFunction
|
||||
* CryptUnregisterOIDInfo
|
||||
|
@ -146,4 +140,140 @@
|
|||
|
||||
#include "crypto.h"
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
static wListDictionary* g_ProtectedMemoryBlocks = NULL;
|
||||
|
||||
BOOL CryptProtectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags)
|
||||
{
|
||||
BYTE* pCipherText;
|
||||
int cbOut, cbFinal;
|
||||
BYTE randomKey[256];
|
||||
WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock;
|
||||
|
||||
if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS)
|
||||
return FALSE;
|
||||
|
||||
if (!g_ProtectedMemoryBlocks)
|
||||
g_ProtectedMemoryBlocks = ListDictionary_New(TRUE);
|
||||
|
||||
pMemBlock = (WINPR_PROTECTED_MEMORY_BLOCK*) malloc(sizeof(WINPR_PROTECTED_MEMORY_BLOCK));
|
||||
ZeroMemory(pMemBlock, sizeof(WINPR_PROTECTED_MEMORY_BLOCK));
|
||||
|
||||
pMemBlock->pData = pData;
|
||||
pMemBlock->cbData = cbData;
|
||||
pMemBlock->dwFlags = dwFlags;
|
||||
|
||||
/* AES Initialization */
|
||||
|
||||
RAND_bytes(pMemBlock->salt, 8);
|
||||
RAND_bytes(randomKey, sizeof(randomKey));
|
||||
|
||||
EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(),
|
||||
pMemBlock->salt,
|
||||
randomKey, sizeof(randomKey),
|
||||
4, pMemBlock->key, pMemBlock->iv);
|
||||
|
||||
SecureZeroMemory(randomKey, sizeof(randomKey));
|
||||
|
||||
EVP_CIPHER_CTX_init(&(pMemBlock->enc));
|
||||
EVP_EncryptInit_ex(&(pMemBlock->enc), EVP_aes_256_cbc(), NULL, pMemBlock->key, pMemBlock->iv);
|
||||
|
||||
EVP_CIPHER_CTX_init(&(pMemBlock->dec));
|
||||
EVP_DecryptInit_ex(&(pMemBlock->dec), EVP_aes_256_cbc(), NULL, pMemBlock->key, pMemBlock->iv);
|
||||
|
||||
/* AES Encryption */
|
||||
|
||||
cbOut = pMemBlock->cbData + AES_BLOCK_SIZE - 1;
|
||||
pCipherText = (BYTE*) malloc(cbOut);
|
||||
|
||||
EVP_EncryptInit_ex(&(pMemBlock->enc), NULL, NULL, NULL, NULL);
|
||||
EVP_EncryptUpdate(&(pMemBlock->enc), pCipherText, &cbOut, pMemBlock->pData, pMemBlock->cbData);
|
||||
EVP_EncryptFinal_ex(&(pMemBlock->enc), pCipherText + cbOut, &cbFinal);
|
||||
|
||||
CopyMemory(pMemBlock->pData, pCipherText, pMemBlock->cbData);
|
||||
free(pCipherText);
|
||||
|
||||
ListDictionary_Add(g_ProtectedMemoryBlocks, pData, pMemBlock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptUnprotectMemory(LPVOID pData, DWORD cbData, DWORD dwFlags)
|
||||
{
|
||||
BYTE* pPlainText;
|
||||
int cbOut, cbFinal;
|
||||
WINPR_PROTECTED_MEMORY_BLOCK* pMemBlock;
|
||||
|
||||
if (dwFlags != CRYPTPROTECTMEMORY_SAME_PROCESS)
|
||||
return FALSE;
|
||||
|
||||
if (!g_ProtectedMemoryBlocks)
|
||||
return FALSE;
|
||||
|
||||
pMemBlock = (WINPR_PROTECTED_MEMORY_BLOCK*) ListDictionary_GetItemValue(g_ProtectedMemoryBlocks, pData);
|
||||
|
||||
if (!pMemBlock)
|
||||
return FALSE;
|
||||
|
||||
/* AES Decryption */
|
||||
|
||||
cbOut = pMemBlock->cbData + AES_BLOCK_SIZE - 1;
|
||||
pPlainText = (BYTE*) malloc(cbOut);
|
||||
|
||||
EVP_DecryptInit_ex(&(pMemBlock->dec), NULL, NULL, NULL, NULL);
|
||||
EVP_DecryptUpdate(&(pMemBlock->dec), pPlainText, &cbOut, pMemBlock->pData, pMemBlock->cbData);
|
||||
EVP_DecryptFinal_ex(&(pMemBlock->dec), pPlainText + cbOut, &cbFinal);
|
||||
|
||||
CopyMemory(pMemBlock->pData, pPlainText, pMemBlock->cbData);
|
||||
SecureZeroMemory(pPlainText, pMemBlock->cbData);
|
||||
free(pPlainText);
|
||||
|
||||
ListDictionary_Remove(g_ProtectedMemoryBlocks, pData);
|
||||
|
||||
/* AES Cleanup */
|
||||
|
||||
EVP_CIPHER_CTX_cleanup(&(pMemBlock->enc));
|
||||
EVP_CIPHER_CTX_cleanup(&(pMemBlock->dec));
|
||||
|
||||
free(pMemBlock);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptProtectData(DATA_BLOB* pDataIn, LPCWSTR szDataDescr, DATA_BLOB* pOptionalEntropy,
|
||||
PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags, DATA_BLOB* pDataOut)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptUnprotectData(DATA_BLOB* pDataIn, LPWSTR* ppszDataDescr, DATA_BLOB* pOptionalEntropy,
|
||||
PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags, DATA_BLOB* pDataOut)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptStringToBinaryW(LPCWSTR pszString, DWORD cchString, DWORD dwFlags, BYTE* pbBinary,
|
||||
DWORD* pcbBinary, DWORD* pdwSkip, DWORD* pdwFlags)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptStringToBinaryA(LPCSTR pszString, DWORD cchString, DWORD dwFlags, BYTE* pbBinary,
|
||||
DWORD* pcbBinary, DWORD* pdwSkip, DWORD* pdwFlags)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptBinaryToStringW(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD* pcchString)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL CryptBinaryToStringA(CONST BYTE* pbBinary, DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD* pcchString)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
struct _WINPR_CERTSTORE
|
||||
{
|
||||
LPCSTR lpszStoreProvider;
|
||||
|
@ -29,6 +33,19 @@ struct _WINPR_CERTSTORE
|
|||
};
|
||||
typedef struct _WINPR_CERTSTORE WINPR_CERTSTORE;
|
||||
|
||||
struct _WINPR_PROTECTED_MEMORY_BLOCK
|
||||
{
|
||||
BYTE* pData;
|
||||
DWORD cbData;
|
||||
DWORD dwFlags;
|
||||
BYTE key[32];
|
||||
BYTE iv[32];
|
||||
BYTE salt[8];
|
||||
EVP_CIPHER_CTX enc;
|
||||
EVP_CIPHER_CTX dec;
|
||||
};
|
||||
typedef struct _WINPR_PROTECTED_MEMORY_BLOCK WINPR_PROTECTED_MEMORY_BLOCK;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* WINPR_CRYPTO_PRIVATE_H */
|
||||
|
|
|
@ -5,7 +5,9 @@ set(MODULE_PREFIX "TEST_CRYPTO")
|
|||
set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
|
||||
|
||||
set(${MODULE_PREFIX}_TESTS
|
||||
TestCertEnumCertificatesInStore.c)
|
||||
TestCryptoProtectData.c
|
||||
TestCryptoProtectMemory.c
|
||||
TestCryptoCertEnumCertificatesInStore.c)
|
||||
|
||||
create_test_sourcelist(${MODULE_PREFIX}_SRCS
|
||||
${${MODULE_PREFIX}_DRIVER}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#include <cryptuiapi.h>
|
||||
#endif
|
||||
|
||||
int TestCertEnumCertificatesInStore(int argc, char* argv[])
|
||||
int TestCryptoCertEnumCertificatesInStore(int argc, char* argv[])
|
||||
{
|
||||
int index;
|
||||
DWORD status;
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/tchar.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
int TestCryptoProtectData(int argc, char* argv[])
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/print.h>
|
||||
#include <winpr/crypto.h>
|
||||
|
||||
static const char* SECRET_PASSWORD_TEST = "MySecretPassword123!";
|
||||
|
||||
int TestCryptoProtectMemory(int argc, char* argv[])
|
||||
{
|
||||
int cbPlainText;
|
||||
int cbCipherText;
|
||||
char* pPlainText;
|
||||
BYTE* pCipherText;
|
||||
|
||||
pPlainText = (char*) SECRET_PASSWORD_TEST;
|
||||
cbPlainText = strlen(pPlainText) + 1;
|
||||
|
||||
cbCipherText = cbPlainText + (CRYPTPROTECTMEMORY_BLOCK_SIZE - (cbPlainText % CRYPTPROTECTMEMORY_BLOCK_SIZE));
|
||||
printf("cbPlainText: %d cbCipherText: %d\n", cbPlainText, cbCipherText);
|
||||
|
||||
pCipherText = (BYTE*) malloc(cbCipherText);
|
||||
CopyMemory(pCipherText, pPlainText, cbPlainText);
|
||||
ZeroMemory(&pCipherText[cbPlainText], (cbCipherText - cbPlainText));
|
||||
|
||||
if (!CryptProtectMemory(pCipherText, cbCipherText, CRYPTPROTECTMEMORY_SAME_PROCESS))
|
||||
{
|
||||
printf("CryptProtectMemory failure\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("PlainText: %s (cbPlainText = %d, cbCipherText = %d)\n", pPlainText, cbPlainText, cbCipherText);
|
||||
|
||||
winpr_HexDump(pCipherText, cbCipherText);
|
||||
|
||||
if (!CryptUnprotectMemory(pCipherText, cbCipherText, CRYPTPROTECTMEMORY_SAME_PROCESS))
|
||||
{
|
||||
printf("CryptUnprotectMemory failure\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("Decrypted CipherText: %s\n", pCipherText);
|
||||
|
||||
SecureZeroMemory(pCipherText, cbCipherText);
|
||||
free(pCipherText);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue