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