|
|
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
! 7: of this file are Copyright (c) 2003-2009 TrueCrypt Developers Association
! 8: and are governed by the TrueCrypt License 2.8 the full text of which is
! 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;
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: 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:
241: headerOffset.QuadPart = hostSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
242: break;
243: }
244:
245: if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.6 root 246: {
1.1.1.13 root 247: nStatus = ERR_OS_ERROR;
248: goto error;
1.1.1.6 root 249: }
1.1 root 250:
1.1.1.13 root 251: /* Read in volume header */
1.1.1.8 root 252: nStatus = _lread ((HFILE) dev, buffer, sizeof (buffer));
1.1.1.6 root 253: if (nStatus != sizeof (buffer))
254: {
1.1.1.14 root 255: // Windows may report EOF when reading sectors from the last cluster of a device formatted as NTFS
256: memset (buffer, 0, sizeof (buffer));
1.1.1.6 root 257: }
1.1 root 258:
1.1.1.6 root 259: /* Try to decrypt the header */
1.1 root 260:
1.1.1.14 root 261: nStatus = ReadVolumeHeader (FALSE, buffer, oldPassword, &cryptoInfo, NULL);
1.1.1.6 root 262: if (nStatus == ERR_CIPHER_INIT_WEAK_KEY)
263: nStatus = 0; // We can ignore this error here
1.1 root 264:
1.1.1.6 root 265: if (nStatus == ERR_PASSWORD_WRONG)
266: {
267: continue; // Try next volume type
268: }
269: else if (nStatus != 0)
270: {
271: cryptoInfo = NULL;
272: goto error;
273: }
274: else
275: break;
276: }
1.1.1.4 root 277:
1.1 root 278: if (nStatus != 0)
279: {
280: cryptoInfo = NULL;
281: goto error;
282: }
283:
1.1.1.13 root 284: if (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_ENCRYPTED_SYSTEM)
285: {
286: nStatus = ERR_SYS_HIDVOL_HEAD_REENC_MODE_WRONG;
287: goto error;
288: }
289:
1.1.1.6 root 290: // Change the PKCS-5 PRF if requested by user
291: if (pkcs5 != 0)
292: cryptoInfo->pkcs5 = pkcs5;
1.1 root 293:
1.1.1.13 root 294: RandSetHashFunction (cryptoInfo->pkcs5);
295:
1.1.1.15 root 296: NormalCursor();
297: UserEnrichRandomPool (hwndDlg);
1.1.1.16 root 298: EnableElevatedCursorChange (hwndDlg);
1.1.1.15 root 299: WaitCursor();
1.1 root 300:
1.1.1.6 root 301: /* Re-encrypt the volume header */
1.1.1.13 root 302: backupHeader = FALSE;
1.1.1.6 root 303:
1.1.1.13 root 304: while (TRUE)
1.1.1.6 root 305: {
1.1.1.13 root 306: /* The header will be re-encrypted PRAND_DISK_WIPE_PASSES times to prevent adversaries from using
307: techniques such as magnetic force microscopy or magnetic force scanning tunnelling microscopy
308: to recover the overwritten header. According to Peter Gutmann, data should be overwritten 22
309: times (ideally, 35 times) using non-random patterns and pseudorandom data. However, as users might
310: impatiently interupt the process (etc.) we will not use the Gutmann's patterns but will write the
311: valid re-encrypted header, i.e. pseudorandom data, and there will be many more passes than Guttman
312: recommends. During each pass we will write a valid working header. Each pass will use the same master
313: key, and also the same header key, secondary key (XTS), etc., derived from the new password. The only
314: item that will be different for each pass will be the salt. This is sufficient to cause each "version"
315: of the header to differ substantially and in a random manner from the versions written during the
316: other passes. */
317:
318: for (wipePass = 0; wipePass < PRAND_DISK_WIPE_PASSES; wipePass++)
319: {
320: // Prepare new volume header
1.1.1.14 root 321: nStatus = CreateVolumeHeaderInMemory (FALSE,
1.1.1.13 root 322: buffer,
323: cryptoInfo->ea,
324: cryptoInfo->mode,
325: newPassword,
326: cryptoInfo->pkcs5,
327: cryptoInfo->master_keydata,
328: &ci,
329: cryptoInfo->VolumeSize.Value,
330: (volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) ? cryptoInfo->hiddenVolumeSize : 0,
331: cryptoInfo->EncryptedAreaStart.Value,
332: cryptoInfo->EncryptedAreaLength.Value,
333: cryptoInfo->RequiredProgramVersion,
334: cryptoInfo->HeaderFlags,
335: wipePass < PRAND_DISK_WIPE_PASSES - 1);
336:
337: if (ci != NULL)
338: crypto_close (ci);
339:
340: if (nStatus != 0)
341: goto error;
342:
343: if (!SetFilePointerEx ((HANDLE) dev, headerOffset, NULL, FILE_BEGIN))
1.1.1.6 root 344: {
1.1.1.13 root 345: nStatus = ERR_OS_ERROR;
1.1.1.6 root 346: goto error;
347: }
1.1.1.3 root 348:
1.1.1.13 root 349: nStatus = _lwrite ((HFILE) dev, buffer, TC_VOLUME_HEADER_EFFECTIVE_SIZE);
350: if (nStatus != TC_VOLUME_HEADER_EFFECTIVE_SIZE)
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 root 355:
1.1.1.15 root 356: if (bDevice
357: && !cryptoInfo->LegacyVolume
358: && !cryptoInfo->hiddenVolume
359: && cryptoInfo->HeaderVersion == 4
360: && (cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) != 0
361: && (cryptoInfo->HeaderFlags & ~TC_HEADER_FLAG_NONSYS_INPLACE_ENC) == 0)
362: {
363: nStatus = WriteRandomDataToReservedHeaderAreas (dev, cryptoInfo, cryptoInfo->VolumeSize.Value, !backupHeader, backupHeader);
364: if (nStatus != ERR_SUCCESS)
365: goto error;
366: }
367:
1.1.1.13 root 368: FlushFileBuffers (dev);
1.1.1.6 root 369: }
1.1.1.13 root 370:
371: if (backupHeader || cryptoInfo->LegacyVolume)
372: break;
373:
374: backupHeader = TRUE;
375: headerOffset.QuadPart += hostSize - TC_VOLUME_HEADER_GROUP_SIZE;
1.1 root 376: }
377:
1.1.1.6 root 378: /* Password successfully changed */
1.1 root 379: nStatus = 0;
380:
1.1.1.6 root 381: error:
1.1.1.10 root 382: dwError = GetLastError ();
383:
1.1 root 384: burn (buffer, sizeof (buffer));
385:
386: if (cryptoInfo != NULL)
387: crypto_close (cryptoInfo);
388:
1.1.1.4 root 389: if (bTimeStampValid)
1.1.1.18! root 390: SetFileTime (dev, &ftCreationTime, &ftLastAccessTime, &ftLastWriteTime);
1.1.1.4 root 391:
1.1.1.10 root 392: if (dev != INVALID_HANDLE_VALUE)
393: CloseHandle ((HANDLE) dev);
1.1 root 394:
1.1.1.10 root 395: if (nDosLinkCreated == 0)
396: RemoveFakeDosName (szDiskFile, szDosDevice);
397:
1.1.1.15 root 398: RandStop (FALSE);
1.1.1.10 root 399: NormalCursor ();
1.1 root 400:
401: SetLastError (dwError);
402:
1.1.1.10 root 403: if (nStatus == ERR_OS_ERROR && dwError == ERROR_ACCESS_DENIED
404: && bDevice
405: && !UacElevated
406: && IsUacSupported ())
407: return nStatus;
1.1 root 408:
1.1.1.10 root 409: if (nStatus != 0)
410: handleError (hwndDlg, nStatus);
1.1.1.6 root 411:
1.1 root 412: return nStatus;
413: }
1.1.1.4 root 414:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.