|
|
1.1.1.5 root 1: /*
2: Copyright (c) TrueCrypt Foundation. All rights reserved.
1.1 root 3:
1.1.1.6 ! root 4: Covered by the TrueCrypt License 2.3 the full text of which is contained
1.1.1.5 root 5: in the file License.txt included in TrueCrypt binary and source code
6: distribution packages.
1.1 root 7: */
8:
1.1.1.5 root 9: #include <stdlib.h>
10: #include <string.h>
1.1 root 11: #include <sys/stat.h>
12: #include <sys/types.h>
13:
14: #include "Tcdefs.h"
15: #include "Keyfiles.h"
16: #include "Crc.h"
17:
18: #ifdef _WIN32
19:
20: #include <io.h>
21: #include "Dlgcode.h"
22: #include "Language.h"
23: #include "../common/resource.h"
24:
25: #define stat _stat
26: #define S_IFDIR _S_IFDIR
27: #define snprintf _snprintf
28:
29: #else
30:
31: #include <dirent.h>
32: #include <utime.h>
33:
34: #endif
35:
36: KeyFile *KeyFileAdd (KeyFile *firstKeyFile, KeyFile *keyFile)
37: {
38: KeyFile *kf = firstKeyFile;
39:
40: if (firstKeyFile != NULL)
41: {
42: while (kf->Next)
43: kf = kf->Next;
44:
45: kf->Next = keyFile;
46: }
47: else
48: firstKeyFile = keyFile;
49:
50: keyFile->Next = NULL;
51:
52: return firstKeyFile;
53: }
54:
55:
56: // Returns first keyfile, NULL if last keyfile was removed
57: static KeyFile *KeyFileRemove (KeyFile *firstKeyFile, KeyFile *keyFile)
58: {
59: KeyFile *prevkf = NULL, *kf = firstKeyFile;
60:
61: if (firstKeyFile == NULL) return NULL;
62: do
63: {
64: if (kf == keyFile)
65: {
66: if (prevkf == NULL)
67: firstKeyFile = kf->Next;
68: else
69: prevkf->Next = kf->Next;
70:
71: memset (keyFile, 0, sizeof(*keyFile)); // wipe
72: free (keyFile);
73: break;
74: }
75: prevkf = kf;
76: }
77: while (kf = kf->Next);
78:
79: return firstKeyFile;
80: }
81:
82:
83: void KeyFileRemoveAll (KeyFile **firstKeyFile)
84: {
85: KeyFile *kf = *firstKeyFile;
86: while (kf != NULL)
87: {
88: KeyFile *d = kf;
89: kf = kf->Next;
90: burn (d, sizeof(*d)); // wipe
91: free (d);
92: }
93:
94: *firstKeyFile = NULL;
95: }
96:
97:
98: KeyFile *KeyFileClone (KeyFile *keyFile)
99: {
100: KeyFile *clone;
101:
102: if (keyFile == NULL) return NULL;
103:
104: clone = malloc (sizeof (KeyFile));
105: strcpy (clone->FileName, keyFile->FileName);
106: clone->Next = NULL;
107: return clone;
108: }
109:
110:
111: KeyFile *KeyFileCloneAll (KeyFile *firstKeyFile)
112: {
113: KeyFile *cloneFirstKeyFile = KeyFileClone (firstKeyFile);
114: KeyFile *kf;
115:
116: if (firstKeyFile == NULL) return NULL;
117: kf = firstKeyFile->Next;
118: while (kf != NULL)
119: {
120: KeyFileAdd (cloneFirstKeyFile, KeyFileClone (kf));
121: kf = kf->Next;
122: }
123:
124: return cloneFirstKeyFile;
125: }
126:
127:
1.1.1.6 ! root 128: static BOOL KeyFileProcess (unsigned __int8 *keyPool, KeyFile *keyFile)
1.1 root 129: {
130: FILE *f;
131: unsigned __int8 buffer[64 * 1024];
132: unsigned __int32 crc = 0xffffffff;
133: int writePos = 0;
134: size_t bytesRead, totalRead = 0;
1.1.1.6 ! root 135: int status = TRUE;
1.1 root 136:
137: #ifdef _WIN32
138: HANDLE src;
139: FILETIME ftCreationTime;
140: FILETIME ftLastWriteTime;
141: FILETIME ftLastAccessTime;
142: #else
143: struct stat kfStat;
144: #endif
145:
146: BOOL bTimeStampValid = FALSE;
147:
1.1.1.6 ! root 148: /* Remember the last access time of the keyfile. It will be preserved in order to prevent
! 149: an adversary from determining which file may have been used as keyfile. */
1.1 root 150: #ifdef _WIN32
1.1.1.6 ! root 151: src = CreateFile (keyFile->FileName,
! 152: GENERIC_READ | GENERIC_WRITE,
! 153: FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
1.1 root 154:
1.1.1.6 ! root 155: if (src != INVALID_HANDLE_VALUE)
! 156: {
! 157: if (GetFileTime ((HANDLE) src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime))
! 158: bTimeStampValid = TRUE;
! 159: else
! 160: Warning ("GETFILETIME_FAILED_KEYFILE");
! 161: }
1.1 root 162: #else
1.1.1.6 ! root 163: bTimeStampValid = stat (keyFile->FileName, &kfStat) == 0;
1.1 root 164: #endif
165:
166: f = fopen (keyFile->FileName, "rb");
167: if (f == NULL) return FALSE;
168:
169: while ((bytesRead = fread (buffer, 1, sizeof (buffer), f)) > 0)
170: {
171: size_t i;
172:
1.1.1.6 ! root 173: if (ferror (f))
! 174: {
! 175: status = FALSE;
! 176: goto close;
! 177: }
! 178:
1.1 root 179: for (i = 0; i < bytesRead; i++)
180: {
181: crc = UPDC32 (buffer[i], crc);
182:
183: keyPool[writePos++] += (unsigned __int8) (crc >> 24);
184: keyPool[writePos++] += (unsigned __int8) (crc >> 16);
185: keyPool[writePos++] += (unsigned __int8) (crc >> 8);
186: keyPool[writePos++] += (unsigned __int8) crc;
187:
188: if (writePos >= KEYFILE_POOL_SIZE)
189: writePos = 0;
190:
191: if (++totalRead >= KEYFILE_MAX_READ_LEN)
192: goto close;
193: }
194: }
195:
1.1.1.6 ! root 196: if (ferror (f))
! 197: status = FALSE;
! 198:
1.1 root 199: close:
200: fclose (f);
201:
202: if (bTimeStampValid)
203: {
204: // Restore the keyfile timestamp
205: #ifdef _WIN32
206: if (!SetFileTime (src, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime))
207: Warning ("SETFILETIME_FAILED_KEYFILE");
208: CloseHandle (src);
209: #else
210: struct utimbuf u;
211: u.actime = kfStat.st_atime;
1.1.1.6 ! root 212: u.modtime = kfStat.st_mtime;
1.1 root 213: utime (keyFile->FileName, &u);
214: #endif
215: }
216:
1.1.1.6 ! root 217: return status;
1.1 root 218: }
219:
220:
1.1.1.6 ! root 221: BOOL KeyFilesApply (Password *password, KeyFile *firstKeyFile)
1.1 root 222: {
223: BOOL status = TRUE;
224: KeyFile kfSubStruct;
225: KeyFile *kf;
226: KeyFile *kfSub = &kfSubStruct;
227: static unsigned __int8 keyPool [KEYFILE_POOL_SIZE];
228: int i;
229: struct stat statStruct;
230: char searchPath [TC_MAX_PATH*2];
231: #ifdef _WIN32
232: struct _finddata_t fBuf;
233: intptr_t searchHandle;
234: #else
235: struct dirent *fBuf;
236: DIR *searchHandle;
237: #endif
238:
239: if (firstKeyFile == NULL) return TRUE;
240:
241: #ifdef _WIN32
242: VirtualLock (keyPool, sizeof (keyPool));
243: #endif
244: memset (keyPool, 0, sizeof (keyPool));
245:
246: for (kf = firstKeyFile; kf != NULL; kf = kf->Next)
247: {
248: // Determine whether it's a path or a file
249: if (stat (kf->FileName, &statStruct) != 0)
250: {
251: #ifdef _WIN32
1.1.1.6 ! root 252: handleWin32Error (MainDlg);
1.1 root 253: Error ("ERR_PROCESS_KEYFILE");
254: #else
255: perror ("stat");
256: #endif
257: status = FALSE;
258: continue;
259: }
260:
261: if (statStruct.st_mode & S_IFDIR) // If it's a directory
262: {
263: /* Find and process all keyfiles in the directory */
264:
265: #ifdef _WIN32
266: snprintf (searchPath, sizeof (searchPath), "%s\\*.*", kf->FileName);
267: if ((searchHandle = _findfirst (searchPath, &fBuf)) == -1)
268: #else
269: if ((searchHandle = opendir (kf->FileName)) == NULL)
270: #endif
271: {
272: #ifdef _WIN32
1.1.1.6 ! root 273: handleWin32Error (MainDlg);
1.1 root 274: Error ("ERR_PROCESS_KEYFILE_PATH");
275: #endif
276: status = FALSE;
277: continue;
278: }
279:
280: #ifdef _WIN32
281: do
282: #else
283: while ((fBuf = readdir (searchHandle)) != NULL)
284: #endif
285: {
286: snprintf (kfSub->FileName, sizeof(kfSub->FileName), "%s%c%s", kf->FileName,
287: #ifdef _WIN32
288: '\\',
289: fBuf.name
290: #else
291: '/',
292: fBuf->d_name
293: #endif
294: );
295:
296: // Determine whether it's a path or a file
297: if (stat (kfSub->FileName, &statStruct) != 0)
298: {
299: #ifdef _WIN32
1.1.1.6 ! root 300: handleWin32Error (MainDlg);
1.1 root 301: Error ("ERR_PROCESS_KEYFILE");
302: #endif
303: status = FALSE;
304: continue;
305: }
306: else if (statStruct.st_mode & S_IFDIR) // If it's a directory
307: {
308: // Prevent recursive folder scanning
309: continue;
310: }
311:
312:
313: // Apply keyfile to the pool
1.1.1.6 ! root 314: if (!KeyFileProcess (keyPool, kfSub))
1.1 root 315: {
316: #ifdef _WIN32
1.1.1.6 ! root 317: handleWin32Error (MainDlg);
1.1 root 318: Error ("ERR_PROCESS_KEYFILE");
319: #endif
320: status = FALSE;
321: }
322:
323: #ifdef _WIN32
324: } while (_findnext (searchHandle, &fBuf) != -1);
325: _findclose (searchHandle);
326: #else
327: }
328: closedir (searchHandle);
329: #endif
330:
331: burn (&kfSubStruct, sizeof (kfSubStruct));
332:
333: }
334: // Apply keyfile to the pool
1.1.1.6 ! root 335: else if (!KeyFileProcess (keyPool, kf))
1.1 root 336: {
337: #ifdef _WIN32
1.1.1.6 ! root 338: handleWin32Error (MainDlg);
1.1 root 339: Error ("ERR_PROCESS_KEYFILE");
340: #endif
341: status = FALSE;
342: }
343: }
344:
345: /* Mix the keyfile pool contents into the password */
346:
347: for (i = 0; i < (int)sizeof(keyPool); i++)
348: {
349: if (i < password->Length)
350: password->Text[i] += keyPool[i];
351: else
352: password->Text[i] = keyPool[i];
353: }
354:
355: if (password->Length < (int)sizeof (keyPool))
356: password->Length = sizeof (keyPool);
357:
358: burn (keyPool, sizeof (keyPool));
359:
360: return status;
361: }
362:
363: #ifdef _WIN32
364:
365: static void LoadKeyList (HWND hwndDlg, KeyFile *firstKeyFile)
366: {
367: KeyFile *kf;
368: LVITEM LvItem;
369: int line = 0;
370: HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST);
371:
372: ListView_DeleteAllItems (hList);
373: EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE), FALSE);
374: EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVEALL), firstKeyFile != NULL);
375: SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, firstKeyFile != NULL);
376:
377: for (kf = firstKeyFile; kf != NULL; kf = kf->Next)
378: {
379: memset (&LvItem,0,sizeof(LvItem));
380: LvItem.mask = LVIF_TEXT|LVIF_PARAM;
381: LvItem.iItem = line++;
382: LvItem.iSubItem = 0;
383: LvItem.pszText = kf->FileName;
384: LvItem.lParam = (LPARAM) kf;
385: SendMessage (hList, LVM_INSERTITEM, 0, (LPARAM)&LvItem);
386: }
387: }
388:
389: #if KEYFILE_POOL_SIZE % 4 != 0
390: #error KEYFILE_POOL_SIZE must be a multiple of 4
391: #endif
392:
1.1.1.6 ! root 393: BOOL CALLBACK KeyFilesDlgProc (HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
1.1 root 394: {
395: static KeyFilesDlgParam *param;
396: static KeyFilesDlgParam origParam;
397:
398: WORD lw = LOWORD (wParam);
399:
400: switch (msg)
401: {
402: case WM_INITDIALOG:
403: {
1.1.1.2 root 404: LVCOLUMNW LvCol;
1.1 root 405: HWND hList = GetDlgItem (hwndDlg, IDC_KEYLIST);
406:
407: param = (KeyFilesDlgParam *) lParam;
408: origParam = *(KeyFilesDlgParam *) lParam;
409:
410: param->FirstKeyFile = KeyFileCloneAll (param->FirstKeyFile);
411:
412: LocalizeDialog (hwndDlg, "IDD_KEYFILES");
413: DragAcceptFiles (hwndDlg, TRUE);
414:
1.1.1.2 root 415: SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0,
1.1 root 416: LVS_EX_FULLROWSELECT|LVS_EX_HEADERDRAGDROP
417: );
418:
419: memset (&LvCol,0,sizeof(LvCol));
420: LvCol.mask = LVCF_TEXT|LVCF_WIDTH|LVCF_SUBITEM|LVCF_FMT;
1.1.1.2 root 421: LvCol.pszText = GetString ("KEYFILE");
1.1.1.6 ! root 422: LvCol.cx = CompensateXDPI (366);
1.1 root 423: LvCol.fmt = LVCFMT_LEFT;
1.1.1.2 root 424: SendMessageW (hList, LVM_INSERTCOLUMNW, 0, (LPARAM)&LvCol);
1.1 root 425:
426: LoadKeyList (hwndDlg, param->FirstKeyFile);
427: SetCheckBox (hwndDlg, IDC_KEYFILES_ENABLE, param->EnableKeyFiles);
428:
429: SetWindowTextW(GetDlgItem(hwndDlg, IDT_KEYFILES_NOTE), GetString ("IDT_KEYFILES_NOTE"));
1.1.1.5 root 430:
431: ToHyperlink (hwndDlg, IDC_LINK_KEYFILES_INFO);
1.1 root 432: }
433: return 1;
434:
435: case WM_COMMAND:
436:
437: if (lw == IDC_KEYADD)
438: {
439: KeyFile *kf = malloc (sizeof (KeyFile));
1.1.1.4 root 440: if (SelectMultipleFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, bHistory))
1.1 root 441: {
1.1.1.3 root 442: do
443: {
444: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
445: LoadKeyList (hwndDlg, param->FirstKeyFile);
446:
447: kf = malloc (sizeof (KeyFile));
448: } while (SelectMultipleFilesNext (kf->FileName));
1.1 root 449: }
1.1.1.3 root 450:
451: free (kf);
1.1 root 452: return 1;
453: }
454:
455: if (lw == IDC_ADD_KEYFILE_PATH)
456: {
457: KeyFile *kf = malloc (sizeof (KeyFile));
458:
459: if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName))
460: {
461: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
462: LoadKeyList (hwndDlg, param->FirstKeyFile);
463: }
464: else
465: {
466: free (kf);
467: }
468: return 1;
469: }
470:
471: if (lw == IDC_KEYREMOVE)
472: {
473: HWND list = GetDlgItem (hwndDlg, IDC_KEYLIST);
474: LVITEM LvItem;
475: memset (&LvItem, 0, sizeof(LvItem));
476: LvItem.mask = LVIF_PARAM;
477: LvItem.iItem = -1;
478:
479: while (-1 != (LvItem.iItem = ListView_GetNextItem (list, LvItem.iItem, LVIS_SELECTED)))
480: {
481: ListView_GetItem (list, &LvItem);
482: param->FirstKeyFile = KeyFileRemove (param->FirstKeyFile, (KeyFile *) LvItem.lParam);
483: }
484:
485: LoadKeyList (hwndDlg, param->FirstKeyFile);
486: return 1;
487: }
488:
489: if (lw == IDC_KEYREMOVEALL)
490: {
491: KeyFileRemoveAll (¶m->FirstKeyFile);
492: LoadKeyList (hwndDlg, NULL);
493: return 1;
494: }
495:
496: if (lw == IDC_GENERATE_KEYFILE)
497: {
498: DialogBoxParamW (hInst,
499: MAKEINTRESOURCEW (IDD_KEYFILE_GENERATOR), hwndDlg,
500: (DLGPROC) KeyfileGeneratorDlgProc, (LPARAM) 0);
501: return 1;
502: }
503:
1.1.1.5 root 504: if (lw == IDC_LINK_KEYFILES_INFO)
505: {
506: Applink ("keyfiles", TRUE, "");
507: }
508:
1.1 root 509: if (lw == IDOK)
510: {
511: param->EnableKeyFiles = IsButtonChecked (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE));
512: EndDialog (hwndDlg, IDOK);
513: return 1;
514: }
515:
516: if (lw == IDCANCEL)
517: {
518: KeyFileRemoveAll (¶m->FirstKeyFile);
519: *param = origParam;
520:
521: EndDialog (hwndDlg, IDCLOSE);
522: return 1;
523: }
524:
525: case WM_DROPFILES:
526: {
527: HDROP hdrop = (HDROP) wParam;
528:
529: int i = 0, count = DragQueryFile (hdrop, -1, NULL, 0);
530:
531: while (count-- > 0)
532: {
533: KeyFile *kf = malloc (sizeof (KeyFile));
534: DragQueryFile (hdrop, i++, kf->FileName, sizeof (kf->FileName));
535: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf);
536: LoadKeyList (hwndDlg, param->FirstKeyFile);
537: }
538:
539: DragFinish (hdrop);
540: }
541: return 1;
542:
543: case WM_NOTIFY:
544: if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED)
545: {
546: EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE),
547: ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_KEYLIST), -1, LVIS_SELECTED) != -1);
548: return 1;
549: }
550: break;
551:
552: case WM_CLOSE:
553: KeyFileRemoveAll (¶m->FirstKeyFile);
554: *param = origParam;
555:
556: EndDialog (hwndDlg, IDCLOSE);
557: return 1;
558:
559: break;
560:
561: }
562:
563: return 0;
564: }
565:
566:
567: #endif /* #ifdef _WIN32 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.