📄 protectdata.c
字号:
if (rc && !CryptDeriveKey(hProv,CRYPT32_PROTECTDATA_KEY_CALG,
hSaltHash,CRYPT_EXPORTABLE,phKey))
{
ERR("CryptDeriveKey\n");
rc = FALSE;
}
/* clean up */
CryptDestroyHash(hSaltHash);
CryptMemFree(szUsername);
return rc;
}
/* debugging tool to print the structures of a ProtectData call */
static void
report(const DATA_BLOB* pDataIn, const DATA_BLOB* pOptionalEntropy,
CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags)
{
TRACE("pPromptStruct: %p\n", pPromptStruct);
if (pPromptStruct)
{
TRACE(" cbSize: 0x%x\n",(unsigned int)pPromptStruct->cbSize);
TRACE(" dwPromptFlags: 0x%x\n",(unsigned int)pPromptStruct->dwPromptFlags);
TRACE(" hwndApp: %p\n", pPromptStruct->hwndApp);
TRACE(" szPrompt: %p %s\n",
pPromptStruct->szPrompt,
pPromptStruct->szPrompt ? debugstr_w(pPromptStruct->szPrompt)
: "");
}
TRACE("dwFlags: 0x%04x\n",(unsigned int)dwFlags);
TRACE_DATA_BLOB(pDataIn);
if (pOptionalEntropy)
{
TRACE_DATA_BLOB(pOptionalEntropy);
TRACE(" %s\n",debugstr_an((LPCSTR)pOptionalEntropy->pbData,pOptionalEntropy->cbData));
}
}
/***************************************************************************
* CryptProtectData [CRYPT32.@]
*
* Generate Cipher data from given Plain and Entropy data.
*
* PARAMS
* pDataIn [I] Plain data to be enciphered
* szDataDescr [I] Optional Unicode string describing the Plain data
* pOptionalEntropy [I] Optional entropy data to adjust cipher, can be NULL
* pvReserved [I] Reserved, must be NULL
* pPromptStruct [I] Structure describing if/how to prompt during ciphering
* dwFlags [I] Flags describing options to the ciphering
* pDataOut [O] Resulting Cipher data, for calls to CryptUnprotectData
*
* RETURNS
* TRUE If a Cipher was generated.
* FALSE If something failed and no Cipher is available.
*
* FIXME
* The true Windows encryption and keying mechanisms are unknown.
*
* dwFlags and pPromptStruct are currently ignored.
*
* NOTES
* Memory allocated in pDataOut must be freed with LocalFree.
*
*/
BOOL WINAPI CryptProtectData(DATA_BLOB* pDataIn,
LPCWSTR szDataDescr,
DATA_BLOB* pOptionalEntropy,
PVOID pvReserved,
CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
DWORD dwFlags,
DATA_BLOB* pDataOut)
{
static const WCHAR empty_str[1];
BOOL rc = FALSE;
HCRYPTPROV hProv;
struct protect_data_t protect_data;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD dwLength;
TRACE("called\n");
SetLastError(ERROR_SUCCESS);
if (!pDataIn || !pDataOut)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto finished;
}
/* debug: show our arguments */
report(pDataIn,pOptionalEntropy,pPromptStruct,dwFlags);
TRACE("\tszDataDescr: %p %s\n", szDataDescr,
szDataDescr ? debugstr_w(szDataDescr) : "");
/* Windows appears to create an empty szDataDescr instead of maintaining
* a NULL */
if (!szDataDescr)
szDataDescr = empty_str;
/* get crypt context */
if (!CryptAcquireContextW(&hProv,NULL,NULL,CRYPT32_PROTECTDATA_PROV,CRYPT_VERIFYCONTEXT))
{
ERR("CryptAcquireContextW failed\n");
goto finished;
}
/* populate our structure */
if (!fill_protect_data(&protect_data,szDataDescr,hProv))
{
ERR("fill_protect_data\n");
goto free_context;
}
/* load key */
if (!load_encryption_key(hProv,&protect_data.salt,pOptionalEntropy,&hKey))
{
goto free_protect_data;
}
/* create a hash for the encryption validation */
if (!CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hHash))
{
ERR("CryptCreateHash\n");
goto free_key;
}
/* calculate storage required */
dwLength=pDataIn->cbData;
if (CryptEncrypt(hKey, 0, TRUE, 0, pDataIn->pbData, &dwLength, 0) ||
GetLastError()!=ERROR_MORE_DATA)
{
ERR("CryptEncrypt\n");
goto free_hash;
}
TRACE("required encrypted storage: %u\n",(unsigned int)dwLength);
/* copy plain text into cipher area for CryptEncrypt call */
protect_data.cipher.cbData=dwLength;
if (!(protect_data.cipher.pbData=CryptMemAlloc(
protect_data.cipher.cbData)))
{
ERR("CryptMemAlloc\n");
goto free_hash;
}
memcpy(protect_data.cipher.pbData,pDataIn->pbData,pDataIn->cbData);
/* encrypt! */
dwLength=pDataIn->cbData;
if (!CryptEncrypt(hKey, hHash, TRUE, 0, protect_data.cipher.pbData,
&dwLength, protect_data.cipher.cbData))
{
ERR("CryptEncrypt %u\n",(unsigned int)GetLastError());
goto free_hash;
}
protect_data.cipher.cbData=dwLength;
/* debug: show the cipher */
TRACE_DATA_BLOB(&protect_data.cipher);
/* attach our fingerprint */
if (!convert_hash_to_blob(hHash, &protect_data.fingerprint))
{
ERR("convert_hash_to_blob\n");
goto free_hash;
}
/* serialize into an opaque blob */
if (!serialize(&protect_data, pDataOut))
{
ERR("serialize\n");
goto free_hash;
}
/* success! */
rc=TRUE;
free_hash:
CryptDestroyHash(hHash);
free_key:
CryptDestroyKey(hKey);
free_protect_data:
free_protect_data(&protect_data);
free_context:
CryptReleaseContext(hProv,0);
finished:
/* If some error occurred, and no error code was set, force one. */
if (!rc && GetLastError()==ERROR_SUCCESS)
{
SetLastError(ERROR_INVALID_DATA);
}
if (rc)
{
SetLastError(ERROR_SUCCESS);
TRACE_DATA_BLOB(pDataOut);
}
TRACE("returning %s\n", rc ? "ok" : "FAIL");
return rc;
}
/***************************************************************************
* CryptUnprotectData [CRYPT32.@]
*
* Generate Plain data and Description from given Cipher and Entropy data.
*
* PARAMS
* pDataIn [I] Cipher data to be decoded
* ppszDataDescr [O] Optional Unicode string describing the Plain data
* pOptionalEntropy [I] Optional entropy data to adjust cipher, can be NULL
* pvReserved [I] Reserved, must be NULL
* pPromptStruct [I] Structure describing if/how to prompt during decoding
* dwFlags [I] Flags describing options to the decoding
* pDataOut [O] Resulting Plain data, from calls to CryptProtectData
*
* RETURNS
* TRUE If a Plain was generated.
* FALSE If something failed and no Plain is available.
*
* FIXME
* The true Windows encryption and keying mechanisms are unknown.
*
* dwFlags and pPromptStruct are currently ignored.
*
* NOTES
* Memory allocated in pDataOut and non-NULL ppszDataDescr must be freed
* with LocalFree.
*
*/
BOOL WINAPI CryptUnprotectData(DATA_BLOB* pDataIn,
LPWSTR * ppszDataDescr,
DATA_BLOB* pOptionalEntropy,
PVOID pvReserved,
CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
DWORD dwFlags,
DATA_BLOB* pDataOut)
{
BOOL rc = FALSE;
HCRYPTPROV hProv;
struct protect_data_t protect_data;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
DWORD dwLength;
const char * announce_bad_opaque_data = "CryptUnprotectData received a DATA_BLOB that seems to have NOT been generated by Wine. Please enable tracing ('export WINEDEBUG=crypt') to see details.";
TRACE("called\n");
SetLastError(ERROR_SUCCESS);
if (!pDataIn || !pDataOut)
{
SetLastError(ERROR_INVALID_PARAMETER);
goto finished;
}
/* debug: show our arguments */
report(pDataIn,pOptionalEntropy,pPromptStruct,dwFlags);
TRACE("\tppszDataDescr: %p\n", ppszDataDescr);
/* take apart the opaque blob */
if (!unserialize(pDataIn, &protect_data))
{
SetLastError(ERROR_INVALID_DATA);
FIXME("%s\n",announce_bad_opaque_data);
goto finished;
}
/* perform basic validation on the resulting structure */
if (!valid_protect_data(&protect_data))
{
SetLastError(ERROR_INVALID_DATA);
FIXME("%s\n",announce_bad_opaque_data);
goto free_protect_data;
}
/* get a crypt context */
if (!CryptAcquireContextW(&hProv,NULL,NULL,CRYPT32_PROTECTDATA_PROV,CRYPT_VERIFYCONTEXT))
{
ERR("CryptAcquireContextW failed\n");
goto free_protect_data;
}
/* load key */
if (!load_encryption_key(hProv,&protect_data.salt,pOptionalEntropy,&hKey))
{
goto free_context;
}
/* create a hash for the decryption validation */
if (!CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hHash))
{
ERR("CryptCreateHash\n");
goto free_key;
}
/* prepare for plaintext */
pDataOut->cbData=protect_data.cipher.cbData;
if (!(pDataOut->pbData=LocalAlloc( LPTR, pDataOut->cbData)))
{
ERR("CryptMemAlloc\n");
goto free_hash;
}
memcpy(pDataOut->pbData,protect_data.cipher.pbData,protect_data.cipher.cbData);
/* decrypt! */
if (!CryptDecrypt(hKey, hHash, TRUE, 0, pDataOut->pbData,
&pDataOut->cbData) ||
/* check the hash fingerprint */
pDataOut->cbData > protect_data.cipher.cbData ||
!hash_matches_blob(hHash, &protect_data.fingerprint))
{
SetLastError(ERROR_INVALID_DATA);
LocalFree( pDataOut->pbData );
pDataOut->pbData = NULL;
pDataOut->cbData = 0;
goto free_hash;
}
/* Copy out the description */
dwLength = (lstrlenW(protect_data.szDataDescr)+1) * sizeof(WCHAR);
if (ppszDataDescr)
{
if (!(*ppszDataDescr = LocalAlloc(LPTR,dwLength)))
{
ERR("LocalAlloc (ppszDataDescr)\n");
goto free_hash;
}
else {
memcpy(*ppszDataDescr,protect_data.szDataDescr,dwLength);
}
}
/* success! */
rc = TRUE;
free_hash:
CryptDestroyHash(hHash);
free_key:
CryptDestroyKey(hKey);
free_context:
CryptReleaseContext(hProv,0);
free_protect_data:
free_protect_data(&protect_data);
finished:
/* If some error occurred, and no error code was set, force one. */
if (!rc && GetLastError()==ERROR_SUCCESS)
{
SetLastError(ERROR_INVALID_DATA);
}
if (rc) {
SetLastError(ERROR_SUCCESS);
if (ppszDataDescr)
{
TRACE("szDataDescr: %s\n",debugstr_w(*ppszDataDescr));
}
TRACE_DATA_BLOB(pDataOut);
}
TRACE("returning %s\n", rc ? "ok" : "FAIL");
return rc;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -