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