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

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

unix.superglobalmegacorp.com

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