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