|
|
1.1 root 1: /* 1.1.1.3 ! root 2: Copyright (c) 2004-2006 TrueCrypt Foundation. All rights reserved. 1.1 root 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: { 1.1.1.2 root 391: LVCOLUMNW LvCol; 1.1 root 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: 1.1.1.2 root 402: SendMessageW (hList,LVM_SETEXTENDEDLISTVIEWSTYLE,0, 1.1 root 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; 1.1.1.2 root 408: LvCol.pszText = GetString ("KEYFILE"); 409: LvCol.cx = 366; 1.1 root 410: LvCol.fmt = LVCFMT_LEFT; 1.1.1.2 root 411: SendMessageW (hList, LVM_INSERTCOLUMNW, 0, (LPARAM)&LvCol); 1.1 root 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)); 1.1.1.3 ! root 425: if (SelectMultipleFiles (hwndDlg, "SELECT_KEYFILE", kf->FileName, FALSE)) 1.1 root 426: { 1.1.1.3 ! root 427: do ! 428: { ! 429: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); ! 430: LoadKeyList (hwndDlg, param->FirstKeyFile); ! 431: ! 432: kf = malloc (sizeof (KeyFile)); ! 433: } while (SelectMultipleFilesNext (kf->FileName)); 1.1 root 434: } 1.1.1.3 ! root 435: ! 436: free (kf); 1.1 root 437: return 1; 438: } 439: 440: if (lw == IDC_ADD_KEYFILE_PATH) 441: { 442: KeyFile *kf = malloc (sizeof (KeyFile)); 443: 444: if (BrowseDirectories (hwndDlg,"SELECT_KEYFILE_PATH", kf->FileName)) 445: { 446: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); 447: LoadKeyList (hwndDlg, param->FirstKeyFile); 448: } 449: else 450: { 451: free (kf); 452: } 453: return 1; 454: } 455: 456: if (lw == IDC_KEYREMOVE) 457: { 458: HWND list = GetDlgItem (hwndDlg, IDC_KEYLIST); 459: LVITEM LvItem; 460: memset (&LvItem, 0, sizeof(LvItem)); 461: LvItem.mask = LVIF_PARAM; 462: LvItem.iItem = -1; 463: 464: while (-1 != (LvItem.iItem = ListView_GetNextItem (list, LvItem.iItem, LVIS_SELECTED))) 465: { 466: ListView_GetItem (list, &LvItem); 467: param->FirstKeyFile = KeyFileRemove (param->FirstKeyFile, (KeyFile *) LvItem.lParam); 468: } 469: 470: LoadKeyList (hwndDlg, param->FirstKeyFile); 471: return 1; 472: } 473: 474: if (lw == IDC_KEYREMOVEALL) 475: { 476: KeyFileRemoveAll (¶m->FirstKeyFile); 477: LoadKeyList (hwndDlg, NULL); 478: return 1; 479: } 480: 481: if (lw == IDC_GENERATE_KEYFILE) 482: { 483: DialogBoxParamW (hInst, 484: MAKEINTRESOURCEW (IDD_KEYFILE_GENERATOR), hwndDlg, 485: (DLGPROC) KeyfileGeneratorDlgProc, (LPARAM) 0); 486: return 1; 487: } 488: 489: if (lw == IDOK) 490: { 491: param->EnableKeyFiles = IsButtonChecked (GetDlgItem (hwndDlg, IDC_KEYFILES_ENABLE)); 492: EndDialog (hwndDlg, IDOK); 493: return 1; 494: } 495: 496: if (lw == IDCANCEL) 497: { 498: KeyFileRemoveAll (¶m->FirstKeyFile); 499: *param = origParam; 500: 501: EndDialog (hwndDlg, IDCLOSE); 502: return 1; 503: } 504: 505: case WM_DROPFILES: 506: { 507: HDROP hdrop = (HDROP) wParam; 508: 509: int i = 0, count = DragQueryFile (hdrop, -1, NULL, 0); 510: 511: while (count-- > 0) 512: { 513: KeyFile *kf = malloc (sizeof (KeyFile)); 514: DragQueryFile (hdrop, i++, kf->FileName, sizeof (kf->FileName)); 515: param->FirstKeyFile = KeyFileAdd (param->FirstKeyFile, kf); 516: LoadKeyList (hwndDlg, param->FirstKeyFile); 517: } 518: 519: DragFinish (hdrop); 520: } 521: return 1; 522: 523: case WM_NOTIFY: 524: if (((LPNMHDR) lParam)->code == LVN_ITEMCHANGED) 525: { 526: EnableWindow (GetDlgItem (hwndDlg, IDC_KEYREMOVE), 527: ListView_GetNextItem (GetDlgItem (hwndDlg, IDC_KEYLIST), -1, LVIS_SELECTED) != -1); 528: return 1; 529: } 530: break; 531: 532: case WM_CLOSE: 533: KeyFileRemoveAll (¶m->FirstKeyFile); 534: *param = origParam; 535: 536: EndDialog (hwndDlg, IDCLOSE); 537: return 1; 538: 539: break; 540: 541: } 542: 543: return 0; 544: } 545: 546: 547: #endif /* #ifdef _WIN32 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.