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