|
|
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; ! 372: ! 373: if (wcslen (pwszMountVolume) < 64) ! 374: wcscpy (Extension->wszVolume, pwszMountVolume); ! 375: else ! 376: { ! 377: memcpy (Extension->wszVolume, pwszMountVolume, 60 * 2); ! 378: Extension->wszVolume[60] = (WCHAR) '.'; ! 379: Extension->wszVolume[61] = (WCHAR) '.'; ! 380: Extension->wszVolume[62] = (WCHAR) '.'; ! 381: Extension->wszVolume[63] = (WCHAR) 0; ! 382: } 1.1.1.4 root 383: } 384: 1.1.1.6 ! root 385: // If we are to protect a hidden volume we cannot exit yet, for we must also ! 386: // decrypt the hidden volume header. ! 387: if (!(volumeType == VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume)) 1.1.1.4 root 388: { 1.1.1.6 ! root 389: TCfree (readBuffer); 1.1.1.4 root 390: 1.1.1.6 ! root 391: if (tmpCryptoInfo != NULL) ! 392: crypto_close (tmpCryptoInfo); ! 393: ! 394: return STATUS_SUCCESS; ! 395: } 1.1.1.4 root 396: } 1.1.1.6 ! root 397: else if (mount->bProtectHiddenVolume ! 398: || mount->nReturnCode != ERR_PASSWORD_WRONG) 1.1.1.4 root 399: { 1.1.1.6 ! root 400: /* If we are not supposed to protect a hidden volume, the only error that is ! 401: tolerated is ERR_PASSWORD_WRONG (to allow mounting a possible hidden volume). 1.1.1.4 root 402: 1.1.1.6 ! root 403: If we _are_ supposed to protect a hidden volume, we do not tolerate any error ! 404: (both volume headers must be successfully decrypted). */ 1.1 root 405: 1.1.1.6 ! root 406: break; 1.1 root 407: } 408: } 409: 410: /* Failed due to some non-OS reason so we drop through and return NT 411: SUCCESS then nReturnCode is checked later in user-mode */ 412: 413: if (mount->nReturnCode == ERR_OUTOFMEMORY) 414: ntStatus = STATUS_INSUFFICIENT_RESOURCES; 415: else 416: ntStatus = STATUS_SUCCESS; 417: 1.1.1.4 root 418: error: 1.1.1.6 ! root 419: if (Extension->bTimeStampValid) 1.1.1.4 root 420: { 421: /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */ 422: RestoreTimeStamp (Extension); 423: } 1.1 root 424: 425: /* Close the hDeviceFile */ 426: if (Extension->hDeviceFile != NULL) 427: ZwClose (Extension->hDeviceFile); 428: 429: /* The cryptoInfo pointer is deallocated if the readheader routines 430: fail so there is no need to deallocate here */ 431: 432: /* Dereference the user-mode file object */ 433: if (Extension->pfoDeviceFile != NULL) 434: ObDereferenceObject (Extension->pfoDeviceFile); 435: 1.1.1.4 root 436: /* Free the tmp IO buffers */ 1.1 root 437: if (readBuffer != NULL) 438: TCfree (readBuffer); 439: 440: return ntStatus; 441: } 442: 443: void 444: TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension) 445: { 446: if (DeviceObject); /* Remove compiler warning */ 447: 448: if (Extension->hDeviceFile != NULL) 1.1.1.4 root 449: { 1.1.1.6 ! root 450: if (Extension->bRawDevice == FALSE ! 451: && Extension->bTimeStampValid) 1.1.1.4 root 452: { 453: /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */ 454: RestoreTimeStamp (Extension); 455: } 1.1.1.6 ! root 456: ZwClose (Extension->hDeviceFile); 1.1.1.4 root 457: } 1.1 root 458: ObDereferenceObject (Extension->pfoDeviceFile); 459: crypto_close (Extension->cryptoInfo); 460: } 461: 462: /* This rountine can be called at any IRQL so we need to tread carefully. Not 463: even DbgPrint or KdPrint are called here as the kernel sometimes faults if 464: they are called at high IRQL */ 465: 466: NTSTATUS 467: TCCompletion (PDEVICE_OBJECT DeviceObject, PIRP Irp, PVOID pUserBuffer) 468: { 469: PIO_STACK_LOCATION irpSp; 470: PEXTENSION Extension; 471: NTSTATUS ntStatus; 472: 473: Extension = (PEXTENSION) DeviceObject->DeviceExtension; 474: 475: /* Check to make sure the DeviceObject passed in is actually ours! */ 476: if (Extension->lMagicNumber != 0xabfeacde) 477: KeBugCheck ((ULONG) 0xabfeacde); 478: 479: ASSERT (Extension->nDosDriveNo >= 0 && Extension->nDosDriveNo <= 0x19); 480: 481: #ifdef USE_KERNEL_MUTEX 482: KeWaitForMutexObject (&Extension->KernelMutex, Executive, KernelMode, 483: FALSE, NULL); 484: #endif 485: 486: #if EXTRA_INFO 487: Dump ("Completing IRP...BEGIN\n"); 488: Dump ("COMPLETION USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress); 489: Dump ("COMPLETION Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject); 490: Dump ("Completing DeviceObject 0x%08x Irp 0x%08x\n", DeviceObject, Irp); 491: #endif 492: 493: /* Note: The Irp stack location we get back here is our one, we setup 494: the next stack location with a copy of this stack data in the send 495: function... here we always get back our own stack location, so 496: it's possible to use Read.Key to store extra pointers if needed. */ 497: irpSp = IoGetCurrentIrpStackLocation (Irp); 498: 499: ntStatus = Irp->IoStatus.Status; 500: 501: if (ntStatus == STATUS_TOO_LATE) 502: KeBugCheck ((ULONG) 0x50ff); 503: 504: if (Irp->PendingReturned) /* From Windows NT File System 505: Internals */ 506: IoMarkIrpPending (Irp); 507: 508: if (Extension->bRawDevice == FALSE) 509: { 510: /* Note: For some reason even though we used DIRECT_IO 511: sometimes the Irp's come back to use with MDLs !! if we 512: get an MDL here we need to free it up otherwise later when 513: we call IoFreeIrp the system will trap */ 514: 515: PMDL pMdl, pNextMdl; 516: 517: pMdl = Irp->MdlAddress; 518: 519: while (pMdl != NULL) 520: { 521: pNextMdl = pMdl->Next; 522: 523: MmUnmapLockedPages (MmGetSystemAddressForMdlSafe (pMdl, HighPagePriority), pMdl); 524: MmUnlockPages (pMdl); 525: IoFreeMdl (pMdl); 526: 527: pMdl = pNextMdl; 528: } 529: } 530: 531: if (NT_SUCCESS (Irp->IoStatus.Status) && irpSp->MajorFunction == IRP_MJ_READ) 532: { 533: __int64 tmpOffset = irpSp->Parameters.Read.ByteOffset.QuadPart; 534: ULONG tmpLength = irpSp->Parameters.Read.Length; 535: PUCHAR CurrentAddress; 536: 1.1.1.6 ! root 537: if (Extension->bRawDevice) 1.1 root 538: CurrentAddress = MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority); 539: else 540: CurrentAddress = Irp->UserBuffer; 541: 542: if (tmpLength > 0) 543: { 544: /* Decrypt the data on read */ 1.1.1.4 root 545: DecryptSectors ((ULONG *) CurrentAddress, 1.1 root 546: tmpOffset / SECTOR_SIZE, 547: tmpLength / SECTOR_SIZE, 1.1.1.4 root 548: Extension->cryptoInfo->ks, 1.1 root 549: Extension->cryptoInfo->iv, 1.1.1.4 root 550: Extension->cryptoInfo->ea); 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.4 root 796: Extension->cryptoInfo->ks, 1.1 root 797: Extension->cryptoInfo->iv, 1.1.1.4 root 798: Extension->cryptoInfo->ea); 799: 1.1.1.6 ! root 800: if (Extension->bRawDevice) 1.1 root 801: { 802: PMDL tmpBufferMdl = IoAllocateMdl (tmpBuffer, irpSp->Parameters.Read.Length, FALSE, FALSE, NULL); 803: PMDL pTrueMdl = Irp->MdlAddress; 804: 805: if (tmpBufferMdl == NULL) 806: { 807: TCfree (tmpBuffer); 808: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0); 809: } 810: 811: MmBuildMdlForNonPagedPool (tmpBufferMdl); 812: 813: Irp->MdlAddress = tmpBufferMdl; 814: 815: #if EXTRA_INFO 816: Dump ("NEW MDL ADDRESS IS 0x%08x UserBuffer = 0x%08x\n", Irp->MdlAddress, Irp->UserBuffer); 817: #endif 818: 819: ntStatus = TCSendIRP_RawDevice (DeviceObject, Extension, 820: pTrueMdl, IRP_WRITE_OPERATION | IRP_NOCACHE, 1.1.1.6 ! root 821: irpSp->MajorFunction, Irp); 1.1 root 822: } 823: else 824: { 825: ntStatus = TCSendIRP_FileDevice (DeviceObject, Extension, 826: tmpBuffer, IRP_WRITE_OPERATION | IRP_NOCACHE, 1.1.1.6 ! root 827: irpSp->MajorFunction, Irp); 1.1 root 828: } 829: } 830: 831: // Dump ("TCReadWrite END\n"); 832: return ntStatus; 833: } 834: 835: NTSTATUS 836: TCSendDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject, 837: PEXTENSION Extension, 838: ULONG IoControlCode, 839: char *OutputBuffer, 840: int OutputBufferSize) 841: { 842: IO_STATUS_BLOCK IoStatusBlock; 843: NTSTATUS ntStatus; 844: PIRP Irp; 845: 846: if (DeviceObject); /* Remove compiler warning */ 847: 848: KeClearEvent (&Extension->keVolumeEvent); 849: 850: Irp = IoBuildDeviceIoControlRequest (IoControlCode, 851: Extension->pFsdDevice, 852: NULL, 0, 853: OutputBuffer, OutputBufferSize, 854: FALSE, 855: &Extension->keVolumeEvent, 856: &IoStatusBlock); 857: 858: if (Irp == NULL) 859: { 860: Dump ("IRP allocation failed\n"); 861: return STATUS_INSUFFICIENT_RESOURCES; 862: } 863: 1.1.1.5 root 864: // Disk device may be used by filesystem driver which needs file object 865: IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile; 866: 1.1 root 867: ntStatus = IoCallDriver (Extension->pFsdDevice, Irp); 868: if (ntStatus == STATUS_PENDING) 869: { 870: KeWaitForSingleObject (&Extension->keVolumeEvent, UserRequest, UserMode, FALSE, NULL); 871: ntStatus = IoStatusBlock.Status; 872: } 873: 874: return ntStatus; 875: } 876: 877: NTSTATUS 878: COMPLETE_IRP (PDEVICE_OBJECT DeviceObject, 879: PIRP Irp, 880: NTSTATUS IrpStatus, 1.1.1.4 root 881: ULONG_PTR IrpInformation) 1.1 root 882: { 883: Irp->IoStatus.Status = IrpStatus; 884: Irp->IoStatus.Information = IrpInformation; 885: 886: if (DeviceObject); /* Remove compiler warning */ 887: 888: #ifdef _DEBUG 1.1.1.4 root 889: //if (!NT_SUCCESS (IrpStatus)) 890: //{ 891: // PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); 892: // Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction), 893: // (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus); 894: //} 1.1 root 895: //else 896: //{ 897: // PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); 898: // Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction), 899: // (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus); 900: //} 901: #endif 902: IoCompleteRequest (Irp, IO_NO_INCREMENT); 903: return IrpStatus; 904: } 1.1.1.4 root 905: 906: // Restores the container timestamp to preserve plausible deniability of possible hidden volume. 907: static void RestoreTimeStamp (PEXTENSION Extension) 908: { 909: NTSTATUS ntStatus; 910: FILE_BASIC_INFORMATION FileBasicInfo; 911: IO_STATUS_BLOCK IoStatusBlock; 912: 1.1.1.6 ! root 913: if (Extension->hDeviceFile != NULL ! 914: && Extension->bRawDevice == FALSE ! 915: && Extension->bReadOnly == FALSE ! 916: && Extension->bTimeStampValid) 1.1.1.4 root 917: { 918: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, 919: &IoStatusBlock, 920: &FileBasicInfo, 921: sizeof (FileBasicInfo), 922: FileBasicInformation); 923: 924: if (!NT_SUCCESS (ntStatus)) 925: { 926: Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n", 927: ntStatus); 928: } 929: else 930: { 931: FileBasicInfo.CreationTime = Extension->fileCreationTime; 932: FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime; 933: FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime; 934: FileBasicInfo.ChangeTime = Extension->fileLastChangeTime; 935: 936: ntStatus = ZwSetInformationFile( 937: Extension->hDeviceFile, 938: &IoStatusBlock, 939: &FileBasicInfo, 940: sizeof (FileBasicInfo), 941: FileBasicInformation); 942: 943: if (!NT_SUCCESS (ntStatus)) 944: Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus); 945: } 946: } 947: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.