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

1.1.1.10  root        1: /*
1.1.1.12  root        2:  Legal Notice: Some portions of the source code contained in this file were
                      3:  derived from the source code of Encryption for the Masses 2.02a, which is
                      4:  Copyright (c) 1998-2000 Paul Le Roux and which is governed by the 'License
                      5:  Agreement for Encryption for the Masses'. Modifications and additions to
                      6:  the original source code (contained in this file) and all other portions of
                      7:  this file are Copyright (c) 2003-2008 TrueCrypt Foundation and are governed
                      8:  by the TrueCrypt License 2.4 the full text of which is contained in the
                      9:  file License.txt included in TrueCrypt binary and source code distribution
1.1.1.10  root       10:  packages. */
1.1       root       11: 
                     12: #include "TCdefs.h"
1.1.1.6   root       13: #include "Crypto.h"
                     14: #include "Volumes.h"
1.1       root       15: 
1.1.1.6   root       16: #include "Apidrvr.h"
                     17: #include "Ntdriver.h"
                     18: #include "Ntvol.h"
1.1       root       19: 
1.1.1.13! root       20: #include "Boot/Windows/BootCommon.h"
        !            21: 
1.1.1.6   root       22: #include "Cache.h"
1.1       root       23: 
1.1.1.10  root       24: #if 0 && _DEBUG
                     25: #define EXTRA_INFO 1
                     26: #endif
1.1       root       27: 
                     28: #pragma warning( disable : 4127 )
                     29: 
                     30: NTSTATUS
                     31: TCOpenVolume (PDEVICE_OBJECT DeviceObject,
                     32:               PEXTENSION Extension,
1.1.1.6   root       33:               MOUNT_STRUCT *mount,
1.1       root       34:               PWSTR pwszMountVolume,
                     35:               BOOL bRawDevice)
                     36: {
                     37:        FILE_STANDARD_INFORMATION FileStandardInfo;
                     38:        FILE_BASIC_INFORMATION FileBasicInfo;
                     39:        OBJECT_ATTRIBUTES oaFileAttributes;
                     40:        UNICODE_STRING FullFileName;
                     41:        IO_STATUS_BLOCK IoStatusBlock;
1.1.1.6   root       42:        PCRYPTO_INFO cryptoInfoPtr = NULL;
                     43:        PCRYPTO_INFO tmpCryptoInfo = NULL;
1.1       root       44:        LARGE_INTEGER lDiskLength;
1.1.1.6   root       45:        LARGE_INTEGER hiddenVolHeaderOffset;
1.1.1.13! root       46:        __int64 partitionStartingOffset;
1.1.1.6   root       47:        int volumeType;
1.1.1.4   root       48:        char *readBuffer = 0;
1.1.1.5   root       49:        NTSTATUS ntStatus = 0;
1.1       root       50: 
                     51:        Extension->pfoDeviceFile = NULL;
                     52:        Extension->hDeviceFile = NULL;
1.1.1.6   root       53:        Extension->bTimeStampValid = FALSE;
1.1       root       54: 
1.1.1.4   root       55:        RtlInitUnicodeString (&FullFileName, pwszMountVolume);
                     56:        InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE,     NULL, NULL);
                     57:        KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE);
                     58: 
                     59:        // If we are opening a device, query its size first
                     60:        if (bRawDevice)
1.1       root       61:        {
1.1.1.5   root       62:                PARTITION_INFORMATION pi;
1.1.1.10  root       63:                PARTITION_INFORMATION_EX pix;
1.1.1.4   root       64:                DISK_GEOMETRY dg;
1.1       root       65: 
1.1.1.4   root       66:                ntStatus = IoGetDeviceObjectPointer (&FullFileName,
                     67:                        FILE_READ_DATA,
                     68:                        &Extension->pfoDeviceFile,
                     69:                        &Extension->pFsdDevice);
                     70: 
                     71:                if (!NT_SUCCESS (ntStatus))
                     72:                        goto error;
                     73: 
1.1.1.12  root       74:                if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY, (char *) &dg, sizeof (dg))))
1.1.1.4   root       75:                {
1.1.1.10  root       76:                        lDiskLength.QuadPart = dg.Cylinders.QuadPart * dg.SectorsPerTrack * dg.TracksPerCylinder * dg.BytesPerSector;
                     77:                        mount->BytesPerSector = dg.BytesPerSector;
1.1.1.4   root       78:                }
1.1.1.5   root       79:                else
1.1.1.10  root       80:                        lDiskLength.QuadPart = 0;
1.1.1.4   root       81: 
1.1.1.10  root       82:                // Drive geometry is used only when IOCTL_DISK_GET_PARTITION_INFO fails
1.1.1.12  root       83:                if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO_EX, (char *) &pix, sizeof (pix))))
1.1.1.13! root       84:                {
1.1.1.10  root       85:                        lDiskLength.QuadPart = pix.PartitionLength.QuadPart;
1.1.1.13! root       86:                        partitionStartingOffset = pix.StartingOffset.QuadPart;
        !            87:                }
