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