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