1.1.1.10  root       88:                // Windows 2000 does not support IOCTL_DISK_GET_PARTITION_INFO_EX
1.1.1.12  root       89:                else if (NT_SUCCESS (TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_PARTITION_INFO, (char *) &pi, sizeof (pi))))
1.1.1.13! root       90:                {
1.1.1.10  root       91:                        lDiskLength.QuadPart = pi.PartitionLength.QuadPart;
1.1.1.13! root       92:                        partitionStartingOffset = pi.StartingOffset.QuadPart;
        !            93:                }
1.1       root       94: 
1.1.1.12  root       95:                if (!mount->bMountReadOnly && TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_IS_WRITABLE, NULL, 0) == STATUS_MEDIA_WRITE_PROTECTED)
1.1.1.10  root       96:                {
                     97:                        mount->bMountReadOnly = TRUE;
                     98:                        DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
1.1.1.4   root       99:                }
                    100:        }
1.1       root      101: 
1.1.1.10  root      102:        if (mount->BytesPerSector == 0)
                    103:                mount->BytesPerSector = SECTOR_SIZE;
                    104: 
                    105:        Extension->HostBytesPerSector = mount->BytesPerSector;
                    106: 
1.1.1.4   root      107:        // Open the volume hosting file/device
                    108:        if (!mount->bMountReadOnly)
                    109:        {
                    110:                ntStatus = ZwCreateFile (&Extension->hDeviceFile,
                    111:                        GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
                    112:                        &oaFileAttributes,
                    113:                        &IoStatusBlock,
                    114:                        NULL,
                    115:                        FILE_ATTRIBUTE_NORMAL |
                    116:                        FILE_ATTRIBUTE_SYSTEM,
                    117:                        mount->bExclusiveAccess ? 0 : FILE_SHARE_READ | FILE_SHARE_WRITE,
                    118:                        FILE_OPEN,
1.1.1.10  root      119:                        FILE_RANDOM_ACCESS |
1.1.1.4   root      120:                        FILE_WRITE_THROUGH |
1.1.1.10  root      121:                        (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
1.1.1.4   root      122:                        FILE_SYNCHRONOUS_IO_NONALERT,
                    123:                        NULL,
                    124:                        0);
                    125:        }
1.1       root      126: 
1.1.1.10  root      127:        /* 26-4-99 NT for some partitions returns this code, it is really a     access denied */
1.1       root      128:        if (ntStatus == 0xc000001b)
                    129:                ntStatus = STATUS_ACCESS_DENIED;
1.1.1.6   root      130:        
1.1.1.4   root      131:        if (mount->bMountReadOnly || ntStatus == STATUS_ACCESS_DENIED)
1.1       root      132:        {
                    133:                ntStatus = ZwCreateFile (&Extension->hDeviceFile,
1.1.1.4   root      134:                        GENERIC_READ | SYNCHRONIZE,
                    135:                        &oaFileAttributes,
                    136:                        &IoStatusBlock,
                    137:                        NULL,
                    138:                        FILE_ATTRIBUTE_NORMAL |
                    139:                        FILE_ATTRIBUTE_SYSTEM,
1.1.1.8   root      140:                        mount->bExclusiveAccess ? FILE_SHARE_READ : FILE_SHARE_READ | FILE_SHARE_WRITE,
1.1.1.4   root      141:                        FILE_OPEN,
1.1.1.10  root      142:                        FILE_RANDOM_ACCESS |
1.1.1.4   root      143:                        FILE_WRITE_THROUGH |
1.1.1.11  root      144:                        (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
1.1.1.4   root      145:                        FILE_SYNCHRONOUS_IO_NONALERT,
                    146:                        NULL,
                    147:                        0);
1.1.1.11  root      148: 
1.1       root      149:                Extension->bReadOnly = TRUE;
1.1.1.11  root      150:                DeviceObject->Characteristics |= FILE_READ_ONLY_DEVICE;
1.1       root      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
1.1.1.12  root      162:                anyone even tries to open the partition (or file for that
1.1.1.4   root      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:                {
1.1.1.6   root      183:                        if (mount->bPreserveTimestamp)
                    184:                        {
                    185:                                /* Remember the container timestamp. (Used to reset access/modification file date/time
                    186:                                of file-hosted volumes upon dismount or after unsuccessful mount attempt to preserve
                    187:                                plausible deniability of hidden volumes.) */
                    188:                                Extension->fileCreationTime = FileBasicInfo.CreationTime;
                    189:                                Extension->fileLastAccessTime = FileBasicInfo.LastAccessTime;
                    190:                                Extension->fileLastWriteTime = FileBasicInfo.LastWriteTime;
                    191:                                Extension->fileLastChangeTime = FileBasicInfo.ChangeTime;
                    192:                                Extension->bTimeStampValid = TRUE;
                    193:                        }
1.1.1.4   root      194: 
1.1       root      195:                        ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
1.1.1.4   root      196:                                &IoStatusBlock,
                    197:                                &FileStandardInfo,
                    198:                                sizeof (FileStandardInfo),
                    199:                                FileStandardInformation);
                    200:                }
1.1       root      201: 
                    202:                if (!NT_SUCCESS (ntStatus))
                    203:                {
                    204:                        Dump ("ZwQueryInformationFile failed while opening file: NTSTATUS 0x%08x\n",
1.1.1.4   root      205:                                ntStatus);
1.1       root      206:                        goto error;
                    207:                }
1.1.1.4   root      208: 
                    209:                lDiskLength.QuadPart = FileStandardInfo.EndOfFile.QuadPart;
1.1       root      210: 
                    211:                if (FileBasicInfo.FileAttributes & FILE_ATTRIBUTE_COMPRESSED)
                    212:                {
                    213:                        Dump ("File \"%ls\" is marked as compressed - not supported!\n", pwszMountVolume);
                    214:                        mount->nReturnCode = ERR_COMPRESSION_NOT_SUPPORTED;
                    215:                        ntStatus = STATUS_SUCCESS;
                    216:                        goto error;
                    217:                }
                    218: 
                    219:                ntStatus = ObReferenceObjectByHandle (Extension->hDeviceFile,
1.1.1.4   root      220:                        FILE_ALL_ACCESS,
                    221:                        *IoFileObjectType,
                    222:                        KernelMode,
                    223:                        &Extension->pfoDeviceFile,
                    224:                        0);
1.1       root      225: 
                    226:                if (!NT_SUCCESS (ntStatus))
                    227:                {
                    228:                        goto error;
                    229:                }
                    230: 
1.1.1.4   root      231:                /* Get the FSD device for the file (probably either NTFS or     FAT) */
1.1       root      232:                Extension->pFsdDevice = IoGetRelatedDeviceObject (Extension->pfoDeviceFile);
                    233:        }
                    234: 
1.1.1.4   root      235:        // Check volume size
                    236:        if (lDiskLength.QuadPart < MIN_VOLUME_SIZE || lDiskLength.QuadPart > MAX_VOLUME_SIZE)
                    237:        {
                    238:                mount->nReturnCode = ERR_VOL_SIZE_WRONG;
                    239:                ntStatus = STATUS_SUCCESS;
                    240:                goto error;
                    241:        }
1.1.1.6   root      242: 
1.1.1.4   root      243:        Extension->DiskLength = lDiskLength.QuadPart;
1.1       root      244: 
1.1.1.6   root      245:        hiddenVolHeaderOffset.QuadPart = lDiskLength.QuadPart - HIDDEN_VOL_HEADER_OFFSET;
                    246: 
1.1.1.4   root      247:        readBuffer = TCalloc (HEADER_SIZE);
                    248:        if (readBuffer == NULL)
                    249:        {
                    250:                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                    251:                goto error;
                    252:        }
1.1       root      253: 
1.1.1.6   root      254:        // Go through all volume types (e.g., normal, hidden)
                    255:        for (volumeType = VOLUME_TYPE_NORMAL;
                    256:                volumeType < NBR_VOLUME_TYPES;
                    257:                volumeType++)   
1.1.1.4   root      258:        {
1.1.1.13! root      259:                if (mount->bPartitionInInactiveSysEncScope
        !           260:                        && volumeType != VOLUME_TYPE_NORMAL)
        !           261:                        continue;               
        !           262: 
1.1.1.6   root      263:                /* Read the volume header */
1.1       root      264: 
1.1.1.13! root      265:                if (!mount->bPartitionInInactiveSysEncScope)
        !           266:                {
        !           267:                        // Header of a volume that is not within the scope of system encryption
        !           268: 
        !           269:                        ntStatus = ZwReadFile (Extension->hDeviceFile,
1.1.1.6   root      270:                        NULL,
                    271:                        NULL,
                    272:                        NULL,
                    273:                        &IoStatusBlock,
                    274:                        readBuffer,
                    275:                        HEADER_SIZE,
                    276:                        volumeType == VOLUME_TYPE_HIDDEN ? &hiddenVolHeaderOffset : NULL,
                    277:                        NULL);
1.1.1.13! root      278:                }
        !           279:                else
        !           280:                {
        !           281:                        // Header of a partition that is within the scope of system encryption
        !           282: 
        !           283:                        WCHAR parentDrivePath [47+1] = {0};
        !           284:                        HANDLE hParentDeviceFile = NULL;
        !           285:                        UNICODE_STRING FullParentPath;
        !           286:                        OBJECT_ATTRIBUTES oaParentFileAttributes;
        !           287:                        LARGE_INTEGER parentKeyDataOffset;
        !           288: 
        !           289:                        _snwprintf (parentDrivePath,
        !           290:                                sizeof (parentDrivePath) / sizeof (WCHAR) - 1,
        !           291:                                WIDE ("\\Device\\Harddisk%d\\Partition0"),
        !           292:                                mount->nPartitionInInactiveSysEncScopeDriveNo);
        !           293: 
        !           294:                        Dump ("Mounting partition within scope of system encryption (reading key data from: %ls)\n", parentDrivePath);
        !           295: 
        !           296:                        RtlInitUnicodeString (&FullParentPath, parentDrivePath);
        !           297:                        InitializeObjectAttributes (&oaParentFileAttributes, &FullParentPath, OBJ_CASE_INSENSITIVE,     NULL, NULL);
        !           298: 
        !           299:                        ntStatus = ZwCreateFile (&hParentDeviceFile,
        !           300:                                GENERIC_READ | SYNCHRONIZE,
        !           301:                                &oaParentFileAttributes,
        !           302:                                &IoStatusBlock,
        !           303:                                NULL,
        !           304:                                FILE_ATTRIBUTE_NORMAL |
        !           305:                                FILE_ATTRIBUTE_SYSTEM,
        !           306:                                FILE_SHARE_READ | FILE_SHARE_WRITE,
        !           307:                                FILE_OPEN,
        !           308:                                FILE_RANDOM_ACCESS |
        !           309:                                FILE_WRITE_THROUGH |
        !           310:                                (Extension->HostBytesPerSector == SECTOR_SIZE ? FILE_NO_INTERMEDIATE_BUFFERING : 0) |
        !           311:                                FILE_SYNCHRONOUS_IO_NONALERT,
        !           312:                                NULL,
        !           313:                                0);
        !           314: 
        !           315:                        if (!NT_SUCCESS (ntStatus))
        !           316:                        {
        !           317:                                if (hParentDeviceFile != NULL)
        !           318:                                        ZwClose (hParentDeviceFile);
        !           319: 
        !           320:                                Dump ("Cannot open %ls\n", parentDrivePath);
        !           321: 
        !           322:                                goto error;
        !           323:                        }
        !           324: 
        !           325:                        parentKeyDataOffset.QuadPart = ((volumeType == VOLUME_TYPE_HIDDEN) ? TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET : TC_BOOT_VOLUME_HEADER_SECTOR_OFFSET);
        !           326: 
        !           327:                        ntStatus = ZwReadFile (hParentDeviceFile,
        !           328:                                NULL,
        !           329:                                NULL,
        !           330:                                NULL,
        !           331:                                &IoStatusBlock,
        !           332:                                readBuffer,
        !           333:                                HEADER_SIZE,
        !           334:                                &parentKeyDataOffset,
        !           335:                                NULL);
        !           336: 
        !           337:                        if (hParentDeviceFile != NULL)
        !           338:                                ZwClose (hParentDeviceFile);
        !           339:                }
1.1.1.6   root      340: 
                    341:                if (!NT_SUCCESS (ntStatus))
1.1       root      342:                {
1.1.1.6   root      343:                        Dump ("Read failed: NTSTATUS 0x%08x\n", ntStatus);
                    344:                }
                    345:                else if (IoStatusBlock.Information != HEADER_SIZE)
                    346:                {
                    347:                        Dump ("Read didn't read enough data in: %lu / %lu\n", IoStatusBlock.Information, HEADER_SIZE);
                    348:                        ntStatus = STATUS_UNSUCCESSFUL;
1.1       root      349:                }
                    350: 
1.1.1.6   root      351:                if (!NT_SUCCESS (ntStatus))
                    352:                {
                    353:                        goto error;
                    354:                }
1.1       root      355: 
1.1.1.6   root      356:                /* Attempt to recognize the volume (decrypt the header) */
1.1       root      357: 
1.1.1.6   root      358:                if (volumeType == VOLUME_TYPE_HIDDEN && mount->bProtectHiddenVolume)
                    359:                {
                    360:                        mount->nReturnCode = VolumeReadHeaderCache (
1.1.1.13! root      361:                                mount->bPartitionInInactiveSysEncScope,
1.1.1.6   root      362:                                mount->bCache,
                    363:                                readBuffer,
                    364:                                &mount->ProtectedHidVolPassword,
                    365:                                &tmpCryptoInfo);
                    366:                }
                    367:                else
                    368:                {
                    369:                        mount->nReturnCode = VolumeReadHeaderCache (
1.1.1.13! root      370:                                mount->bPartitionInInactiveSysEncScope,
1.1.1.6   root      371:                                mount->bCache,
                    372:                                readBuffer,
                    373:                                &mount->VolumePassword,
                    374:                                &Extension->cryptoInfo);
                    375:                }
1.1.1.4   root      376: 
1.1.1.6   root      377:                if (mount->nReturnCode == 0 || mount->nReturnCode == ERR_CIPHER_INIT_WEAK_KEY)
                    378:                {
                    379:                        /* Volume header successfully decrypted */
1.1       root      380: 
1.1.1.6   root      381:                        Extension->cryptoInfo->bProtectHiddenVolume = FALSE;
                    382:                        Extension->cryptoInfo->bHiddenVolProtectionAction = FALSE;
1.1       root      383: 
1.1.1.13! root      384:                        Extension->cryptoInfo->bPartitionInInactiveSysEncScope = mount->bPartitionInInactiveSysEncScope;
        !           385: 
        !           386:                        if (mount->bPartitionInInactiveSysEncScope)
        !           387:                        {
        !           388:                                if (Extension->cryptoInfo->EncryptedAreaStart.Value > (unsigned __int64) partitionStartingOffset
        !           389:                                        || Extension->cryptoInfo->EncryptedAreaStart.Value + Extension->cryptoInfo->VolumeSize.Value <= (unsigned __int64) partitionStartingOffset)
        !           390:                                {
        !           391:                                        // The partition is not within the key scope of system encryption
        !           392:                                        mount->nReturnCode = ERR_PASSWORD_WRONG;
        !           393:                                        ntStatus = STATUS_SUCCESS;
        !           394:                                        goto error;
        !           395:                                }
        !           396: 
        !           397:                                if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value)
        !           398:                                {
        !           399:                                        // Partial encryption is not supported for volumes mounted as regular
        !           400:                                        mount->nReturnCode = ERR_ENCRYPTION_NOT_COMPLETED;
        !           401:                                        ntStatus = STATUS_SUCCESS;
        !           402:                                        goto error;
        !           403:                                }
        !           404:                        }
        !           405: 
1.1.1.6   root      406:                        switch (volumeType)
                    407:                        {
                    408:                        case VOLUME_TYPE_NORMAL:
1.1       root      409: 
1.1.1.13! root      410:                                if (!mount->bPartitionInInactiveSysEncScope)
        !           411:                                {
        !           412:                                        // Correct the volume size for this volume type. Later on, this must be undone
        !           413:                                        // if Extension->DiskLength is used in deriving hidden volume offset
        !           414:                                        Extension->DiskLength -= HEADER_SIZE;   
        !           415:                                }
        !           416: 
1.1.1.6   root      417:                                Extension->cryptoInfo->hiddenVolume = FALSE;
1.1.1.13! root      418:                                Extension->cryptoInfo->volDataAreaOffset = mount->bPartitionInInactiveSysEncScope ? 0 : HEADER_SIZE;
        !           419: 
        !           420:                                Extension->cryptoInfo->FirstDataUnitNo.Value = mount->bPartitionInInactiveSysEncScope ? 
        !           421:                                        partitionStartingOffset / ENCRYPTION_DATA_UNIT_SIZE : 0;
1.1.1.6   root      422: 
                    423:                                break;
                    424: 
                    425:                        case VOLUME_TYPE_HIDDEN:
                    426: 
                    427:                                cryptoInfoPtr = mount->bProtectHiddenVolume ? tmpCryptoInfo : Extension->cryptoInfo;
                    428: 
                    429:                                // Validate the size of the hidden volume specified in the header
                    430:                                if (Extension->DiskLength < (__int64) cryptoInfoPtr->hiddenVolumeSize + HIDDEN_VOL_HEADER_OFFSET + HEADER_SIZE
                    431:                                        || cryptoInfoPtr->hiddenVolumeSize <= 0)
                    432:                                {
                    433:                                        mount->nReturnCode = ERR_VOL_SIZE_WRONG;
                    434:                                        ntStatus = STATUS_SUCCESS;
                    435:                                        goto error;
                    436:                                }
                    437: 
                    438:                                // Determine the offset of the hidden volume
                    439:                                Extension->cryptoInfo->hiddenVolumeOffset = Extension->DiskLength - cryptoInfoPtr->hiddenVolumeSize - HIDDEN_VOL_HEADER_OFFSET;
                    440: 
                    441:                                Dump("Hidden volume size = %I64d", cryptoInfoPtr->hiddenVolumeSize);
                    442:                                Dump("Hidden volume offset = %I64d", Extension->cryptoInfo->hiddenVolumeOffset);
                    443: 
                    444:                                // Validate the offset
1.1.1.12  root      445:                                if (Extension->cryptoInfo->hiddenVolumeOffset % ENCRYPTION_DATA_UNIT_SIZE != 0)
1.1.1.6   root      446:                                {
                    447:                                        mount->nReturnCode = ERR_VOL_SIZE_WRONG;
                    448:                                        ntStatus = STATUS_SUCCESS;
                    449:                                        goto error;
                    450:                                }
                    451: 
                    452:                                // If we are supposed to actually mount the hidden volume (not just to protect it)
                    453:                                if (!mount->bProtectHiddenVolume)       
                    454:                                {
                    455:                                        Extension->DiskLength = cryptoInfoPtr->hiddenVolumeSize;
                    456:                                        Extension->cryptoInfo->hiddenVolume = TRUE;
1.1.1.13! root      457:                                        Extension->cryptoInfo->volDataAreaOffset = Extension->cryptoInfo->hiddenVolumeOffset;
        !           458: 
        !           459:                                        Extension->cryptoInfo->FirstDataUnitNo.Value = mount->bPartitionInInactiveSysEncScope ? 
        !           460:                                                (partitionStartingOffset + Extension->cryptoInfo->hiddenVolumeOffset) / ENCRYPTION_DATA_UNIT_SIZE 
        !           461:                                                : 0;
        !           462: 
1.1.1.6   root      463:                                }
                    464:                                else
                    465:                                {
                    466:                                        // Hidden volume protection
                    467:                                        Extension->cryptoInfo->hiddenVolume = FALSE;
                    468:                                        Extension->cryptoInfo->bProtectHiddenVolume = TRUE;
1.1.1.13! root      469: 
        !           470:                                        if (!mount->bPartitionInInactiveSysEncScope)
        !           471:                                                Extension->cryptoInfo->hiddenVolumeOffset += HEADER_SIZE;       // Offset was incorrect due to loop processing
        !           472: 
1.1.1.6   root      473:                                        Dump("Hidden volume protection active (offset = %I64d)", Extension->cryptoInfo->hiddenVolumeOffset);
                    474:                                }
1.1.1.4   root      475: 
1.1.1.6   root      476:                                break;
                    477:                        }
1.1.1.4   root      478: 
1.1.1.6   root      479:                        // If this is a hidden volume, make sure we are supposed to actually
                    480:                        // mount it (i.e. not just to protect it)
                    481:                        if (!(volumeType == VOLUME_TYPE_HIDDEN && mount->bProtectHiddenVolume)) 
1.1.1.4   root      482:                        {
1.1.1.6   root      483:                                // Calculate virtual volume geometry
                    484:                                Extension->TracksPerCylinder = 1;
                    485:                                Extension->SectorsPerTrack = 1;
1.1.1.10  root      486:                                Extension->BytesPerSector = SECTOR_SIZE;
                    487:                                Extension->NumberOfCylinders = Extension->DiskLength / SECTOR_SIZE;
1.1.1.6   root      488:                                Extension->PartitionType = 0;
                    489: 
                    490:                                Extension->bRawDevice = bRawDevice;
1.1.1.7   root      491:                                
1.1.1.8   root      492:                                memset (Extension->wszVolume, 0, sizeof (Extension->wszVolume));
1.1.1.7   root      493:                                if (wcsstr (pwszMountVolume, WIDE ("\\??\\UNC\\")) == pwszMountVolume)
                    494:                                {
                    495:                                        /* UNC path */
                    496:                                        _snwprintf (Extension->wszVolume,
                    497:                                                sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1,
                    498:                                                WIDE ("\\??\\\\%s"),
                    499:                                                pwszMountVolume + 7);
                    500:                                }
1.1.1.6   root      501:                                else
                    502:                                {
1.1.1.7   root      503:                                        wcsncpy (Extension->wszVolume, pwszMountVolume, sizeof (Extension->wszVolume) / sizeof (WCHAR) - 1);
1.1.1.6   root      504:                                }
1.1.1.4   root      505:                        }
                    506: 
1.1.1.6   root      507:                        // If we are to protect a hidden volume we cannot exit yet, for we must also
                    508:                        // decrypt the hidden volume header.
                    509:                        if (!(volumeType == VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume))
1.1.1.4   root      510:                        {
1.1.1.6   root      511:                                TCfree (readBuffer);
1.1.1.4   root      512: 
1.1.1.6   root      513:                                if (tmpCryptoInfo != NULL)
                    514:                                        crypto_close (tmpCryptoInfo);
                    515:                                
                    516:                                return STATUS_SUCCESS;
                    517:                        }
1.1.1.4   root      518:                }
1.1.1.6   root      519:                else if (mount->bProtectHiddenVolume
                    520:                          || mount->nReturnCode != ERR_PASSWORD_WRONG)
1.1.1.4   root      521:                {
1.1.1.6   root      522:                         /* If we are not supposed to protect a hidden volume, the only error that is
                    523:                                tolerated is ERR_PASSWORD_WRONG (to allow mounting a possible hidden volume). 
1.1.1.4   root      524: 
1.1.1.6   root      525:                                If we _are_ supposed to protect a hidden volume, we do not tolerate any error
                    526:                                (both volume headers must be successfully decrypted). */
1.1       root      527: 
1.1.1.6   root      528:                        break;
1.1       root      529:                }
                    530:        }
                    531: 
                    532:        /* Failed due to some non-OS reason so we drop through and return NT
                    533:           SUCCESS then nReturnCode is checked later in user-mode */
                    534: 
                    535:        if (mount->nReturnCode == ERR_OUTOFMEMORY)
                    536:                ntStatus = STATUS_INSUFFICIENT_RESOURCES;
                    537:        else
                    538:                ntStatus = STATUS_SUCCESS;
                    539: 
1.1.1.4   root      540: error:
1.1.1.6   root      541:        if (Extension->bTimeStampValid)
1.1.1.4   root      542:        {
                    543:                /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
                    544:                RestoreTimeStamp (Extension);
                    545:        }
1.1       root      546: 
                    547:        /* Close the hDeviceFile */
                    548:        if (Extension->hDeviceFile != NULL)
                    549:                ZwClose (Extension->hDeviceFile);
                    550: 
                    551:        /* The cryptoInfo pointer is deallocated if the readheader routines
                    552:           fail so there is no need to deallocate here  */
                    553: 
                    554:        /* Dereference the user-mode file object */
                    555:        if (Extension->pfoDeviceFile != NULL)
                    556:                ObDereferenceObject (Extension->pfoDeviceFile);
                    557: 
1.1.1.4   root      558:        /* Free the tmp IO buffers */
1.1       root      559:        if (readBuffer != NULL)
                    560:                TCfree (readBuffer);
                    561: 
                    562:        return ntStatus;
                    563: }
                    564: 
                    565: void
                    566: TCCloseVolume (PDEVICE_OBJECT DeviceObject, PEXTENSION Extension)
                    567: {
                    568:        if (DeviceObject);      /* Remove compiler warning */
                    569: 
                    570:        if (Extension->hDeviceFile != NULL)
1.1.1.4   root      571:        {
1.1.1.6   root      572:                if (Extension->bRawDevice == FALSE
                    573:                        && Extension->bTimeStampValid)
1.1.1.4   root      574:                {
                    575:                        /* Restore the container timestamp to preserve plausible deniability of possible hidden volume. */
                    576:                        RestoreTimeStamp (Extension);
                    577:                }
1.1.1.6   root      578:                ZwClose (Extension->hDeviceFile);
1.1.1.4   root      579:        }
1.1       root      580:        ObDereferenceObject (Extension->pfoDeviceFile);
                    581:        crypto_close (Extension->cryptoInfo);
                    582: }
                    583: 
                    584: 
                    585: NTSTATUS
