|
|
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
6: the original source code (contained in this file) and all other portions of
7: this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed
1.1.1.14! root 8: by the TrueCrypt License 2.5 the full text of which is contained in the
1.1.1.12 root 9: file License.txt included in TrueCrypt binary and source code distribution
1.1.1.10 root 10: packages. */
1.1 root 11:
12: #include "TCdefs.h"
1.1.1.6 root 13: #include "Crypto.h"
14: #include "Volumes.h"
1.1 root 15:
1.1.1.6 root 16: #include "Apidrvr.h"
1.1.1.14! root 17: #include "DriveFilter.h"
1.1.1.6 root 18: #include "Ntdriver.h"
19: #include "Ntvol.h"
1.1.1.14! root 20: #include "VolumeFilter.h"
1.1 root 21:
1.1.1.13 root 22: #include "Boot/Windows/BootCommon.h"
23:
1.1.1.6 root 24: #include "Cache.h"
1.1 root 25:
1.1.1.10 root 26: #if 0 && _DEBUG
27: #define EXTRA_INFO 1
28: #endif
1.1 root 29:
30: #pragma warning( disable : 4127 )
31:
1.1.1.14! root 32: volatile BOOL ProbingHostDeviceForWrite = FALSE;
! 33:
! 34:
1.1 root 35: NTSTATUS
36: TCOpenVolume (PDEVICE_OBJECT DeviceObject,
37: PEXTENSION Extension,
1.1.1.6 root 38: MOUNT_STRUCT *mount,
1.1 root 39: PWSTR pwszMountVolume,
40: BOOL bRawDevice)
41: {
42: FILE_STANDARD_INFORMATION FileStandardInfo;
43: FILE_BASIC_INFORMATION FileBasicInfo;
44: OBJECT_ATTRIBUTES oaFileAttributes;
45: UNICODE_STRING FullFileName;
46: IO_STATUS_BLOCK IoStatusBlock;
1.1.1.6 root 47: PCRYPTO_INFO cryptoInfoPtr = NULL;
48: PCRYPTO_INFO tmpCryptoInfo = NULL;
1.1 root 49: LARGE_INTEGER lDiskLength;
1.1.1.13 root 50: __int64 partitionStartingOffset;
1.1.1.6 root 51: int volumeType;
1.1.1.4 root 52: char *readBuffer = 0;
1.1.1.5 root 53: NTSTATUS ntStatus = 0;
1.1 root 54:
55: Extension->pfoDeviceFile = NULL;
56: Extension->hDeviceFile = NULL;
1.1.1.6 root 57: Extension->bTimeStampValid = FALSE;
1.1 root 58:
1.1.1.4 root 59: RtlInitUnicodeString (&FullFileName, pwszMountVolume);
60: InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
61: KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE);
62:
63: // If we are opening a device, query its size first
64: if (bRawDevice)
1.1 root 65: {
1.1.1.5 root 66: PARTITION_INFORMATION pi;
1.1.1.10 root 67: PARTITION_INFORMATION_EX pix;
1.1.1.4 root 68: DISK_GEOMETRY dg;
1.1 root 69:
1.1.1.4 root 70: ntStatus = IoGetDeviceObjectPointer (&FullFileName,
71: FILE_READ_DATA,
72: &Extension->pfoDeviceFile,
73: &Extension->pFsdDevice);
74:
75: if (!NT_SUCCESS (ntStatus))
76: goto error;
77:
1.1.1.12 root 78: if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY, (char *) &dg, sizeof (dg))))
1.1.1.4 root 79: {
1.1.1.10 root 80: lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.BytesPerSector;
81: mount->BytesPerSector = dg.BytesPerSector;
1.1.1.4 root 82: }
1.1.1.5 root 83: else
1.1.1.10 root 84: lDiskLength.QuadPart = 0;
1.1.1.4 root 85:
1.1.1.10 root 86: // Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails
1.1.1.12 root 87: if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO_EX, (char *) &pix, sizeof (pix))))
1.1.1.13 root 88: {
1.1.1.10 root 89: lDiskLength.QuadPart = pix.PartitionLength.QuadPart;
1.1.1.13 root 90: partitionStartingOffset = pix.StartingOffset.QuadPart;
91: }
1.1.1.10 root 92: // Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX
1.1.1.12 root 93: else if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO, (char *) &pi, sizeof (pi))))
1.1.1.13 root 94: {
1.1.1.10 root 95: lDiskLength.QuadPart = pi.PartitionLength.QuadPart;
1.1.1.13 root 96: partitionStartingOffset = pi.StartingOffset.QuadPart;
97: }
1.1 root 98:
1.1.1.14! root 99: ProbingHostDeviceForWrite = TRUE;
! 100:
! 101: if (!mount->bMountReadOnly
! 102: && TCSendHostDeviceIoControlRequest (DeviceObject, Extension,
! 103: IsHiddenSystemRunning() ? TC_IOCTL_DISK_IS_WRITABLE : IOCTL_DISK_IS_WRITABLE, NULL, 0) == STATUS_MEDIA_WRITE_PROTECTED)
1.1.1.10 root 104: {
105: mount->bMountReadOnly = TRUE;
106: DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
1.1.1.4 root 107: }
1.1.1.14! root 108:
! 109: ProbingHostDeviceForWrite = FALSE;
1.1.1.4 root 110: }
1.1 root 111:
1.1.1.10 root 112: if (mount->BytesPerSector == 0)
113: mount->BytesPerSector = SECTOR_SIZE;
114:
115: Extension->HostBytesPerSector = mount->BytesPerSector;
116:
1.1.1.4 root 117: // Open the volume hosting file/device
118: if (!mount->bMountReadOnly)
119: {
120: ntStatus = ZwCreateFile (&Extension->hDeviceFile,
121: GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
122: &oaFileAttributes,
123: &IoStatusBlock,
124: NULL,
125: FILE_ATTRIBUTE_NORMAL |
126: FILE_ATTRIBUTE_SYSTEM,
127: mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE,
128: FILE_OPEN,
1.1.1.10 root 129: FILE_RANDOM_ACCESS |
1.1.1.4 root 130: FILE_WRITE_THROUGH |
1.1.1.10 root 131: (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
1.1.1.4 root 132: FILE_SYNCHRONOUS_IO_NONALERT,
133: NULL,
134: 0);
135: }
1.1 root 136:
1.1.1.10 root 137: /* 26-4-99 NT for some partitions returns this code, it is really a access denied */
1.1 root 138: if (ntStatus == 0xc000001b)
139: ntStatus = STATUS_ACCESS_DENIED;
1.1.1.6 root 140:
1.1.1.4 root 141: if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED)
1.1 root 142: {
143: ntStatus = ZwCreateFile (&Extension->hDeviceFile,
1.1.1.4 root 144: GENERIC_READ | SYNCHRONIZE,
145: &oaFileAttributes,
146: &IoStatusBlock,
147: NULL,
148: FILE_ATTRIBUTE_NORMAL |
149: FILE_ATTRIBUTE_SYSTEM,
1.1.1.8 root 150: mount->bExclusiveAccess ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE,
1.1.1.4 root 151: FILE_OPEN,
1.1.1.10 root 152: FILE_RANDOM_ACCESS |
1.1.1.4 root 153: FILE_WRITE_THROUGH |
1.1.1.11 root 154: (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
1.1.1.4 root 155: FILE_SYNCHRONOUS_IO_NONALERT,
156: NULL,
157: 0);
1.1.1.11 root 158:
1.1 root 159: Extension->bReadOnly = TRUE;
1.1.1.11 root 160: DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
1.1 root 161: }
162: else
163: Extension->bReadOnly = FALSE;
164:
165: /* 26-4-99 NT for some partitions returns this code, it is really a
1.1.1.4 root 166: access denied */
1.1 root 167: if (ntStatus == 0xc000001b)
168: {
169: /* Partitions which return this code can still be opened with
1.1.1.4 root 170: FILE_SHARE_READ but this causes NT problems elsewhere in
171: particular if you do FILE_SHARE_READ NT will die later if
1.1.1.12 root 172: anyone even tries to open the partition (or file for that
1.1.1.4 root 173: matter...) */
1.1 root 174: ntStatus = STATUS_SHARING_VIOLATION;
175: }
176:
177: if (!NT_SUCCESS (ntStatus))
178: {
179: goto error;
180: }
181:
1.1.1.4 root 182: // If we have opened a file, query its size now
1.1 root 183: if (bRawDevice == FALSE)
184: {
185: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
1.1.1.4 root 186: &IoStatusBlock,
187: &FileBasicInfo,
188: sizeof (FileBasicInfo),
189: FileBasicInformation);
1.1 root 190:
191: if (NT_SUCCESS (ntStatus))
1.1.1.4 root 192: {
1.1.1.6 root 193: if (mount->bPreserveTimestamp)
194: {
195: /* Remember the container timestamp. (Used to reset access/modification file date/time
196: of file-hosted volumes upon dismount or after unsuccessful mount attempt to preserve
197: plausible deniability of hidden volumes.) */
198: Extension->fileCreationTime = FileBasicInfo.CreationTime;
199: Extension->fileLastAccessTime = FileBasicInfo.LastAccessTime;
200: Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime;
201: Extension->fileLastChangeTime = FileBasicInfo.ChangeTime;
202: Extension->bTimeStampValid = TRUE;
203: }
1.1.1.4 root 204:
1.1 root 205: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
1.1.1.4 root 206: &IoStatusBlock,
207: &FileStandardInfo,
208: sizeof (FileStandardInfo),
209: FileStandardInformation);
210: }
1.1 root 211:
212: if (!NT_SUCCESS (ntStatus))
213: {
214: Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n",
1.1.1.4 root 215: ntStatus);
1.1 root 216: goto error;
217: }
1.1.1.4 root 218:
219: lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart;
1.1 root 220:
221: if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED)
222: {
223: Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume);
224: mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED;
225: ntStatus = STATUS_SUCCESS;
226: goto error;
227: }
228:
229: ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile,
1.1.1.4 root 230: FILE_ALL_ACCESS,
231: *IoFileObjectType,
232: KernelMode,
233: &Extension->pfoDeviceFile,
234: 0);
1.1 root 235:
236: if (!NT_SUCCESS (ntStatus))
237: {
238: goto error;
239: }
240:
1.1.1.4 root 241: /* Get the FSD device for the file (probably either NTFS or FAT) */
1.1 root 242: Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile);
243: }
244:
1.1.1.4 root 245: // Check volume size
1.1.1.14! root 246: if (lDiskLength.QuadPart < TC_MIN_VOLUME_SIZE_LEGACY || lDiskLength.QuadPart > TC_MAX_VOLUME_SIZE)
1.1.1.4 root 247: {
248: mount->nReturnCode = ERR_VOL_SIZE_WRONG;
249: ntStatus = STATUS_SUCCESS;
250: goto error;
251: }
1.1.1.6 root 252:
1.1.1.4 root 253: Extension->DiskLength = lDiskLength.QuadPart;
1.1 root 254:
1.1.1.14! root 255: readBuffer = TCalloc (TC_VOLUME_HEADER_EFFECTIVE_SIZE);
1.1.1.4 root 256: if (readBuffer == NULL)
257: {
258: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
259: goto error;
260: }
1.1 root 261:
1.1.1.6 root 262: // Go through all volume types (e.g., normal, hidden)
1.1.1.14! root 263: for (volumeType = TC_VOLUME_TYPE_NORMAL;
! 264: volumeType < TC_VOLUME_TYPE_COUNT;
1.1.1.6 root 265: volumeType++)
1.1.1.4 root 266: {
1.1.1.14! root 267: Dump ("Trying to open volume type %d\n", volumeType);
! 268:
1.1.1.13 root 269: if (mount->bPartitionInInactiveSysEncScope
1.1.1.14! root 270: && volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY)
1.1.1.13 root 271: continue;
272:
1.1.1.6 root 273: /* Read the volume header */
1.1 root 274:
1.1.1.14! root 275: if (!mount->bPartitionInInactiveSysEncScope
! 276: || (mount->bPartitionInInactiveSysEncScope && volumeType == TC_VOLUME_TYPE_HIDDEN))
1.1.1.13 root 277: {
1.1.1.14! root 278: // Header of a volume that is not within the scope of system encryption, or
! 279: // header of a system hidden volume (containing a hidden OS)
! 280:
! 281: LARGE_INTEGER headerOffset;
! 282:
! 283: if (mount->UseBackupHeader && lDiskLength.QuadPart <= TC_TOTAL_VOLUME_HEADERS_SIZE)
! 284: continue;
! 285:
! 286: switch (volumeType)
! 287: {
! 288: case TC_VOLUME_TYPE_NORMAL:
! 289: headerOffset.QuadPart = mount->UseBackupHeader ? lDiskLength.QuadPart - TC_VOLUME_HEADER_GROUP_SIZE : TC_VOLUME_HEADER_OFFSET;
! 290: break;
! 291:
! 292: case TC_VOLUME_TYPE_HIDDEN:
! 293: if (lDiskLength.QuadPart <= TC_VOLUME_HEADER_GROUP_SIZE)
! 294: continue;
! 295:
! 296: headerOffset.QuadPart = mount->UseBackupHeader ? lDiskLength.QuadPart - TC_HIDDEN_VOLUME_HEADER_OFFSET : TC_HIDDEN_VOLUME_HEADER_OFFSET;
! 297: break;
! 298:
! 299: case TC_VOLUME_TYPE_HIDDEN_LEGACY:
! 300: if (mount->UseBackupHeader)
! 301: continue;
! 302:
! 303: headerOffset.QuadPart = lDiskLength.QuadPart - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
! 304: break;
! 305: }
! 306:
! 307: Dump ("Reading volume header at %I64d\n", headerOffset.QuadPart);
1.1.1.13 root 308:
309: ntStatus = ZwReadFile (Extension->hDeviceFile,
1.1.1.6 root 310: NULL,
311: NULL,
312: NULL,
313: &IoStatusBlock,
314: readBuffer,
1.1.1.14! root 315: TC_VOLUME_HEADER_EFFECTIVE_SIZE,
! 316: &headerOffset,
1.1.1.6 root 317: NULL);
1.1.1.13 root 318: }
319: else
320: {
321: // Header of a partition that is within the scope of system encryption
322:
323: WCHAR parentDrivePath [47+1] = {0};
324: HANDLE hParentDeviceFile = NULL;
325: UNICODE_STRING FullParentPath;
326: OBJECT_ATTRIBUTES oaParentFileAttributes;
327: LARGE_INTEGER parentKeyDataOffset;
328:
329: _snwprintf (parentDrivePath,
330: sizeof (parentDrivePath) / sizeof (WCHAR) - 1,
331: WIDE ("\\Device\\Harddisk%d\\Partition0"),
332: mount->nPartitionInInactiveSysEncScopeDriveNo);
333:
334: Dump ("Mounting partition within scope of system encryption (reading key data from: %ls)\n", parentDrivePath);
335:
336: RtlInitUnicodeString (&FullParentPath, parentDrivePath);
337: InitializeObjectAttributes (&oaParentFileAttributes, &FullParentPath, OBJ_CASE_INSENSITIVE, NULL, NULL);
338:
339: ntStatus = ZwCreateFile (&hParentDeviceFile,
340: GENERIC_READ | SYNCHRONIZE,
341: &oaParentFileAttributes,
342: &IoStatusBlock,
343: NULL,
344: FILE_ATTRIBUTE_NORMAL |
345: FILE_ATTRIBUTE_SYSTEM,
346: FILE_SHARE_READ | FILE_SHARE_WRITE,
347: FILE_OPEN,
348: FILE_RANDOM_ACCESS |
349: FILE_WRITE_THROUGH |
350: (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
351: FILE_SYNCHRONOUS_IO_NONALERT,
352: NULL,
353: 0);
354:
355: if (!NT_SUCCESS (ntStatus))
356: {
357: if (hParentDeviceFile != NULL)
358: ZwClose (hParentDeviceFile);
359:
360: Dump ("Cannot open %ls\n", parentDrivePath);
361:
362: goto error;
363: }
364:
1.1.1.14! root 365: parentKeyDataOffset.QuadPart = TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET;
1.1.1.13 root 366:
367: ntStatus = ZwReadFile (hParentDeviceFile,
368: NULL,
369: NULL,
370: NULL,
371: &IoStatusBlock,
372: readBuffer,
1.1.1.14! root 373: TC_VOLUME_HEADER_EFFECTIVE_SIZE,
1.1.1.13 root 374: &parentKeyDataOffset,
375: NULL);
376:
377: if (hParentDeviceFile != NULL)
378: ZwClose (hParentDeviceFile);
379: }
1.1.1.6 root 380:
381: if (!NT_SUCCESS (ntStatus))
1.1 root 382: {
1.1.1.6 root 383: Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus);
1.1.1.14! root 384: goto error;
1.1 root 385: }
386:
1.1.1.14! root 387: if (IoStatusBlock.Information != TC_VOLUME_HEADER_EFFECTIVE_SIZE)
1.1.1.6 root 388: {
1.1.1.14! root 389: Dump ("Read didn't read enough data\n");
! 390: mount->nReturnCode = ERR_VOL_SIZE_WRONG;
! 391: ntStatus = STATUS_SUCCESS;
1.1.1.6 root 392: goto error;
393: }
1.1 root 394:
1.1.1.6 root 395: /* Attempt to recognize the volume (decrypt the header) */
1.1 root 396:
1.1.1.14! root 397: if ((volumeType == TC_VOLUME_TYPE_HIDDEN || volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY) && mount->bProtectHiddenVolume)
1.1.1.6 root 398: {
399: mount->nReturnCode = VolumeReadHeaderCache (
1.1.1.14! root 400: FALSE,
1.1.1.6 root 401: mount->bCache,
402: readBuffer,
403: &mount->ProtectedHidVolPassword,
404: &tmpCryptoInfo);
405: }
406: else
407: {
408: mount->nReturnCode = VolumeReadHeaderCache (
1.1.1.14! root 409: mount->bPartitionInInactiveSysEncScope && volumeType == TC_VOLUME_TYPE_NORMAL,
1.1.1.6 root 410: mount->bCache,
411: readBuffer,
412: &mount->VolumePassword,
413: &Extension->cryptoInfo);
414: }
1.1.1.4 root 415:
1.1.1.6 root 416: if (mount->nReturnCode == 0 || mount->nReturnCode == ERR_CIPHER_INIT_WEAK_KEY)
417: {
418: /* Volume header successfully decrypted */
1.1 root 419:
1.1.1.14! root 420: Dump ("Volume header decrypted\n");
! 421: Dump ("Required program version = %x\n", (int) Extension->cryptoInfo->RequiredProgramVersion);
! 422: Dump ("Legacy volume = %d\n", (int) Extension->cryptoInfo->LegacyVolume);
! 423:
! 424: if (IsHiddenSystemRunning() && !Extension->cryptoInfo->hiddenVolume)
! 425: {
! 426: Extension->bReadOnly = mount->bMountReadOnly = TRUE;
! 427: HiddenSysLeakProtectionCount++;
! 428: }
! 429:
1.1.1.6 root 430: Extension->cryptoInfo->bProtectHiddenVolume = FALSE;
431: Extension->cryptoInfo->bHiddenVolProtectionAction = FALSE;
1.1 root 432:
1.1.1.13 root 433: Extension->cryptoInfo->bPartitionInInactiveSysEncScope = mount->bPartitionInInactiveSysEncScope;
434:
1.1.1.14! root 435: if (mount->bPartitionInInactiveSysEncScope && volumeType == TC_VOLUME_TYPE_NORMAL)
1.1.1.13 root 436: {
437: if (Extension->cryptoInfo->EncryptedAreaStart.Value > (unsigned __int64) partitionStartingOffset
438: || Extension->cryptoInfo->EncryptedAreaStart.Value + Extension->cryptoInfo->VolumeSize.Value <= (unsigned __int64) partitionStartingOffset)
439: {
440: // The partition is not within the key scope of system encryption
441: mount->nReturnCode = ERR_PASSWORD_WRONG;
442: ntStatus = STATUS_SUCCESS;
443: goto error;
444: }
445:
446: if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value)
447: {
448: // Partial encryption is not supported for volumes mounted as regular
449: mount->nReturnCode = ERR_ENCRYPTION_NOT_COMPLETED;
450: ntStatus = STATUS_SUCCESS;
451: goto error;
452: }
453: }
454:
1.1.1.14! root 455: Extension->cryptoInfo->FirstDataUnitNo.Value = 0;
1.1 root 456:
1.1.1.14! root 457: if (Extension->cryptoInfo->hiddenVolume && IsHiddenSystemRunning())
! 458: {
! 459: // Prevent mount of a hidden system partition if the system hosted on it is currently running
! 460: if (memcmp (Extension->cryptoInfo->master_keydata, GetSystemDriveCryptoInfo()->master_keydata, EAGetKeySize (Extension->cryptoInfo->ea)) == 0)
1.1.1.13 root 461: {
1.1.1.14! root 462: mount->nReturnCode = ERR_VOL_ALREADY_MOUNTED;
! 463: ntStatus = STATUS_SUCCESS;
! 464: goto error;
1.1.1.13 root 465: }
1.1.1.14! root 466: }
! 467:
! 468: switch (volumeType)
! 469: {
! 470: case TC_VOLUME_TYPE_NORMAL:
1.1.1.13 root 471:
1.1.1.6 root 472: Extension->cryptoInfo->hiddenVolume = FALSE;
1.1.1.13 root 473:
1.1.1.14! root 474: if (mount->bPartitionInInactiveSysEncScope)
! 475: {
! 476: Extension->cryptoInfo->volDataAreaOffset = 0;
! 477: Extension->DiskLength = lDiskLength.QuadPart;
! 478: Extension->cryptoInfo->FirstDataUnitNo.Value = partitionStartingOffset / ENCRYPTION_DATA_UNIT_SIZE;
! 479: }
! 480: else if (Extension->cryptoInfo->LegacyVolume)
! 481: {
! 482: Extension->cryptoInfo->volDataAreaOffset = TC_VOLUME_HEADER_SIZE_LEGACY;
! 483: Extension->DiskLength = lDiskLength.QuadPart - TC_VOLUME_HEADER_SIZE_LEGACY;
! 484: }
! 485: else
! 486: {
! 487: Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->EncryptedAreaStart.Value;
! 488: Extension->DiskLength = Extension->cryptoInfo->VolumeSize.Value;
! 489: }
1.1.1.6 root 490:
491: break;
492:
1.1.1.14! root 493: case TC_VOLUME_TYPE_HIDDEN:
! 494: case TC_VOLUME_TYPE_HIDDEN_LEGACY:
1.1.1.6 root 495:
496: cryptoInfoPtr = mount->bProtectHiddenVolume ? tmpCryptoInfo : Extension->cryptoInfo;
497:
1.1.1.14! root 498: if (volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY)
! 499: Extension->cryptoInfo->hiddenVolumeOffset = lDiskLength.QuadPart - cryptoInfoPtr->hiddenVolumeSize - TC_HIDDEN_VOLUME_HEADER_OFFSET_LEGACY;
! 500: else
! 501: Extension->cryptoInfo->hiddenVolumeOffset = cryptoInfoPtr->EncryptedAreaStart.Value;
1.1.1.6 root 502:
1.1.1.14! root 503: Dump ("Hidden volume offset = %I64d\n", Extension->cryptoInfo->hiddenVolumeOffset);
! 504: Dump ("Hidden volume size = %I64d\n", cryptoInfoPtr->hiddenVolumeSize);
! 505: Dump ("Hidden volume end = %I64d\n", Extension->cryptoInfo->hiddenVolumeOffset + cryptoInfoPtr->hiddenVolumeSize - 1);
1.1.1.6 root 506:
507: // Validate the offset
1.1.1.12 root 508: if (Extension->cryptoInfo->hiddenVolumeOffset % ENCRYPTION_DATA_UNIT_SIZE != 0)
1.1.1.6 root 509: {
510: mount->nReturnCode = ERR_VOL_SIZE_WRONG;
511: ntStatus = STATUS_SUCCESS;
512: goto error;
513: }
514:
515: // If we are supposed to actually mount the hidden volume (not just to protect it)
516: if (!mount->bProtectHiddenVolume)
517: {
518: Extension->DiskLength = cryptoInfoPtr->hiddenVolumeSize;
519: Extension->cryptoInfo->hiddenVolume = TRUE;
1.1.1.13 root 520: Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->hiddenVolumeOffset;
1.1.1.6 root 521: }
522: else
523: {
524: // Hidden volume protection
525: Extension->cryptoInfo->hiddenVolume = FALSE;
526: Extension->cryptoInfo->bProtectHiddenVolume = TRUE;
1.1.1.14! root 527:
! 528: Extension->cryptoInfo->hiddenVolumeProtectedSize = tmpCryptoInfo->hiddenVolumeSize;
1.1.1.13 root 529:
1.1.1.14! root 530: if (volumeType == TC_VOLUME_TYPE_HIDDEN_LEGACY)
! 531: Extension->cryptoInfo->hiddenVolumeProtectedSize += TC_VOLUME_HEADER_SIZE_LEGACY;
1.1.1.13 root 532:
1.1.1.14! root 533: Dump ("Hidden volume protection active: %I64d-%I64d (%I64d)\n", Extension->cryptoInfo->hiddenVolumeOffset, Extension->cryptoInfo->hiddenVolumeProtectedSize + Extension->cryptoInfo->hiddenVolumeOffset - 1, Extension->cryptoInfo->hiddenVolumeProtectedSize);
1.1.1.6 root 534: }
1.1.1.4 root 535:
1.1.1.6 root 536: break;
537: }
1.1.1.4 root 538:
1.1.1.14! root 539: Dump ("Volume data offset = %I64d\n", Extension->cryptoInfo->volDataAreaOffset);
! 540: Dump ("Volume data size = %I64d\n", Extension->DiskLength);
! 541: Dump ("Volume data end = %I64d\n", Extension->cryptoInfo->volDataAreaOffset + Extension->DiskLength - 1);
! 542:
1.1.1.6 root 543: // If this is a hidden volume, make sure we are supposed to actually
544: // mount it (i.e. not just to protect it)
1.1.1.14! root 545: if (volumeType == TC_VOLUME_TYPE_NORMAL || !mount->bProtectHiddenVolume)
1.1.1.4 root 546: {
1.1.1.6 root 547: // Calculate virtual volume geometry
548: Extension->TracksPerCylinder = 1;
549: Extension->SectorsPerTrack = 1;
1.1.1.10 root 550: Extension->BytesPerSector = SECTOR_SIZE;
551: Extension->NumberOfCylinders = Extension->DiskLength / SECTOR_SIZE;
1.1.1.6 root 552: Extension->PartitionType = 0;
553:
554: Extension->bRawDevice = bRawDevice;
1.1.1.7 root 555:
1.1.1.8 root 556: memset (Extension->wszVolume, 0, sizeof (Extension->wszVolume));
1.1.1.7 root 557: if (wcsstr (pwszMountVolume, WIDE ("\\??\\UNC\\")) == pwszMountVolume)
558: {
559: /* UNC path */
560: _snwprintf (Extension->wszVolume,
561: sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1,
562: WIDE ("\\??\\\\%s"),
563: pwszMountVolume + 7);
564: }
1.1.1.6 root 565: else
566: {
1.1.1.7 root 567: wcsncpy (Extension->wszVolume, pwszMountVolume, sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1);
1.1.1.6 root 568: }
1.1.1.4 root 569: }
570:
1.1.1.6 root 571: // If we are to protect a hidden volume we cannot exit yet, for we must also
572: // decrypt the hidden volume header.
1.1.1.14! root 573: if (!(volumeType == TC_VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume))
1.1.1.4 root 574: {
1.1.1.6 root 575: TCfree (readBuffer);
1.1.1.4 root 576:
1.1.1.6 root 577: if (tmpCryptoInfo != NULL)
1.1.1.14! root 578: {
1.1.1.6 root 579: crypto_close (tmpCryptoInfo);
1.1.1.14! root 580: tmpCryptoInfo = NULL;
! 581: }
1.1.1.6 root 582:
583: return STATUS_SUCCESS;
584: }
1.1.1.4 root 585: }
1.1.1.14! root 586: else if ((mount->bProtectHiddenVolume && volumeType == TC_VOLUME_TYPE_NORMAL)
1.1.1.6 root 587: || mount->nReturnCode != ERR_PASSWORD_WRONG)
1.1.1.4 root 588: {
1.1.1.6 root 589: /* If we are not supposed to protect a hidden volume, the only error that is
590: tolerated is ERR_PASSWORD_WRONG (to allow mounting a possible hidden volume).
1.1.1.4 root 591:
1.1.1.6 root 592: If we _are_ supposed to protect a hidden volume, we do not tolerate any error
593: (both volume headers must be successfully decrypted). */
1.1 root 594:
1.1.1.6 root 595: break;
1.1 root 596: }
597: }
598:
599: /* Failed due to some non-OS reason so we drop through and return NT
600: SUCCESS then nReturnCode is checked later in user-mode */
601:
602: if (mount->nReturnCode == ERR_OUTOFMEMORY)
603: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
604: else
605: ntStatus = STATUS_SUCCESS;
606:
1.1.1.4 root 607: error:
1.1.1.14! root 608: if (mount->nReturnCode == ERR_SUCCESS)
! 609: mount->nReturnCode = ERR_PASSWORD_WRONG;
! 610:
! 611: if (tmpCryptoInfo != NULL)
! 612: {
! 613: crypto_close (tmpCryptoInfo);
! 614: tmpCryptoInfo = NULL;
! 615: }
! 616:
! 617: if (Extension->cryptoInfo)
! 618: {
! 619: crypto_close (Extension->cryptoInfo);
! 620: Extension->cryptoInfo = NULL;
! 621: }
! 622:
1.1.1.6 root 623: if (Extension->bTimeStampValid)
1.1.1.4 root 624: {
625: /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
626: RestoreTimeStamp (Extension);
627: }
1.1 root 628:
629: /* Close the hDeviceFile */
630: if (Extension->hDeviceFile != NULL)
631: ZwClose (Extension->hDeviceFile);
632:
633: /* The cryptoInfo pointer is deallocated if the readheader routines
634: fail so there is no need to deallocate here */
635:
636: /* Dereference the user-mode file object */
637: if (Extension->pfoDeviceFile != NULL)
638: ObDereferenceObject (Extension->pfoDeviceFile);
639:
1.1.1.4 root 640: /* Free the tmp IO buffers */
1.1 root 641: if (readBuffer != NULL)
642: TCfree (readBuffer);
643:
644: return ntStatus;
645: }
646:
1.1.1.14! root 647: void TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
1.1 root 648: {
649: if (DeviceObject); /* Remove compiler warning */
650:
651: if (Extension->hDeviceFile != NULL)
1.1.1.4 root 652: {
1.1.1.6 root 653: if (Extension->bRawDevice == FALSE
654: && Extension->bTimeStampValid)
1.1.1.4 root 655: {
656: /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
657: RestoreTimeStamp (Extension);
658: }
1.1.1.6 root 659: ZwClose (Extension->hDeviceFile);
1.1.1.4 root 660: }
1.1 root 661: ObDereferenceObject (Extension->pfoDeviceFile);
662: crypto_close (Extension->cryptoInfo);
663: }
664:
665:
1.1.1.14! root 666: NTSTATUS TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject,
1.1 root 667: PEXTENSION Extension,
668: ULONG IoControlCode,
669: char *OutputBuffer,
670: int OutputBufferSize)
671: {
672: IO_STATUS_BLOCK IoStatusBlock;
673: NTSTATUS ntStatus;
674: PIRP Irp;
675:
676: if (DeviceObject); /* Remove compiler warning */
677:
678: KeClearEvent (&Extension->keVolumeEvent);
679:
680: Irp = IoBuildDeviceIoControlRequest (IoControlCode,
681: Extension->pFsdDevice,
682: NULL, 0,
683: OutputBuffer, OutputBufferSize,
684: FALSE,
685: &Extension->keVolumeEvent,
686: &IoStatusBlock);
687:
688: if (Irp == NULL)
689: {
690: Dump ("IRP allocation failed\n");
691: return STATUS_INSUFFICIENT_RESOURCES;
692: }
693:
1.1.1.5 root 694: // Disk device may be used by filesystem driver which needs file object
695: IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile;
696:
1.1 root 697: ntStatus = IoCallDriver (Extension->pFsdDevice, Irp);
698: if (ntStatus == STATUS_PENDING)
699: {
1.1.1.12 root 700: KeWaitForSingleObject (&Extension->keVolumeEvent, Executive, KernelMode, FALSE, NULL);
1.1 root 701: ntStatus = IoStatusBlock.Status;
702: }
703:
704: return ntStatus;
705: }
706:
1.1.1.14! root 707: NTSTATUS COMPLETE_IRP (PDEVICE_OBJECT DeviceObject,
1.1 root 708: PIRP Irp,
709: NTSTATUS IrpStatus,
1.1.1.4 root 710: ULONG_PTR IrpInformation)
1.1 root 711: {
712: Irp->IoStatus.Status = IrpStatus;
713: Irp->IoStatus.Information = IrpInformation;
714:
715: if (DeviceObject); /* Remove compiler warning */
716:
1.1.1.10 root 717: #if EXTRA_INFO
718: if (!NT_SUCCESS (IrpStatus))
719: {
720: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
721: Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
722: (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
723: }
724: else
725: {
726: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
727: Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
728: (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
729: }
1.1 root 730: #endif
731: IoCompleteRequest (Irp, IO_NO_INCREMENT);
732: return IrpStatus;
733: }
1.1.1.4 root 734:
735: // Restores the container timestamp to preserve plausible deniability of possible hidden volume.
736: static void RestoreTimeStamp (PEXTENSION Extension)
737: {
738: NTSTATUS ntStatus;
739: FILE_BASIC_INFORMATION FileBasicInfo;
740: IO_STATUS_BLOCK IoStatusBlock;
741:
1.1.1.6 root 742: if (Extension->hDeviceFile != NULL
743: && Extension->bRawDevice == FALSE
744: && Extension->bReadOnly == FALSE
745: && Extension->bTimeStampValid)
1.1.1.4 root 746: {
747: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
748: &IoStatusBlock,
749: &FileBasicInfo,
750: sizeof (FileBasicInfo),
751: FileBasicInformation);
752:
753: if (!NT_SUCCESS (ntStatus))
754: {
755: Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",
756: ntStatus);
757: }
758: else
759: {
760: FileBasicInfo.CreationTime = Extension->fileCreationTime;
761: FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime;
762: FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime;
763: FileBasicInfo.ChangeTime = Extension->fileLastChangeTime;
764:
765: ntStatus = ZwSetInformationFile(
766: Extension->hDeviceFile,
767: &IoStatusBlock,
768: &FileBasicInfo,
769: sizeof (FileBasicInfo),
770: FileBasicInformation);
771:
772: if (!NT_SUCCESS (ntStatus))
773: Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus);
774: }
775: }
776: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.