diff options
Diffstat (limited to 'src/Driver/Ntvol.c')
-rw-r--r-- | src/Driver/Ntvol.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/src/Driver/Ntvol.c b/src/Driver/Ntvol.c index 177c0bf3..68f63f16 100644 --- a/src/Driver/Ntvol.c +++ b/src/Driver/Ntvol.c @@ -61,70 +61,72 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, /* when mounting with hidden volume protection, we cache the passwords after both outer and hidden volumes are mounted successfully*/ BOOL bAutoCachePassword = mount->bProtectHiddenVolume? FALSE : mount->bCache; Extension->pfoDeviceFile = NULL; Extension->hDeviceFile = NULL; Extension->bTimeStampValid = FALSE; /* default value for storage alignment */ Extension->HostMaximumTransferLength = 65536; Extension->HostMaximumPhysicalPages = 17; Extension->HostAlignmentMask = 0; /* default values for non-SSD drives */ Extension->IncursSeekPenalty = TRUE; Extension->TrimEnabled = FALSE; Extension->DeviceNumber = (ULONG) -1; RtlInitUnicodeString (&FullFileName, pwszMountVolume); InitializeObjectAttributes (&oaFileAttributes, &FullFileName, OBJ_CASE_INSENSITIVE | (forceAccessCheck ? OBJ_FORCE_ACCESS_CHECK : 0) | OBJ_KERNEL_HANDLE, NULL, NULL); KeInitializeEvent (&Extension->keVolumeEvent, NotificationEvent, FALSE); if (Extension->SecurityClientContextValid) { ntStatus = SeImpersonateClientEx (&Extension->SecurityClientContext, NULL); if (!NT_SUCCESS (ntStatus)) goto error; } mount->VolumeMountedReadOnlyAfterDeviceWriteProtected = FALSE; + mount->VolumeMountedReadOnlyAfterPartialSysEnc = FALSE; + mount->VolumeMasterKeyVulnerable = FALSE; // If we are opening a device, query its size first if (bRawDevice) { PARTITION_INFORMATION pi; PARTITION_INFORMATION_EX pix; LARGE_INTEGER diskLengthInfo; DISK_GEOMETRY_EX dg; STORAGE_PROPERTY_QUERY storagePropertyQuery = {0}; - byte* dgBuffer; + uint8* dgBuffer; STORAGE_DEVICE_NUMBER storageDeviceNumber; ntStatus = IoGetDeviceObjectPointer (&FullFileName, FILE_READ_DATA | FILE_READ_ATTRIBUTES, &Extension->pfoDeviceFile, &Extension->pFsdDevice); if (!NT_SUCCESS (ntStatus)) goto error; dgBuffer = TCalloc (256); if (!dgBuffer) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto error; } ntStatus = TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, (char *) dgBuffer, 256); if (!NT_SUCCESS (ntStatus)) { DISK_GEOMETRY geo; ntStatus = TCSendHostDeviceIoControlRequest (DeviceObject, Extension, IOCTL_DISK_GET_DRIVE_GEOMETRY, (char *) &geo, sizeof (geo)); if (!NT_SUCCESS (ntStatus)) { TCfree (dgBuffer); goto error; } memset (&dg, 0, sizeof (dg)); memcpy (&dg.Geometry, &geo, sizeof (geo)); dg.DiskSize.QuadPart = geo.Cylinders.QuadPart * geo.SectorsPerTrack * geo.TracksPerCylinder * geo.BytesPerSector; @@ -620,94 +622,96 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, mount->bCachePim, readBuffer, &mount->VolumePassword, mount->pkcs5_prf, mount->VolumePim, &Extension->cryptoInfo); } ReadVolumeHeaderRecoveryMode = FALSE; if (mount->nReturnCode == 0 || mount->nReturnCode == ERR_CIPHER_INIT_WEAK_KEY) { /* Volume header successfully decrypted */ if (!Extension->cryptoInfo) { /* should never happen */ mount->nReturnCode = ERR_OUTOFMEMORY; ntStatus = STATUS_SUCCESS; goto error; } #ifdef _WIN64 if (IsRamEncryptionEnabled() && (volumeType == TC_VOLUME_TYPE_NORMAL || !mount->bProtectHiddenVolume)) VcProtectKeys (Extension->cryptoInfo, VcGetEncryptionID (Extension->cryptoInfo)); #endif Dump ("Volume header decrypted\n"); Dump ("Required program version = %x\n", (int) Extension->cryptoInfo->RequiredProgramVersion); Dump ("Legacy volume = %d\n", (int) Extension->cryptoInfo->LegacyVolume); + Dump ("Master key vulnerable = %d\n", (int) Extension->cryptoInfo->bVulnerableMasterKey); + + mount->VolumeMasterKeyVulnerable = Extension->cryptoInfo->bVulnerableMasterKey; if (IsHiddenSystemRunning() && !Extension->cryptoInfo->hiddenVolume) { Extension->bReadOnly = mount->bMountReadOnly = TRUE; HiddenSysLeakProtectionCount++; } Extension->cryptoInfo->bProtectHiddenVolume = FALSE; Extension->cryptoInfo->bHiddenVolProtectionAction = FALSE; Extension->cryptoInfo->bPartitionInInactiveSysEncScope = mount->bPartitionInInactiveSysEncScope; /* compute the ID of this volume: SHA-256 of the effective header */ sha256 (Extension->volumeID, readBuffer, TC_VOLUME_HEADER_EFFECTIVE_SIZE); if (volumeType == TC_VOLUME_TYPE_NORMAL) { if (mount->bPartitionInInactiveSysEncScope) { if (Extension->cryptoInfo->EncryptedAreaStart.Value > (unsigned __int64) partitionStartingOffset || Extension->cryptoInfo->EncryptedAreaStart.Value + Extension->cryptoInfo->VolumeSize.Value <= (unsigned __int64) partitionStartingOffset) { // The partition is not within the key scope of system encryption mount->nReturnCode = ERR_PASSWORD_WRONG; ntStatus = STATUS_SUCCESS; goto error; } if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value) { - // Partial encryption is not supported for volumes mounted as regular - mount->nReturnCode = ERR_ENCRYPTION_NOT_COMPLETED; - ntStatus = STATUS_SUCCESS; - goto error; + // mount as readonly in case of partial system encryption + Extension->bReadOnly = mount->bMountReadOnly = TRUE; + mount->VolumeMountedReadOnlyAfterPartialSysEnc = TRUE; } } else if (Extension->cryptoInfo->HeaderFlags & TC_HEADER_FLAG_NONSYS_INPLACE_ENC) { if (Extension->cryptoInfo->EncryptedAreaLength.Value != Extension->cryptoInfo->VolumeSize.Value) { // Non-system in-place encryption process has not been completed on this volume mount->nReturnCode = ERR_NONSYS_INPLACE_ENC_INCOMPLETE; ntStatus = STATUS_SUCCESS; goto error; } } } Extension->cryptoInfo->FirstDataUnitNo.Value = 0; if (Extension->cryptoInfo->hiddenVolume && IsHiddenSystemRunning()) { // Prevent mount of a hidden system partition if the system hosted on it is currently running if (memcmp (Extension->cryptoInfo->master_keydata_hash, GetSystemDriveCryptoInfo()->master_keydata_hash, sizeof(Extension->cryptoInfo->master_keydata_hash)) == 0) { mount->nReturnCode = ERR_VOL_ALREADY_MOUNTED; ntStatus = STATUS_SUCCESS; goto error; } } switch (volumeType) { case TC_VOLUME_TYPE_NORMAL: @@ -771,62 +775,61 @@ NTSTATUS TCOpenVolume (PDEVICE_OBJECT DeviceObject, break; } Dump ("Volume data offset = %I64d\n", Extension->cryptoInfo->volDataAreaOffset); Dump ("Volume data size = %I64d\n", Extension->DiskLength); Dump ("Volume data end = %I64d\n", Extension->cryptoInfo->volDataAreaOffset + Extension->DiskLength - 1); if (Extension->DiskLength == 0) { Dump ("Incorrect volume size\n"); continue; } // If this is a hidden volume, make sure we are supposed to actually // mount it (i.e. not just to protect it) if (volumeType == TC_VOLUME_TYPE_NORMAL || !mount->bProtectHiddenVolume) { // Validate sector size if (bRawDevice && Extension->cryptoInfo->SectorSize != Extension->HostBytesPerSector) { mount->nReturnCode = ERR_PARAMETER_INCORRECT; ntStatus = STATUS_SUCCESS; goto error; } // Calculate virtual volume geometry Extension->TracksPerCylinder = 1; Extension->SectorsPerTrack = 1; Extension->BytesPerSector = Extension->cryptoInfo->SectorSize; - // Add extra sector since our virtual partition starts at Extension->BytesPerSector and not 0 - Extension->NumberOfCylinders = (Extension->DiskLength / Extension->BytesPerSector) + 1; + Extension->NumberOfCylinders = Extension->DiskLength / Extension->BytesPerSector; Extension->PartitionType = 0; Extension->bRawDevice = bRawDevice; memset (Extension->wszVolume, 0, sizeof (Extension->wszVolume)); if ((wcslen (pwszMountVolume) > 8) && (0 == memcmp (pwszMountVolume, WIDE ("\\??\\UNC\\"), 8 * sizeof (WCHAR)))) { /* UNC path */ RtlStringCbPrintfW (Extension->wszVolume, sizeof (Extension->wszVolume), WIDE ("\\??\\\\%s"), pwszMountVolume + 7); } else { RtlStringCbCopyW (Extension->wszVolume, sizeof(Extension->wszVolume),pwszMountVolume); } memset (Extension->wszLabel, 0, sizeof (Extension->wszLabel)); RtlStringCbCopyW (Extension->wszLabel, sizeof(Extension->wszLabel), mount->wszLabel); } // If we are to protect a hidden volume we cannot exit yet, for we must also // decrypt the hidden volume header. if (!(volumeType == TC_VOLUME_TYPE_NORMAL && mount->bProtectHiddenVolume)) { /* in case of mounting with hidden volume protection, we cache both passwords manually after bother outer and hidden volumes are mounted*/ if (mount->bProtectHiddenVolume && mount->bCache) { AddPasswordToCache(&mount->VolumePassword, mount->VolumePim, mount->bCachePim); |