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