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