105 lines
4.0 KiB
C
105 lines
4.0 KiB
C
![]() |
/*
|
||
|
* Copyright 2005 Kees Cook <kees@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
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*
|
||
|
* 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 <stdarg.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#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;
|
||
|
};
|