|
|
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
1.1.1.13! root 8: by the TrueCrypt License 2.5 the full text of which is contained in the
1.1.1.12 root 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.13! root 126: char buffer[TC_VOLUME_HEADER_EFFECTIVE_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.13! root 131: unsigned __int64 hostSize = 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.13! root 138: LARGE_INTEGER headerOffset;
! 139: BOOL backupHeader;
1.1.1.10 root 140:
1.1.1.6 root 141: if (oldPassword->Length == 0 || newPassword->Length == 0) return -1;
1.1 root 142:
1.1.1.10 root 143: WaitCursor ();
144:
1.1 root 145: CreateFullVolumePath (szDiskFile, lpszVolume, &bDevice);
146:
1.1.1.4 root 147: if (bDevice == FALSE)
148: {
149: strcpy (szCFDevice, szDiskFile);
150: }
151: else
1.1 root 152: {
1.1.1.4 root 153: nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE);
1.1.1.10 root 154:
1.1.1.4 root 155: if (nDosLinkCreated != 0)
1.1.1.10 root 156: goto error;
1.1.1.4 root 157: }
1.1 root 158:
1.1.1.4 root 159: dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
160:
1.1.1.6 root 161: if (bDevice)
1.1.1.4 root 162: {
1.1.1.6 root 163: /* This is necessary to determine the hidden volume header offset */
1.1.1.4 root 164:
165: if (dev == INVALID_HANDLE_VALUE)
1.1 root 166: {
1.1.1.10 root 167: goto error;
1.1 root 168: }
169: else
170: {
1.1.1.6 root 171: PARTITION_INFORMATION diskInfo;
1.1.1.4 root 172: DWORD dwResult;
173: BOOL bResult;
174:
1.1.1.10 root 175: bResult = GetPartitionInfo (lpszVolume, &diskInfo);
1.1.1.4 root 176:
1.1.1.6 root 177: if (bResult)
1.1 root 178: {
1.1.1.13! root 179: hostSize = diskInfo.PartitionLength.QuadPart;
1.1.1.6 root 180: }
181: else
182: {
183: DISK_GEOMETRY driveInfo;
1.1.1.4 root 184:
1.1.1.6 root 185: bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
186: &driveInfo, sizeof (driveInfo), &dwResult, NULL);
1.1.1.4 root 187:
1.1.1.6 root 188: if (!bResult)
1.1.1.10 root 189: goto error;
1.1.1.6 root 190:
1.1.1.13! root 191: hostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector *
1.1.1.4 root 192: driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder;
1.1 root 193: }
1.1.1.6 root 194:
1.1.1.13! root 195: if (hostSize == 0)
1.1.1.6 root 196: {
1.1.1.10 root 197: nStatus = ERR_VOL_SIZE_WRONG;
198: goto error;
1.1.1.6 root 199: }
1.1 root 200: }
201: }
1.1.1.13! root 202: else
! 203: {
! 204: LARGE_INTEGER fileSize;
! 205: if (!GetFileSizeEx (dev, &fileSize))
! 206: {
! 207: nStatus = ERR_OS_ERROR;
! 208: goto error;
! 209: }
! 210:
! 211: hostSize = fileSize.QuadPart;
! 212: }
1.1.1.4 root 213:
1.1.1.6 root 214: if (dev == INVALID_HANDLE_VALUE)
1.1.1.10 root 215: goto error;
1.1.1.4 root 216:
1.1.1.6 root 217: if (Randinit ())
1.1.1.10 root 218: goto error;
1.1.1.6 root 219:
220: if (!bDevice && bPreserveTimestamp)
1.1 root 221: {
1.1.1.4 root 222: /* Remember the container modification/creation date and time, (used to reset file date and time of
1.1.1.6 root 223: file-hosted volumes after password change (or attempt to), in order to preserve plausible deniability
1.1.1.4 root 224: of hidden volumes (last password change time is stored in the volume header). */
1.1 root 225:
1.1.1.4 root 226: if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1 root 227: {
1.1.1.4 root 228: bTimeStampValid = FALSE;
1.1.1.6 root 229: MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
1.1 root 230: }
1.1.1.4 root 231: else
232: bTimeStampValid = TRUE;
1.1 root 233: }
234:
1.1.1.13! root 235: for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++)
1.1 root 236: {
1.1.1.13! root 237: // Seek the volume header
! 238: switch (volumeType)
! 239: {
! 240: case TC_VOLUME_TYPE_NORMAL:
! 241: headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET;
! 242: break;
1.1 root 243:
1.1.1.13! root 244: case TC_VOLUME_TYPE_HIDDEN:
! 245: if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > hostSize)
! 246: continue;
1.1 root 247:
1.1.1.13! root 248: headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
! 249: break;
! 250:
! 251: case TC_VOLUME_TYPE_HIDDEN_LEGACY:
! 252: headerOffset.QuadPart = hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
! 253: break;
! 254: }
! 255:
! 256: if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.6 root 257: {
1.1.1.13! root 258: nStatus = ERR_OS_ERROR;
! 259: goto error;
1.1.1.6 root 260: }
1.1 root 261:
1.1.1.13! root 262: /* Read in volume header */
1.1.1.8 root 263: nStatus = _lread ((HFILE) dev, buffer, sizeof (buffer));
1.1.1.6 root 264: if (nStatus != sizeof (buffer))
265: {
266: nStatus = ERR_VOL_SIZE_WRONG;
267: goto error;
268: }
1.1 root 269:
1.1.1.6 root 270: /* Try to decrypt the header */
1.1 root 271:
1.1.1.12 root 272: nStatus = VolumeReadHeader (FALSE, buffer, oldPassword, &cryptoInfo, NULL);
1.1.1.6 root 273: if (nStatus == ERR_CIPHER_INIT_WEAK_KEY)
274: nStatus = 0; // We can ignore this error here
1.1 root 275:
1.1.1.6 root 276: if (nStatus == ERR_PASSWORD_WRONG)
277: {
278: continue; // Try next volume type
279: }
280: else if (nStatus != 0)
281: {
282: cryptoInfo = NULL;
283: goto error;
284: }
285: else
286: break;
287: }
1.1.1.4 root 288:
1.1 root 289: if (nStatus != 0)
290: {
291: cryptoInfo = NULL;
292: goto error;
293: }
294:
1.1.1.13! root 295: if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)
! 296: {
! 297: nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG;
! 298: goto error;
! 299: }
! 300:
1.1.1.6 root 301: // Change the PKCS-5 PRF if requested by user
302: if (pkcs5 != 0)
303: cryptoInfo->pkcs5 = pkcs5;
1.1 root 304:
1.1.1.13! root 305: RandSetHashFunction (cryptoInfo->pkcs5);
! 306:
1.1 root 307:
1.1.1.6 root 308: /* Re-encrypt the volume header */
1.1.1.13! root 309: backupHeader = FALSE;
1.1.1.6 root 310:
1.1.1.13! root 311: while (TRUE)
1.1.1.6 root 312: {
1.1.1.13! root 313: /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using
! 314: techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy
! 315: to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22
! 316: times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might
! 317: impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the
! 318: valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman
! 319: recommends. During each pass we will write a valid working header. Each pass will use the same master
! 320: key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only
! 321: item that will be different for each pass will be the salt. This is sufficient to cause each "version"
! 322: of the header to differ substantially and in a random manner from the versions written during the
! 323: other passes. */
! 324:
! 325: for (wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
! 326: {
! 327: // Prepare new volume header
! 328: nStatus = VolumeWriteHeader (FALSE,
! 329: buffer,
! 330: cryptoInfo->ea,
! 331: cryptoInfo->mode,
! 332: newPassword,
! 333: cryptoInfo->pkcs5,
! 334: cryptoInfo->master_keydata,
! 335: &ci,
! 336: cryptoInfo->VolumeSize.Value,
! 337: (volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) ? cryptoInfo->hiddenVolumeSize : 0,
! 338: cryptoInfo->EncryptedAreaStart.Value,
! 339: cryptoInfo->EncryptedAreaLength.Value,
! 340: cryptoInfo->RequiredProgramVersion,
! 341: cryptoInfo->HeaderFlags,
! 342: wipePass < PRAND_DISK_WIPE_PASSES - 1);
! 343:
! 344: if (ci != NULL)
! 345: crypto_close (ci);
! 346:
! 347: if (nStatus != 0)
! 348: goto error;
! 349:
! 350: if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.6 root 351: {
1.1.1.13! root 352: nStatus = ERR_OS_ERROR;
1.1.1.6 root 353: goto error;
354: }
1.1.1.3 root 355:
1.1.1.13! root 356: nStatus = _lwrite ((HFILE) dev, buffer, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
! 357: if (nStatus != TC_VOLUME_HEADER_EFFECTIVE_SIZE)
1.1.1.6 root 358: {
1.1.1.13! root 359: nStatus = ERR_OS_ERROR;
1.1.1.6 root 360: goto error;
361: }
1.1 root 362:
1.1.1.13! root 363: FlushFileBuffers (dev);
1.1.1.6 root 364: }
1.1.1.13! root 365:
! 366: if (backupHeader || cryptoInfo->LegacyVolume)
! 367: break;
! 368:
! 369: backupHeader = TRUE;
! 370: headerOffset.QuadPart += hostSize - TC_VOLUME_HEADER_GROUP_SIZE;
1.1 root 371: }
372:
1.1.1.6 root 373: /* Password successfully changed */
1.1 root 374: nStatus = 0;
375:
1.1.1.6 root 376: error:
1.1.1.10 root 377: dwError = GetLastError ();
378:
1.1 root 379: burn (buffer, sizeof (buffer));
380:
381: if (cryptoInfo != NULL)
382: crypto_close (cryptoInfo);
383:
1.1.1.4 root 384: if (bTimeStampValid)
1.1 root 385: {
1.1.1.4 root 386: // Restore the container timestamp (to preserve plausible deniability of possible hidden volume).
387: if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1.1.6 root 388: MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
1.1.1.4 root 389: }
390:
1.1.1.10 root 391: if (dev != INVALID_HANDLE_VALUE)
392: CloseHandle ((HANDLE) dev);
1.1 root 393:
1.1.1.10 root 394: if (nDosLinkCreated == 0)
395: RemoveFakeDosName (szDiskFile, szDosDevice);
396:
397: NormalCursor ();
398: Randfree ();
1.1 root 399:
400: SetLastError (dwError);
401:
1.1.1.10 root 402: if (nStatus == ERR_OS_ERROR && dwError == ERROR_ACCESS_DENIED
403: && bDevice
404: && !UacElevated
405: && IsUacSupported ())
406: return nStatus;
1.1 root 407:
1.1.1.10 root 408: if (nStatus != 0)
409: handleError (hwndDlg, nStatus);
1.1.1.6 root 410:
1.1 root 411: return nStatus;
412: }
1.1.1.4 root 413:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.