diff --git a/dlls/crypt32/Makefile.in b/dlls/crypt32/Makefile.in index 604188c217e..feb83619f04 100644 --- a/dlls/crypt32/Makefile.in +++ b/dlls/crypt32/Makefile.in @@ -9,6 +9,7 @@ IMPORTS = advapi32 kernel32 C_SRCS = \ cert.c \ + protectdata.c \ main.c @MAKE_DLL_RULES@ diff --git a/dlls/crypt32/protectdata.c b/dlls/crypt32/protectdata.c new file mode 100644 index 00000000000..2cfac2f2712 --- /dev/null +++ b/dlls/crypt32/protectdata.c @@ -0,0 +1,104 @@ +/* + * Copyright 2005 Kees Cook + * + * 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 + */ + + +/* + * 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 doesn't have to exactly + * match the real Windows version. However, attempts have been made to + * at least try to look like the Windows version, including guesses at the + * purpose of various portions of the "opaque data blob" that is used. + * + */ + +#include +#include +#include +#include + +#include "windef.h" +#include "winbase.h" +#include "wincrypt.h" +#include "winreg.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(crypt); + +#define CRYPT32_PROTECTDATA_PROV PROV_RSA_FULL +#define CRYPT32_PROTECTDATA_HASH_CALG CALG_MD5 +#define CRYPT32_PROTECTDATA_KEY_CALG CALG_RC2 +#define CRYPT32_PROTECTDATA_SALT_LEN 16 + +#define CRYPT32_PROTECTDATA_SECRET "I'm hunting wabbits" + +/* + * The data format returned by the real Windows CryptProtectData seems + * to be something like this: + + DWORD count0; - how many "info0_*[16]" blocks follow (was always 1) + BYTE info0_0[16]; - unknown information + ... + DWORD count1; - how many "info1_*[16]" blocks follow (was always 1) + BYTE info1_0[16]; - unknown information + ... + DWORD null0; - NULL "end of records"? + DWORD str_len; - length of WCHAR string including term + WCHAR str[str_len]; - The "dataDescription" value + DWORD unknown0; - unknown value (seems large, but only WORD large) + DWORD unknown1; - unknown value (seems small, less than a BYTE) + DWORD data_len; - length of data (was 16 in samples) + BYTE data[data_len]; - unknown data (fingerprint?) + DWORD null1; - NULL ? + DWORD unknown2; - unknown value (seems large, but only WORD large) + DWORD unknown3; - unknown value (seems small, less than a BYTE) + DWORD salt_len; - length of salt(?) data + BYTE salt[salt_len]; - salt(?) for symmetric encryption + DWORD cipher_len; - length of cipher(?) data - was close to plain len + BYTE cipher[cipher_len]; - cipher text? + DWORD crc_len; - length of fingerprint(?) data - was 20 byte==160b SHA1 + BYTE crc[crc_len]; - fingerprint of record? + + * The data structures used in Wine are modelled after this guess. + */ + +struct protect_data_t +{ + DWORD count0; + DATA_BLOB info0; /* using this to hold crypt_magic_str */ + DWORD count1; + DATA_BLOB info1; + DWORD null0; + WCHAR * szDataDescr; /* serialized differently than the DATA_BLOBs */ + DWORD unknown0; /* perhaps the HASH alg const should go here? */ + DWORD unknown1; + DATA_BLOB data0; + DWORD null1; + DWORD unknown2; /* perhaps the KEY alg const should go here? */ + DWORD unknown3; + DATA_BLOB salt; + DATA_BLOB cipher; + DATA_BLOB fingerprint; +};