|
|
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
1.1.1.8 root 5: contained in this file are Copyright (c) 2004-2006 TrueCrypt Foundation and
1.1.1.9 ! root 6: Copyright (c) 2004 TrueCrypt Team, and are covered by TrueCrypt License 2.1
1.1.1.6 root 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,
1.1.1.8 root 133: mount->bExclusiveAccess ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE,
1.1.1.4 root 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:
1.1.1.8 root 373: memset (Extension->wszVolume, 0, sizeof (Extension->wszVolume));
1.1.1.7 root 374: if (wcsstr (pwszMountVolume, WIDE ("\\??\\UNC\\")) == pwszMountVolume)
375: {
376: /* UNC path */
377: _snwprintf (Extension->wszVolume,
378: sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1,
379: WIDE ("\\??\\\\%s"),
380: pwszMountVolume + 7);
381: }
1.1.1.6 root 382: else
383: {
1.1.1.7 root 384: wcsncpy (Extension->wszVolume, pwszMountVolume, sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1);
1.1.1.6 root 385: }
1.1.1.4 root 386: }
387:
1.1.1.6 root 388: // If we are to protect a hidden volume we cannot exit yet, for we must also
389: // decrypt the hidden volume header.
390: if (!(volumeType == VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume))
1.1.1.4 root 391: {
1.1.1.6 root 392: TCfree (readBuffer);
1.1.1.4 root 393:
1.1.1.6 root 394: if (tmpCryptoInfo != NULL)
395: crypto_close (tmpCryptoInfo);
396:
397: return STATUS_SUCCESS;
398: }
1.1.1.4 root 399: }
1.1.1.6 root 400: else if (mount->bProtectHiddenVolume
401: || mount->nReturnCode != ERR_PASSWORD_WRONG)
1.1.1.4 root 402: {
1.1.1.6 root 403: /* If we are not supposed to protect a hidden volume, the only error that is
404: tolerated is ERR_PASSWORD_WRONG (to allow mounting a possible hidden volume).
1.1.1.4 root 405:
1.1.1.6 root 406: If we _are_ supposed to protect a hidden volume, we do not tolerate any error
407: (both volume headers must be successfully decrypted). */
1.1 root 408:
1.1.1.6 root 409: break;
1.1 root 410: }
411: }
412:
413: /* Failed due to some non-OS reason so we drop through and return NT
414: SUCCESS then nReturnCode is checked later in user-mode */
415:
416: if (mount->nReturnCode == ERR_OUTOFMEMORY)
417: ntStatus = STATUS_INSUFFICIENT_RESOURCES;
418: else
419: ntStatus = STATUS_SUCCESS;
420:
1.1.1.4 root 421: error:
1.1.1.6 root 422: if (Extension->bTimeStampValid)
1.1.1.4 root 423: {
424: /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
425: RestoreTimeStamp (Extension);
426: }
1.1 root 427:
428: /* Close the hDeviceFile */
429: if (Extension->hDeviceFile != NULL)
430: ZwClose (Extension->hDeviceFile);
431:
432: /* The cryptoInfo pointer is deallocated if the readheader routines
433: fail so there is no need to deallocate here */
434:
435: /* Dereference the user-mode file object */
436: if (Extension->pfoDeviceFile != NULL)
437: ObDereferenceObject (Extension->pfoDeviceFile);
438:
1.1.1.4 root 439: /* Free the tmp IO buffers */
1.1 root 440: if (readBuffer != NULL)
441: TCfree (readBuffer);
442:
443: return ntStatus;
444: }
445:
446: void
447: TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
448: {
449: if (DeviceObject); /* Remove compiler warning */
450:
451: if (Extension->hDeviceFile != NULL)
1.1.1.4 root 452: {
1.1.1.6 root 453: if (Extension->bRawDevice == FALSE
454: && Extension->bTimeStampValid)
1.1.1.4 root 455: {
456: /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
457: RestoreTimeStamp (Extension);
458: }
1.1.1.6 root 459: ZwClose (Extension->hDeviceFile);
1.1.1.4 root 460: }
1.1 root 461: ObDereferenceObject (Extension->pfoDeviceFile);
462: crypto_close (Extension->cryptoInfo);
463: }
464:
465: /* This rountine can be called at any IRQL so we need to tread carefully. Not
466: even DbgPrint or KdPrint are called here as the kernel sometimes faults if
467: they are called at high IRQL */
468:
469: NTSTATUS
470: TCCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID pUserBuffer)
471: {
472: PIO_STACK_LOCATION irpSp;
473: PEXTENSION Extension;
474: NTSTATUS ntStatus;
475:
476: Extension = (PEXTENSION) DeviceObject->DeviceExtension;
477:
478: /* Check to make sure the DeviceObject passed in is actually ours! */
479: if (Extension->lMagicNumber != 0xabfeacde)
480: KeBugCheck ((ULONG) 0xabfeacde);
481:
482: ASSERT (Extension->nDosDriveNo >= 0 && Extension->nDosDriveNo <= 0x19);
483:
484: #ifdef USE_KERNEL_MUTEX
485: KeWaitForMutexObject (&Extension->KernelMutex, Executive, KernelMode,
486: FALSE, NULL);
487: #endif
488:
489: #if EXTRA_INFO
490: Dump ("Completing IRP...BEGIN\n");
491: Dump ("COMPLETION USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress);
492: Dump ("COMPLETION Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject);
493: Dump ("Completing DeviceObject 0x%08x Irp 0x%08x\n", DeviceObject, Irp);
494: #endif
495:
496: /* Note: The Irp stack location we get back here is our one, we setup
497: the next stack location with a copy of this stack data in the send
498: function... here we always get back our own stack location, so
499: it's possible to use Read.Key to store extra pointers if needed. */
500: irpSp = IoGetCurrentIrpStackLocation (Irp);
501:
502: ntStatus = Irp->IoStatus.Status;
503:
504: if (ntStatus == STATUS_TOO_LATE)
505: KeBugCheck ((ULONG) 0x50ff);
506:
507: if (Irp->PendingReturned) /* From Windows NT File System
508: Internals */
509: IoMarkIrpPending (Irp);
510:
511: if (Extension->bRawDevice == FALSE)
512: {
513: /* Note: For some reason even though we used DIRECT_IO
514: sometimes the Irp's come back to use with MDLs !! if we
515: get an MDL here we need to free it up otherwise later when
516: we call IoFreeIrp the system will trap */
517:
518: PMDL pMdl, pNextMdl;
519:
520: pMdl = Irp->MdlAddress;
521:
522: while (pMdl != NULL)
523: {
524: pNextMdl = pMdl->Next;
525:
526: MmUnmapLockedPages (MmGetSystemAddressForMdlSafe (pMdl, HighPagePriority), pMdl);
527: MmUnlockPages (pMdl);
528: IoFreeMdl (pMdl);
529:
530: pMdl = pNextMdl;
531: }
532: }
533:
534: if (NT_SUCCESS (Irp->IoStatus.Status) && irpSp->MajorFunction == IRP_MJ_READ)
535: {
536: __int64 tmpOffset = irpSp->Parameters.Read.ByteOffset.QuadPart;
537: ULONG tmpLength = irpSp->Parameters.Read.Length;
538: PUCHAR CurrentAddress;
539:
1.1.1.6 root 540: if (Extension->bRawDevice)
1.1 root 541: CurrentAddress = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
542: else
543: CurrentAddress = Irp->UserBuffer;
544:
545: if (tmpLength > 0)
546: {
547: /* Decrypt the data on read */
1.1.1.4 root 548: DecryptSectors ((ULONG *) CurrentAddress,
1.1 root 549: tmpOffset / SECTOR_SIZE,
550: tmpLength / SECTOR_SIZE,
1.1.1.7 root 551: Extension->cryptoInfo);
1.1 root 552: }
553:
554: if (Extension->bRawDevice == FALSE)
555: {
556: PIRP OldIrp = (PIRP) pUserBuffer;
557: PUCHAR OriginalAddress;
558: CurrentAddress = Irp->UserBuffer;
559: OriginalAddress = MmGetSystemAddressForMdlSafe (OldIrp->MdlAddress, HighPagePriority);
560: memcpy (OriginalAddress, CurrentAddress, Irp->IoStatus.Information);
561: }
562:
563: }
564:
565: if (NT_SUCCESS (Irp->IoStatus.Status) && irpSp->MajorFunction == IRP_MJ_WRITE)
566: {
567: PUCHAR CurrentAddress;
568: PUCHAR OriginalAddress;
569:
1.1.1.6 root 570: if (Extension->bRawDevice)
1.1 root 571: {
572: CurrentAddress = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
573: OriginalAddress = MmGetSystemAddressForMdlSafe ((PMDL) pUserBuffer, HighPagePriority);
574: }
575: else
576: {
577: PIRP OldIrp = (PIRP) pUserBuffer;
578: CurrentAddress = Irp->UserBuffer;
579: OriginalAddress = MmGetSystemAddressForMdlSafe (OldIrp->MdlAddress, HighPagePriority);
580: }
581: }
582:
1.1.1.6 root 583: if (Extension->bRawDevice && irpSp->MajorFunction == IRP_MJ_WRITE)
1.1 root 584: {
585: PUCHAR tmpBuffer = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
586: /* Free the temp buffer we allocated */
587: TCfree (tmpBuffer);
588: /* Free the Mdl we allocated */
589: IoFreeMdl (Irp->MdlAddress);
590: /* Reset the Irp */
591: Irp->MdlAddress = pUserBuffer;
592: }
593:
1.1.1.6 root 594: if (Extension->bRawDevice && irpSp->MajorFunction == IRP_MJ_READ)
1.1 root 595: {
596: /* Nothing to do */
597: }
598:
599: #if EXTRA_INFO
600: Dump ("COMPLETION OLD USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress);
601: Dump ("COMPLETION OLD Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject);
602: Dump ("Completing IRP 0x%08x NTSTATUS 0x%08x information %lu END\n", (ULONG) irpSp->MajorFunction,
603: Irp->IoStatus.Status, Irp->IoStatus.Information);
604: #endif
605:
606: if (Extension->bRawDevice == FALSE)
607: {
608: PIRP OldIrp = (PIRP) pUserBuffer;
609: PVOID tmpBuffer = Irp->UserBuffer;
610: BOOL bFreeBuffer = irpSp->MajorFunction == IRP_MJ_WRITE || irpSp->MajorFunction == IRP_MJ_READ;
611:
612: OldIrp->IoStatus.Status = Irp->IoStatus.Status;
613: OldIrp->IoStatus.Information = Irp->IoStatus.Information;
614:
615: IoCompleteRequest (OldIrp, IO_DISK_INCREMENT);
616:
617: #if EXTRA_INFO
618: Dump ("About to free allocated IRP\n");
619: #endif
620:
621: Irp->UserBuffer = NULL;
622:
623: /* Free the allocated IRP. Note: This must be done before we
624: free tmpBuffer! */
625: IoFreeIrp (Irp);
626:
627: /* Note: From here on we cannot touch the Irp or irpSp */
628:
629: #if EXTRA_INFO
630: Dump ("Free allocated buffer = %d\n", bFreeBuffer);
631: #endif
632:
1.1.1.6 root 633: if (bFreeBuffer)
1.1 root 634: TCfree (tmpBuffer);
635:
636: ntStatus = STATUS_MORE_PROCESSING_REQUIRED;
637: }
638:
639: #ifdef USE_KERNEL_MUTEX
640: KeReleaseMutex (&Extension->KernelMutex, FALSE);
641: #endif
642:
643: return ntStatus;
644: }
645:
646: NTSTATUS
647: TCReadWrite (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp)
648: {
649: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
650: PUCHAR tmpBuffer = NULL;/* Remove compiler warning */
651: NTSTATUS ntStatus;
652:
653: // Dump ("TCReadWrite BEGIN\n");
654:
655: /* Check for invalid parameters. It is an error for the starting
656: offset + length to go past the end of the buffer, or for the
657: length to not be a proper multiple of the sector size. Others are
658: possible, but we don't check them since we trust the file system
659: and they aren't deadly. */
660: if (irpSp->Parameters.Read.ByteOffset.QuadPart + irpSp->Parameters.Read.Length > Extension->DiskLength
661: || (irpSp->Parameters.Read.Length & (Extension->BytesPerSector - 1)))
662: {
663: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0);
664: }
665: else
666: {
667: if (irpSp->Parameters.Read.Length == 0)
668: {
669: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0);
670: }
671: }
672:
673: #if EXTRA_INFO
674: Dump ("USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress);
675: Dump ("Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject);
676: Dump ("irpSp->FileObject = 0x%08x\n", irpSp->FileObject);
677:
678: if (Irp->Tail.Overlay.OriginalFileObject != NULL)
679: {
680: if (Irp->Tail.Overlay.OriginalFileObject->FileName.Length != 0)
681: Dump ("Irp->Tail.Overlay.OriginalFileObject = %ls\n", Irp->Tail.Overlay.OriginalFileObject->FileName.Buffer);
682: else
683: Dump ("Irp->Tail.Overlay.OriginalFileObject = %ls\n", WIDE ("null value"));
684:
685: }
686:
687: if (irpSp->FileObject != NULL)
688: {
689: if (irpSp->FileObject->FileName.Length != 0)
690: Dump ("irpSp->FileObject = %ls\n", irpSp->FileObject->FileName.Buffer);
691: else
692: Dump ("irpSp->FileObject = %ls\n", WIDE ("null value"));
693:
694: }
695: #endif
696:
1.1.1.6 root 697: // Volume protection
698: if (irpSp->MajorFunction == IRP_MJ_WRITE)
699: {
700: // Read-only mode
701: if (Extension->bReadOnly)
702: return COMPLETE_IRP (DeviceObject, Irp, STATUS_MEDIA_WRITE_PROTECTED, 0);
703:
704: // Hidden volume protection
705: if (Extension->cryptoInfo->bProtectHiddenVolume)
706: {
707: // If there has already been a write operation denied in order to protect the
708: // hidden volume (since the volume mount time)
709: if (Extension->cryptoInfo->bHiddenVolProtectionAction)
710: {
711: Dump("Write operation denied due to a previous hidden volume protection action");
712:
713: // Do not allow writing to this volume anymore. This is to fake a complete volume
714: // or system failure (otherwise certain kinds of inconsistency within the file
715: // system could indicate that this volume has used hidden volume protection).
716: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0);
717: }
718:
719: // Verify that no byte is going to be written to the hidden volume area
720: if (RegionsOverlap ((unsigned __int64) irpSp->Parameters.Read.ByteOffset.QuadPart + HEADER_SIZE,
721: (unsigned __int64) irpSp->Parameters.Read.ByteOffset.QuadPart + HEADER_SIZE + irpSp->Parameters.Read.Length - 1,
722: Extension->cryptoInfo->hiddenVolumeOffset,
723: (unsigned __int64) Extension->DiskLength + HEADER_SIZE - (HIDDEN_VOL_HEADER_OFFSET - HEADER_SIZE) - 1))
724: {
725: Extension->cryptoInfo->bHiddenVolProtectionAction = TRUE;
726: Dump("Write operation denied (offset = %I64d) to protect hidden volume", irpSp->Parameters.Read.ByteOffset.QuadPart);
727:
728: // Deny this write operation to prevent the hidden volume from being overwritten
729: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0);
730: }
731:
732: }
733: }
1.1 root 734:
735: if (Extension->bRawDevice == FALSE || irpSp->MajorFunction == IRP_MJ_WRITE)
736: {
737: tmpBuffer = TCalloc (irpSp->Parameters.Read.Length);
738: if (tmpBuffer == NULL)
739: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
740: }
741:
742: if (irpSp->MajorFunction == IRP_MJ_READ)
743: {
744: // Dump ("Read: 0x%08x for %lu bytes...\n", irpSp->Parameters.Read.ByteOffset.LowPart,
745: // irpSp->Parameters.Read.Length);
746:
1.1.1.6 root 747: Extension->TotalBytesRead += irpSp->Parameters.Read.Length;
1.1.1.4 root 748:
749: if (Extension->cryptoInfo->hiddenVolume)
750: {
751: /* Hidden volume offset */
752: irpSp->Parameters.Read.ByteOffset.QuadPart += Extension->cryptoInfo->hiddenVolumeOffset;
753: }
754: else
755: {
756: /* Fixup the parameters to handle this particular volume type */
757: irpSp->Parameters.Read.ByteOffset.QuadPart += HEADER_SIZE;
758: }
1.1 root 759:
1.1.1.6 root 760: if (Extension->bRawDevice)
1.1 root 761: ntStatus = TCSendIRP_RawDevice (DeviceObject, Extension,
762: NULL, IRP_READ_OPERATION | IRP_NOCACHE,
1.1.1.6 root 763: irpSp->MajorFunction, Irp);
1.1 root 764: else
765: ntStatus = TCSendIRP_FileDevice (DeviceObject, Extension,
766: tmpBuffer, IRP_READ_OPERATION | IRP_NOCACHE,
1.1.1.6 root 767: irpSp->MajorFunction, Irp);
1.1 root 768: }
769: else
770: {
771: PUCHAR CurrentAddress;
772:
773: // Dump ("Write: 0x%08x for %lu bytes...\n", irpSp->Parameters.Read.ByteOffset.LowPart,
774: // irpSp->Parameters.Read.Length);
775:
1.1.1.6 root 776: Extension->TotalBytesWritten += irpSp->Parameters.Read.Length;
1.1 root 777:
1.1.1.6 root 778: CurrentAddress = (PUCHAR) MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority);
1.1.1.9 ! root 779: if (CurrentAddress == NULL)
! 780: {
! 781: TCfree (tmpBuffer);
! 782: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
! 783: }
1.1.1.4 root 784:
785: if (Extension->cryptoInfo->hiddenVolume)
786: {
787: /* Hidden volume offset */
788: irpSp->Parameters.Read.ByteOffset.QuadPart += Extension->cryptoInfo->hiddenVolumeOffset;
789: }
790: else
791: {
792: /* Fixup the parameters to handle this particular volume type */
793: irpSp->Parameters.Read.ByteOffset.QuadPart += HEADER_SIZE;
794: }
1.1 root 795:
796: memcpy (tmpBuffer, CurrentAddress, irpSp->Parameters.Read.Length);
797:
798: /* Encrypt the data */
1.1.1.4 root 799: EncryptSectors ((ULONG *) tmpBuffer,
1.1 root 800: irpSp->Parameters.Read.ByteOffset.QuadPart / SECTOR_SIZE,
801: irpSp->Parameters.Read.Length / SECTOR_SIZE,
1.1.1.7 root 802: Extension->cryptoInfo);
1.1.1.4 root 803:
1.1.1.6 root 804: if (Extension->bRawDevice)
1.1 root 805: {
806: PMDL tmpBufferMdl = IoAllocateMdl (tmpBuffer, irpSp->Parameters.Read.Length, FALSE, FALSE, NULL);
807: PMDL pTrueMdl = Irp->MdlAddress;
808:
809: if (tmpBufferMdl == NULL)
810: {
811: TCfree (tmpBuffer);
812: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0);
813: }
814:
815: MmBuildMdlForNonPagedPool (tmpBufferMdl);
816:
817: Irp->MdlAddress = tmpBufferMdl;
818:
819: #if EXTRA_INFO
820: Dump ("NEW MDL ADDRESS IS 0x%08x UserBuffer = 0x%08x\n", Irp->MdlAddress, Irp->UserBuffer);
821: #endif
822:
823: ntStatus = TCSendIRP_RawDevice (DeviceObject, Extension,
824: pTrueMdl, IRP_WRITE_OPERATION | IRP_NOCACHE,
1.1.1.6 root 825: irpSp->MajorFunction, Irp);
1.1 root 826: }
827: else
828: {
829: ntStatus = TCSendIRP_FileDevice (DeviceObject, Extension,
830: tmpBuffer, IRP_WRITE_OPERATION | IRP_NOCACHE,
1.1.1.6 root 831: irpSp->MajorFunction, Irp);
1.1 root 832: }
833: }
834:
835: // Dump ("TCReadWrite END\n");
836: return ntStatus;
837: }
838:
839: NTSTATUS
840: TCSendDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject,
841: PEXTENSION Extension,
842: ULONG IoControlCode,
843: char *OutputBuffer,
844: int OutputBufferSize)
845: {
846: IO_STATUS_BLOCK IoStatusBlock;
847: NTSTATUS ntStatus;
848: PIRP Irp;
849:
850: if (DeviceObject); /* Remove compiler warning */
851:
852: KeClearEvent (&Extension->keVolumeEvent);
853:
854: Irp = IoBuildDeviceIoControlRequest (IoControlCode,
855: Extension->pFsdDevice,
856: NULL, 0,
857: OutputBuffer, OutputBufferSize,
858: FALSE,
859: &Extension->keVolumeEvent,
860: &IoStatusBlock);
861:
862: if (Irp == NULL)
863: {
864: Dump ("IRP allocation failed\n");
865: return STATUS_INSUFFICIENT_RESOURCES;
866: }
867:
1.1.1.5 root 868: // Disk device may be used by filesystem driver which needs file object
869: IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile;
870:
1.1 root 871: ntStatus = IoCallDriver (Extension->pFsdDevice, Irp);
872: if (ntStatus == STATUS_PENDING)
873: {
874: KeWaitForSingleObject (&Extension->keVolumeEvent, UserRequest, UserMode, FALSE, NULL);
875: ntStatus = IoStatusBlock.Status;
876: }
877:
878: return ntStatus;
879: }
880:
881: NTSTATUS
882: COMPLETE_IRP (PDEVICE_OBJECT DeviceObject,
883: PIRP Irp,
884: NTSTATUS IrpStatus,
1.1.1.4 root 885: ULONG_PTR IrpInformation)
1.1 root 886: {
887: Irp->IoStatus.Status = IrpStatus;
888: Irp->IoStatus.Information = IrpInformation;
889:
890: if (DeviceObject); /* Remove compiler warning */
891:
892: #ifdef _DEBUG
1.1.1.4 root 893: //if (!NT_SUCCESS (IrpStatus))
894: //{
895: // PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
896: // Dump ("COMPLETE_IRP FAILING 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: //}
1.1 root 899: //else
900: //{
901: // PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
902: // Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
903: // (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
904: //}
905: #endif
906: IoCompleteRequest (Irp, IO_NO_INCREMENT);
907: return IrpStatus;
908: }
1.1.1.4 root 909:
910: // Restores the container timestamp to preserve plausible deniability of possible hidden volume.
911: static void RestoreTimeStamp (PEXTENSION Extension)
912: {
913: NTSTATUS ntStatus;
914: FILE_BASIC_INFORMATION FileBasicInfo;
915: IO_STATUS_BLOCK IoStatusBlock;
916:
1.1.1.6 root 917: if (Extension->hDeviceFile != NULL
918: && Extension->bRawDevice == FALSE
919: && Extension->bReadOnly == FALSE
920: && Extension->bTimeStampValid)
1.1.1.4 root 921: {
922: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
923: &IoStatusBlock,
924: &FileBasicInfo,
925: sizeof (FileBasicInfo),
926: FileBasicInformation);
927:
928: if (!NT_SUCCESS (ntStatus))
929: {
930: Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",
931: ntStatus);
932: }
933: else
934: {
935: FileBasicInfo.CreationTime = Extension->fileCreationTime;
936: FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime;
937: FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime;
938: FileBasicInfo.ChangeTime = Extension->fileLastChangeTime;
939:
940: ntStatus = ZwSetInformationFile(
941: Extension->hDeviceFile,
942: &IoStatusBlock,
943: &FileBasicInfo,
944: sizeof (FileBasicInfo),
945: FileBasicInformation);
946:
947: if (!NT_SUCCESS (ntStatus))
948: Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus);
949: }
950: }
951: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.