XP returns E_INVALIDARG on failure.
[wine] / dlls / crypt32 / protectdata.c
1 /*
2  * Copyright 2005 Kees Cook <kees@outflux.net>
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17  */
18
19
20 /*
21  * The Win32 CryptProtectData and CryptUnprotectData functions are meant
22  * to provide a mechanism for encrypting data on a machine where other users
23  * of the system can't be trusted.  It is used in many examples as a way
24  * to store username and password information to the registry, but store
25  * it not in the clear.
26  *
27  * The encryption is symmetric, but the method is unknown.  However, since
28  * it is keyed to the machine and the user, it is unlikely that the values
29  * would be portable.  Since programs must first call CryptProtectData to
30  * get a cipher text, the underlying system doesn't have to exactly
31  * match the real Windows version.  However, attempts have been made to
32  * at least try to look like the Windows version, including guesses at the
33  * purpose of various portions of the "opaque data blob" that is used.
34  *
35  */
36
37 #include <stdarg.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <stdlib.h>
41
42 #include "windef.h"
43 #include "winbase.h"
44 #include "wincrypt.h"
45 #include "winreg.h"
46 #include "wine/debug.h"
47
48 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
49
50 #define CRYPT32_PROTECTDATA_PROV      PROV_RSA_FULL
51 #define CRYPT32_PROTECTDATA_HASH_CALG CALG_MD5
52 #define CRYPT32_PROTECTDATA_KEY_CALG  CALG_RC2
53 #define CRYPT32_PROTECTDATA_SALT_LEN  16
54
55 #define CRYPT32_PROTECTDATA_SECRET "I'm hunting wabbits"
56
57 /*
58  * The data format returned by the real Windows CryptProtectData seems
59  * to be something like this:
60
61  DWORD  count0;         - how many "info0_*[16]" blocks follow (was always 1)
62  BYTE   info0_0[16];    - unknown information
63  ...
64  DWORD  count1;         - how many "info1_*[16]" blocks follow (was always 1)
65  BYTE   info1_0[16];    - unknown information
66  ...
67  DWORD  null0;          - NULL "end of records"?
68  DWORD  str_len;        - length of WCHAR string including term
69  WCHAR  str[str_len];   - The "dataDescription" value
70  DWORD  unknown0;       - unknown value (seems large, but only WORD large)
71  DWORD  unknown1;       - unknown value (seems small, less than a BYTE)
72  DWORD  data_len;       - length of data (was 16 in samples)
73  BYTE   data[data_len]; - unknown data (fingerprint?)
74  DWORD  null1;          - NULL ?
75  DWORD  unknown2;       - unknown value (seems large, but only WORD large)
76  DWORD  unknown3;       - unknown value (seems small, less than a BYTE)
77  DWORD  salt_len;       - length of salt(?) data
78  BYTE   salt[salt_len]; - salt(?) for symmetric encryption
79  DWORD  cipher_len;     - length of cipher(?) data - was close to plain len
80  BYTE   cipher[cipher_len]; - cipher text?
81  DWORD  crc_len;        - length of fingerprint(?) data - was 20 byte==160b SHA1
82  BYTE   crc[crc_len];   - fingerprint of record?
83
84  * The data structures used in Wine are modelled after this guess.
85  */
86
87 struct protect_data_t
88 {
89     DWORD       count0;
90     DATA_BLOB   info0;        /* using this to hold crypt_magic_str */
91     DWORD       count1;
92     DATA_BLOB   info1;
93     DWORD       null0;
94     WCHAR *     szDataDescr;  /* serialized differently than the DATA_BLOBs */
95     DWORD       unknown0;     /* perhaps the HASH alg const should go here? */
96     DWORD       unknown1;
97     DATA_BLOB   data0;
98     DWORD       null1;
99     DWORD       unknown2;     /* perhaps the KEY alg const should go here? */
100     DWORD       unknown3;
101     DATA_BLOB   salt;
102     DATA_BLOB   cipher;
103     DATA_BLOB   fingerprint;
104 };
105
106 /* this is used to check if an incoming structure was built by Wine */
107 static const char * crypt_magic_str = "Wine Crypt32 ok";
108
109 /* debugging tool to print strings of hex chars */
110 static const char *
111 hex_str(unsigned char *p, int n)
112 {
113     const char * ptr;
114     char report[80];
115     int r=-1;
116     report[0]='\0';
117     ptr = wine_dbg_sprintf("%s","");
118     while (--n >= 0)
119     {
120         if (r++ % 20 == 19)
121         {
122             ptr = wine_dbg_sprintf("%s%s",ptr,report);
123             report[0]='\0';
124         }
125         sprintf(report+strlen(report),"%s%02x", r ? "," : "", *p++);
126     }
127     return wine_dbg_sprintf("%s%s",ptr,report);
128 }
129
130 #define TRACE_DATA_BLOB(blob) do { \
131     TRACE("%s cbData: %u\n", #blob ,(unsigned int)((blob)->cbData)); \
132     TRACE("%s pbData @ 0x%x:%s\n", #blob ,(unsigned int)((blob)->pbData), \
133           hex_str((blob)->pbData, (blob)->cbData)); \
134 } while (0)
135
136 static
137 void serialize_dword(DWORD value,BYTE ** ptr)
138 {
139     /*TRACE("called\n");*/
140
141     memcpy(*ptr,&value,sizeof(DWORD));
142     *ptr+=sizeof(DWORD);
143 }
144
145 static
146 void serialize_string(BYTE * str,BYTE ** ptr,DWORD len, DWORD width,
147                       BOOL prepend_len)
148 {
149     /*TRACE("called %ux%u\n",(unsigned int)len,(unsigned int)width);*/
150
151     if (prepend_len)
152     {
153         serialize_dword(len,ptr);
154     }
155     memcpy(*ptr,str,len*width);
156     *ptr+=len*width;
157 }
158
159 static
160 BOOL unserialize_dword(BYTE * ptr, DWORD *index, DWORD size, DWORD * value)
161 {
162     /*TRACE("called\n");*/
163
164     if (!ptr || !index || !value) return FALSE;
165
166     if (*index+sizeof(DWORD)>size)
167     {
168         return FALSE;
169     }
170
171     memcpy(value,&(ptr[*index]),sizeof(DWORD));
172     *index+=sizeof(DWORD);
173
174     return TRUE;
175 }
176
177 static
178 BOOL unserialize_string(BYTE * ptr, DWORD *index, DWORD size,
179                         DWORD len, DWORD width, BOOL inline_len,
180                         BYTE ** data, DWORD * stored)
181 {
182     /*TRACE("called\n");*/
183
184     if (!ptr || !data) return FALSE;
185
186     if (inline_len) {
187         if (!unserialize_dword(ptr,index,size,&len))
188             return FALSE;
189     }
190
191     if (*index+len*width>size)
192     {
193         return FALSE;
194     }
195
196     if (!(*data = HeapAlloc( GetProcessHeap(), 0, len*width)))
197     {
198         return FALSE;
199     }
200
201     memcpy(*data,&(ptr[*index]),len*width);
202     if (stored)
203     {
204         *stored = len;
205     }
206     *index+=len*width;
207
208     return TRUE;
209 }
210
211 static
212 BOOL serialize(struct protect_data_t * pInfo, DATA_BLOB * pSerial)
213 {
214     BYTE * ptr;
215     DWORD dwStrLen;
216     DWORD dwStruct;
217
218     TRACE("called\n");
219
220     if (!pInfo || !pInfo->szDataDescr || !pSerial ||
221         !pInfo->info0.pbData || !pInfo->info1.pbData ||
222         !pInfo->data0.pbData || !pInfo->salt.pbData ||
223         !pInfo->cipher.pbData || !pInfo->fingerprint.pbData)
224     {
225         return FALSE;
226     }
227
228     if (pInfo->info0.cbData!=16)
229     {
230         ERR("protect_data_t info0 not 16 bytes long\n");
231     }
232
233     if (pInfo->info1.cbData!=16)
234     {
235         ERR("protect_data_t info1 not 16 bytes long\n");
236     }
237
238     dwStrLen=lstrlenW(pInfo->szDataDescr);
239
240     pSerial->cbData=0;
241     pSerial->cbData+=sizeof(DWORD)*8; /* 8 raw DWORDs */
242     pSerial->cbData+=sizeof(DWORD)*4; /* 4 BLOBs with size */
243     pSerial->cbData+=pInfo->info0.cbData;
244     pSerial->cbData+=pInfo->info1.cbData;
245     pSerial->cbData+=(dwStrLen+1)*sizeof(WCHAR) + 4; /* str, null, size */
246     pSerial->cbData+=pInfo->data0.cbData;
247     pSerial->cbData+=pInfo->salt.cbData;
248     pSerial->cbData+=pInfo->cipher.cbData;
249     pSerial->cbData+=pInfo->fingerprint.cbData;
250
251     /* save the actual structure size */
252     dwStruct = pSerial->cbData;
253     /* There may be a 256 byte minimum, but I can't prove it. */
254     /*if (pSerial->cbData<256) pSerial->cbData=256;*/
255
256     pSerial->pbData=LocalAlloc(LPTR,pSerial->cbData);
257     if (!pSerial->pbData) return FALSE;
258
259     ptr=pSerial->pbData;
260
261     /* count0 */
262     serialize_dword(pInfo->count0,&ptr);
263     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
264     
265     /* info0 */
266     serialize_string(pInfo->info0.pbData,&ptr,
267                      pInfo->info0.cbData,sizeof(BYTE),FALSE);
268     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
269
270     /* count1 */
271     serialize_dword(pInfo->count1,&ptr);
272     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
273
274     /* info1 */
275     serialize_string(pInfo->info1.pbData,&ptr,
276                      pInfo->info1.cbData,sizeof(BYTE),FALSE);
277     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
278
279     /* null0 */
280     serialize_dword(pInfo->null0,&ptr);
281     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
282     
283     /* szDataDescr */
284     serialize_string((BYTE*)pInfo->szDataDescr,&ptr,
285                      (dwStrLen+1)*sizeof(WCHAR),sizeof(BYTE),TRUE);
286     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
287
288     /* unknown0 */
289     serialize_dword(pInfo->unknown0,&ptr);
290     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
291     /* unknown1 */
292     serialize_dword(pInfo->unknown1,&ptr);
293     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
294     
295     /* data0 */
296     serialize_string(pInfo->data0.pbData,&ptr,
297                      pInfo->data0.cbData,sizeof(BYTE),TRUE);
298     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
299
300     /* null1 */
301     serialize_dword(pInfo->null1,&ptr);
302     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
303     
304     /* unknown2 */
305     serialize_dword(pInfo->unknown2,&ptr);
306     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
307     /* unknown3 */
308     serialize_dword(pInfo->unknown3,&ptr);
309     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
310     
311     /* salt */
312     serialize_string(pInfo->salt.pbData,&ptr,
313                      pInfo->salt.cbData,sizeof(BYTE),TRUE);
314     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
315
316     /* cipher */
317     serialize_string(pInfo->cipher.pbData,&ptr,
318                      pInfo->cipher.cbData,sizeof(BYTE),TRUE);
319     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
320
321     /* fingerprint */
322     serialize_string(pInfo->fingerprint.pbData,&ptr,
323                      pInfo->fingerprint.cbData,sizeof(BYTE),TRUE);
324     /*TRACE("used %u\n",ptr-pSerial->pbData);*/
325
326     if (ptr - pSerial->pbData != dwStruct)
327     {
328         ERR("struct size changed!? %u != expected %u\n",
329             ptr - pSerial->pbData, (unsigned int)dwStruct);
330         LocalFree(pSerial->pbData);
331         pSerial->pbData=NULL;
332         pSerial->cbData=0;
333         return FALSE;
334     }
335
336     return TRUE;
337 }
338
339 static
340 BOOL unserialize(DATA_BLOB * pSerial, struct protect_data_t * pInfo)
341 {
342     BYTE * ptr;
343     DWORD index;
344     DWORD size;
345     BOOL status=TRUE;
346
347     TRACE("called\n");
348
349     if (!pInfo || !pSerial || !pSerial->pbData)
350         return FALSE;
351
352     index=0;
353     ptr=pSerial->pbData;
354     size=pSerial->cbData;
355
356     /* count0 */
357     if (!unserialize_dword(ptr,&index,size,&pInfo->count0))
358     {
359         ERR("reading count0 failed!\n");
360         return FALSE;
361     }
362     
363     /* info0 */
364     if (!unserialize_string(ptr,&index,size,16,sizeof(BYTE),FALSE,
365                             &pInfo->info0.pbData, &pInfo->info0.cbData))
366     {
367         ERR("reading info0 failed!\n");
368         return FALSE;
369     }
370
371     /* count1 */
372     if (!unserialize_dword(ptr,&index,size,&pInfo->count1))
373     {
374         ERR("reading count1 failed!\n");
375         return FALSE;
376     }
377
378     /* info1 */
379     if (!unserialize_string(ptr,&index,size,16,sizeof(BYTE),FALSE,
380                             &pInfo->info1.pbData, &pInfo->info1.cbData))
381     {
382         ERR("reading info1 failed!\n");
383         return FALSE;
384     }
385
386     /* null0 */
387     if (!unserialize_dword(ptr,&index,size,&pInfo->null0))
388     {
389         ERR("reading null0 failed!\n");
390         return FALSE;
391     }
392     
393     /* szDataDescr */
394     if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE,
395                             (BYTE**)&pInfo->szDataDescr, NULL))
396     {
397         ERR("reading szDataDescr failed!\n");
398         return FALSE;
399     }
400
401     /* unknown0 */
402     if (!unserialize_dword(ptr,&index,size,&pInfo->unknown0))
403     {
404         ERR("reading unknown0 failed!\n");
405         return FALSE;
406     }
407     
408     /* unknown1 */
409     if (!unserialize_dword(ptr,&index,size,&pInfo->unknown1))
410     {
411         ERR("reading unknown1 failed!\n");
412         return FALSE;
413     }
414     
415     /* data0 */
416     if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE,
417                             &pInfo->data0.pbData, &pInfo->data0.cbData))
418     {
419         ERR("reading data0 failed!\n");
420         return FALSE;
421     }
422
423     /* null1 */
424     if (!unserialize_dword(ptr,&index,size,&pInfo->null1))
425     {
426         ERR("reading null1 failed!\n");
427         return FALSE;
428     }
429     
430     /* unknown2 */
431     if (!unserialize_dword(ptr,&index,size,&pInfo->unknown2))
432     {
433         ERR("reading unknown2 failed!\n");
434         return FALSE;
435     }
436     
437     /* unknown3 */
438     if (!unserialize_dword(ptr,&index,size,&pInfo->unknown3))
439     {
440         ERR("reading unknown3 failed!\n");
441         return FALSE;
442     }
443     
444     /* salt */
445     if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE,
446                             &pInfo->salt.pbData, &pInfo->salt.cbData))
447     {
448         ERR("reading salt failed!\n");
449         return FALSE;
450     }
451
452     /* cipher */
453     if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE,
454                             &pInfo->cipher.pbData, &pInfo->cipher.cbData))
455     {
456         ERR("reading cipher failed!\n");
457         return FALSE;
458     }
459
460     /* fingerprint */
461     if (!unserialize_string(ptr,&index,size,0,sizeof(BYTE),TRUE,
462                             &pInfo->fingerprint.pbData, &pInfo->fingerprint.cbData))
463     {
464         ERR("reading fingerprint failed!\n");
465         return FALSE;
466     }
467
468     /* allow structure size to be too big (since some applications
469      * will pad this up to 256 bytes, it seems) */
470     if (index>size)
471     {
472         /* this is an impossible-to-reach test, but if the padding
473          * issue is ever understood, this may become more useful */
474         ERR("loaded corrupt structure! (used %u expected %u)\n",
475                 (unsigned int)index, (unsigned int)size);
476         status=FALSE;
477     }
478
479     return status;
480 }
481
482 /* perform sanity checks */
483 static
484 BOOL valid_protect_data(struct protect_data_t * pInfo)
485 {
486     BOOL status=TRUE;
487
488     TRACE("called\n");
489
490     if (pInfo->count0 != 0x0001)
491     {
492         ERR("count0 != 0x0001 !\n");
493         status=FALSE;
494     }
495     if (pInfo->count1 != 0x0001)
496     {
497         ERR("count0 != 0x0001 !\n");
498         status=FALSE;
499     }
500     if (pInfo->null0 != 0x0000)
501     {
502         ERR("null0 != 0x0000 !\n");
503         status=FALSE;
504     }
505     if (pInfo->null1 != 0x0000)
506     {
507         ERR("null1 != 0x0000 !\n");
508         status=FALSE;
509     }
510     /* since we have no idea what info0 is used for, and it seems
511      * rather constant, we can test for a Wine-specific magic string
512      * there to be reasonably sure we're using data created by the Wine
513      * implementation of CryptProtectData.
514      */
515     if (pInfo->info0.cbData!=strlen(crypt_magic_str)+1 ||
516         strcmp(pInfo->info0.pbData,crypt_magic_str) != 0)
517     {
518         ERR("info0 magic value not matched !\n");
519         status=FALSE;
520     }
521
522     if (!status)
523     {
524         ERR("unrecognized CryptProtectData block\n");
525     }
526
527     return status;
528 }
529
530 static
531 void free_protect_data(struct protect_data_t * pInfo)
532 {
533     TRACE("called\n");
534
535     if (!pInfo) return;
536
537     if (pInfo->info0.pbData)
538         HeapFree( GetProcessHeap(), 0, pInfo->info0.pbData);
539     if (pInfo->info1.pbData)
540         HeapFree( GetProcessHeap(), 0, pInfo->info1.pbData);
541     if (pInfo->szDataDescr)
542         HeapFree( GetProcessHeap(), 0, pInfo->szDataDescr);
543     if (pInfo->data0.pbData)
544         HeapFree( GetProcessHeap(), 0, pInfo->data0.pbData);
545     if (pInfo->salt.pbData)
546         HeapFree( GetProcessHeap(), 0, pInfo->salt.pbData);
547     if (pInfo->cipher.pbData)
548         HeapFree( GetProcessHeap(), 0, pInfo->cipher.pbData);
549     if (pInfo->fingerprint.pbData)
550         HeapFree( GetProcessHeap(), 0, pInfo->fingerprint.pbData);
551 }
552
553 /* copies a string into a data blob */
554 static
555 BYTE * convert_str_to_blob(char* str, DATA_BLOB* blob)
556 {
557     if (!str || !blob) return NULL;
558
559     blob->cbData=strlen(str)+1;
560     if (!(blob->pbData=HeapAlloc(GetProcessHeap(),0,blob->cbData)))
561     {
562         blob->cbData=0;
563     }
564     else {
565         strcpy(blob->pbData, str);
566     }
567
568     return blob->pbData;
569 }
570
571 /*
572  * Populates everything except "cipher" and "fingerprint".
573  */
574 static
575 BOOL fill_protect_data(struct protect_data_t * pInfo, LPCWSTR szDataDescr,
576                        HCRYPTPROV hProv)
577 {
578     DWORD dwStrLen;
579
580     TRACE("called\n");
581
582     if (!pInfo) return FALSE;
583
584     dwStrLen=lstrlenW(szDataDescr);
585
586     memset(pInfo,0,sizeof(*pInfo));
587
588     pInfo->count0=0x0001;
589
590     convert_str_to_blob((char*)crypt_magic_str,&pInfo->info0);
591
592     pInfo->count1=0x0001;
593
594     convert_str_to_blob((char*)crypt_magic_str,&pInfo->info1);
595
596     pInfo->null0=0x0000;
597
598     if ((pInfo->szDataDescr=HeapAlloc( GetProcessHeap(), 0, (dwStrLen+1)*sizeof(WCHAR))))
599     {
600         memcpy(pInfo->szDataDescr,szDataDescr,(dwStrLen+1)*sizeof(WCHAR));
601     }
602
603     pInfo->unknown0=0x0000;
604     pInfo->unknown1=0x0000;
605
606     convert_str_to_blob((char*)crypt_magic_str,&pInfo->data0);
607
608     pInfo->null1=0x0000;
609     pInfo->unknown2=0x0000;
610     pInfo->unknown3=0x0000;
611
612     /* allocate memory to hold a salt */
613     pInfo->salt.cbData=CRYPT32_PROTECTDATA_SALT_LEN;
614     if ((pInfo->salt.pbData=HeapAlloc( GetProcessHeap(),0,pInfo->salt.cbData)))
615     {
616         /* generate random salt */
617         if (!CryptGenRandom(hProv, pInfo->salt.cbData, pInfo->salt.pbData))
618         {
619             ERR("CryptGenRandom\n");
620             free_protect_data(pInfo);
621             return FALSE;
622         }
623     }
624
625     /* debug: show our salt */
626     TRACE_DATA_BLOB(&pInfo->salt);
627
628     pInfo->cipher.cbData=0;
629     pInfo->cipher.pbData=NULL;
630
631     pInfo->fingerprint.cbData=0;
632     pInfo->fingerprint.pbData=NULL;
633
634     /* check all the allocations at once */
635     if (!pInfo->info0.pbData ||
636         !pInfo->info1.pbData ||
637         !pInfo->szDataDescr  ||
638         !pInfo->data0.pbData ||
639         !pInfo->salt.pbData
640         )
641     {
642         ERR("could not allocate protect_data structures\n");
643         free_protect_data(pInfo);
644         return FALSE;
645     }
646
647     return TRUE;
648 }
649
650 static
651 BOOL convert_hash_to_blob(HCRYPTHASH hHash, DATA_BLOB * blob)
652 {
653     DWORD dwSize;
654
655     TRACE("called\n");
656
657     if (!blob) return FALSE;
658
659     dwSize=sizeof(DWORD);
660     if (!CryptGetHashParam(hHash, HP_HASHSIZE, (BYTE*)&blob->cbData,
661                            &dwSize, 0))
662     {
663         ERR("failed to get hash size\n");
664         return FALSE;
665     }
666
667     if (!(blob->pbData=HeapAlloc( GetProcessHeap(), 0, blob->cbData)))
668     {
669         ERR("failed to allocate blob memory\n");
670         return FALSE;
671     }
672
673     dwSize=blob->cbData;
674     if (!CryptGetHashParam(hHash, HP_HASHVAL, blob->pbData, &dwSize, 0))
675     {
676         ERR("failed to get hash value\n");
677         HeapFree( GetProcessHeap(), 0, blob->pbData);
678         blob->pbData=NULL;
679         blob->cbData=0;
680         return FALSE;
681     }
682
683     return TRUE;
684 }
685
686 /* test that a given hash matches an exported-to-blob hash value */
687 static
688 BOOL hash_matches_blob(HCRYPTHASH hHash, DATA_BLOB * two)
689 {
690     BOOL rc = FALSE;
691     DATA_BLOB one;
692
693     if (!two || !two->pbData) return FALSE;
694
695     if (!convert_hash_to_blob(hHash,&one)) {
696         return FALSE;
697     }
698
699     if ( one.cbData == two->cbData &&
700          memcmp( one.pbData, two->pbData, one.cbData ) == 0 )
701     {
702         rc = TRUE;
703     }
704
705     HeapFree( GetProcessHeap(), 0, one.pbData );
706     return rc;
707 }
708
709 /* create an encryption key from a given salt and optional entropy */
710 static
711 BOOL load_encryption_key(HCRYPTPROV hProv, DATA_BLOB * salt,
712                          DATA_BLOB * pOptionalEntropy, HCRYPTKEY * phKey)
713 {
714     BOOL rc = TRUE;
715     HCRYPTHASH hSaltHash;
716     char * szUsername = NULL;
717     DWORD dwUsernameLen;
718     DWORD dwError;
719
720     /* create hash for salt */
721     if (!salt || !phKey ||
722         !CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hSaltHash))
723     {
724         ERR("CryptCreateHash\n");
725         return FALSE;
726     }
727
728     /* This should be the "logon credentials" instead of username */
729     dwError=GetLastError();
730     dwUsernameLen = 0;
731     if (!GetUserNameA(NULL,&dwUsernameLen) &&
732         GetLastError()==ERROR_MORE_DATA && dwUsernameLen &&
733         (szUsername = HeapAlloc( GetProcessHeap(), 0, dwUsernameLen)))
734     {
735         szUsername[0]='\0';
736         GetUserNameA( szUsername, &dwUsernameLen );
737     }
738     SetLastError(dwError);
739
740     /* salt the hash with:
741      * - the user id
742      * - an "internal secret"
743      * - randomness (from the salt)
744      * - user-supplied entropy
745      */
746     if ((szUsername && !CryptHashData(hSaltHash,szUsername,dwUsernameLen,0)) ||
747         !CryptHashData(hSaltHash,CRYPT32_PROTECTDATA_SECRET,
748                                  strlen(CRYPT32_PROTECTDATA_SECRET),0) ||
749         !CryptHashData(hSaltHash,salt->pbData,salt->cbData,0) ||
750         (pOptionalEntropy && !CryptHashData(hSaltHash,
751                                             pOptionalEntropy->pbData,
752                                             pOptionalEntropy->cbData,0)))
753     {
754         ERR("CryptHashData\n");
755         rc = FALSE;
756     }
757
758     /* produce a symmetric key */
759     if (rc && !CryptDeriveKey(hProv,CRYPT32_PROTECTDATA_KEY_CALG,
760                               hSaltHash,CRYPT_EXPORTABLE,phKey))
761     {
762         ERR("CryptDeriveKey\n");
763         rc = FALSE;
764     }
765
766     /* clean up */
767     CryptDestroyHash(hSaltHash);
768     if (szUsername) HeapFree( GetProcessHeap(), 0, szUsername );
769
770     return rc;
771 }
772
773 /* debugging tool to print the structures of a ProtectData call */
774 static void
775 report(DATA_BLOB* pDataIn, DATA_BLOB* pOptionalEntropy,
776        CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct, DWORD dwFlags)
777 {
778     TRACE("pPromptStruct: 0x%x\n",(unsigned int)pPromptStruct);
779     if (pPromptStruct)
780     {
781         TRACE("  cbSize: 0x%x\n",(unsigned int)pPromptStruct->cbSize);
782         TRACE("  dwPromptFlags: 0x%x\n",(unsigned int)pPromptStruct->dwPromptFlags);
783         TRACE("  hwndApp: 0x%x\n",(unsigned int)pPromptStruct->hwndApp);
784         TRACE("  szPrompt: 0x%x %s\n",
785               (unsigned int)pPromptStruct->szPrompt,
786               pPromptStruct->szPrompt ? debugstr_w(pPromptStruct->szPrompt)
787               : "");
788     }
789     TRACE("dwFlags: 0x%04x\n",(unsigned int)dwFlags);
790     TRACE_DATA_BLOB(pDataIn);
791     if (pOptionalEntropy)
792     {
793         TRACE_DATA_BLOB(pOptionalEntropy);
794         TRACE("  %s\n",debugstr_an(pOptionalEntropy->pbData,pOptionalEntropy->cbData));
795     }
796
797 }
798
799
800 /***************************************************************************
801  * CryptProtectData     [CRYPT32.@]
802  *
803  * Generate Cipher data from given Plain and Entropy data.
804  *
805  * PARAMS
806  *  pDataIn          [I] Plain data to be enciphered
807  *  szDataDescr      [I] Optional Unicode string describing the Plain data
808  *  pOptionalEntropy [I] Optional entropy data to adjust cipher, can be NULL
809  *  pvReserved       [I] Reserved, must be NULL
810  *  pPromptStruct    [I] Structure describing if/how to prompt during ciphering
811  *  dwFlags          [I] Flags describing options to the ciphering
812  *  pDataOut         [O] Resulting Cipher data, for calls to CryptUnprotectData
813  *
814  * RETURNS
815  *  TRUE  If a Cipher was generated.
816  *  FALSE If something failed and no Cipher is available.
817  *
818  * FIXME
819  *  The true Windows encryption and keying mechanisms are unknown.
820  *
821  *  dwFlags and pPromptStruct are currently ignored.
822  *
823  * NOTES
824  *  Memory allocated in pDataOut must be freed with LocalFree.
825  *
826  */
827 BOOL WINAPI CryptProtectData(DATA_BLOB* pDataIn,
828                              LPCWSTR szDataDescr,
829                              DATA_BLOB* pOptionalEntropy,
830                              PVOID pvReserved,
831                              CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
832                              DWORD dwFlags,
833                              DATA_BLOB* pDataOut)
834 {
835     BOOL rc = FALSE;
836
837     HCRYPTPROV hProv;
838     struct protect_data_t protect_data;
839     HCRYPTHASH hHash;
840     HCRYPTKEY hKey;
841     DWORD dwLength;
842
843     TRACE("called\n");
844
845     SetLastError(ERROR_SUCCESS);
846
847     if (!pDataIn || !pDataOut)
848     {
849         SetLastError(ERROR_INVALID_PARAMETER);
850         goto finished;
851     }
852
853     /* debug: show our arguments */
854     report(pDataIn,pOptionalEntropy,pPromptStruct,dwFlags);
855     TRACE("\tszDataDescr: 0x%x %s\n",(unsigned int)szDataDescr,
856           szDataDescr ? debugstr_w(szDataDescr) : "");
857
858     /* Windows appears to create an empty szDataDescr instead of maintaining
859      * a NULL */
860     if (!szDataDescr)
861         szDataDescr=(WCHAR[]){'\0'};
862
863     /* get crypt context */
864     if (!CryptAcquireContextW(&hProv,NULL,NULL,CRYPT32_PROTECTDATA_PROV,CRYPT_VERIFYCONTEXT))
865     {
866         ERR("CryptAcquireContextW failed\n");
867         goto finished;
868     }
869
870     /* populate our structure */
871     if (!fill_protect_data(&protect_data,szDataDescr,hProv))
872     {
873         ERR("fill_protect_data\n");
874         goto free_context;
875     }
876
877     /* load key */
878     if (!load_encryption_key(hProv,&protect_data.salt,pOptionalEntropy,&hKey))
879     {
880         goto free_protect_data;
881     }
882
883     /* create a hash for the encryption validation */
884     if (!CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hHash))
885     {
886         ERR("CryptCreateHash\n");
887         goto free_key;
888     }
889
890     /* calculate storage required */
891     dwLength=pDataIn->cbData;
892     if (CryptEncrypt(hKey, 0, TRUE, 0, pDataIn->pbData, &dwLength, 0) ||
893         GetLastError()!=ERROR_MORE_DATA)
894     {
895         ERR("CryptEncrypt\n");
896         goto free_hash;
897     }
898     TRACE("required encrypted storage: %u\n",(unsigned int)dwLength);
899
900     /* copy plain text into cipher area for CryptEncrypt call */
901     protect_data.cipher.cbData=dwLength;
902     if (!(protect_data.cipher.pbData=HeapAlloc( GetProcessHeap(), 0,
903                                                 protect_data.cipher.cbData)))
904     {
905         ERR("HeapAlloc\n");
906         goto free_hash;
907     }
908     memcpy(protect_data.cipher.pbData,pDataIn->pbData,pDataIn->cbData);
909
910     /* encrypt! */
911     dwLength=pDataIn->cbData;
912     if (!CryptEncrypt(hKey, hHash, TRUE, 0, protect_data.cipher.pbData,
913                       &dwLength, protect_data.cipher.cbData))
914     {
915         ERR("CryptEncrypt %u\n",(unsigned int)GetLastError());
916         goto free_hash;
917     }
918     protect_data.cipher.cbData=dwLength;
919
920     /* debug: show the cipher */
921     TRACE_DATA_BLOB(&protect_data.cipher);
922
923     /* attach our fingerprint */
924     if (!convert_hash_to_blob(hHash, &protect_data.fingerprint))
925     {
926         ERR("convert_hash_to_blob\n");
927         goto free_hash;
928     }
929
930     /* serialize into an opaque blob */
931     if (!serialize(&protect_data, pDataOut))
932     {
933         ERR("serialize\n");
934         goto free_hash;
935     }
936
937     /* success! */
938     rc=TRUE;
939
940 free_hash:
941     CryptDestroyHash(hHash);
942 free_key:
943     CryptDestroyKey(hKey);
944 free_protect_data:
945     free_protect_data(&protect_data);
946 free_context:
947     CryptReleaseContext(hProv,0);
948 finished:
949     /* If some error occurred, and no error code was set, force one. */
950     if (!rc && GetLastError()==ERROR_SUCCESS)
951     {
952         SetLastError(ERROR_INVALID_DATA);
953     }
954
955     if (rc)
956     {
957         SetLastError(ERROR_SUCCESS);
958
959         TRACE_DATA_BLOB(pDataOut);
960     }
961
962     TRACE("returning %s\n", rc ? "ok" : "FAIL");
963
964     return rc;
965 }
966
967
968 /***************************************************************************
969  * CryptUnprotectData   [CRYPT32.@]
970  *
971  * Generate Plain data and Description from given Cipher and Entropy data.
972  *
973  * PARAMS
974  *  pDataIn          [I] Cipher data to be decoded
975  *  ppszDataDescr    [O] Optional Unicode string describing the Plain data
976  *  pOptionalEntropy [I] Optional entropy data to adjust cipher, can be NULL
977  *  pvReserved       [I] Reserved, must be NULL
978  *  pPromptStruct    [I] Structure describing if/how to prompt during decoding
979  *  dwFlags          [I] Flags describing options to the decoding
980  *  pDataOut         [O] Resulting Plain data, from calls to CryptProtectData
981  *
982  * RETURNS
983  *  TRUE  If a Plain was generated.
984  *  FALSE If something failed and no Plain is available.
985  *
986  * FIXME
987  *  The true Windows encryption and keying mechanisms are unknown.
988  *
989  *  dwFlags and pPromptStruct are currently ignored.
990  *
991  * NOTES
992  *  Memory allocated in pDataOut and non-NULL ppszDataDescr must be freed
993  *  with LocalFree.
994  *
995  */
996 BOOL WINAPI CryptUnprotectData(DATA_BLOB* pDataIn,
997                                LPWSTR * ppszDataDescr,
998                                DATA_BLOB* pOptionalEntropy,
999                                PVOID pvReserved,
1000                                CRYPTPROTECT_PROMPTSTRUCT* pPromptStruct,
1001                                DWORD dwFlags,
1002                                DATA_BLOB* pDataOut)
1003 {
1004     BOOL rc = FALSE;
1005
1006     HCRYPTPROV hProv;
1007     struct protect_data_t protect_data;
1008     HCRYPTHASH hHash;
1009     HCRYPTKEY hKey;
1010     DWORD dwLength;
1011
1012     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.";
1013
1014     TRACE("called\n");
1015
1016     SetLastError(ERROR_SUCCESS);
1017
1018     if (!pDataIn || !pDataOut)
1019     {
1020         SetLastError(ERROR_INVALID_PARAMETER);
1021         goto finished;
1022     }
1023
1024     /* debug: show our arguments */
1025     report(pDataIn,pOptionalEntropy,pPromptStruct,dwFlags);
1026     TRACE("\tppszDataDescr: 0x%x\n",(unsigned int)ppszDataDescr);
1027
1028     /* take apart the opaque blob */
1029     if (!unserialize(pDataIn, &protect_data))
1030     {
1031         SetLastError(ERROR_INVALID_DATA);
1032         FIXME("%s\n",announce_bad_opaque_data);
1033         goto finished;
1034     }
1035
1036     /* perform basic validation on the resulting structure */
1037     if (!valid_protect_data(&protect_data))
1038     {
1039         SetLastError(ERROR_INVALID_DATA);
1040         FIXME("%s\n",announce_bad_opaque_data);
1041         goto free_protect_data;
1042     }
1043
1044     /* get a crypt context */
1045     if (!CryptAcquireContextW(&hProv,NULL,NULL,CRYPT32_PROTECTDATA_PROV,CRYPT_VERIFYCONTEXT))
1046     {
1047         ERR("CryptAcquireContextW failed\n");
1048         goto free_protect_data;
1049     }
1050
1051     /* load key */
1052     if (!load_encryption_key(hProv,&protect_data.salt,pOptionalEntropy,&hKey))
1053     {
1054         goto free_context;
1055     }
1056
1057     /* create a hash for the decryption validation */
1058     if (!CryptCreateHash(hProv,CRYPT32_PROTECTDATA_HASH_CALG,0,0,&hHash))
1059     {
1060         ERR("CryptCreateHash\n");
1061         goto free_key;
1062     }
1063
1064     /* prepare for plaintext */
1065     pDataOut->cbData=protect_data.cipher.cbData;
1066     if (!(pDataOut->pbData=LocalAlloc( LPTR, pDataOut->cbData)))
1067     {
1068         ERR("HeapAlloc\n");
1069         goto free_hash;
1070     }
1071     memcpy(pDataOut->pbData,protect_data.cipher.pbData,protect_data.cipher.cbData);
1072
1073     /* decrypt! */
1074     if (!CryptDecrypt(hKey, hHash, TRUE, 0, pDataOut->pbData,
1075                       &pDataOut->cbData) ||
1076         /* check the hash fingerprint */
1077         pDataOut->cbData > protect_data.cipher.cbData ||
1078         !hash_matches_blob(hHash, &protect_data.fingerprint))
1079     {
1080         SetLastError(ERROR_INVALID_DATA);
1081
1082         LocalFree( pDataOut->pbData );
1083         pDataOut->pbData = NULL;
1084         pDataOut->cbData = 0;
1085
1086         goto free_hash;
1087     }
1088
1089     /* Copy out the description */
1090     dwLength = (lstrlenW(protect_data.szDataDescr)+1) * sizeof(WCHAR);
1091     if (ppszDataDescr)
1092     {
1093         if (!(*ppszDataDescr = LocalAlloc(LPTR,dwLength)))
1094         {
1095             ERR("LocalAlloc (ppszDataDescr)\n");
1096             goto free_hash;
1097         }
1098         else {
1099             memcpy(*ppszDataDescr,protect_data.szDataDescr,dwLength);
1100         }
1101     }
1102
1103     /* success! */
1104     rc = TRUE;
1105
1106 free_hash:
1107     CryptDestroyHash(hHash);
1108 free_key:
1109     CryptDestroyKey(hKey);
1110 free_context:
1111     CryptReleaseContext(hProv,0);
1112 free_protect_data:
1113     free_protect_data(&protect_data);
1114 finished:
1115     /* If some error occurred, and no error code was set, force one. */
1116     if (!rc && GetLastError()==ERROR_SUCCESS)
1117     {
1118         SetLastError(ERROR_INVALID_DATA);
1119     }
1120
1121     if (rc) {
1122         SetLastError(ERROR_SUCCESS);
1123
1124         if (ppszDataDescr)
1125         {
1126             TRACE("szDataDescr: %s\n",debugstr_w(*ppszDataDescr));
1127         }
1128         TRACE_DATA_BLOB(pDataOut);
1129     }
1130
1131     TRACE("returning %s\n", rc ? "ok" : "FAIL");
1132
1133     return rc;
1134 }