Annotation of truecrypt/driver/ntvol.c, revision 1.1.1.5

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.