crypt32: CryptProtectData/CryptUnprotectData

Kees Cook kees at
Wed May 4 11:12:24 CDT 2005

On Wed, May 04, 2005 at 10:38:40AM +0200, Michael Jung wrote:
> DATA_BLOB somewhere. He also has to be able to restore in some way the 
> entropy and the description, if he wants to decrypt the DATA_BLOB at some 
> later time.

Actually, the description is returned by CryptUnprotectData (and is 
stored in the clear in the "opaque" blob).

> DATA_BLOB's are opaque by nature. Applications should not expect anything of 
> the format. So there is no benefit in trying to mimic the Windows data 
> format. (Sometimes MSDN states that a format should be considered opaque, 

Well, no, applications don't care, but Wine's implementation (and future 
implementation) of Crypt*protectData should attempt a guess at it.  This 
is what I've got so far:

 * The data format returned by CryptProtectData seems to be something like:

 DWORD  count0;         - how many "info0_*[16]" blocks follow (was always 1)
 BYTE   info0_0[16];    - unknown information (was the same between calls)
 DWORD  count1;         - how many "info1_*[16]" blocks follow (was always 1)
 BYTE   info1_0[16];    - unknown information (different between calls)
 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, same)
 DWORD  unknown1;       - unknown value (seems small, less than a BYTE, same)
 DWORD  data_len;       - length of data (was 16 bytes) md5?
 BYTE   data[data_len]; - unknown data (fingerprint? changes)
 DWORD  null1;          - NULL ? (same)
 DWORD  unknown2;       - unknown value (seems large, but only WORD large, same)
 DWORD  unknown3;       - unknown value (seems small, less than a BYTE, same)
 DWORD  salt_len;       - salt length(?) - was 16 bytes==128b md5?
 BYTE   salt[salt_len]; - salt for symmetric encryption (changes)
 DWORD  cipher_len;     - length of cipher(?) data - was close to plain 
                          len, symmetric block ciphers like 3DES are in 
                          40 byte chunks, I think
 BYTE   cipher[cipher_len]; - cipher text? (changes)
 DWORD  fingerprint_len; - length of fingerprint(?) data
 BYTE   fingerprint[fingerprint_len]; - SHA1 fingerprint(?) (20 bytes, changes) 

> Like already said, we don't have access to a hash of the user's login 
> password, so we can't provide real security here. Therefore I think we should 
> not try to pretend it. IMO you should'nt do any encryption. Just pass back 
> the DATA_BLOB.

I think what I'm going to do is use (for now) the uid appended to a 
string that includes the time.  Maybe md5 it for fun.  I really don't 
know yet.  (Before encryption, though, I have to add on the entropy.)
Something like:

> is accessible by the Crypt* family of API's in advapi32.dll. All that is 
> necessary for this to implement should be available in wine already.

Cool, that's good news.  I haven't had the chance to review that stuff 

Kees Cook                                  

More information about the wine-devel mailing list