1.1.1.12  root      586: TCSendHostDeviceIoControlRequest (PDEVICE_OBJECT DeviceObject,
1.1       root      587:                               PEXTENSION Extension,
                    588:                               ULONG IoControlCode,
                    589:                               char *OutputBuffer,
                    590:                               int OutputBufferSize)
                    591: {
                    592:        IO_STATUS_BLOCK IoStatusBlock;
                    593:        NTSTATUS ntStatus;
                    594:        PIRP Irp;
                    595: 
                    596:        if (DeviceObject);      /* Remove compiler warning */
                    597: 
                    598:        KeClearEvent (&Extension->keVolumeEvent);
                    599: 
                    600:        Irp = IoBuildDeviceIoControlRequest (IoControlCode,
                    601:                                             Extension->pFsdDevice,
                    602:                                             NULL, 0,
                    603:                                             OutputBuffer, OutputBufferSize,
                    604:                                             FALSE,
                    605:                                             &Extension->keVolumeEvent,
                    606:                                             &IoStatusBlock);
                    607: 
                    608:        if (Irp == NULL)
                    609:        {
                    610:                Dump ("IRP allocation failed\n");
                    611:                return STATUS_INSUFFICIENT_RESOURCES;
                    612:        }
                    613: 
1.1.1.5   root      614:        // Disk device may be used by filesystem driver which needs file object
                    615:        IoGetNextIrpStackLocation (Irp) -> FileObject = Extension->pfoDeviceFile;
                    616: 
1.1       root      617:        ntStatus = IoCallDriver (Extension->pFsdDevice, Irp);
                    618:        if (ntStatus == STATUS_PENDING)
                    619:        {
1.1.1.12  root      620:                KeWaitForSingleObject (&Extension->keVolumeEvent, Executive, KernelMode, FALSE, NULL);
1.1       root      621:                ntStatus = IoStatusBlock.Status;
                    622:        }
                    623: 
                    624:        return ntStatus;
                    625: }
                    626: 
                    627: NTSTATUS
                    628: COMPLETE_IRP (PDEVICE_OBJECT DeviceObject,
                    629:              PIRP Irp,
                    630:              NTSTATUS IrpStatus,
1.1.1.4   root      631:              ULONG_PTR IrpInformation)
1.1       root      632: {
                    633:        Irp->IoStatus.Status = IrpStatus;
                    634:        Irp->IoStatus.Information = IrpInformation;
                    635: 
                    636:        if (DeviceObject);      /* Remove compiler warning */
                    637: 
1.1.1.10  root      638: #if EXTRA_INFO
                    639:        if (!NT_SUCCESS (IrpStatus))
                    640:        {
                    641:                PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
                    642:                Dump ("COMPLETE_IRP FAILING IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
                    643:                      (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
                    644:        }
                    645:        else
                    646:        {
                    647:                PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation (Irp);
                    648:                Dump ("COMPLETE_IRP SUCCESS IRP %ls Flags 0x%08x vpb 0x%08x NTSTATUS 0x%08x\n", TCTranslateCode (irpSp->MajorFunction),
                    649:                      (ULONG) DeviceObject->Flags, (ULONG) DeviceObject->Vpb->Flags, IrpStatus);
                    650:        }
1.1       root      651: #endif
                    652:        IoCompleteRequest (Irp, IO_NO_INCREMENT);
                    653:        return IrpStatus;
                    654: }
1.1.1.4   root      655: 
                    656: // Restores the container timestamp to preserve plausible deniability of possible hidden volume.
                    657: static void RestoreTimeStamp (PEXTENSION Extension)
                    658: {
                    659:        NTSTATUS ntStatus;
                    660:        FILE_BASIC_INFORMATION FileBasicInfo;
                    661:        IO_STATUS_BLOCK IoStatusBlock;
                    662: 
1.1.1.6   root      663:        if (Extension->hDeviceFile != NULL 
                    664:                && Extension->bRawDevice == FALSE 
                    665:                && Extension->bReadOnly == FALSE
                    666:                && Extension->bTimeStampValid)
1.1.1.4   root      667:        {
                    668:                ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
                    669:                        &IoStatusBlock,
                    670:                        &FileBasicInfo,
                    671:                        sizeof (FileBasicInfo),
                    672:                        FileBasicInformation); 
                    673: 
                    674:                if (!NT_SUCCESS (ntStatus))
                    675:                {
                    676:                        Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",
                    677:                                ntStatus);
                    678:                }
                    679:                else
                    680:                {
                    681:                        FileBasicInfo.CreationTime = Extension->fileCreationTime;
                    682:                        FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime;
                    683:                        FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime;
                    684:                        FileBasicInfo.ChangeTime = Extension->fileLastChangeTime;
                    685: 
                    686:                        ntStatus = ZwSetInformationFile(
                    687:                                Extension->hDeviceFile,
                    688:                                &IoStatusBlock,
                    689:                                &FileBasicInfo,
                    690:                                sizeof (FileBasicInfo),
                    691:                                FileBasicInformation); 
                    692: 
                    693:                        if (!NT_SUCCESS (ntStatus))
                    694:                                Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus);
                    695:                }
                    696:        }
                    697: }

unix.superglobalmegacorp.com

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