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

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

unix.superglobalmegacorp.com

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