|
|
1.1.1.5 root 1: /* 1.1.1.7 ! root 2: Copyright (c) 2005 TrueCrypt Foundation. All rights reserved. 1.1 root 3: 1.1.1.7 ! root 4: Governed by the TrueCrypt License 2.4 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: 1.1.1.7 ! root 71: burn (keyFile, sizeof(*keyFile)); // wipe 1.1 root 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.