|
|
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
1.1.1.18 root 6: the original source code (contained in this file) and all other portions
1.1.1.19! root 7: of this file are Copyright (c) 2003-2010 TrueCrypt Developers Association
! 8: and are governed by the TrueCrypt License 3.0 the full text of which is
1.1.1.18 root 9: contained in the file License.txt included in TrueCrypt binary and source
10: code distribution 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;
1.1.1.19! root 126: DWORD bytesRead;
1.1 root 127: BOOL bDevice;
1.1.1.13 root 128: unsigned __int64 hostSize = 0;
1.1.1.6 root 129: int volumeType;
130: int wipePass;
1.1.1.4 root 131: FILETIME ftCreationTime;
132: FILETIME ftLastWriteTime;
133: FILETIME ftLastAccessTime;
134: BOOL bTimeStampValid = FALSE;
1.1.1.13 root 135: LARGE_INTEGER headerOffset;
136: BOOL backupHeader;
1.1.1.19! root 137: DISK_GEOMETRY driveInfo;
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.14 root 159: if (dev == INVALID_HANDLE_VALUE)
160: goto error;
161:
1.1.1.6 root 162: if (bDevice)
1.1.1.4 root 163: {
1.1.1.6 root 164: /* This is necessary to determine the hidden volume header offset */
1.1.1.4 root 165:
166: if (dev == INVALID_HANDLE_VALUE)
1.1 root 167: {
1.1.1.10 root 168: goto error;
1.1 root 169: }
170: else
171: {
1.1.1.6 root 172: PARTITION_INFORMATION diskInfo;
1.1.1.4 root 173: DWORD dwResult;
174: BOOL bResult;
175:
1.1.1.19! root 176: bResult = DeviceIoControl (dev, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
! 177: &driveInfo, sizeof (driveInfo), &dwResult, NULL);
! 178:
! 179: if (!bResult)
! 180: goto error;
! 181:
1.1.1.10 root 182: bResult = GetPartitionInfo (lpszVolume, &diskInfo);
1.1.1.4 root 183:
1.1.1.6 root 184: if (bResult)
1.1 root 185: {
1.1.1.13 root 186: hostSize = diskInfo.PartitionLength.QuadPart;
1.1.1.6 root 187: }
188: else
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: if (GetFileTime ((HANDLE) dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime) == 0)
219: bTimeStampValid = FALSE;
220: else
221: bTimeStampValid = TRUE;
1.1 root 222: }
223:
1.1.1.13 root 224: for (volumeType = TC_VOLUME_TYPE_NORMAL; volumeType < TC_VOLUME_TYPE_COUNT; volumeType++)
1.1 root 225: {
1.1.1.13 root 226: // Seek the volume header
227: switch (volumeType)
228: {
229: case TC_VOLUME_TYPE_NORMAL:
230: headerOffset.QuadPart = TC_VOLUME_HEADER_OFFSET;
231: break;
1.1 root 232:
1.1.1.13 root 233: case TC_VOLUME_TYPE_HIDDEN:
234: if (TC_HIDDEN_VOLUME_HEADER_OFFSET + TC_VOLUME_HEADER_SIZE > hostSize)
235: continue;
1.1 root 236:
1.1.1.13 root 237: headerOffset.QuadPart = TC_HIDDEN_VOLUME_HEADER_OFFSET;
238: break;
239:
240: case TC_VOLUME_TYPE_HIDDEN_LEGACY:
1.1.1.19! root 241: if (bDevice && driveInfo.BytesPerSector != TC_SECTOR_SIZE_LEGACY)
! 242: continue;
! 243:
1.1.1.13 root 244: headerOffset.QuadPart = hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
245: break;
246: }
247:
248: if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.6 root 249: {
1.1.1.13 root 250: nStatus = ERR_OS_ERROR;
251: goto error;
1.1.1.6 root 252: }
1.1 root 253:
1.1.1.13 root 254: /* Read in volume header */
1.1.1.19! root 255: if (!ReadEffectiveVolumeHeader (bDevice, dev, buffer, &bytesRead))
! 256: {
! 257: nStatus = ERR_OS_ERROR;
! 258: goto error;
! 259: }
! 260:
! 261: if (bytesRead != sizeof (buffer))
1.1.1.6 root 262: {
1.1.1.14 root 263: // Windows may report EOF when reading sectors from the last cluster of a device formatted as NTFS
264: memset (buffer, 0, sizeof (buffer));
1.1.1.6 root 265: }
1.1 root 266:
1.1.1.6 root 267: /* Try to decrypt the header */
1.1 root 268:
1.1.1.14 root 269: nStatus = ReadVolumeHeader (FALSE, buffer, oldPassword, &cryptoInfo, NULL);
1.1.1.6 root 270: if (nStatus == ERR_CIPHER_INIT_WEAK_KEY)
271: nStatus = 0; // We can ignore this error here
1.1 root 272:
1.1.1.6 root 273: if (nStatus == ERR_PASSWORD_WRONG)
274: {
275: continue; // Try next volume type
276: }
277: else if (nStatus != 0)
278: {
279: cryptoInfo = NULL;
280: goto error;
281: }
282: else
283: break;
284: }
1.1.1.4 root 285:
1.1 root 286: if (nStatus != 0)
287: {
288: cryptoInfo = NULL;
289: goto error;
290: }
291:
1.1.1.13 root 292: if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)
293: {
294: nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG;
295: goto error;
296: }
297:
1.1.1.6 root 298: // Change the PKCS-5 PRF if requested by user
299: if (pkcs5 != 0)
300: cryptoInfo->pkcs5 = pkcs5;
1.1 root 301:
1.1.1.13 root 302: RandSetHashFunction (cryptoInfo->pkcs5);
303:
1.1.1.15 root 304: NormalCursor();
305: UserEnrichRandomPool (hwndDlg);
1.1.1.16 root 306: EnableElevatedCursorChange (hwndDlg);
1.1.1.15 root 307: WaitCursor();
1.1 root 308:
1.1.1.6 root 309: /* Re-encrypt the volume header */
1.1.1.13 root 310: backupHeader = FALSE;
1.1.1.6 root 311:
1.1.1.13 root 312: while (TRUE)
1.1.1.6 root 313: {
1.1.1.13 root 314: /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using
315: techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy
316: to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22
317: times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might
318: impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the
319: valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman
320: recommends. During each pass we will write a valid working header. Each pass will use the same master
321: key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only
322: item that will be different for each pass will be the salt. This is sufficient to cause each "version"
323: of the header to differ substantially and in a random manner from the versions written during the
324: other passes. */
325:
326: for (wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
327: {
328: // Prepare new volume header
1.1.1.14 root 329: nStatus = CreateVolumeHeaderInMemory (FALSE,
1.1.1.13 root 330: buffer,
331: cryptoInfo->ea,
332: cryptoInfo->mode,
333: newPassword,
334: cryptoInfo->pkcs5,
335: cryptoInfo->master_keydata,
336: &ci,
337: cryptoInfo->VolumeSize.Value,
338: (volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) ? cryptoInfo->hiddenVolumeSize : 0,
339: cryptoInfo->EncryptedAreaStart.Value,
340: cryptoInfo->EncryptedAreaLength.Value,
341: cryptoInfo->RequiredProgramVersion,
342: cryptoInfo->HeaderFlags,
1.1.1.19! root 343: cryptoInfo->SectorSize,
1.1.1.13 root 344: wipePass < PRAND_DISK_WIPE_PASSES - 1);
345:
346: if (ci != NULL)
347: crypto_close (ci);
348:
349: if (nStatus != 0)
350: goto error;
351:
352: if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.6 root 353: {
1.1.1.13 root 354: nStatus = ERR_OS_ERROR;
1.1.1.6 root 355: goto error;
356: }
1.1.1.3 root 357:
1.1.1.19! root 358: if (!WriteEffectiveVolumeHeader (bDevice, dev, buffer))
1.1.1.6 root 359: {
1.1.1.13 root 360: nStatus = ERR_OS_ERROR;
1.1.1.6 root 361: goto error;
362: }
1.1 root 363:
1.1.1.15 root 364: if (bDevice
365: && !cryptoInfo->LegacyVolume
366: && !cryptoInfo->hiddenVolume
367: && cryptoInfo->HeaderVersion == 4
368: && (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0
369: && (cryptoInfo->HeaderFlags & ~TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0)
370: {
371: nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, cryptoInfo->VolumeSize.Value, !backupHeader, backupHeader);
372: if (nStatus != ERR_SUCCESS)
373: goto error;
374: }
375:
1.1.1.13 root 376: FlushFileBuffers (dev);
1.1.1.6 root 377: }
1.1.1.13 root 378:
379: if (backupHeader || cryptoInfo->LegacyVolume)
380: break;
381:
382: backupHeader = TRUE;
383: headerOffset.QuadPart += hostSize - TC_VOLUME_HEADER_GROUP_SIZE;
1.1 root 384: }
385:
1.1.1.6 root 386: /* Password successfully changed */
1.1 root 387: nStatus = 0;
388:
1.1.1.6 root 389: error:
1.1.1.10 root 390: dwError = GetLastError ();
391:
1.1 root 392: burn (buffer, sizeof (buffer));
393:
394: if (cryptoInfo != NULL)
395: crypto_close (cryptoInfo);
396:
1.1.1.4 root 397: if (bTimeStampValid)
1.1.1.18 root 398: SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);
1.1.1.4 root 399:
1.1.1.10 root 400: if (dev != INVALID_HANDLE_VALUE)
401: CloseHandle ((HANDLE) dev);
1.1 root 402:
1.1.1.10 root 403: if (nDosLinkCreated == 0)
404: RemoveFakeDosName (szDiskFile, szDosDevice);
405:
1.1.1.15 root 406: RandStop (FALSE);
1.1.1.10 root 407: NormalCursor ();
1.1 root 408:
409: SetLastError (dwError);
410:
1.1.1.10 root 411: if (nStatus == ERR_OS_ERROR && dwError == ERROR_ACCESS_DENIED
412: && bDevice
413: && !UacElevated
414: && IsUacSupported ())
415: return nStatus;
1.1 root 416:
1.1.1.10 root 417: if (nStatus != 0)
418: handleError (hwndDlg, nStatus);
1.1.1.6 root 419:
1.1 root 420: return nStatus;
421: }
1.1.1.4 root 422:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.