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