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

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

unix.superglobalmegacorp.com

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