|
|
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
1.1.1.15 root 7: this file are Copyright (c) 2003-2009 TrueCrypt Foundation and are governed
1.1.1.16! root 8: by the TrueCrypt License 2.7 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 "Volumes.h"
16: #include "Password.h"
17: #include "Dlgcode.h"
18: #include "Language.h"
19: #include "Pkcs5.h"
1.1.1.14 root 20: #include "Endian.h"
1.1.1.6 root 21: #include "Random.h"
1.1 root 22:
23: #include <io.h>
24:
1.1.1.14 root 25: void VerifyPasswordAndUpdate (HWND hwndDlg, HWND hButton, HWND hPassword,
1.1.1.12 root 26: HWND hVerify, unsigned char *szPassword,
1.1.1.6 root 27: char *szVerify,
28: BOOL keyFilesEnabled)
1.1 root 29: {
30: char szTmp1[MAX_PASSWORD + 1];
31: char szTmp2[MAX_PASSWORD + 1];
32: int k = GetWindowTextLength (hPassword);
33: BOOL bEnable = FALSE;
34:
35: if (hwndDlg); /* Remove warning */
36:
37: GetWindowText (hPassword, szTmp1, sizeof (szTmp1));
38: GetWindowText (hVerify, szTmp2, sizeof (szTmp2));
39:
40: if (strcmp (szTmp1, szTmp2) != 0)
41: bEnable = FALSE;
42: else
43: {
1.1.1.6 root 44: if (k >= MIN_PASSWORD || keyFilesEnabled)
1.1 root 45: bEnable = TRUE;
46: else
47: bEnable = FALSE;
48: }
49:
50: if (szPassword != NULL)
51: memcpy (szPassword, szTmp1, sizeof (szTmp1));
52:
53: if (szVerify != NULL)
54: memcpy (szVerify, szTmp2, sizeof (szTmp2));
55:
56: burn (szTmp1, sizeof (szTmp1));
57: burn (szTmp2, sizeof (szTmp2));
58:
59: EnableWindow (hButton, bEnable);
60: }
61:
1.1.1.6 root 62:
63: BOOL CheckPasswordCharEncoding (HWND hPassword, Password *ptrPw)
64: {
1.1.1.8 root 65: int i, len;
1.1.1.6 root 66:
67: if (hPassword == NULL)
68: {
1.1.1.8 root 69: unsigned char *pw;
1.1.1.6 root 70: len = ptrPw->Length;
71: pw = (unsigned char *) ptrPw->Text;
1.1.1.8 root 72:
73: for (i = 0; i < len; i++)
74: {
75: if (pw[i] >= 0x7f || pw[i] < 0x20) // A non-ASCII or non-printable character?
76: return FALSE;
77: }
1.1.1.6 root 78: }
79: else
80: {
1.1.1.8 root 81: wchar_t s[MAX_PASSWORD + 1];
1.1.1.6 root 82: len = GetWindowTextLength (hPassword);
83:
1.1.1.8 root 84: if (len > MAX_PASSWORD)
85: return FALSE;
86:
87: GetWindowTextW (hPassword, s, sizeof (s) / sizeof (wchar_t));
88:
89: for (i = 0; i < len; i++)
90: {
91: if (s[i] >= 0x7f || s[i] < 0x20) // A non-ASCII or non-printable character?
92: break;
93: }
94:
95: burn (s, sizeof(s));
96:
97: if (i < len)
98: return FALSE;
1.1.1.6 root 99: }
1.1.1.8 root 100:
1.1.1.6 root 101: return TRUE;
102: }
103:
104:
105: BOOL CheckPasswordLength (HWND hwndDlg, HWND hwndItem)
106: {
107: if (GetWindowTextLength (hwndItem) < PASSWORD_LEN_WARNING)
108: {
1.1.1.14 root 109: #ifndef _DEBUG
1.1.1.6 root 110: if (MessageBoxW (hwndDlg, GetString ("PASSWORD_LENGTH_WARNING"), lpszTitle, MB_YESNO|MB_ICONWARNING|MB_DEFBUTTON2) != IDYES)
111: return FALSE;
1.1.1.14 root 112: #endif
1.1.1.6 root 113: }
114: return TRUE;
115: }
116:
1.1.1.14 root 117: int ChangePwd (char *lpszVolume, Password *oldPassword, Password *newPassword, int pkcs5, HWND hwndDlg)
1.1 root 118: {
1.1.1.10 root 119: int nDosLinkCreated = 1, nStatus = ERR_OS_ERROR;
1.1 root 120: char szDiskFile[TC_MAX_PATH], szCFDevice[TC_MAX_PATH];
121: char szDosDevice[TC_MAX_PATH];
1.1.1.13 root 122: char buffer[TC_VOLUME_HEADER_EFFECTIVE_SIZE];
1.1 root 123: PCRYPTO_INFO cryptoInfo = NULL, ci = NULL;
124: void *dev = INVALID_HANDLE_VALUE;
125: DWORD dwError;
126: BOOL bDevice;
1.1.1.13 root 127: unsigned __int64 hostSize = 0;
1.1.1.6 root 128: int volumeType;
129: int wipePass;
1.1.1.4 root 130: FILETIME ftCreationTime;
131: FILETIME ftLastWriteTime;
132: FILETIME ftLastAccessTime;
133: BOOL bTimeStampValid = FALSE;
1.1.1.13 root 134: LARGE_INTEGER headerOffset;
135: BOOL backupHeader;
1.1.1.10 root 136:
1.1.1.6 root 137: if (oldPassword->Length == 0 || newPassword->Length == 0) return -1;
1.1 root 138:
1.1.1.10 root 139: WaitCursor ();
140:
1.1 root 141: CreateFullVolumePath (szDiskFile, lpszVolume, &bDevice);
142:
1.1.1.4 root 143: if (bDevice == FALSE)
144: {
145: strcpy (szCFDevice, szDiskFile);
146: }
147: else
1.1 root 148: {
1.1.1.4 root 149: nDosLinkCreated = FakeDosNameForDevice (szDiskFile, szDosDevice, szCFDevice, FALSE);
1.1.1.10 root 150:
1.1.1.4 root 151: if (nDosLinkCreated != 0)
1.1.1.10 root 152: goto error;
1.1.1.4 root 153: }
1.1 root 154:
1.1.1.4 root 155: dev = CreateFile (szCFDevice, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
156:
1.1.1.14 root 157: if (dev == INVALID_HANDLE_VALUE)
158: goto error;
159:
1.1.1.6 root 160: if (bDevice)
1.1.1.4 root 161: {
1.1.1.6 root 162: /* This is necessary to determine the hidden volume header offset */
1.1.1.4 root 163:
164: if (dev == INVALID_HANDLE_VALUE)
1.1 root 165: {
1.1.1.10 root 166: goto error;
1.1 root 167: }
168: else
169: {
1.1.1.6 root 170: PARTITION_INFORMATION diskInfo;
1.1.1.4 root 171: DWORD dwResult;
172: BOOL bResult;
173:
1.1.1.10 root 174: bResult = GetPartitionInfo (lpszVolume, &diskInfo);
1.1.1.4 root 175:
1.1.1.6 root 176: if (bResult)
1.1 root 177: {
1.1.1.13 root 178: hostSize = diskInfo.PartitionLength.QuadPart;
1.1.1.6 root 179: }
180: else
181: {
182: DISK_GEOMETRY driveInfo;
1.1.1.4 root 183:
1.1.1.6 root 184: bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
185: &driveInfo, sizeof (driveInfo), &dwResult, NULL);
1.1.1.4 root 186:
1.1.1.6 root 187: if (!bResult)
1.1.1.10 root 188: goto error;
1.1.1.6 root 189:
1.1.1.13 root 190: hostSize = driveInfo.Cylinders.QuadPart * driveInfo.BytesPerSector *
1.1.1.4 root 191: driveInfo.SectorsPerTrack * driveInfo.TracksPerCylinder;
1.1 root 192: }
1.1.1.6 root 193:
1.1.1.13 root 194: if (hostSize == 0)
1.1.1.6 root 195: {
1.1.1.10 root 196: nStatus = ERR_VOL_SIZE_WRONG;
197: goto error;
1.1.1.6 root 198: }
1.1 root 199: }
200: }
1.1.1.13 root 201: else
202: {
203: LARGE_INTEGER fileSize;
204: if (!GetFileSizeEx (dev, &fileSize))
205: {
206: nStatus = ERR_OS_ERROR;
207: goto error;
208: }
209:
210: hostSize = fileSize.QuadPart;
211: }
1.1.1.4 root 212:
1.1.1.6 root 213: if (Randinit ())
1.1.1.10 root 214: goto error;
1.1.1.6 root 215:
216: if (!bDevice && bPreserveTimestamp)
1.1 root 217: {
1.1.1.4 root 218: /* Remember the container modification/creation date and time, (used to reset file date and time of
1.1.1.6 root 219: file-hosted volumes after password change (or attempt to), in order to preserve plausible deniability
1.1.1.4 root 220: of hidden volumes (last password change time is stored in the volume header). */
1.1 root 221:
1.1.1.4 root 222: if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1 root 223: {
1.1.1.4 root 224: bTimeStampValid = FALSE;
1.1.1.6 root 225: MessageBoxW (hwndDlg, GetString ("GETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
1.1 root 226: }
1.1.1.4 root 227: else
228: bTimeStampValid = TRUE;
1.1 root 229: }
230:
1.1.1.13 root 231: for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++)
1.1 root 232: {
1.1.1.13 root 233: // Seek the volume header
234: switch (volumeType)
235: {
236: case TC_VOLUME_TYPE_NORMAL:
237: headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET;
238: break;
1.1 root 239:
1.1.1.13 root 240: case TC_VOLUME_TYPE_HIDDEN:
241: if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > hostSize)
242: continue;
1.1 root 243:
1.1.1.13 root 244: headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
245: break;
246:
247: case TC_VOLUME_TYPE_HIDDEN_LEGACY:
248: headerOffset.QuadPart = hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
249: break;
250: }
251:
252: if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.6 root 253: {
1.1.1.13 root 254: nStatus = ERR_OS_ERROR;
255: goto error;
1.1.1.6 root 256: }
1.1 root 257:
1.1.1.13 root 258: /* Read in volume header */
1.1.1.8 root 259: nStatus = _lread ((HFILE) dev, buffer, sizeof (buffer));
1.1.1.6 root 260: if (nStatus != sizeof (buffer))
261: {
1.1.1.14 root 262: // Windows may report EOF when reading sectors from the last cluster of a device formatted as NTFS
263: memset (buffer, 0, sizeof (buffer));
1.1.1.6 root 264: }
1.1 root 265:
1.1.1.6 root 266: /* Try to decrypt the header */
1.1 root 267:
1.1.1.14 root 268: nStatus = ReadVolumeHeader (FALSE, buffer, oldPassword, &cryptoInfo, NULL);
1.1.1.6 root 269: if (nStatus == ERR_CIPHER_INIT_WEAK_KEY)
270: nStatus = 0; // We can ignore this error here
1.1 root 271:
1.1.1.6 root 272: if (nStatus == ERR_PASSWORD_WRONG)
273: {
274: continue; // Try next volume type
275: }
276: else if (nStatus != 0)
277: {
278: cryptoInfo = NULL;
279: goto error;
280: }
281: else
282: break;
283: }
1.1.1.4 root 284:
1.1 root 285: if (nStatus != 0)
286: {
287: cryptoInfo = NULL;
288: goto error;
289: }
290:
1.1.1.13 root 291: if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)
292: {
293: nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG;
294: goto error;
295: }
296:
1.1.1.6 root 297: // Change the PKCS-5 PRF if requested by user
298: if (pkcs5 != 0)
299: cryptoInfo->pkcs5 = pkcs5;
1.1 root 300:
1.1.1.13 root 301: RandSetHashFunction (cryptoInfo->pkcs5);
302:
1.1.1.15 root 303: NormalCursor();
304: UserEnrichRandomPool (hwndDlg);
1.1.1.16! root 305: EnableElevatedCursorChange (hwndDlg);
1.1.1.15 root 306: WaitCursor();
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
1.1.1.14 root 328: nStatus = CreateVolumeHeaderInMemory (FALSE,
1.1.1.13 root 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.15 root 363: if (bDevice
364: && !cryptoInfo->LegacyVolume
365: && !cryptoInfo->hiddenVolume
366: && cryptoInfo->HeaderVersion == 4
367: && (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0
368: && (cryptoInfo->HeaderFlags & ~TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0)
369: {
370: nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, cryptoInfo->VolumeSize.Value, !backupHeader, backupHeader);
371: if (nStatus != ERR_SUCCESS)
372: goto error;
373: }
374:
1.1.1.13 root 375: FlushFileBuffers (dev);
1.1.1.6 root 376: }
1.1.1.13 root 377:
378: if (backupHeader || cryptoInfo->LegacyVolume)
379: break;
380:
381: backupHeader = TRUE;
382: headerOffset.QuadPart += hostSize - TC_VOLUME_HEADER_GROUP_SIZE;
1.1 root 383: }
384:
1.1.1.6 root 385: /* Password successfully changed */
1.1 root 386: nStatus = 0;
387:
1.1.1.6 root 388: error:
1.1.1.10 root 389: dwError = GetLastError ();
390:
1.1 root 391: burn (buffer, sizeof (buffer));
392:
393: if (cryptoInfo != NULL)
394: crypto_close (cryptoInfo);
395:
1.1.1.4 root 396: if (bTimeStampValid)
1.1 root 397: {
1.1.1.4 root 398: // Restore the container timestamp (to preserve plausible deniability of possible hidden volume).
399: if (SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
1.1.1.6 root 400: MessageBoxW (hwndDlg, GetString ("SETFILETIME_FAILED_PW"), L"TrueCrypt", MB_OK | MB_ICONEXCLAMATION);
1.1.1.4 root 401: }
402:
1.1.1.10 root 403: if (dev != INVALID_HANDLE_VALUE)
404: CloseHandle ((HANDLE) dev);
1.1 root 405:
1.1.1.10 root 406: if (nDosLinkCreated == 0)
407: RemoveFakeDosName (szDiskFile, szDosDevice);
408:
1.1.1.15 root 409: RandStop (FALSE);
1.1.1.10 root 410: NormalCursor ();
1.1 root 411:
412: SetLastError (dwError);
413:
1.1.1.10 root 414: if (nStatus == ERR_OS_ERROR && dwError == ERROR_ACCESS_DENIED
415: && bDevice
416: && !UacElevated
417: && IsUacSupported ())
418: return nStatus;
1.1 root 419:
1.1.1.10 root 420: if (nStatus != 0)
421: handleError (hwndDlg, nStatus);
1.1.1.6 root 422:
1.1 root 423: return nStatus;
424: }
1.1.1.4 root 425:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.