crypt32: CryptProtectData/CryptUnprotectData take 2
Kees Cook
kees at outflux.net
Mon Apr 4 13:06:47 CDT 2005
ChangeLog:
Black-box implementation of CryptProtectData/CryptUnprotectData.
Here is an updated patch with various recommendations implemented.
--
Kees Cook @outflux.net
-------------- next part --------------
Index: dlls/crypt32/Makefile.in
===================================================================
RCS file: /home/wine/wine/dlls/crypt32/Makefile.in,v
retrieving revision 1.8
diff -u -p -u -p -r1.8 Makefile.in
--- dlls/crypt32/Makefile.in 1 Mar 2004 21:19:37 -0000 1.8
+++ dlls/crypt32/Makefile.in 4 Apr 2005 17:55:23 -0000
@@ -8,6 +8,7 @@ IMPORTS = advapi32 kernel32
C_SRCS = \
cert.c \
+ protectdata.c \
main.c
@MAKE_DLL_RULES@
Index: dlls/crypt32/crypt32.spec
===================================================================
RCS file: /home/wine/wine/dlls/crypt32/crypt32.spec,v
retrieving revision 1.19
diff -u -p -u -p -r1.19 crypt32.spec
--- dlls/crypt32/crypt32.spec 10 Nov 2004 01:31:50 -0000 1.19
+++ dlls/crypt32/crypt32.spec 4 Apr 2005 17:55:23 -0000
@@ -133,6 +133,7 @@
@ stub CryptMsgUpdate
@ stub CryptMsgVerifyCountersignatureEncoded
@ stdcall CryptProtectData(ptr wstr ptr ptr ptr long ptr)
+@ stdcall CryptUnprotectData(ptr ptr ptr ptr ptr long ptr)
@ stdcall CryptRegisterDefaultOIDFunction(long str long wstr)
@ stdcall CryptRegisterOIDFunction(long str str wstr str)
@ stub CryptRegisterOIDInfo
@@ -149,7 +150,6 @@
@ stub CryptSignHashU
@ stub CryptSignMessage
@ stub CryptSignMessageWithKey
-@ stub CryptUnprotectData
@ stub CryptUnregisterDefaultOIDFunction
@ stub CryptUnregisterOIDFunction
@ stub CryptUnregisterOIDInfo
Index: dlls/crypt32/main.c
===================================================================
RCS file: /home/wine/wine/dlls/crypt32/main.c,v
retrieving revision 1.19
diff -u -p -u -p -r1.19 main.c
--- dlls/crypt32/main.c 30 Nov 2004 21:39:00 -0000 1.19
+++ dlls/crypt32/main.c 4 Apr 2005 17:55:23 -0000
@@ -56,14 +56,6 @@ BOOL WINAPI I_CryptFreeLruCache(DWORD x)
return FALSE;
}
-BOOL WINAPI CryptProtectData(DATA_BLOB* pDataIn, LPCWSTR szDataDescr, DATA_BLOB* pOptionalEntropy,
- PVOID pvReserved, CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
- DWORD dwFlags, DATA_BLOB* pDataOut)
-{
- FIXME("stub!\n");
- return FALSE;
-}
-
BOOL WINAPI CryptSIPRemoveProvider(GUID *pgProv)
{
FIXME("stub!\n");
--- /dev/null 2005-02-11 19:52:11.491673144 -0800
+++ dlls/crypt32/protectdata.c 2005-04-04 10:52:29.268502372 -0700
@@ -0,0 +1,654 @@
+/*
+ * Copyright 2005 Kees Cook <kees at outflux.net>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include "config.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "wincrypt.h"
+#include "winreg.h"
+#include "winnls.h"
+#include "mssip.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(crypt);
+
+#define CRYPT_MAX_REGISTRY_NAME_LENGTH 255
+static const WCHAR wszProtectDataMap[] = {
+ 'S','o','f','t','w','a','r','e','\\',
+ 'W','i','n','e','\\',
+ 'C','r','y','p','t','\\',
+ 'P','r','o','t','e','c','t','D','a','t','a','\\',
+ 'M','a','p',
+ 0};
+static const WCHAR wszCipher[] = {'C','i','p','h','e','r',0};
+static const WCHAR wszPlain[] = {'P','l','a','i','n',0};
+static const WCHAR wszEntropy[] = {'E','n','t','r','o','p','y',0};
+static const WCHAR wszDataDescr[] = {'D','a','t','a','D','e','s','c','r',0};
+
+/*
+ * The Win32 CryptProtectData and CryptUnprotectData functions are meant
+ * to provide a mechanism for encrypting data on a machine where other users
+ * of the system can't be trusted. It is used in many examples as a way
+ * to store username and password information to the registry, but store
+ * it not in the clear.
+ *
+ * The encryption is symmetric, but the method is unknown. However, since
+ * it is keyed to the machine and the user, it is unlikely that the values
+ * would be portable. Since programs must first call CryptProtectData to
+ * get a cipher text, the underlying system just has to track the
+ * plain/entropy/cipher triplet to be able to return the plain text on a
+ * later call to CryptUnprotectData.
+ *
+ * These functions DO NOT encrypt the data, but rather, track the calls
+ * in the registry, so that programs that rely on this mechanism will
+ * still function. Some programs refuse to run unless they can successfully
+ * call CryptProtectData and CryptUnprotectData, getting the expected values
+ * back.
+ *
+ * To store the triplets, these functions use the registry:
+ *
+ * Registry Layout:
+ * HKEY_CURRENT_USER\Software\Wine\Crypt\ProtectData\Map\[index]
+ * Cipher: HEX string
+ * Entropy: HEX string
+ * DataDescription: WCHAR
+ * Plain: HEX string
+ *
+ * If a call is made to CryptUnprotectData for an unknown cipher/entropy
+ * pair, a new registry entry is created with a plain text of "[unknown]".
+ *
+ */
+
+
+
+/*
+ * Top-level searching function, which uses a callback to evaluate
+ * if a given registry item matches. If the callback returns TRUE,
+ * this function stores the dwMaxValueLen & hkey, and returns TRUE.
+ * It is up to the caller to close the open registry item hkey.
+ */
+static BOOL
+crypt_search_registry(HKEY *phkeyOut,
+ DWORD *pMaxValueLen,
+ BOOL (*reg_match_callback)(HKEY hkey,
+ DWORD maxValueLen,
+ DATA_BLOB *pDataMatch,
+ DATA_BLOB *pOptionalEntropy),
+ DATA_BLOB *pDataToMatch,
+ DATA_BLOB *pOptionalEntropy)
+{
+ LONG r;
+ HKEY hkeyMap = NULL;
+ BOOL bFound = FALSE;
+ DWORD dwIndex;
+
+ TRACE("called\n");
+
+ if (!pDataToMatch || !phkeyOut || !reg_match_callback)
+ return FALSE;
+
+ r = RegOpenKeyExW(HKEY_CURRENT_USER, wszProtectDataMap, 0, KEY_READ, &hkeyMap);
+ if (r != ERROR_SUCCESS)
+ {
+ ERR("ProtectData registry not found\n");
+ return FALSE;
+ }
+
+ for (dwIndex = 0; !bFound; dwIndex++)
+ {
+ HKEY hkeyIndex;
+ WCHAR wszIndexKey[CRYPT_MAX_REGISTRY_NAME_LENGTH];
+ DWORD dwIndexKeyLength=CRYPT_MAX_REGISTRY_NAME_LENGTH;
+ DWORD dwMaxValueLen;
+
+ r = RegEnumKeyExW(hkeyMap, dwIndex, wszIndexKey, &dwIndexKeyLength, NULL, NULL, NULL, NULL);
+ if (r != ERROR_SUCCESS)
+ break;
+ r = RegOpenKeyExW(hkeyMap, wszIndexKey, 0, KEY_READ, &hkeyIndex);
+ if (r != ERROR_SUCCESS)
+ break;
+
+ /* don't want the function-name prefixing from "TRACE" */
+ if (WINE_TRACE_ON(crypt))
+ wine_dbg_printf("\tChecking Map Index %s\n", debugstr_w(wszIndexKey));
+
+ r = RegQueryInfoKeyW(hkeyIndex, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxValueLen, NULL, NULL);
+ if (r != ERROR_SUCCESS)
+ {
+ CloseHandle(hkeyIndex);
+ break;
+ }
+
+ if (reg_match_callback(hkeyIndex,dwMaxValueLen,
+ pDataToMatch,pOptionalEntropy))
+ {
+ bFound=TRUE;
+ if (phkeyOut) *phkeyOut=hkeyIndex;
+ if (pMaxValueLen) *pMaxValueLen=dwMaxValueLen;
+ }
+ else
+ {
+ CloseHandle(hkeyIndex);
+ }
+ }
+
+ if (!bFound)
+ {
+ TRACE("no matches\n");
+ }
+
+ CloseHandle(hkeyMap);
+ return bFound;
+}
+
+
+/*
+ * Utility function for matching Entropy against a given registry item.
+ */
+static BOOL
+crypt_reg_match_entropy(HKEY hkeyIndex,
+ DWORD maxValueLen,
+ DATA_BLOB *pOptionalEntropy)
+{
+ /* assume that lack of Entropy means "match" */
+ if (pOptionalEntropy)
+ {
+ LONG r;
+ BYTE * pbValue;
+ DWORD dwValueLen;
+
+ dwValueLen = maxValueLen;
+ pbValue = HeapAlloc(GetProcessHeap(), 0, maxValueLen);
+
+ r = RegQueryValueExW(hkeyIndex, wszEntropy, NULL, NULL, pbValue, &dwValueLen);
+ if (r != ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, pbValue);
+ return FALSE;
+ }
+
+ /* Does the Entropy match? */
+ if (dwValueLen!=pOptionalEntropy->cbData ||
+ memcmp(pOptionalEntropy->pbData,pbValue,dwValueLen))
+ {
+ HeapFree(GetProcessHeap(), 0, pbValue);
+ return FALSE;
+ }
+
+ HeapFree(GetProcessHeap(), 0, pbValue);
+ }
+
+ /* don't want the function-name prefix that "TRACE" writes */
+ if (WINE_TRACE_ON(crypt))
+ wine_dbg_printf("\tEntropy matched\n");
+ return TRUE;
+}
+
+/*
+ * registry matching callback for plain-text searches. This is used
+ * to find already "encrypted" items.
+ */
+static BOOL crypt_reg_callback_match_plain(HKEY hkeyIndex,
+ DWORD maxValueLen,
+ DATA_BLOB *pDataMatch,
+ DATA_BLOB *pOptionalEntropy)
+{
+ LONG r;
+ BYTE * pbValue;
+ DWORD dwValueLen;
+
+ if (!pDataMatch)
+ return FALSE;
+
+ pbValue = HeapAlloc(GetProcessHeap(), 0, maxValueLen);
+
+ dwValueLen = maxValueLen;
+ r = RegQueryValueExW(hkeyIndex, wszPlain, NULL, NULL, pbValue, &dwValueLen);
+ if (r != ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, pbValue);
+ return FALSE;
+ }
+
+ /* Does the Plain match? */
+ if (dwValueLen!=pDataMatch->cbData ||
+ memcmp(pDataMatch->pbData,pbValue,dwValueLen))
+ {
+ HeapFree(GetProcessHeap(), 0, pbValue);
+ return FALSE;
+ }
+ /* don't want the function-name prefix that "TRACE" writes */
+ if (WINE_TRACE_ON(crypt))
+ wine_dbg_printf("\tPlain matched\n");
+
+ HeapFree(GetProcessHeap(), 0, pbValue);
+
+ if (!crypt_reg_match_entropy(hkeyIndex,maxValueLen,pOptionalEntropy))
+ return FALSE;
+
+ return TRUE;
+}
+
+/*
+ * registry matching callback for cipher-text searches. This is used
+ * to find "encrypted" items based on their cipher text.
+ * One thing different here is that cipher may sometimes be NULL padded
+ * if they are unexpectedly small (<256 bytes).
+ */
+static BOOL crypt_reg_callback_match_cipher(HKEY hkeyIndex,
+ DWORD maxValueLen,
+ DATA_BLOB *pDataMatch,
+ DATA_BLOB *pOptionalEntropy)
+{
+ LONG r;
+ BYTE * pbValue;
+ DWORD dwValueLen;
+
+ if (!pDataMatch)
+ return FALSE;
+
+ /* Need to NULL-pad ciphers */
+ if (maxValueLen<pDataMatch->cbData)
+ maxValueLen=pDataMatch->cbData;
+ pbValue = HeapAlloc(GetProcessHeap(), 0, maxValueLen);
+
+ dwValueLen = maxValueLen;
+ r = RegQueryValueExW(hkeyIndex, wszCipher, NULL, NULL, pbValue, &dwValueLen);
+ if (r != ERROR_SUCCESS)
+ {
+ HeapFree(GetProcessHeap(), 0, pbValue);
+ return FALSE;
+ }
+ /* Perform NULL padding */
+ for (; dwValueLen<pDataMatch->cbData; dwValueLen++)
+ pbValue[dwValueLen]=0;
+
+ /* Does the Cipher match? */
+ if (dwValueLen!=pDataMatch->cbData ||
+ memcmp(pDataMatch->pbData,pbValue,dwValueLen))
+ {
+ HeapFree(GetProcessHeap(), 0, pbValue);
+ return FALSE;
+ }
+
+ /* don't want the function-name prefix that "TRACE" writes */
+ if (WINE_TRACE_ON(crypt))
+ wine_dbg_printf("\tCipher matched\n");
+
+ HeapFree(GetProcessHeap(), 0, pbValue);
+
+ if (!crypt_reg_match_entropy(hkeyIndex,maxValueLen,pOptionalEntropy))
+ return FALSE;
+
+ return TRUE;
+}
+
+static BOOL
+crypt_find_cipher_by_plain(DATA_BLOB* pDataOut, DATA_BLOB* pDataIn,
+ DATA_BLOB* pOptionalEntropy, LPCWSTR szDataDescr)
+{
+ LONG r;
+ HKEY hkeyIndex;
+ DWORD maxValueLen;
+ DWORD dwValueLen;
+ BYTE * pbValue;
+ BOOL result=FALSE;
+
+ TRACE("called\n");
+
+ if (!crypt_search_registry(&hkeyIndex,&maxValueLen,
+ crypt_reg_callback_match_plain,
+ pDataIn,pOptionalEntropy))
+ {
+ return result;
+ }
+ /* found the registry entry */
+
+ pbValue = HeapAlloc(GetProcessHeap(), 0, maxValueLen);
+
+ dwValueLen = maxValueLen;
+ r = RegQueryValueExW(hkeyIndex, wszCipher, NULL, NULL, pbValue, &dwValueLen);
+ if (r == ERROR_SUCCESS)
+ {
+ /* make a copy of the cipher text */
+ pDataOut->cbData=dwValueLen;
+ pDataOut->pbData=LocalAlloc(LPTR,pDataOut->cbData);
+ memcpy(pDataOut->pbData,pbValue,pDataOut->cbData);
+
+ result=TRUE;
+ }
+ else
+ {
+ ERR("\tCipher value not found\n");
+ }
+
+ HeapFree(GetProcessHeap(), 0, pbValue);
+ CloseHandle(hkeyIndex);
+ return result;
+}
+
+static BOOL
+crypt_find_plain_by_cipher(DATA_BLOB* pDataOut, LPWSTR *ppszDataDescr,
+ DATA_BLOB* pDataIn, DATA_BLOB* pOptionalEntropy)
+{
+ LONG r;
+ HKEY hkeyIndex;
+ DWORD maxValueLen;
+ DWORD dwValueLen;
+ BYTE * pbValue;
+ BOOL result=FALSE;
+
+ TRACE("called\n");
+
+ if (!crypt_search_registry(&hkeyIndex,&maxValueLen,
+ crypt_reg_callback_match_cipher,
+ pDataIn,pOptionalEntropy))
+ {
+ return result;
+ }
+ /* found the registry entry */
+
+ pbValue = HeapAlloc(GetProcessHeap(), 0, maxValueLen);
+
+ dwValueLen = maxValueLen;
+ r = RegQueryValueExW(hkeyIndex, wszPlain, NULL, NULL, pbValue, &dwValueLen);
+ if (r == ERROR_SUCCESS)
+ {
+ /* copy the plain text */
+ pDataOut->cbData=dwValueLen;
+ pDataOut->pbData=LocalAlloc(LPTR,pDataOut->cbData);
+ memcpy(pDataOut->pbData,pbValue,pDataOut->cbData);
+
+ /* copy the DataDescription */
+ if (ppszDataDescr)
+ {
+ dwValueLen = maxValueLen;
+ r = RegQueryValueExW(hkeyIndex, wszDataDescr, NULL, NULL, pbValue, &dwValueLen);
+ if (r != ERROR_SUCCESS)
+ {
+ /* if we don't have one stored, just return an empty string */
+ dwValueLen=2;
+ pbValue[0]='\0';
+ }
+
+ *ppszDataDescr=LocalAlloc(LPTR,dwValueLen);
+ memcpy(*ppszDataDescr,pbValue,dwValueLen);
+ }
+
+ result = TRUE;
+ }
+ else
+ {
+ ERR("\tPlain value not found\n");
+ }
+
+ HeapFree(GetProcessHeap(), 0, pbValue);
+ CloseHandle(hkeyIndex);
+ return result;
+}
+
+/*
+ * Creates a registry value, falling back to a string default.
+ * If fallback happens, the stored value is written to pDataOut
+ * if it isn't NULL
+ */
+static BOOL
+crypt_write_registry_value(HKEY hkeyOpen,
+ const WCHAR * wszName,
+ DWORD dwType,
+ DATA_BLOB *pDataIn,
+ WCHAR * wszDefault,
+ DATA_BLOB *pDataOut)
+{
+ LONG r;
+ DATA_BLOB pData;
+
+ if (pDataIn)
+ {
+ pData.pbData=pDataIn->pbData;
+ pData.cbData=pDataIn->cbData;
+ }
+ else
+ {
+ pData.pbData=(void*)wszDefault;
+ pData.cbData=(lstrlenW(wszDefault)+1)*sizeof(WCHAR);
+
+ if (pDataOut)
+ {
+ pDataOut->cbData=pData.cbData;
+ pDataOut->pbData=LocalAlloc(LPTR,pDataOut->cbData);
+ memcpy(pDataOut->pbData,pData.pbData,pData.cbData);
+ }
+ }
+
+ r = RegSetValueExW(hkeyOpen,wszName,0,dwType, pData.pbData,pData.cbData);
+ return (r == ERROR_SUCCESS);
+}
+
+static BOOL
+crypt_create_registry_item(DATA_BLOB *pDataCipher,
+ DATA_BLOB *pDataPlain,
+ DATA_BLOB *pOptionalEntropy,
+ WCHAR * szDataDescr,
+ DATA_BLOB *pDataOut)
+{
+ LONG r;
+ BOOL okay=TRUE;
+ BOOL bFound=FALSE;
+ HKEY hkeyMap;
+ DWORD dwIndex;
+ HKEY hkeyOpen;
+ WCHAR wszIndexKey[CRYPT_MAX_REGISTRY_NAME_LENGTH];
+ WCHAR wszUnknown[] = {'[','u','n','k','n','o','w','n',']',0};
+
+ r = RegOpenKeyExW(HKEY_CURRENT_USER, wszProtectDataMap, 0, KEY_ALL_ACCESS, &hkeyMap);
+ if (r != ERROR_SUCCESS)
+ {
+ ERR("ProtectData registry not found\n");
+ return FALSE;
+ }
+
+ /* set our search limit to 1024, arbitrarily */
+ for (dwIndex = 0; !bFound && dwIndex<1024; dwIndex++)
+ {
+ DWORD dwDisposition;
+ int i, len;
+ char buf[CRYPT_MAX_REGISTRY_NAME_LENGTH];
+ sprintf(buf,"%u",(unsigned int)dwIndex);
+ len=strlen(buf)+1;
+ for (i=0; i<len; i++) {
+ wszIndexKey[i]=buf[i];
+ }
+
+ r = RegCreateKeyExW(hkeyMap, wszIndexKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkeyOpen, &dwDisposition);
+ if (r != ERROR_SUCCESS)
+ continue;
+ if (dwDisposition == REG_OPENED_EXISTING_KEY)
+ {
+ /* already exists, skip */
+ CloseHandle(hkeyOpen);
+ continue;
+ }
+
+ bFound=TRUE;
+ }
+ CloseHandle(hkeyMap);
+
+ if (!bFound)
+ {
+ ERR("Cannot find room for new ProtectData registry item\n");
+ return FALSE;
+ }
+
+ if (!crypt_write_registry_value(hkeyOpen, wszCipher, REG_BINARY,
+ pDataCipher, wszIndexKey, pDataOut))
+ okay=FALSE;
+ if (!crypt_write_registry_value(hkeyOpen, wszPlain, REG_BINARY,
+ pDataPlain, wszUnknown, pDataOut))
+ okay=FALSE;
+ if (szDataDescr)
+ {
+ if (!crypt_write_registry_value(hkeyOpen, wszDataDescr, REG_SZ,
+ NULL, szDataDescr, NULL))
+ okay=FALSE;
+ }
+ if (pOptionalEntropy)
+ {
+ if (!crypt_write_registry_value(hkeyOpen, wszEntropy, REG_BINARY,
+ pOptionalEntropy, NULL, NULL))
+ okay=FALSE;
+ }
+
+ CloseHandle(hkeyOpen);
+ return okay;
+}
+
+
+static BOOL
+crypt_create_cipher_from_plain(DATA_BLOB* pDataOut, DATA_BLOB* pDataIn,
+ DATA_BLOB* pOptionalEntropy, LPCWSTR szDataDescr)
+{
+ TRACE("called\n");
+
+ return crypt_create_registry_item(NULL,pDataIn,pOptionalEntropy,(WCHAR*)szDataDescr,pDataOut);
+}
+
+static void
+crypt_create_unknown_from_cipher(DATA_BLOB * pDataIn,
+ DATA_BLOB* pOptionalEntropy)
+{
+ TRACE("called\n");
+
+ crypt_create_registry_item(pDataIn,NULL,pOptionalEntropy,NULL,NULL);
+}
+
+static int
+hexprint(const char *s, unsigned char *p, int n)
+{
+ char report[80];
+ int r=-1;
+ snprintf(report,16,"%14s:", s);
+ while (--n >= 0)
+ {
+ if (r++ % 20 == 19)
+ {
+ wine_dbg_printf("%s\n",report);
+ snprintf(report,16,"%14s ", "");
+ }
+ sprintf(report+strlen(report)," %02x", *p++);
+ }
+ wine_dbg_printf("%s\n",report);
+ return 0;
+}
+
+static void
+crypt_report_func_input(DATA_BLOB* pDataIn,
+ DATA_BLOB* pOptionalEntropy,
+ CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
+ DWORD dwFlags)
+{
+ wine_dbg_printf("\tpPromptStruct: 0x%x\n",(unsigned int)pPromptStruct);
+ if (pPromptStruct)
+ {
+ wine_dbg_printf("\t\tcbSize: 0x%x\n",(unsigned int)pPromptStruct->cbSize);
+ wine_dbg_printf("\t\tdwPromptFlags: 0x%x\n",(unsigned int)pPromptStruct->dwPromptFlags);
+ wine_dbg_printf("\t\thwndApp: 0x%x\n",(unsigned int)pPromptStruct->hwndApp);
+ wine_dbg_printf("\t\tszPrompt: 0x%x %s\n",
+ (unsigned int)pPromptStruct->szPrompt,
+ pPromptStruct->szPrompt ? debugstr_w(pPromptStruct->szPrompt)
+ : "");
+ }
+ wine_dbg_printf("\tdwFlags: 0x%04x\n",(unsigned int)dwFlags);
+ wine_dbg_printf("\tpDataIn->cbData: %u\n",(unsigned int)pDataIn->cbData);
+ hexprint("pbData", pDataIn->pbData, pDataIn->cbData);
+ if (pOptionalEntropy)
+ {
+ wine_dbg_printf("\tpOptionalEntropy->cbData: %u\n",(unsigned int)pOptionalEntropy->cbData);
+ hexprint("pbData", pOptionalEntropy->pbData, pOptionalEntropy->cbData);
+ wine_dbg_printf("\t\t%s\n",debugstr_an(pOptionalEntropy->pbData,pOptionalEntropy->cbData));
+ }
+
+}
+
+BOOL WINAPI CryptProtectData(DATA_BLOB* pDataIn,
+ LPCWSTR szDataDescr,
+ DATA_BLOB* pOptionalEntropy,
+ PVOID pvReserved,
+ CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
+ DWORD dwFlags,
+ DATA_BLOB* pDataOut)
+{
+ TRACE("called\n");
+
+ if (WINE_TRACE_ON(crypt))
+ {
+ crypt_report_func_input(pDataIn,pOptionalEntropy,pPromptStruct,dwFlags);
+ wine_dbg_printf("\tszDataDescr: 0x%x %s\n",(unsigned int)szDataDescr,
+ szDataDescr ? debugstr_w(szDataDescr) : "");
+ }
+
+ if (crypt_find_cipher_by_plain(pDataOut, pDataIn, pOptionalEntropy, szDataDescr))
+ {
+ return TRUE;
+ }
+ if (crypt_create_cipher_from_plain(pDataOut, pDataIn, pOptionalEntropy, szDataDescr))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL WINAPI CryptUnprotectData(DATA_BLOB* pDataIn,
+ LPWSTR * ppszDataDescr,
+ DATA_BLOB* pOptionalEntropy,
+ PVOID pvReserved,
+ CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
+ DWORD dwFlags,
+ DATA_BLOB* pDataOut)
+{
+ TRACE("called\n");
+
+ if (WINE_TRACE_ON(crypt)) {
+ crypt_report_func_input(pDataIn,pOptionalEntropy,pPromptStruct,dwFlags);
+ wine_dbg_printf("\tppszDataDescr: 0x%x\n",(unsigned int)ppszDataDescr);
+ }
+
+ if (crypt_find_plain_by_cipher(pDataOut, ppszDataDescr, pDataIn, pOptionalEntropy))
+ {
+ if (WINE_TRACE_ON(crypt))
+ {
+ if (ppszDataDescr)
+ {
+ wine_dbg_printf("\tszDataDescr: %s\n",debugstr_w(*ppszDataDescr));
+ }
+ wine_dbg_printf("\tpDataOut->cbData: %u\n",(unsigned int)pDataOut->cbData);
+ hexprint("pbData", pDataOut->pbData, pDataOut->cbData);
+ }
+ return TRUE;
+ }
+ /* Record the cipher and entropy for the future */
+ crypt_create_unknown_from_cipher(pDataIn, pOptionalEntropy);
+
+ return FALSE;
+}
+
+
More information about the wine-patches
mailing list