|
|
1.1.1.3 root 1: /* The source code contained in this file has been derived from the source code
2: of Encryption for the Masses 2.02a by Paul Le Roux. Modifications and
1.1.1.5 ! root 3: additions to that source code contained in this file are Copyright (c) 2004-2005
1.1.1.4 root 4: TrueCrypt Foundation and Copyright (c) 2004 TrueCrypt Team. Unmodified
1.1.1.3 root 5: parts are Copyright (c) 1998-99 Paul Le Roux. This is a TrueCrypt Foundation
6: release. Please see the file license.txt for full license details. */
1.1 root 7:
8: #include "TCdefs.h"
9: #include "crypto.h"
10: #include "volumes.h"
11:
12: #include "apidrvr.h"
13: #include "ntdriver.h"
14: #include "ntvol.h"
15: #include "ntrawdv.h"
16: #include "ntfiledv.h"
17:
18: #include "cache.h"
19:
20: //#ifdef _DEBUG
21: //#define EXTRA_INFO 1
22: //#endif
23:
24: #pragma warning( disable : 4127 )
25:
26: NTSTATUS
27: TCOpenVolume (PDEVICE_OBJECT DeviceObject,
28: PEXTENSION Extension,
29: MOUNT_STRUCT * mount,
30: PWSTR pwszMountVolume,
31: BOOL bRawDevice)
32: {
33: FILE_STANDARD_INFORMATION FileStandardInfo;
34: FILE_BASIC_INFORMATION FileBasicInfo;
35: OBJECT_ATTRIBUTES oaFileAttributes;
36: UNICODE_STRING FullFileName;
37: IO_STATUS_BLOCK IoStatusBlock;
38: LARGE_INTEGER lDiskLength;
1.1.1.4 root 39: char *readBuffer = 0;
40: char *readBufferHiddenVol = 0;
1.1.1.5 ! root 41: NTSTATUS ntStatus = 0;
1.1.1.4 root 42: BOOL bTimeStampValid = FALSE;
1.1 root 43:
44: Extension->pfoDeviceFile = NULL;
45: Extension->hDeviceFile = NULL;
46:
1.1.1.4 root 47: RtlInitUnicodeString (&FullFileName, pwszMountVolume);
48: InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE, NULL, NULL);
49: KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE);
50:
51: // If we are opening a device, query its size first
52: if (bRawDevice)
1.1 root 53: {
1.1.1.5 ! root 54: PARTITION_INFORMATION pi;
1.1.1.4 root 55: DISK_GEOMETRY dg;
1.1 root 56:
1.1.1.4 root 57: ntStatus = IoGetDeviceObjectPointer (&FullFileName,
58: FILE_READ_DATA,
59: &Extension->pfoDeviceFile,
60: &Extension->pFsdDevice);
61:
62: if (!NT_SUCCESS (ntStatus))
63: {
64: goto error;
65: }
66:
67: DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1);
68:
1.1.1.5 ! root 69: // Query partition size
1.1.1.4 root 70: ntStatus = TCSendDeviceIoControlRequest (DeviceObject,
1.1.1.5 ! root 71: Extension, IOCTL_DISK_GET_PARTITION_INFO,
! 72: (char *) &pi, sizeof (pi));
1.1.1.4 root 73:
1.1.1.5 ! root 74: if (NT_SUCCESS (ntStatus))
1.1.1.4 root 75: {
1.1.1.5 ! root 76: lDiskLength.QuadPart = pi.PartitionLength.QuadPart;
1.1.1.4 root 77: }
1.1.1.5 ! root 78: else
1.1.1.4 root 79: {
1.1.1.5 ! root 80: // Drive geometry info is used only when IOCTL_DISK_GET_PARTITION_INFO fails
1.1.1.4 root 81: ntStatus = TCSendDeviceIoControlRequest (DeviceObject,
1.1.1.5 ! root 82: Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY,
! 83: (char *) &dg, sizeof (dg));
1.1.1.4 root 84:
85: if (!NT_SUCCESS (ntStatus))
86: goto error;
1.1 root 87:
1.1.1.4 root 88: lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack *
89: dg.TracksPerCylinder * dg.BytesPerSector;
90: }
91: }
1.1 root 92:
1.1.1.4 root 93: // Open the volume hosting file/device
94: if (!mount->bMountReadOnly)
95: {
96: ntStatus = ZwCreateFile (&Extension->hDeviceFile,
97: GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
98: &oaFileAttributes,
99: &IoStatusBlock,
100: NULL,
101: FILE_ATTRIBUTE_NORMAL |
102: FILE_ATTRIBUTE_SYSTEM,
103: mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE,
104: FILE_OPEN,
105: FILE_WRITE_THROUGH |
106: FILE_NO_INTERMEDIATE_BUFFERING |
107: FILE_SYNCHRONOUS_IO_NONALERT,
108: NULL,
109: 0);
110: }
1.1 root 111:
112: /* 26-4-99 NT for some partitions returns this code, it is really a
1.1.1.4 root 113: access denied */
1.1 root 114: if (ntStatus == 0xc000001b)
115: {
116: ntStatus = STATUS_ACCESS_DENIED;
117: }
118:
1.1.1.4 root 119: if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED)
1.1 root 120: {
121: ntStatus = ZwCreateFile (&Extension->hDeviceFile,
1.1.1.4 root 122: GENERIC_READ | SYNCHRONIZE,
123: &oaFileAttributes,
124: &IoStatusBlock,
125: NULL,
126: FILE_ATTRIBUTE_NORMAL |
127: FILE_ATTRIBUTE_SYSTEM,
128: mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE,
129: FILE_OPEN,
130: FILE_WRITE_THROUGH |
131: FILE_NO_INTERMEDIATE_BUFFERING |
132: FILE_SYNCHRONOUS_IO_NONALERT,
133: NULL,
134: 0);
1.1 root 135: Extension->bReadOnly = TRUE;
136: }
137: else
138: Extension->bReadOnly = FALSE;
139:
140: /* 26-4-99 NT for some partitions returns this code, it is really a
1.1.1.4 root 141: access denied */
1.1 root 142: if (ntStatus == 0xc000001b)
143: {
144: /* Partitions which return this code can still be opened with
1.1.1.4 root 145: FILE_SHARE_READ but this causes NT problems elsewhere in
146: particular if you do FILE_SHARE_READ NT will die later if
147: anyone even tries to open the partition (or file for that
148: matter...) */
1.1 root 149: ntStatus = STATUS_SHARING_VIOLATION;
150: }
151:
152: if (!NT_SUCCESS (ntStatus))
153: {
154: goto error;
155: }
156:
1.1.1.4 root 157: // If we have opened a file, query its size now
1.1 root 158: if (bRawDevice == FALSE)
159: {
160: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
1.1.1.4 root 161: &IoStatusBlock,
162: &FileBasicInfo,
163: sizeof (FileBasicInfo),
164: FileBasicInformation);
1.1 root 165:
166: if (NT_SUCCESS (ntStatus))
1.1.1.4 root 167: {
168: /* Remember the container timestamp. (Used to reset access/modification file date/time
169: of file-hosted containers upon dismount or after unsuccessful mount attempt to preserve
170: plausible deniability of hidden volumes.) */
171: Extension->fileCreationTime = FileBasicInfo.CreationTime;
172: Extension->fileLastAccessTime = FileBasicInfo.LastAccessTime;
173: Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime;
174: Extension->fileLastChangeTime = FileBasicInfo.ChangeTime;
175: bTimeStampValid = TRUE;
176:
1.1 root 177: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
1.1.1.4 root 178: &IoStatusBlock,
179: &FileStandardInfo,
180: sizeof (FileStandardInfo),
181: FileStandardInformation);
182: }
1.1 root 183:
184: if (!NT_SUCCESS (ntStatus))
185: {
186: Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n",
1.1.1.4 root 187: ntStatus);
1.1 root 188: goto error;
189: }
1.1.1.4 root 190:
191: lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart;
1.1 root 192:
193: if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED)
194: {
195: Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume);
196: mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED;
197: ntStatus = STATUS_SUCCESS;
198: goto error;
199: }
200:
201: ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile,
1.1.1.4 root 202: FILE_ALL_ACCESS,
203: *IoFileObjectType,
204: KernelMode,
205: &Extension->pfoDeviceFile,
206: 0);
1.1 root 207:
208: if (!NT_SUCCESS (ntStatus))
209: {
210: goto error;
211: }
212:
1.1.1.4 root 213: /* Get the FSD device for the file (probably either NTFS or FAT) */
1.1 root 214: Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile);
215:
216: DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1);
217: }
218:
1.1.1.4 root 219: // Check volume size
220: if (lDiskLength.QuadPart < MIN_VOLUME_SIZE || lDiskLength.QuadPart > MAX_VOLUME_SIZE)
221: {
222: mount->nReturnCode = ERR_VOL_SIZE_WRONG;
223: ntStatus = STATUS_SUCCESS;
224: goto error;
225: }
226:
227: Extension->DiskLength = lDiskLength.QuadPart;
1.1 root 228:
1.1.1.4 root 229: // Read normal volume header
230: readBuffer = TCalloc (HEADER_SIZE);
231: if (readBuffer == NULL)
232: {
233: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
234: goto error;
235: }
1.1 root 236:
1.1.1.4 root 237: ntStatus = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL,
238: &IoStatusBlock, readBuffer, HEADER_SIZE, NULL, NULL);
1.1 root 239:
1.1.1.4 root 240: // Read hidden volume header if needed
241: if (mountingHiddenVolumesAllowed)
242: {
243: LARGE_INTEGER byteOffset;
1.1 root 244:
1.1.1.4 root 245: readBufferHiddenVol = TCalloc (HEADER_SIZE);
246: if (readBufferHiddenVol == NULL)
1.1 root 247: {
1.1.1.4 root 248: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
1.1 root 249: goto error;
250: }
251:
1.1.1.4 root 252: byteOffset.QuadPart = lDiskLength.QuadPart - HIDDEN_VOL_HEADER_OFFSET;
253: ntStatus = ZwReadFile (Extension->hDeviceFile, NULL, NULL, NULL,
254: &IoStatusBlock, readBufferHiddenVol, HEADER_SIZE, &byteOffset, NULL);
255: }
1.1 root 256:
1.1.1.4 root 257: if (!NT_SUCCESS (ntStatus))
258: {
259: Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus);
260: }
261: else if (IoStatusBlock.Information != HEADER_SIZE)
262: {
263: Dump ("Read didn't read enough data in: %lu / %lu\n", IoStatusBlock.Information, HEADER_SIZE);
264: ntStatus = STATUS_UNSUCCESSFUL;
1.1 root 265: }
266:
1.1.1.4 root 267: if (!NT_SUCCESS (ntStatus))
1.1 root 268: {
269: goto error;
270: }
1.1.1.4 root 271:
1.1 root 272:
273: /* Attempt to recognize the volume */
274:
275: mount->nReturnCode = VolumeReadHeaderCache (
1.1.1.4 root 276: mount->bCache,
277: readBuffer,
278: readBufferHiddenVol,
279: mount->szPassword,
280: strlen (mount->szPassword),
281: &Extension->cryptoInfo);
1.1 root 282:
283: if (mount->nReturnCode == 0)
284: {
1.1.1.4 root 285: /* Volume header successfully decrypted */
286:
287: if (Extension->cryptoInfo->hiddenVolume)
288: {
289: // Hidden volume setup
290:
291: // Validate the size of the hidden volume specified in the header
292: if (Extension->DiskLength < (__int64) Extension->cryptoInfo->hiddenVolumeSize + HIDDEN_VOL_HEADER_OFFSET + HEADER_SIZE
293: || Extension->cryptoInfo->hiddenVolumeSize <= 0)
294: {
295: mount->nReturnCode = ERR_VOL_SIZE_WRONG;
296: ntStatus = STATUS_SUCCESS;
297: goto error;
298: }
299:
300: // Determine the offset of the hidden volume
301: Extension->cryptoInfo->hiddenVolumeOffset = Extension->DiskLength - Extension->cryptoInfo->hiddenVolumeSize - HIDDEN_VOL_HEADER_OFFSET;
302:
303: Dump("Hidden volume offset = %I64d", Extension->cryptoInfo->hiddenVolumeOffset);
304:
305: // Validate the offset
306: if (Extension->cryptoInfo->hiddenVolumeOffset % SECTOR_SIZE != 0)
307: {
308: mount->nReturnCode = ERR_VOL_SIZE_WRONG;
309: ntStatus = STATUS_SUCCESS;
310: goto error;
311: }
312:
313: // Set volume size
314: Extension->DiskLength = Extension->cryptoInfo->hiddenVolumeSize;
315: }
316: else
317: {
318: // Normal (not a hidden) volume
319:
320: // Set volume size
321: Extension->DiskLength -= HEADER_SIZE;
322: }
1.1 root 323:
1.1.1.4 root 324: // Calculate virtual volume geometry
1.1 root 325: Extension->TracksPerCylinder = 1;
326: Extension->SectorsPerTrack = 1;
1.1.1.3 root 327: Extension->BytesPerSector = 512;
328: Extension->NumberOfCylinders = Extension->DiskLength / 512;
329: Extension->PartitionType = 0;
1.1.1.4 root 330:
1.1 root 331: Extension->bRawDevice = bRawDevice;
332:
333: if (wcslen (pwszMountVolume) < 64)
334: wcscpy (Extension->wszVolume, pwszMountVolume);
335: else
336: {
337: memcpy (Extension->wszVolume, pwszMountVolume, 60 * 2);
338: Extension->wszVolume[60] = (WCHAR) '.';
339: Extension->wszVolume[61] = (WCHAR) '.';
340: Extension->wszVolume[62] = (WCHAR) '.';
341: Extension->wszVolume[63] = (WCHAR) 0;
342: }
343:
344: Extension->mountTime = mount->time;
345:
346: TCfree (readBuffer);
347: return STATUS_SUCCESS;
348: }
349:
350:
351: /* Failed due to some non-OS reason so we drop through and return NT
352: SUCCESS then nReturnCode is checked later in user-mode */
353:
354: if (mount->nReturnCode == ERR_OUTOFMEMORY)
355: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
356: else
357: ntStatus = STATUS_SUCCESS;
358:
1.1.1.4 root 359: error:
360:
361: if (bTimeStampValid)
362: {
363: /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
364: RestoreTimeStamp (Extension);
365: bTimeStampValid = FALSE;
366: }
1.1 root 367:
368: /* Close the hDeviceFile */
369: if (Extension->hDeviceFile != NULL)
370: ZwClose (Extension->hDeviceFile);
371:
372: /* The cryptoInfo pointer is deallocated if the readheader routines
373: fail so there is no need to deallocate here */
374:
375: /* Dereference the user-mode file object */
376: if (Extension->pfoDeviceFile != NULL)
377: ObDereferenceObject (Extension->pfoDeviceFile);
378:
1.1.1.4 root 379: /* Free the tmp IO buffers */
1.1 root 380: if (readBuffer != NULL)
381: TCfree (readBuffer);
382:
1.1.1.4 root 383: if (readBufferHiddenVol != NULL)
384: TCfree (readBufferHiddenVol);
385:
1.1 root 386: return ntStatus;
387: }
388:
389: void
390: TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
391: {
1.1.1.4 root 392: NTSTATUS ntStatus;
393:
1.1 root 394: if (DeviceObject); /* Remove compiler warning */
395:
396: if (Extension->hDeviceFile != NULL)
1.1.1.4 root 397: {
398: if (Extension->bRawDevice == FALSE)
399: {
400: /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
401: RestoreTimeStamp (Extension);
402: }
403:
404: ntStatus = ZwClose (Extension->hDeviceFile);
405: if (!NT_SUCCESS (ntStatus))
406: Dump ("ZwClose failed in TCCloseVolume: NTSTATUS 0x%08x\n", ntStatus);
407: }
1.1 root 408: ObDereferenceObject (Extension->pfoDeviceFile);
409: crypto_close (Extension->cryptoInfo);
410: }
411:
412: /* This rountine can be called at any IRQL so we need to tread carefully. Not
413: even DbgPrint or KdPrint are called here as the kernel sometimes faults if
414: they are called at high IRQL */
415:
416: NTSTATUS
417: TCCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID pUserBuffer)
418: {
419: PIO_STACK_LOCATION irpSp;
420: PEXTENSION Extension;
421: NTSTATUS ntStatus;
422:
423: Extension = (PEXTENSION) DeviceObject->DeviceExtension;
424:
425: /* Check to make sure the DeviceObject passed in is actually ours! */
426: if (Extension->lMagicNumber != 0xabfeacde)
427: KeBugCheck ((ULONG) 0xabfeacde);
428:
429: ASSERT (Extension->nDosDriveNo >= 0 && Extension->nDosDriveNo <= 0x19);
430:
431: #ifdef USE_KERNEL_MUTEX
432: KeWaitForMutexObject (&Extension->KernelMutex, Executive, KernelMode,
433: FALSE, NULL);
434: #endif
435:
436: #if EXTRA_INFO
437: Dump ("Completing IRP...BEGIN\n");
438: Dump ("COMPLETION USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress);
439: Dump ("COMPLETION Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject);
440: Dump ("Completing DeviceObject 0x%08x Irp 0x%08x\n", DeviceObject, Irp);
441: #endif
442:
443: /* Note: The Irp stack location we get back here is our one, we setup
444: the next stack location with a copy of this stack data in the send
445: function... here we always get back our own stack location, so
446: it's possible to use Read.Key to store extra pointers if needed. */
447: irpSp = IoGetCurrentIrpStackLocation (Irp);
448:
449: ntStatus = Irp->IoStatus.Status;
450:
451: if (ntStatus == STATUS_TOO_LATE)
452: KeBugCheck ((ULONG) 0x50ff);
453:
454: if (Irp->PendingReturned) /* From Windows NT File System
455: Internals */
456: IoMarkIrpPending (Irp);
457:
458: if (Extension->bRawDevice == FALSE)
459: {
460: /* Note: For some reason even though we used DIRECT_IO
461: sometimes the Irp's come back to use with MDLs !! if we
462: get an MDL here we need to free it up otherwise later when
463: we call IoFreeIrp the system will trap */
464:
465: PMDL pMdl, pNextMdl;
466:
467: pMdl = Irp->MdlAddress;
468:
469: while (pMdl != NULL)
470: {
471: pNextMdl = pMdl->Next;
472:
473: MmUnmapLockedPages (MmGetSystemAddressForMdlSafe (pMdl, HighPagePriority), pMdl);
474: MmUnlockPages (pMdl);
475: IoFreeMdl (pMdl);
476:
477: pMdl = pNextMdl;
478: }
479: }
480:
481: if (NT_SUCCESS (Irp->IoStatus.Status) && irpSp->MajorFunction == IRP_MJ_READ)
482: {
483: __int64 tmpOffset = irpSp->Parameters.Read.ByteOffset.QuadPart;
484: ULONG tmpLength = irpSp->Parameters.Read.Length;
485: PUCHAR CurrentAddress;
486:
487: if (Extension->bRawDevice == TRUE)
488: CurrentAddress = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
489: else
490: CurrentAddress = Irp->UserBuffer;
491:
492: if (tmpLength > 0)
493: {
494: /* Decrypt the data on read */
1.1.1.4 root 495: DecryptSectors ((ULONG *) CurrentAddress,
1.1 root 496: tmpOffset / SECTOR_SIZE,
497: tmpLength / SECTOR_SIZE,
1.1.1.4 root 498: Extension->cryptoInfo->ks,
1.1 root 499: Extension->cryptoInfo->iv,
1.1.1.4 root 500: Extension->cryptoInfo->ea);
1.1 root 501: }
502:
503: if (Extension->bRawDevice == FALSE)
504: {
505: PIRP OldIrp = (PIRP) pUserBuffer;
506: PUCHAR OriginalAddress;
507: CurrentAddress = Irp->UserBuffer;
508: OriginalAddress = MmGetSystemAddressForMdlSafe (OldIrp->MdlAddress, HighPagePriority);
509: memcpy (OriginalAddress, CurrentAddress, Irp->IoStatus.Information);
510: }
511:
512: }
513:
514: if (NT_SUCCESS (Irp->IoStatus.Status) && irpSp->MajorFunction == IRP_MJ_WRITE)
515: {
516: PUCHAR CurrentAddress;
517: PUCHAR OriginalAddress;
518:
519: if (Extension->bRawDevice == TRUE)
520: {
521: CurrentAddress = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
522: OriginalAddress = MmGetSystemAddressForMdlSafe ((PMDL) pUserBuffer, HighPagePriority);
523: }
524: else
525: {
526: PIRP OldIrp = (PIRP) pUserBuffer;
527: CurrentAddress = Irp->UserBuffer;
528: OriginalAddress = MmGetSystemAddressForMdlSafe (OldIrp->MdlAddress, HighPagePriority);
529: }
530:
531: //if (NT_SUCCESS (Irp->IoStatus.Status))
532: //{
533: // __int64 tmpOffset = irpSp->Parameters.Read.ByteOffset.QuadPart;
534: //}
535: }
536:
537: if (Extension->bRawDevice == TRUE && irpSp->MajorFunction == IRP_MJ_WRITE)
538: {
539: PUCHAR tmpBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
540: /* Free the temp buffer we allocated */
541: TCfree (tmpBuffer);
542: /* Free the Mdl we allocated */
543: IoFreeMdl (Irp->MdlAddress);
544: /* Reset the Irp */
545: Irp->MdlAddress = pUserBuffer;
546: }
547:
548: if (Extension->bRawDevice == TRUE && irpSp->MajorFunction == IRP_MJ_READ)
549: {
550: /* Nothing to do */
551: }
552:
553: #if EXTRA_INFO
554: Dump ("COMPLETION OLD USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress);
555: Dump ("COMPLETION OLD Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject);
556: Dump ("Completing IRP 0x%08x NTSTATUS 0x%08x information %lu END\n", (ULONG) irpSp->MajorFunction,
557: Irp->IoStatus.Status, Irp->IoStatus.Information);
558: #endif
559:
560: if (Extension->bRawDevice == FALSE)
561: {
562: PIRP OldIrp = (PIRP) pUserBuffer;
563: PVOID tmpBuffer = Irp->UserBuffer;
564: BOOL bFreeBuffer = irpSp->MajorFunction == IRP_MJ_WRITE || irpSp->MajorFunction == IRP_MJ_READ;
565:
566: OldIrp->IoStatus.Status = Irp->IoStatus.Status;
567: OldIrp->IoStatus.Information = Irp->IoStatus.Information;
568:
569: IoCompleteRequest (OldIrp, IO_DISK_INCREMENT);
570:
571: #if EXTRA_INFO
572: Dump ("About to free allocated IRP\n");
573: #endif
574:
575: Irp->UserBuffer = NULL;
576:
577: /* Free the allocated IRP. Note: This must be done before we
578: free tmpBuffer! */
579: IoFreeIrp (Irp);
580:
581: /* Note: From here on we cannot touch the Irp or irpSp */
582:
583: #if EXTRA_INFO
584: Dump ("Free allocated buffer = %d\n", bFreeBuffer);
585: #endif
586:
587: if (bFreeBuffer == TRUE)
588: TCfree (tmpBuffer);
589:
590: ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
591: }
592:
593: #ifdef USE_KERNEL_MUTEX
594: KeReleaseMutex (&Extension->KernelMutex, FALSE);
595: #endif
596:
597: return ntStatus;
598: }
599:
600: NTSTATUS
601: TCReadWrite (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp)
602: {
603: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
604: PUCHAR tmpBuffer = NULL;/* Remove compiler warning */
605: NTSTATUS ntStatus;
606:
607: // Dump ("TCReadWrite BEGIN\n");
608:
609: /* Check for invalid parameters. It is an error for the starting
610: offset + length to go past the end of the buffer, or for the
611: length to not be a proper multiple of the sector size. Others are
612: possible, but we don't check them since we trust the file system
613: and they aren't deadly. */
614: if (irpSp->Parameters.Read.ByteOffset.QuadPart + irpSp->Parameters.Read.Length > Extension->DiskLength
615: || (irpSp->Parameters.Read.Length & (Extension->BytesPerSector - 1)))
616: {
617: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0);
618: }
619: else
620: {
621: if (irpSp->Parameters.Read.Length == 0)
622: {
623: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0);
624: }
625: }
626:
627: #if EXTRA_INFO
628: Dump ("USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress);
629: Dump ("Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject);
630: Dump ("irpSp->FileObject = 0x%08x\n", irpSp->FileObject);
631:
632: if (Irp->Tail.Overlay.OriginalFileObject != NULL)
633: {
634: if (Irp->Tail.Overlay.OriginalFileObject->FileName.Length != 0)
635: Dump ("Irp->Tail.Overlay.OriginalFileObject = %ls\n", Irp->Tail.Overlay.OriginalFileObject->FileName.Buffer);
636: else
637: Dump ("Irp->Tail.Overlay.OriginalFileObject = %ls\n", WIDE ("null value"));
638:
639: }
640:
641: if (irpSp->FileObject != NULL)
642: {
643: if (irpSp->FileObject->FileName.Length != 0)
644: Dump ("irpSp->FileObject = %ls\n", irpSp->FileObject->FileName.Buffer);
645: else
646: Dump ("irpSp->FileObject = %ls\n", WIDE ("null value"));
647:
648: }
649: #endif
650:
651: if (Extension->bReadOnly == TRUE && irpSp->MajorFunction == IRP_MJ_WRITE)
652: return COMPLETE_IRP (DeviceObject, Irp, STATUS_MEDIA_WRITE_PROTECTED, 0);
653:
654: if (Extension->bRawDevice == FALSE || irpSp->MajorFunction == IRP_MJ_WRITE)
655: {
656: tmpBuffer = TCalloc (irpSp->Parameters.Read.Length);
657: if (tmpBuffer == NULL)
658: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
659: }
660:
661: if (irpSp->MajorFunction == IRP_MJ_READ)
662: {
663: // Dump ("Read: 0x%08x for %lu bytes...\n", irpSp->Parameters.Read.ByteOffset.LowPart,
664: // irpSp->Parameters.Read.Length);
665:
1.1.1.4 root 666:
667: if (Extension->cryptoInfo->hiddenVolume)
668: {
669: /* Hidden volume offset */
670: irpSp->Parameters.Read.ByteOffset.QuadPart += Extension->cryptoInfo->hiddenVolumeOffset;
671: }
672: else
673: {
674: /* Fixup the parameters to handle this particular volume type */
675: irpSp->Parameters.Read.ByteOffset.QuadPart += HEADER_SIZE;
676: }
1.1 root 677:
678: if (Extension->bRawDevice == TRUE)
679: ntStatus = TCSendIRP_RawDevice (DeviceObject, Extension,
680: NULL, IRP_READ_OPERATION | IRP_NOCACHE,
681: irpSp->MajorFunction,
682: Irp);
683: else
684: ntStatus = TCSendIRP_FileDevice (DeviceObject, Extension,
685: tmpBuffer, IRP_READ_OPERATION | IRP_NOCACHE,
686: irpSp->MajorFunction,
687: Irp);
688: }
689: else
690: {
691: PUCHAR CurrentAddress;
692:
693: // Dump ("Write: 0x%08x for %lu bytes...\n", irpSp->Parameters.Read.ByteOffset.LowPart,
694: // irpSp->Parameters.Read.Length);
695:
696: CurrentAddress = (PUCHAR) MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
697:
1.1.1.4 root 698:
699: if (Extension->cryptoInfo->hiddenVolume)
700: {
701: /* Hidden volume offset */
702: irpSp->Parameters.Read.ByteOffset.QuadPart += Extension->cryptoInfo->hiddenVolumeOffset;
703: }
704: else
705: {
706: /* Fixup the parameters to handle this particular volume type */
707: irpSp->Parameters.Read.ByteOffset.QuadPart += HEADER_SIZE;
708: }
1.1 root 709:
710: memcpy (tmpBuffer, CurrentAddress, irpSp->Parameters.Read.Length);
711:
712: /* Encrypt the data */
1.1.1.4 root 713: EncryptSectors ((ULONG *) tmpBuffer,
1.1 root 714: irpSp->Parameters.Read.ByteOffset.QuadPart / SECTOR_SIZE,
715: irpSp->Parameters.Read.Length / SECTOR_SIZE,
1.1.1.4 root 716: Extension->cryptoInfo->ks,
1.1 root 717: Extension->cryptoInfo->iv,
1.1.1.4 root 718: Extension->cryptoInfo->ea);
719:
1.1 root 720:
721: if (Extension->bRawDevice == TRUE)
722: {
723: PMDL tmpBufferMdl = IoAllocateMdl (tmpBuffer, irpSp->Parameters.Read.Length, FALSE, FALSE, NULL);
724: PMDL pTrueMdl = Irp->MdlAddress;
725:
726: if (tmpBufferMdl == NULL)
727: {
728: TCfree (tmpBuffer);
729: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
730: }
731:
732: MmBuildMdlForNonPagedPool (tmpBufferMdl);
733:
734: Irp->MdlAddress = tmpBufferMdl;
735:
736: #if EXTRA_INFO
737: Dump ("NEW MDL ADDRESS IS 0x%08x UserBuffer = 0x%08x\n", Irp->MdlAddress, Irp->UserBuffer);
738: #endif
739:
740: ntStatus = TCSendIRP_RawDevice (DeviceObject, Extension,
741: pTrueMdl, IRP_WRITE_OPERATION | IRP_NOCACHE,
742: irpSp->MajorFunction,
743: Irp);
744: }
745: else
746: {
747: ntStatus = TCSendIRP_FileDevice (DeviceObject, Extension,
748: tmpBuffer, IRP_WRITE_OPERATION | IRP_NOCACHE,
749: irpSp->MajorFunction,
750: Irp);
751: }
752:
753: }
754:
755: // Dump ("TCReadWrite END\n");
756: return ntStatus;
757: }
758:
759: NTSTATUS
760: TCSendDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject,
761: PEXTENSION Extension,
762: ULONG IoControlCode,
763: char *OutputBuffer,
764: int OutputBufferSize)
765: {
766: IO_STATUS_BLOCK IoStatusBlock;
767: NTSTATUS ntStatus;
768: PIRP Irp;
769:
770: if (DeviceObject); /* Remove compiler warning */
771:
772: KeClearEvent (&Extension->keVolumeEvent);
773:
774: Irp = IoBuildDeviceIoControlRequest (IoControlCode,
775: Extension->pFsdDevice,
776: NULL, 0,
777: OutputBuffer, OutputBufferSize,
778: FALSE,
779: &Extension->keVolumeEvent,
780: &IoStatusBlock);
781:
782: if (Irp == NULL)
783: {
784: Dump ("IRP allocation failed\n");
785: return STATUS_INSUFFICIENT_RESOURCES;
786: }
787:
1.1.1.5 ! root 788: // Disk device may be used by filesystem driver which needs file object
! 789: IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile;
! 790:
1.1 root 791: ntStatus = IoCallDriver (Extension->pFsdDevice, Irp);
792: if (ntStatus == STATUS_PENDING)
793: {
794: KeWaitForSingleObject (&Extension->keVolumeEvent, UserRequest, UserMode, FALSE, NULL);
795: ntStatus = IoStatusBlock.Status;
796: }
797:
798: return ntStatus;
799: }
800:
801: NTSTATUS
802: COMPLETE_IRP (PDEVICE_OBJECT DeviceObject,
803: PIRP Irp,
804: NTSTATUS IrpStatus,
1.1.1.4 root 805: ULONG_PTR IrpInformation)
1.1 root 806: {
807: Irp->IoStatus.Status = IrpStatus;
808: Irp->IoStatus.Information = IrpInformation;
809:
810: if (DeviceObject); /* Remove compiler warning */
811:
812: #ifdef _DEBUG
1.1.1.4 root 813: //if (!NT_SUCCESS (IrpStatus))
814: //{
815: // PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
816: // Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
817: // (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
818: //}
1.1 root 819: //else
820: //{
821: // PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
822: // Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
823: // (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
824: //}
825: #endif
826: IoCompleteRequest (Irp, IO_NO_INCREMENT);
827: return IrpStatus;
828: }
1.1.1.4 root 829:
830: // Restores the container timestamp to preserve plausible deniability of possible hidden volume.
831: static void RestoreTimeStamp (PEXTENSION Extension)
832: {
833: NTSTATUS ntStatus;
834: FILE_BASIC_INFORMATION FileBasicInfo;
835: IO_STATUS_BLOCK IoStatusBlock;
836:
837: if (Extension->hDeviceFile != NULL && Extension->bRawDevice == FALSE && Extension->bReadOnly == FALSE)
838: {
839: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
840: &IoStatusBlock,
841: &FileBasicInfo,
842: sizeof (FileBasicInfo),
843: FileBasicInformation);
844:
845: if (!NT_SUCCESS (ntStatus))
846: {
847: Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",
848: ntStatus);
849: }
850: else
851: {
852: FileBasicInfo.CreationTime = Extension->fileCreationTime;
853: FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime;
854: FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime;
855: FileBasicInfo.ChangeTime = Extension->fileLastChangeTime;
856:
857: ntStatus = ZwSetInformationFile(
858: Extension->hDeviceFile,
859: &IoStatusBlock,
860: &FileBasicInfo,
861: sizeof (FileBasicInfo),
862: FileBasicInformation);
863:
864: if (!NT_SUCCESS (ntStatus))
865: Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus);
866: }
867: }
868: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.