|
|
1.1.1.10! root 1: /* ! 2: Legal Notice: The source code contained in this file has been derived from ! 3: the source code of Encryption for the Masses 2.02a, which is Copyright (c) ! 4: Paul Le Roux and which is covered by the 'License Agreement for Encryption ! 5: for the Masses'. Modifications and additions to that source code contained ! 6: in this file are Copyright (c) TrueCrypt Foundation and are covered by the ! 7: TrueCrypt License 2.2 the full text of which is contained in the file ! 8: License.txt included in TrueCrypt binary and source code distribution ! 9: packages. */ 1.1 root 10: 11: #include "TCdefs.h" 1.1.1.6 root 12: #include "Crypto.h" 13: #include "Volumes.h" 1.1 root 14: 1.1.1.6 root 15: #include "Apidrvr.h" 16: #include "Ntdriver.h" 17: #include "Ntvol.h" 1.1 root 18: 1.1.1.6 root 19: #include "Cache.h" 1.1 root 20: 1.1.1.10! root 21: #if 0 && _DEBUG ! 22: #define EXTRA_INFO 1 ! 23: #endif 1.1 root 24: 25: #pragma warning( disable : 4127 ) 26: 27: NTSTATUS 28: TCOpenVolume (PDEVICE_OBJECT DeviceObject, 29: PEXTENSION Extension, 1.1.1.6 root 30: MOUNT_STRUCT *mount, 1.1 root 31: PWSTR pwszMountVolume, 32: BOOL bRawDevice) 33: { 34: FILE_STANDARD_INFORMATION FileStandardInfo; 35: FILE_BASIC_INFORMATION FileBasicInfo; 36: OBJECT_ATTRIBUTES oaFileAttributes; 37: UNICODE_STRING FullFileName; 38: IO_STATUS_BLOCK IoStatusBlock; 1.1.1.6 root 39: PCRYPTO_INFO cryptoInfoPtr = NULL; 40: PCRYPTO_INFO tmpCryptoInfo = NULL; 1.1 root 41: LARGE_INTEGER lDiskLength; 1.1.1.6 root 42: LARGE_INTEGER hiddenVolHeaderOffset; 43: int volumeType; 1.1.1.4 root 44: char *readBuffer = 0; 1.1.1.5 root 45: NTSTATUS ntStatus = 0; 1.1 root 46: 47: Extension->pfoDeviceFile = NULL; 48: Extension->hDeviceFile = NULL; 1.1.1.6 root 49: Extension->bTimeStampValid = FALSE; 1.1 root 50: 1.1.1.4 root 51: RtlInitUnicodeString (&FullFileName, pwszMountVolume); 52: InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE, NULL, NULL); 53: KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE); 54: 55: // If we are opening a device, query its size first 56: if (bRawDevice) 1.1 root 57: { 1.1.1.5 root 58: PARTITION_INFORMATION pi; 1.1.1.10! root 59: PARTITION_INFORMATION_EX pix; 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: goto error; 69: 70: DeviceObject->StackSize = (CCHAR) (Extension->pFsdDevice->StackSize + 1); 71: 1.1.1.10! root 72: if (NT_SUCCESS (TCSendDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY, (char *) &dg, sizeof (dg)))) 1.1.1.4 root 73: { 1.1.1.10! root 74: lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.BytesPerSector; ! 75: mount->BytesPerSector = dg.BytesPerSector; 1.1.1.4 root 76: } 1.1.1.5 root 77: else 1.1.1.10! root 78: lDiskLength.QuadPart = 0; 1.1.1.4 root 79: 1.1.1.10! root 80: // Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails ! 81: if (NT_SUCCESS (TCSendDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO_EX, (char *) &pix, sizeof (pix)))) ! 82: lDiskLength.QuadPart = pix.PartitionLength.QuadPart; ! 83: // Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX ! 84: else if (NT_SUCCESS (TCSendDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO, (char *) &pi, sizeof (pi)))) ! 85: lDiskLength.QuadPart = pi.PartitionLength.QuadPart; 1.1 root 86: 1.1.1.10! root 87: if (!mount->bMountReadOnly && TCDeviceIoControl (pwszMountVolume, IOCTL_DISK_IS_WRITABLE, NULL, 0, NULL, 0) == STATUS_MEDIA_WRITE_PROTECTED) ! 88: { ! 89: mount->bMountReadOnly = TRUE; ! 90: DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE; 1.1.1.4 root 91: } 92: } 1.1 root 93: 1.1.1.10! root 94: if (mount->BytesPerSector == 0) ! 95: mount->BytesPerSector = SECTOR_SIZE; ! 96: ! 97: Extension->HostBytesPerSector = mount->BytesPerSector; ! 98: 1.1.1.4 root 99: // Open the volume hosting file/device 100: if (!mount->bMountReadOnly) 101: { 102: ntStatus = ZwCreateFile (&Extension->hDeviceFile, 103: GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE, 104: &oaFileAttributes, 105: &IoStatusBlock, 106: NULL, 107: FILE_ATTRIBUTE_NORMAL | 108: FILE_ATTRIBUTE_SYSTEM, 109: mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE, 110: FILE_OPEN, 1.1.1.10! root 111: FILE_RANDOM_ACCESS | 1.1.1.4 root 112: FILE_WRITE_THROUGH | 1.1.1.10! root 113: (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) | 1.1.1.4 root 114: FILE_SYNCHRONOUS_IO_NONALERT, 115: NULL, 116: 0); 117: } 1.1 root 118: 1.1.1.10! root 119: /* 26-4-99 NT for some partitions returns this code, it is really a access denied */ 1.1 root 120: if (ntStatus == 0xc000001b) 121: ntStatus = STATUS_ACCESS_DENIED; 1.1.1.6 root 122: 1.1.1.4 root 123: if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED) 1.1 root 124: { 125: ntStatus = ZwCreateFile (&Extension->hDeviceFile, 1.1.1.4 root 126: GENERIC_READ | SYNCHRONIZE, 127: &oaFileAttributes, 128: &IoStatusBlock, 129: NULL, 130: FILE_ATTRIBUTE_NORMAL | 131: FILE_ATTRIBUTE_SYSTEM, 1.1.1.8 root 132: mount->bExclusiveAccess ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE, 1.1.1.4 root 133: FILE_OPEN, 1.1.1.10! root 134: FILE_RANDOM_ACCESS | 1.1.1.4 root 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; 1.1.1.10! root 367: Extension->BytesPerSector = SECTOR_SIZE; ! 368: Extension->NumberOfCylinders = Extension->DiskLength / SECTOR_SIZE; 1.1.1.6 root 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: 466: NTSTATUS 1.1.1.10! root 467: TCReadWrite (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension, PIRP Irp) 1.1 root 468: { 1.1.1.10! root 469: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); ! 470: PUCHAR currentAddress; ! 471: PUCHAR tmpBuffer; 1.1 root 472: NTSTATUS ntStatus; 1.1.1.10! root 473: BOOL lowerPriority = (OsMajorVersion >= 6 && KeNumberProcessors == 1); 1.1 root 474: 475: #if EXTRA_INFO 1.1.1.10! root 476: Dump ("USER BUFFER IS 0x%08x MDL ADDRESS IS 0x%08x\n", Irp->UserBuffer, Irp->MdlAddress); ! 477: Dump ("Irp->Tail.Overlay.OriginalFileObject = 0x%08x\n", Irp->Tail.Overlay.OriginalFileObject); ! 478: Dump ("irpSp->FileObject = 0x%08x\n", irpSp->FileObject); 1.1 root 479: 1.1.1.10! root 480: if (Irp->Tail.Overlay.OriginalFileObject != NULL) 1.1 root 481: { 1.1.1.10! root 482: if (Irp->Tail.Overlay.OriginalFileObject->FileName.Length != 0) ! 483: Dump ("Irp->Tail.Overlay.OriginalFileObject = %ls\n", Irp->Tail.Overlay.OriginalFileObject->FileName.Buffer); 1.1 root 484: else 1.1.1.10! root 485: Dump ("Irp->Tail.Overlay.OriginalFileObject = %ls\n", WIDE ("null value")); 1.1 root 486: 487: } 488: 1.1.1.10! root 489: if (irpSp->FileObject != NULL) 1.1 root 490: { 1.1.1.10! root 491: if (irpSp->FileObject->FileName.Length != 0) ! 492: Dump ("irpSp->FileObject = %ls\n", irpSp->FileObject->FileName.Buffer); 1.1 root 493: else 1.1.1.10! root 494: Dump ("irpSp->FileObject = %ls\n", WIDE ("null value")); 1.1 root 495: 496: } 497: #endif 498: 1.1.1.10! root 499: currentAddress = (PUCHAR) MmGetSystemAddressForMdlSafe (Irp->MdlAddress, HighPagePriority); ! 500: if (currentAddress == NULL) ! 501: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0); 1.1 root 502: 1.1.1.10! root 503: if (irpSp->MajorFunction == IRP_MJ_READ) ! 504: { ! 505: LARGE_INTEGER readOffset; 1.1 root 506: 1.1.1.10! root 507: readOffset.QuadPart = irpSp->Parameters.Read.ByteOffset.QuadPart; 1.1 root 508: 1.1.1.10! root 509: if (irpSp->Parameters.Read.Length == 0 ! 510: || (irpSp->Parameters.Read.Length & (SECTOR_SIZE - 1)) ! 511: || readOffset.QuadPart + irpSp->Parameters.Read.Length > Extension->DiskLength) ! 512: { ! 513: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0); ! 514: } 1.1 root 515: 1.1.1.10! root 516: if (Extension->cryptoInfo->hiddenVolume) ! 517: readOffset.QuadPart += Extension->cryptoInfo->hiddenVolumeOffset; ! 518: else ! 519: readOffset.QuadPart += HEADER_SIZE; 1.1 root 520: 1.1.1.10! root 521: tmpBuffer = TCalloc (irpSp->Parameters.Read.Length); ! 522: if (tmpBuffer == NULL) ! 523: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0); 1.1 root 524: 1.1.1.10! root 525: ntStatus = ZwReadFile (Extension->hDeviceFile, ! 526: NULL, ! 527: NULL, ! 528: NULL, ! 529: &Irp->IoStatus, ! 530: tmpBuffer, ! 531: irpSp->Parameters.Read.Length, ! 532: &readOffset, ! 533: NULL); 1.1 root 534: 1.1.1.10! root 535: Irp->IoStatus.Status = ntStatus; 1.1 root 536: 1.1.1.10! root 537: if (NT_SUCCESS(ntStatus)) ! 538: { ! 539: Extension->TotalBytesRead += irpSp->Parameters.Read.Length; 1.1 root 540: 1.1.1.10! root 541: memcpy (currentAddress, tmpBuffer, irpSp->Parameters.Read.Length); 1.1 root 542: 1.1.1.10! root 543: if (lowerPriority) ! 544: KeSetPriorityThread (KeGetCurrentThread (), LOW_REALTIME_PRIORITY - 5); 1.1 root 545: 1.1.1.10! root 546: DecryptSectors ((ULONG *) currentAddress, ! 547: readOffset.QuadPart / SECTOR_SIZE, ! 548: irpSp->Parameters.Read.Length / SECTOR_SIZE, ! 549: Extension->cryptoInfo); 1.1 root 550: 1.1.1.10! root 551: if (lowerPriority) ! 552: KeSetPriorityThread (KeGetCurrentThread (), LOW_REALTIME_PRIORITY); 1.1 root 553: } 554: 1.1.1.10! root 555: TCfree (tmpBuffer); 1.1 root 556: } 1.1.1.10! root 557: else if (irpSp->MajorFunction == IRP_MJ_WRITE) 1.1 root 558: { 1.1.1.10! root 559: LARGE_INTEGER writeOffset; 1.1 root 560: 1.1.1.6 root 561: if (Extension->bReadOnly) 562: return COMPLETE_IRP (DeviceObject, Irp, STATUS_MEDIA_WRITE_PROTECTED, 0); 563: 1.1.1.10! root 564: writeOffset.QuadPart = irpSp->Parameters.Write.ByteOffset.QuadPart; ! 565: ! 566: if (irpSp->Parameters.Write.Length == 0 ! 567: || (irpSp->Parameters.Write.Length & (SECTOR_SIZE - 1)) ! 568: || writeOffset.QuadPart + irpSp->Parameters.Write.Length > Extension->DiskLength) ! 569: { ! 570: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0); ! 571: } ! 572: 1.1.1.6 root 573: // Hidden volume protection 574: if (Extension->cryptoInfo->bProtectHiddenVolume) 575: { 576: // If there has already been a write operation denied in order to protect the 577: // hidden volume (since the volume mount time) 578: if (Extension->cryptoInfo->bHiddenVolProtectionAction) 579: { 580: // Do not allow writing to this volume anymore. This is to fake a complete volume 581: // or system failure (otherwise certain kinds of inconsistency within the file 582: // system could indicate that this volume has used hidden volume protection). 583: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0); 584: } 585: 586: // Verify that no byte is going to be written to the hidden volume area 1.1.1.10! root 587: if (RegionsOverlap ((unsigned __int64) irpSp->Parameters.Write.ByteOffset.QuadPart + HEADER_SIZE, ! 588: (unsigned __int64) irpSp->Parameters.Write.ByteOffset.QuadPart + HEADER_SIZE + irpSp->Parameters.Write.Length - 1, 1.1.1.6 root 589: Extension->cryptoInfo->hiddenVolumeOffset, 590: (unsigned __int64) Extension->DiskLength + HEADER_SIZE - (HIDDEN_VOL_HEADER_OFFSET - HEADER_SIZE) - 1)) 591: { 592: Extension->cryptoInfo->bHiddenVolProtectionAction = TRUE; 593: 594: // Deny this write operation to prevent the hidden volume from being overwritten 595: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0); 596: } 597: } 1.1.1.4 root 598: 599: if (Extension->cryptoInfo->hiddenVolume) 1.1.1.10! root 600: writeOffset.QuadPart += Extension->cryptoInfo->hiddenVolumeOffset; 1.1.1.4 root 601: else 1.1.1.10! root 602: writeOffset.QuadPart += HEADER_SIZE; 1.1 root 603: 1.1.1.10! root 604: tmpBuffer = TCalloc (irpSp->Parameters.Write.Length); ! 605: if (tmpBuffer == NULL) 1.1.1.9 root 606: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INSUFFICIENT_RESOURCES, 0); 1.1.1.4 root 607: 1.1.1.10! root 608: memcpy (tmpBuffer, currentAddress, irpSp->Parameters.Write.Length); 1.1 root 609: 1.1.1.10! root 610: if (lowerPriority) ! 611: KeSetPriorityThread (KeGetCurrentThread (), LOW_REALTIME_PRIORITY - 5); 1.1 root 612: 1.1.1.4 root 613: EncryptSectors ((ULONG *) tmpBuffer, 1.1.1.10! root 614: writeOffset.QuadPart / SECTOR_SIZE, ! 615: irpSp->Parameters.Write.Length / SECTOR_SIZE, 1.1.1.7 root 616: Extension->cryptoInfo); 1.1.1.10! root 617: ! 618: if (lowerPriority) ! 619: KeSetPriorityThread (KeGetCurrentThread (), LOW_REALTIME_PRIORITY); 1.1.1.4 root 620: 1.1.1.10! root 621: ntStatus = ZwWriteFile (Extension->hDeviceFile, ! 622: NULL, ! 623: NULL, ! 624: NULL, ! 625: &Irp->IoStatus, ! 626: tmpBuffer, ! 627: irpSp->Parameters.Write.Length, ! 628: &writeOffset, ! 629: NULL); 1.1 root 630: 1.1.1.10! root 631: Irp->IoStatus.Status = ntStatus; 1.1 root 632: 1.1.1.10! root 633: if (NT_SUCCESS(ntStatus)) ! 634: Extension->TotalBytesWritten += irpSp->Parameters.Write.Length; 1.1 root 635: 1.1.1.10! root 636: TCfree (tmpBuffer); 1.1 root 637: } 1.1.1.10! root 638: else ! 639: return COMPLETE_IRP (DeviceObject, Irp, STATUS_INVALID_PARAMETER, 0); 1.1 root 640: 1.1.1.10! root 641: IoCompleteRequest (Irp, NT_SUCCESS(ntStatus) ? IO_DISK_INCREMENT : IO_NO_INCREMENT); 1.1 root 642: return ntStatus; 643: } 644: 1.1.1.10! root 645: 1.1 root 646: NTSTATUS 647: TCSendDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject, 648: PEXTENSION Extension, 649: ULONG IoControlCode, 650: char *OutputBuffer, 651: int OutputBufferSize) 652: { 653: IO_STATUS_BLOCK IoStatusBlock; 654: NTSTATUS ntStatus; 655: PIRP Irp; 656: 657: if (DeviceObject); /* Remove compiler warning */ 658: 659: KeClearEvent (&Extension->keVolumeEvent); 660: 661: Irp = IoBuildDeviceIoControlRequest (IoControlCode, 662: Extension->pFsdDevice, 663: NULL, 0, 664: OutputBuffer, OutputBufferSize, 665: FALSE, 666: &Extension->keVolumeEvent, 667: &IoStatusBlock); 668: 669: if (Irp == NULL) 670: { 671: Dump ("IRP allocation failed\n"); 672: return STATUS_INSUFFICIENT_RESOURCES; 673: } 674: 1.1.1.5 root 675: // Disk device may be used by filesystem driver which needs file object 676: IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile; 677: 1.1 root 678: ntStatus = IoCallDriver (Extension->pFsdDevice, Irp); 679: if (ntStatus == STATUS_PENDING) 680: { 681: KeWaitForSingleObject (&Extension->keVolumeEvent, UserRequest, UserMode, FALSE, NULL); 682: ntStatus = IoStatusBlock.Status; 683: } 684: 685: return ntStatus; 686: } 687: 688: NTSTATUS 689: COMPLETE_IRP (PDEVICE_OBJECT DeviceObject, 690: PIRP Irp, 691: NTSTATUS IrpStatus, 1.1.1.4 root 692: ULONG_PTR IrpInformation) 1.1 root 693: { 694: Irp->IoStatus.Status = IrpStatus; 695: Irp->IoStatus.Information = IrpInformation; 696: 697: if (DeviceObject); /* Remove compiler warning */ 698: 1.1.1.10! root 699: #if EXTRA_INFO ! 700: if (!NT_SUCCESS (IrpStatus)) ! 701: { ! 702: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); ! 703: Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction), ! 704: (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus); ! 705: } ! 706: else ! 707: { ! 708: PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp); ! 709: Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction), ! 710: (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus); ! 711: } 1.1 root 712: #endif 713: IoCompleteRequest (Irp, IO_NO_INCREMENT); 714: return IrpStatus; 715: } 1.1.1.4 root 716: 717: // Restores the container timestamp to preserve plausible deniability of possible hidden volume. 718: static void RestoreTimeStamp (PEXTENSION Extension) 719: { 720: NTSTATUS ntStatus; 721: FILE_BASIC_INFORMATION FileBasicInfo; 722: IO_STATUS_BLOCK IoStatusBlock; 723: 1.1.1.6 root 724: if (Extension->hDeviceFile != NULL 725: && Extension->bRawDevice == FALSE 726: && Extension->bReadOnly == FALSE 727: && Extension->bTimeStampValid) 1.1.1.4 root 728: { 729: ntStatus = ZwQueryInformationFile (Extension->hDeviceFile, 730: &IoStatusBlock, 731: &FileBasicInfo, 732: sizeof (FileBasicInfo), 733: FileBasicInformation); 734: 735: if (!NT_SUCCESS (ntStatus)) 736: { 737: Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n", 738: ntStatus); 739: } 740: else 741: { 742: FileBasicInfo.CreationTime = Extension->fileCreationTime; 743: FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime; 744: FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime; 745: FileBasicInfo.ChangeTime = Extension->fileLastChangeTime; 746: 747: ntStatus = ZwSetInformationFile( 748: Extension->hDeviceFile, 749: &IoStatusBlock, 750: &FileBasicInfo, 751: sizeof (FileBasicInfo), 752: FileBasicInformation); 753: 754: if (!NT_SUCCESS (ntStatus)) 755: Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus); 756: } 757: } 758: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.