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