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