|
|
1.1.1.6 ! root 1: /* Legal Notice: The source code contained in this file has been derived from ! 2: the source code of Encryption for the Masses 2.02a, which is Copyright (c) ! 3: 1998-99 Paul Le Roux and which is covered by the 'License Agreement for ! 4: Encryption for the Masses'. Modifications and additions to that source code ! 5: contained in this file are Copyright (c) 2004-2005 TrueCrypt Foundation and ! 6: Copyright (c) 2004 TrueCrypt Team, and are covered by TrueCrypt License 2.0 ! 7: the full text of which is contained in the file License.txt included in ! 8: TrueCrypt binary and source code distribution archives. */ ! 9: ! 10: #include "Tcdefs.h" ! 11: ! 12: #include "Crypto.h" ! 13: #include "Fat.h" ! 14: #include "Format.h" ! 15: #include "Volumes.h" ! 16: #include "Password.h" ! 17: #include "Apidrvr.h" ! 18: #include "Dlgcode.h" ! 19: #include "Language.h" ! 20: #include "Pkcs5.h" ! 21: #include "Endian.h" ! 22: #include "Resource.h" ! 23: #include "Random.h" 1.1 root 24: 25: #include <io.h> 26: 27: void 28: VerifyPasswordAndUpdate (HWND hwndDlg, HWND hButton, HWND hPassword, 29: HWND hVerify, char *szPassword, 1.1.1.6 ! root 30: char *szVerify, ! 31: BOOL keyFilesEnabled) 1.1 root 32: { 33: char szTmp1[MAX_PASSWORD + 1]; 34: char szTmp2[MAX_PASSWORD + 1]; 35: int k = GetWindowTextLength (hPassword); 36: BOOL bEnable = FALSE; 37: 38: if (hwndDlg); /* Remove warning */ 39: 40: GetWindowText (hPassword, szTmp1, sizeof (szTmp1)); 41: GetWindowText (hVerify, szTmp2, sizeof (szTmp2)); 42: 43: if (strcmp (szTmp1, szTmp2) != 0) 44: bEnable = FALSE; 45: else 46: { 1.1.1.6 ! root 47: if (k >= MIN_PASSWORD || keyFilesEnabled) 1.1 root 48: bEnable = TRUE; 49: else 50: bEnable = FALSE; 51: } 52: 53: if (szPassword != NULL) 54: memcpy (szPassword, szTmp1, sizeof (szTmp1)); 55: 56: if (szVerify != NULL) 57: memcpy (szVerify, szTmp2, sizeof (szTmp2)); 58: 59: burn (szTmp1, sizeof (szTmp1)); 60: burn (szTmp2, sizeof (szTmp2)); 61: 62: EnableWindow (hButton, bEnable); 63: } 64: 1.1.1.6 ! root 65: ! 66: BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw) ! 67: { ! 68: char szTmp[MAX_PASSWORD + 1]; ! 69: unsigned char *pw; ! 70: int i; ! 71: int len; ! 72: ! 73: if (hPassword == NULL) ! 74: { ! 75: len = ptrPw->Length; ! 76: pw = (unsigned char *) ptrPw->Text; ! 77: } ! 78: else ! 79: { ! 80: len = GetWindowTextLength (hPassword); ! 81: GetWindowText (hPassword, szTmp, sizeof (szTmp)); ! 82: pw = (unsigned char *) szTmp; ! 83: } ! 84: ! 85: for (i = 0; i < len; i++) ! 86: { ! 87: if (pw[i] >= 0x7f || pw[i] < 0x20) // A non-ASCII or non-printable character? ! 88: return FALSE; ! 89: } ! 90: return TRUE; ! 91: } ! 92: ! 93: ! 94: BOOL CheckPasswordLength (HWND hwndDlg, HWND hwndItem) ! 95: { ! 96: if (GetWindowTextLength (hwndItem) < PASSWORD_LEN_WARNING) ! 97: { ! 98: if (MessageBoxW (hwndDlg, GetString ("PASSWORD_LENGTH_WARNING"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) != IDYES) ! 99: return FALSE; ! 100: } ! 101: return TRUE; ! 102: } ! 103: 1.1 root 104: int 1.1.1.6 ! root 105: ChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg) 1.1 root 106: { 107: int nDosLinkCreated = 0, nStatus; 108: char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH]; 109: char szDosDevice[TC_MAX_PATH]; 1.1.1.6 ! root 110: char buffer[HEADER_SIZE]; 1.1 root 111: PCRYPTO_INFO cryptoInfo = NULL, ci = NULL; 112: void *dev = INVALID_HANDLE_VALUE; 113: diskio_f write, read; 114: DWORD dwError; 115: BOOL bDevice; 1.1.1.4 root 116: unsigned __int64 volSize = 0; 1.1.1.6 ! root 117: int volumeType; ! 118: int wipePass; 1.1.1.4 root 119: FILETIME ftCreationTime; 120: FILETIME ftLastWriteTime; 121: FILETIME ftLastAccessTime; 122: BOOL bTimeStampValid = FALSE; 1.1 root 123: 1.1.1.6 ! root 124: if (oldPassword->Length == 0 || newPassword->Length == 0) return -1; 1.1 root 125: 126: CreateFullVolumePath (szDiskFile, lpszVolume, &bDevice); 127: 1.1.1.4 root 128: write = (diskio_f) _lwrite; 129: read = (diskio_f) _lread; 130: 131: if (bDevice == FALSE) 132: { 133: strcpy (szCFDevice, szDiskFile); 134: } 135: else 1.1 root 136: { 1.1.1.4 root 137: nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE); 138: if (nDosLinkCreated != 0) 139: { 140: return nDosLinkCreated; 141: } 142: } 1.1 root 143: 1.1.1.4 root 144: dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); 145: 1.1.1.6 ! root 146: if (bDevice) 1.1.1.4 root 147: { 1.1.1.6 ! root 148: /* This is necessary to determine the hidden volume header offset */ 1.1.1.4 root 149: 150: if (dev == INVALID_HANDLE_VALUE) 1.1 root 151: { 1.1.1.4 root 152: return ERR_OS_ERROR; 1.1 root 153: } 154: else 155: { 1.1.1.6 ! root 156: PARTITION_INFORMATION diskInfo; 1.1.1.4 root 157: DWORD dwResult; 158: BOOL bResult; 159: 1.1.1.6 ! root 160: bResult = DeviceIoControl (dev, IOCTL_DISK_GET_PARTITION_INFO, NULL, 0, ! 161: &diskInfo, sizeof (diskInfo), &dwResult, NULL); 1.1.1.4 root 162: 1.1.1.6 ! root 163: if (bResult) 1.1 root 164: { 1.1.1.6 ! root 165: volSize = diskInfo.PartitionLength.QuadPart; ! 166: } ! 167: else ! 168: { ! 169: DISK_GEOMETRY driveInfo; 1.1.1.4 root 170: 1.1.1.6 ! root 171: bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, ! 172: &driveInfo, sizeof (driveInfo), &dwResult, NULL); 1.1.1.4 root 173: 1.1.1.6 ! root 174: if (!bResult) 1.1.1.4 root 175: { 176: CloseHandle (dev); 177: return ERR_OS_ERROR; 178: } 1.1.1.6 ! root 179: 1.1.1.4 root 180: volSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector * 181: driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder; 1.1 root 182: } 1.1.1.6 ! root 183: ! 184: if (volSize == 0) ! 185: { ! 186: CloseHandle (dev); ! 187: return ERR_VOL_SIZE_WRONG; ! 188: } 1.1 root 189: } 190: } 1.1.1.4 root 191: 1.1.1.6 ! root 192: if (dev == INVALID_HANDLE_VALUE) ! 193: return ERR_OS_ERROR; 1.1.1.4 root 194: 195: WaitCursor (); 196: 1.1.1.6 ! root 197: if (Randinit ()) ! 198: return -1; ! 199: ! 200: if (!bDevice && bPreserveTimestamp) 1.1 root 201: { 1.1.1.4 root 202: /* Remember the container modification/creation date and time, (used to reset file date and time of 1.1.1.6 ! root 203: file-hosted volumes after password change (or attempt to), in order to preserve plausible deniability 1.1.1.4 root 204: of hidden volumes (last password change time is stored in the volume header). */ 1.1 root 205: 1.1.1.4 root 206: if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) 1.1 root 207: { 1.1.1.4 root 208: bTimeStampValid = FALSE; 1.1.1.6 ! root 209: MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION); 1.1 root 210: } 1.1.1.4 root 211: else 212: bTimeStampValid = TRUE; 1.1 root 213: } 214: 1.1.1.6 ! root 215: for (volumeType = VOLUME_TYPE_NORMAL; volumeType < NBR_VOLUME_TYPES; volumeType++) 1.1 root 216: { 217: 1.1.1.6 ! root 218: /* Read in volume header */ 1.1 root 219: 1.1.1.6 ! root 220: if (volumeType == VOLUME_TYPE_HIDDEN) ! 221: { ! 222: if (!SeekHiddenVolHeader ((HFILE) dev, volSize, bDevice)) ! 223: { ! 224: nStatus = ERR_VOL_SEEKING; ! 225: goto error; ! 226: } ! 227: } 1.1 root 228: 1.1.1.6 ! root 229: nStatus = (*read) ((HFILE) dev, buffer, sizeof (buffer)); ! 230: if (nStatus != sizeof (buffer)) ! 231: { ! 232: nStatus = ERR_VOL_SIZE_WRONG; ! 233: goto error; ! 234: } 1.1 root 235: 1.1.1.6 ! root 236: /* Try to decrypt the header */ 1.1 root 237: 1.1.1.6 ! root 238: nStatus = VolumeReadHeader (buffer, oldPassword, &cryptoInfo); ! 239: if (nStatus == ERR_CIPHER_INIT_WEAK_KEY) ! 240: nStatus = 0; // We can ignore this error here 1.1 root 241: 1.1.1.6 ! root 242: if (nStatus == ERR_PASSWORD_WRONG) ! 243: { ! 244: continue; // Try next volume type ! 245: } ! 246: else if (nStatus != 0) ! 247: { ! 248: cryptoInfo = NULL; ! 249: goto error; ! 250: } ! 251: else ! 252: break; ! 253: } 1.1.1.4 root 254: 1.1 root 255: if (nStatus != 0) 256: { 257: cryptoInfo = NULL; 258: goto error; 259: } 260: 1.1.1.6 ! root 261: // Change the PKCS-5 PRF if requested by user ! 262: if (pkcs5 != 0) ! 263: cryptoInfo->pkcs5 = pkcs5; 1.1 root 264: 265: 1.1.1.6 ! root 266: /* Re-encrypt the volume header */ ! 267: ! 268: /* The header will be re-encrypted DISK_WIPE_PASSES times to prevent adversaries from using ! 269: techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy ! 270: to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22 ! 271: times (ideally, 35 times). As users might impatiently interupt the process (e.g. on slow media) ! 272: we will not wipe with just random data. Instead, during each pass we will write a valid working ! 273: header. Each pass will use the same master key, and also the same header key, IV, etc. derived ! 274: from the new password. The only item that will be different for each pass will be the salt. ! 275: This is sufficient to cause each "version" of the header to differ substantially and in a ! 276: random manner from the versions written during the other passes. */ ! 277: for (wipePass = 0; wipePass < DISK_WIPE_PASSES; wipePass++) ! 278: { ! 279: // Seek the volume header ! 280: if (volumeType == VOLUME_TYPE_HIDDEN) 1.1 root 281: { 1.1.1.6 ! root 282: if (!SeekHiddenVolHeader ((HFILE) dev, volSize, bDevice)) ! 283: { ! 284: nStatus = ERR_VOL_SEEKING; ! 285: goto error; ! 286: } 1.1 root 287: } 1.1.1.6 ! root 288: else ! 289: { ! 290: nStatus = _llseek ((HFILE) dev, 0, FILE_BEGIN); 1.1.1.3 root 291: 1.1.1.6 ! root 292: if (nStatus != 0) ! 293: { ! 294: nStatus = ERR_VOL_SEEKING; ! 295: goto error; ! 296: } ! 297: } 1.1 root 298: 1.1.1.6 ! root 299: // Prepare new volume header ! 300: nStatus = VolumeWriteHeader (buffer, ! 301: cryptoInfo->ea, ! 302: newPassword, ! 303: cryptoInfo->pkcs5, ! 304: cryptoInfo->master_key, ! 305: cryptoInfo->volume_creation_time, ! 306: &ci, ! 307: volumeType == VOLUME_TYPE_HIDDEN ? cryptoInfo->hiddenVolumeSize : 0, ! 308: wipePass < DISK_WIPE_PASSES - 1); 1.1 root 309: 1.1.1.6 ! root 310: if (ci != NULL) ! 311: crypto_close (ci); 1.1 root 312: 1.1.1.6 ! root 313: if (nStatus != 0) ! 314: goto error; 1.1.1.4 root 315: 1.1.1.6 ! root 316: // Write the new header ! 317: nStatus = (*write) ((HFILE) dev, buffer, HEADER_SIZE); ! 318: if (nStatus != HEADER_SIZE) ! 319: { ! 320: nStatus = ERR_VOL_WRITING; ! 321: goto error; ! 322: } ! 323: FlushFileBuffers (dev); 1.1 root 324: } 325: 1.1.1.6 ! root 326: /* Password successfully changed */ 1.1 root 327: nStatus = 0; 328: 1.1.1.6 ! root 329: error: 1.1 root 330: burn (buffer, sizeof (buffer)); 331: 332: if (cryptoInfo != NULL) 333: crypto_close (cryptoInfo); 334: 335: dwError = GetLastError (); 336: 1.1.1.4 root 337: if (bTimeStampValid) 1.1 root 338: { 1.1.1.4 root 339: // Restore the container timestamp (to preserve plausible deniability of possible hidden volume). 340: if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0) 1.1.1.6 ! root 341: MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION); 1.1.1.4 root 342: } 343: 344: CloseHandle ((HANDLE) dev); 1.1 root 345: 1.1.1.6 ! root 346: if (bDevice && nDosLinkCreated != 0) 1.1.1.4 root 347: { 348: int x = RemoveFakeDosName (szDiskFile, szDosDevice); 349: if (x != 0) 1.1 root 350: { 1.1.1.4 root 351: dwError = GetLastError (); 352: nStatus = x; 1.1 root 353: } 354: } 355: 356: SetLastError (dwError); 357: 358: NormalCursor (); 359: 1.1.1.6 ! root 360: Randfree (); ! 361: 1.1 root 362: return nStatus; 363: } 1.1.1.4 root 364:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.