|
Server : Apache/2.4.58 (Win64) OpenSSL/3.1.3 PHP/8.2.12 System : Windows NT SERVER-PC 10.0 build 26200 (Windows 11) AMD64 User : ServerPC ( 0) PHP Version : 8.2.12 Disable Function : NONE Directory : C:/Windows/SysWOW64/WindowsPowerShell/v1.0/Modules/BitLocker/ |
Upload File : |
Import-LocalizedData -BindingVariable stringTable
#########################################################################################
# Copyright (c) Microsoft Corporation
#
# BitLocker PowerShell Module
#
#
#########################################################################################
$E_NOTFOUND = 2147943568
$E_KEYREQUIRED = 2150694941
$E_AUTOUNLOCK_ENABLED = 2150694953
$E_VOLUMEBOUND = 2150694943
$E_FAIL = 2147500037
$TPM_E_DEACTIVATED = 2150105094
$FVE_E_NOT_DECRYPTED = 2150694969
$S_FALSE = 1
$FVE_HARDWARE_TEST_NOT_FAILED_OR_PENDING = 0
$FVE_HARDWARE_TEST_FAILED = 1
$FVE_HARDWARE_TEST_PENDING = 2
$DEFAULT_DISCOVERY_VOLUME_TYPE = "<default>"
$MINIMUM_REQUIRED_RECOVERY_PROTECTORS_WITH_TPM = 2
$MINIMUM_REQUIRED_RECOVERY_PROTECTORS_WITHOUT_TPM = 3
$FVE_CONV_FLAG_DATAONLY = 1
$FVE_FORCE_ENCRYPTION_TYPE_UNSPECIFIED = 0
$FVE_FORCE_ENCRYPTION_TYPE_SOFTWARE = 1
$FVE_FORCE_ENCRYPTION_TYPE_HARDWARE = 2
$FVE_PROVISIONING_MODIFIER_USED_SPACE = 256
#########################################################################################
# Internal Function: Get-ExceptionForHrInternal
#
# Returns the COMException for a given HRESULT
#
# Ex: Get-ExceptionForHrInternal 2147942402
#
# Input: Unsigned integer - Must be a valid HRESULT
#
# Return: COMException class corresponding to the HRESULT.
#########################################################################################
function Get-ExceptionForHrInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[System.UInt32]
$HrUInt32)
process
{
$HrHexString = [string]::Format("0x{0:X}", $HrUInt32)
$ExceptionForHr = [System.Runtime.InteropServices.Marshal]::GetExceptionForHR($HrHexString)
$ExceptionForHr
}
}
#########################################################################################
# Internal Function: IsNanoPowerShell
#
# Determines if this module is running on Nano PowerShell instead of full PowerShell.
#
# Return: Boolean describing the PowerShell environment.
#
#########################################################################################
function IsNanoPowerShell
{
if ($PSEdition -eq "Core")
{
return $true
}
else
{
return $false
}
}
#########################################################################################
# Internal Function: Decrypt-SecureStringInternal
#
# Returns a clear text string that had been protected by a SecureString.
#
# Input: SecureString - a password
#
# Return: String contained within the SecureString
#########################################################################################
function Decrypt-SecureStringInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[System.Security.SecureString]
$SecurePassword
)
process
{
if (IsNanoPowerShell)
{
$intPtr = [System.Security.SecureStringMarshal]::SecureStringToCoTaskMemUnicode($SecurePassword)
$ClearTextPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($intPtr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeCoTaskMemUnicode($intPtr)
}
else
{
$bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecurePassword)
$ClearTextPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($bstr)
[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($bstr)
}
return $ClearTextPassword
}
}
#########################################################################################
# Internal Function: Get-Win32EncryptableVolumeInternal
#
# Returns Win32_EncryptableVolume WMI objects that describes volume [or volumes]
#
# Ex: Get-Win32EncryptableVolumeInternal c: - returns volume information for drive c:
# Get-Win32EncryptableVolumeInternal - returns all volumes with volume information. Only for encryptable volumes
#
# Input: String - volume name. Could be: drive letter or volume id or a directory that corresponds to a mounted volume.
# This is an optional parameter.
#
# Return: WMI object [Microsoft.Management.Infrastructure.CimInstance] that is a Win32_EncryptableVolume
#########################################################################################
function Get-Win32EncryptableVolumeInternal
{
Param(
[Parameter(Position = 0, Mandatory = $false)]
[string]
$MountPoint)
process
{
Write-Debug "Begin Get-Win32EncryptableVolumeInternal($MountPoint)"
$Win32EncryptableVolumes = `
Get-CimInstance `
-Namespace "root\cimv2\Security\MicrosoftVolumeEncryption" `
-ClassName Win32_EncryptableVolume
if (!$Win32EncryptableVolumes)
{
Write-Debug "No Win32_EncryptableVolume objects have been returned by Get-CimInstance"
}
if (!$MountPoint)
{
#
# MountPoint is not set so all Win32_EncryptableVolumes are returned
#
$Win32EncryptableVolume = $null
Write-Debug "No Filtering of Win32_EncryptableVolumes"
}
elseif ($MountPoint -match "^[a-zA-Z]$" -or $MountPoint -match "^[a-zA-Z]:$" -or $MountPoint -match "^[a-zA-Z]:\$")
{
#
# MountPoint is a drive letter followed by an optional colon with an optional slash. ex: "c" or "c:" or "c:\"
#
$DriveLetter = $MountPoint.TrimEnd("\")
if (!$DriveLetter.EndsWith(":"))
{
$DriveLetter = $DriveLetter + ":" # WMI needs to have the colon at the end
}
Write-Debug "Filtering Win32_EncryptableVolumes by $DriveLetter"
$Win32EncryptableVolume = $Win32EncryptableVolumes | where {$_.DriveLetter -eq $DriveLetter}
#If there is no encryptable volume then fall through and report the error
}
elseif ($MountPoint -match "^\\\\\?\\Volume\{[A-Fa-f0-9]{8}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{4}-[A-Fa-f0-9]{12}\}\\$")
{
#
# MountPoint is a device id. An example of a valid device id is: \\?\Volume{cb96dd9a-4f54-11e0-8d6c-806e6f6e6963}\
#
$DeviceId = $MountPoint
Write-Debug "Filtering Win32_EncryptableVolumes by $DeviceId"
$Win32EncryptableVolume = $Win32EncryptableVolumes | where {$_.DeviceId -eq $DeviceId}
#If there is no encryptable volume then fall through and report the error
}
else
{
#
# MountPoint is a directory that is mounted to a volume. Get the volume that it belongs to.
#
$MsftVolume = Get-Volume -FilePath $MountPoint
if (!$MsftVolume)
{
Write-Debug "No volume can be found mounted at $MountPoint"
# Fall through and report error
}
else
{
$DeviceId = $MsftVolume.UniqueId
Write-Debug "Volume at $MountPoint has Device Id $DeviceId. Filtering Win32_EncryptableVolumes by this Device Id."
$Win32EncryptableVolume = $Win32EncryptableVolumes | where {$_.DeviceID -eq $DeviceId}
}
}
if ($Win32EncryptableVolume)
{
$Win32EncryptableVolume
Write-Debug "End Get-Win32EncryptableVolumeInternal. Return $Win32EncryptableVolume"
}
elseif (!$MountPoint -and $Win32EncryptableVolumes)
{
# $null for $MountPoint means return all encryptable volumes
$Win32EncryptableVolumes
Write-Debug "End Get-Win32EncryptableVolumeInternal. Return $Win32EncryptableVolumes"
}
else
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $E_NOTFOUND
$ErrorMessage = [string]::Format($stringTable.ErrorMountPointNotFound, $MountPoint)
Write-Error -Exception $ExceptionForHr -Message $ErrorMessage
}
}
}
#########################################################################################
# Internal Function: Read-UserSecretInternal
#
# Returns a single SecureString that is a secret [password or pin] entered
# by the user. This secret is confirmed by requiring the user to enter it
# twice and verifying that they are the same.
#
# If the two secrets are not the same then we re-prompt the user for both secrets.
#
# Ex: Read-UserSecretInternal -Message "Enter Password:" -ConfirmMessage "Confirm Password:" -NotMatchMessage "Passwords do not match. Re-enter"
#
# Input: Message String - Output to user to enter the secret
# Confirm Message String - Output to user to confirm secret
# NotMessage Message String - Output to the user if the two secrets
# do not match
#
# Return: One of the SecureStrings that the user entered.
#########################################################################################
function Read-UserSecretInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$Message,
[Parameter(Position = 1, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$ConfirmMessage,
[Parameter(Position = 2, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$NotMatchMessage)
process
{
#
# Break out of this loop when the two secrets entered by the user
# match
#
while ($true)
{
Write-Host $Message -NoNewLine
$Secret1 = Read-Host -AsSecureString
Write-Host $ConfirmMessage -NoNewLine
$Secret2 = Read-Host -AsSecureString
$ClearTextPassword1 = Decrypt-SecureStringInternal $Secret1
$ClearTextPassword2 = Decrypt-SecureStringInternal $Secret2
if ($ClearTextPassword1 -eq $ClearTextPassword2)
{
break
}
#
# The two secrets don't match so tell the user and ask user again
#
Write-Host $NotMatchMessage
}
# Clear the clear text password strings.
$ClearTextPassword1 = ""
$ClearTextPassword1 = ""
return $Secret1
}
}
#########################################################################################
# Internal Function: Get-BitLockerVolumeInternal
#
# Returns a single BitLockerVolume structure that describes a volume
#
# Ex: Get-BitLockerVolumeInternal c: - returns volume information for drive c:
#
# Input: String - volume name. Could be: drive letter or volume id
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume
#########################################################################################
function Get-BitLockerVolumeInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint)
process
{
Write-Debug "Begin Get-BitLockerVolumeInternal($MountPoint)"
$FREE_SPACE_WIPE_IN_PROGRESS = 2
$FREE_SPACE_WIPE_SUSPENDED = 3
$BYTES_IN_GIGABYTE = 1024*1024*1024
#######
# Get Win32_EncryptableVolume
#######
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
if (!$Win32EncryptableVolume)
{
Write-Debug "The following operation failed: Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint"
return
}
#######
# Get MSFT_Volume associated with Win32_EncryptableVolume.
# Use Win32_EncryptableVolume.DeviceID
#######
$WmiVolumeFilter = "UniqueID = '$($Win32EncryptableVolume.DeviceID.Replace("\", "\\"))'"
$MsftVolume = Get-CimInstance MSFT_Volume -NameSpace 'Root\Microsoft\Windows\Storage' -Filter $WmiVolumeFilter
if (!$MsftVolume)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $E_NOTFOUND
$ErrorMessage = [string]::Format($stringTable.ErrorVolumeNotFound, $Win32EncryptableVolume.DeviceId)
Write-Error -Exception $ExceptionForHr -Message $ErrorMessage
Write-Debug "Filter: $WmiVolumeFilter"
return
}
#
# This matches WMI .Net's $Win32EncryptableVolume.__SERVER.
# MI .Net exposes $Win32EncryptableVolume.CimSystemProperties.ServerName as "localhost"
#
$ComputerName = $env:computername
#
# Overwrite the passed in $MountPoint parameter with the the info from Win32_EncryptableVolume
#
if ($Win32EncryptableVolume.DriveLetter)
{
$MountPoint = $Win32EncryptableVolume.DriveLetter
}
else
{
$MountPoint = $Win32EncryptableVolume.DeviceID
}
#######
# Get LockStatus. Win32_EncryptableVolume::GetLockStatus
#######
$LockStatusResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetLockStatus
if ($LockStatusResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $LockStatusResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$LockStatus = $LockStatusResult.LockStatus
Write-Debug "ComputerName: $ComputerName. MountPoint: $MountPoint. LockStatus: $LockStatus"
#######
# Get EncryptionMethod. Win32_EncryptableVolume::GetEncryptionMethod
#######
$EncryptionMethodResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetEncryptionMethod
if ($EncryptionMethodResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $EncryptionMethodResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$EncryptionMethod = $EncryptionMethodResult.EncryptionMethod
Write-Debug "EncryptionMethod: $EncryptionMethod"
#######
# Get EncryptionMethodFlags. Win32_EncryptableVolume::GetEncryptionMethodFlags
#######
$EncryptionMethodFlags = $EncryptionMethodResult.EncryptionMethodFlags
Write-Debug "EncryptionMethodFlags: $EncryptionMethodFlags"
#######
# AutoUnlock. Win32_EncryptableVolume::IsAutoUnlockEnabled
# This will determine if autounlock is enabled for the volume and what the
# protector id is. This is relevant only for data volumes.
# Failure is ok. It means the setting does not apply to this volume.
#######
$AutoUnlockEnabledResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName IsAutoUnlockEnabled
$AutoUnlockKeyProtectorId = $null
if ($AutoUnlockEnabledResult.ReturnValue -ne 0)
{
Write-Debug "Win32EncryptableVolume.IsAutoUnlockEnabled() returned error $AutoUnlockEnabledResult.ReturnValue"
$AutoUnlockEnabled = $null
}
else
{
$AutoUnlockEnabled = $AutoUnlockEnabledResult.IsAutoUnlockEnabled
if ($AutoUnlockEnabled -eq $true)
{
$AutoUnlockKeyProtectorId = $AutoUnlockEnabledResult.VolumeKeyProtectorID
}
}
Write-Debug "AutoUnlockEnabled: $AutoUnlockEnabled. AutoUnlockKeyProtectorId: $AutoUnlockKeyProtectorId"
#######
# AutoUnlockKeyStored. Win32_EncryptableVolume::IsAutoUnlockKeyStored
# This will determine if autounlock keys are stored in the volume.
# This is only applicable to OS volumes.
# Failure is ok. It means the setting does not apply to this volume.
#######
$AutoUnlockKeyStoredResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName IsAutoUnlockKeyStored
if ($AutoUnlockKeyStoredResult.ReturnValue -ne 0)
{
Write-Debug "Win32EncryptableVolume.IsAutoUnlockKeyStored() returned error $AutoUnlockKeyStoredResult.ReturnValue"
$AutoUnlockKeyStored = $null
}
else
{
$AutoUnlockKeyStored = $AutoUnlockKeyStoredResult.IsAutoUnlockKeyStored
}
Write-Debug "AutoUnlockKeyStored: $AutoUnlockKeyStored"
#######
# Get MetaDataVersion. Win32_EncryptableVolume::GetVersion()
#######
$MetaDataVersionResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetVersion
if ($MetaDataVersionResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $MetaDataVersionResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$MetaDataVersion = $MetaDataVersionResult.Version
Write-Debug "MetaDataVersion: $MetaDataVersion"
#######
# Get ConversionStatus, WipingStatus, EncryptionPercentage, WipePercentage.
# Win32_EncryptableVolume::GetConversionStatus()
# We make these calls only on unlocked volumes. Otherwise, the values are initialized to $null
#######
if ($LockStatus -eq [uint32][Microsoft.BitLocker.Structures.BitLockerVolumeLockStatus]::Unlocked)
{
$ConversionStatusResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetConversionStatus
if ($ConversionStatusResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $ConversionStatusResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$ConversionStatus = $ConversionStatusResult.ConversionStatus
$WipingStatus = $ConversionStatusResult.WipingStatus
$EncryptionPercentage = $ConversionStatusResult.EncryptionPercentage
$WipePercentage = $ConversionStatusResult.WipingPercentage
Write-Debug "ConversionStatus: $ConversionStatus. WipingStatus: $WipingStatus. EncryptionPercentage: $EncryptionPercentage. WipePercentage: $WipePercentage"
if ($ConversionStatus -eq [uint32][Microsoft.BitLocker.Structures.BitLockerVolumeStatus]::FullyEncrypted -and $WipingStatus -eq $FREE_SPACE_WIPE_IN_PROGRESS)
{
$VolumeStatus = [Microsoft.BitLocker.Structures.BitLockerVolumeStatus]::FullyEncryptedWipeInProgress
}
elseif ($ConversionStatus -eq [uint32][Microsoft.BitLocker.Structures.BitLockerVolumeStatus]::FullyEncryptedWipeInProgress -and $WipingStatus -eq $FREE_SPACE_WIPE_SUSPENDED)
{
$VolumeStatus = [Microsoft.BitLocker.Structures.BitLockerVolumeStatus]::FullyEncryptedWipeSuspended
}
else
{
$VolumeStatus = $ConversionStatus
}
}
else
{
$ConversionStatus = $null
$WipingStatus = $null
$VolumeStatus = $null
$WipePercentage = $null
$EncryptionPercentage = $null
}
#######
# Get ProtectionStatus
# Win32_EncryptableVolume::GetProtectionStatus()
#######
$ProtectionStatusResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetProtectionStatus
if ($ProtectionStatusResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $ProtectionStatusResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$ProtectionStatus = $ProtectionStatusResult.ProtectionStatus
Write-Debug "ProtectionStatus: $ProtectionStatus."
#######
# Get VolumeType [OS, Data] and capacity from MSFT_Volume
#######
if ($MsftVolume.DriveLetter -eq $env:SystemDrive[0])
{
$VolumeType = [Microsoft.BitLocker.Structures.BitLockerVolumeType]::OperatingSystem
}
else
{
$VolumeType = [Microsoft.BitLocker.Structures.BitLockerVolumeType]::Data
}
$CapacityGB = $MsftVolume.Size / $BYTES_IN_GIGABYTE
Write-Debug "VolumeType: $VolumeType. CapacityGB: $CapacityGB"
#######
# Get list of key protector ids Win32_EncryptableVolume::GetKeyProtectors
# For each key protector id we do:
# - Get key protector type Win32_EncryptableVolume::GetKeyProtectorType
# - For Unlocked volumes we also get extra data for external key, numerical password
# and public key, and tpm network key.
#######
$KeyProtectorIdsResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetKeyProtectors
if ($KeyProtectorIdsResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $KeyProtectorIdsResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$KeyProtectorIds = $KeyProtectorIdsResult.VolumeKeyProtectorID
Write-Debug "KeyProtectorIds: $KeyProtectorIds"
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtector[]]$KeyProtectors = $null
for ($i=0; $i -lt $KeyProtectorIds.Length; $i++)
{
$KeyProtectorId = $KeyProtectorIds[$i]
$KeyProtectorTypeResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetKeyProtectorType -Arguments @{VolumeKeyProtectorID = $KeyProtectorId}
if ($KeyProtectorTypeResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $KeyProtectorTypeResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$KeyProtectorType = $KeyProtectorTypeResult.KeyProtectorType
Write-Debug "KeyProtector[$i] = KeyProtectorId: $KeyProtectorId. KeyProtectorType: $KeyProtectorType"
$KeyProtectorFileName = $null
$KeyProtectorRecoveryPassword = $null
$KeyProtectorThumbprint = $null
$KeyProtectorCertificateType = $null
$AutoUnlockProtector = $null # true or false only for external key protector type
if ($LockStatus -eq [uint32][Microsoft.BitLocker.Structures.BitLockerVolumeLockStatus]::Unlocked)
{
if ($KeyProtectorType -eq [uint32][Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::ExternalKey)
{
$KeyProtectorFileNameResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetExternalKeyFileName -Arguments @{VolumeKeyProtectorID = $keyProtectorId}
if ($KeyProtectorFileNameResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $KeyProtectorFileNameResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$KeyProtectorFileName = $KeyProtectorFileNameResult.FileName
if ($AutoUnlockKeyProtectorId -ne $null)
{
if ($AutoUnlockKeyProtectorId -eq $KeyProtectorId)
{
$AutoUnlockProtector = $true
}
else
{
$AutoUnlockProtector = $false
}
}
Write-Debug "KeyProtectorFileName: $KeyProtectorFileName. AutoUnlockProtector: $AutoUnlockProtector"
}
elseif ($KeyProtectorType -eq [uint32][Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::RecoveryPassword)
{
$KeyProtectorRecoveryPasswordResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetKeyProtectorNumericalPassword -Arguments @{VolumeKeyProtectorID = $keyProtectorId}
if ($KeyProtectorRecoveryPasswordResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $KeyProtectorRecoveryPasswordResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$KeyProtectorRecoveryPassword = $KeyProtectorRecoveryPasswordResult.NumericalPassword
Write-Debug "KeyProtectorRecoveryPassword found"
}
elseif ($KeyProtectorType -eq [uint32][Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::PublicKey -or $KeyProtectorType -eq [uint32][Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::TpmNetworkKey)
{
$KeyProtectorCertificateResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetKeyProtectorCertificate -Arguments @{VolumeKeyProtectorID = $KeyProtectorId}
if ($KeyProtectorCertificateResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $KeyProtectorCertificateResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$KeyProtectorThumbprint = $KeyProtectorCertificateResult.CertThumbprint
$KeyProtectorCertificateType = $KeyProtectorCertificateResult.CertType
Write-Debug "KeyProtectorThumbprint: $KeyProtectorThumbprint. KeyProtectorCertificateType: $KeyProtectorCertificateType"
}
}
$KeyProtector = new-object Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtector -argumentlist $KeyProtectorId,$AutoUnlockProtector,$KeyProtectorType,$KeyProtectorFileName,$KeyProtectorRecoveryPassword,$KeyProtectorCertificateType,$KeyProtectorThumbprint
$KeyProtectors = $KeyProtectors + $KeyProtector
}
$BitLockerVolume = new-object Microsoft.BitLocker.Structures.BitLockerVolume -argumentlist $ComputerName, $MountPoint, $EncryptionMethod, $EncryptionMethodFlags, $AutoUnlockEnabled, $AutoUnlockKeyStored, $MetaDataVersion, $VolumeStatus, $ProtectionStatus, $LockStatus, $EncryptionPercentage, $WipePercentage, $VolumeType, $CapacityGB, $KeyProtectors
$BitLockerVolume
Write-Debug "End Get-BitLockerVolumeInternal. Return $BitLockerVolume"
}
}
#########################################################################################
# Get-BitLockerVolume
#
# Returns BitLockerVolume structures that describes a volume [or volumes]
#
# Ex: Get-BitLockerVolume c: - returns volume information for drive c:
# Get-BitLockerVolume - returns volume information for all volumes that are encryptable
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
# This is an optional input parameter.
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Get-BitLockerVolume
{
[CmdletBinding()]
Param(
[Parameter(Position = 0, Mandatory = $false, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[string[]]
$MountPoint)
process
{
Write-Debug "Begin Get-BitLockerVolume($MountPoint)"
if ($MountPoint)
{
$MountPoint | ForEach-Object -process {Get-BitLockerVolumeInternal -MountPoint $_}
}
else
{
$AllWin32EncryptableVolume = Get-Win32EncryptableVolumeInternal
$AllWin32EncryptableVolume | ForEach-Object -process { if ($_.DriveLetter) {Get-BitLockerVolumeInternal -MountPoint $_.DriveLetter} else {Get-BitLockerVolumeInternal -MountPoint $_.DeviceId} }
}
Write-Debug "End Get-BitLockerVolume"
}
}
#########################################################################################
# Suspend-BitLocker
#
# Returns BitLockerVolume structures that describes the volumes which have been suspended.
# Suspended means that the key protectors have been disabled. The drive contents are still
# encrypted and if encryption or decryption is in progress then this cmdlet will not change
# that. To stop the encryption or decryption process you need to call the WMI method
# PauseConversion.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
# RebootCount - Number of reboots until the volume has its key protectors re-enabled. 0 means
# never enable key protectors automatically after a reboot. You need to Resume-BitLocker.
# For data volumes, it doesn't make sense to specify a value; if you do the WMI layer
# returns an error. For OS volumes, the default
# is determined by the WMI layer which is 1.
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Suspend-BitLocker
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint,
[Parameter(Position = 1, Mandatory = $false)]
[ValidateRange(0,15)]
[int]
$RebootCount = -1)
process
{
Write-Debug "Begin Suspend-BitLocker($MountPoint, $RebootCount)"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point whose protectors
# can be disabled then the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $BitLockerVolumeInternal.MountPoint
if ($RebootCount -ne -1)
{
$DisableKeyProtectorsResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DisableKeyProtectors -Arguments @{DisableCount = [uint32]$RebootCount}
}
else
{
$DisableKeyProtectorsResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DisableKeyProtectors
}
if ($DisableKeyProtectorsResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $DisableKeyProtectorsResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid mount point was provided that can be suspended"
}
Write-Debug "End Suspend-BitLocker. Return $BitLockerVolume"
}
}
#########################################################################################
# Resume-BitLocker
#
# Returns BitLockerVolume structures that describes the volumes which have been resumed.
# Resumed means that the key protectors have been enabled. The drive contents are still
# encrypted and if encryption or decryption is paused then this cmdlet will not change
# that. To resume the encryption or decryption process you need to call the WMI method
# ResumeConversion.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Resume-BitLocker
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint)
process
{
Write-Debug "Begin Resume-BitLocker($MountPoint)"
<#
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point whose protectors
# can be disabled then the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#>
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $BitLockerVolumeInternal.MountPoint
$EnableKeyProtectorsResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName EnableKeyProtectors
if ($EnableKeyProtectorsResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $EnableKeyProtectorsResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid mount point was provided that can be resumed"
}
Write-Debug "End Resume-BitLocker. Return $BitLockerVolume"
}
}
#########################################################################################
# Lock-BitLocker
#
# Returns BitLockerVolume structures that describes the volumes which have been locked.
# Locked means volume is dismounted and the volume's encryption key is removed from system memory.
# The contents of the volume remain inacessible until it is unlocked.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
# Bool - ForceDismount flag. If $true the disk is forcefully dismounted
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Lock-BitLocker
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint,
[Parameter(Mandatory = $false)]
[Alias("fd")]
[System.Management.Automation.SwitchParameter]
$ForceDismount = $false)
process
{
Write-Debug "Begin Lock-BitLocker($MountPoint)"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point then
# the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $BitLockerVolumeInternal.MountPoint
$LockResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName Lock -Arguments @{ForceDismount = $ForceDismount.IsPresent}
if ($LockResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $LockResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid mount point was provided that can be locked"
}
Write-Debug "End Lock-BitLocker. Return $BitLockerVolume"
}
}
#########################################################################################
# Unlock-PasswordInternal
#
# Returns BitLockerVolume structure that describes the volume after it was unlocked
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# SecureString - password to use for unlocking
#
# Return: 0 for success
#########################################################################################
function Unlock-PasswordInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true)]
[System.Security.SecureString]
$Password
)
process
{
Write-Debug "Begin Unlock-PasswordInternal"
#
# Convert secure string to cleartext.
#
$ClearTextPassword = Decrypt-SecureStringInternal $Password
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$UnlockResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName UnlockWithPassphrase -Arguments @{PassPhrase = $ClearTextPassword}
# Clear the clear text password string
$ClearTextPassword = ""
if ($UnlockResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $UnlockResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $UnlockResult.ReturnValue
}
Write-Debug "End Unlock-PasswordInternal"
return 0
}
}
#########################################################################################
# Unlock-RecoveryPasswordInternal
#
# Returns BitLockerVolume structure that describes the volume after it was unlocked
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# String - recovery password to use for unlocking
#
# Return: 0 for success
#########################################################################################
function Unlock-RecoveryPasswordInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true)]
[string]
$RecoveryPassword
)
process
{
Write-Debug "Begin Unlock-RecoveryPasswordInternal"
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$UnlockResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName UnlockWithNumericalPassword -Arguments @{NumericalPassword = $RecoveryPassword}
if ($UnlockResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $UnlockResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $UnlockResult.ReturnValue
}
Write-Debug "End Unlock-RecoveryPasswordInternal"
return 0
}
}
#########################################################################################
# Unlock-RecoveryKeyInternal
#
# Returns BitLockerVolume structure that describes the volume after it was unlocked
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# String - recovery key to use for unlocking
#
# Return: 0 for success
#########################################################################################
function Unlock-RecoveryKeyInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true)]
[string]
$RecoveryKeyPath
)
process
{
Write-Debug "Begin Unlock-RecoveryKeyInternal"
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$GetExternalKeyFromFileResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetExternalKeyFromFile -Arguments @{PathWithFileName = $RecoveryKeyPath}
if ($GetExternalKeyFromFileResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $GetExternalKeyFromFileResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $GetExternalKeyFromFileResult.ReturnValue
}
$UnlockResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName UnlockWithExternalKey -Arguments @{ExternalKey = $GetExternalKeyFromFileResult.ExternalKey}
if ($UnlockResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $UnlockResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $UnlockResult.ReturnValue
}
Write-Debug "End Unlock-RecoveryKeyInternal"
return 0
}
}
#########################################################################################
# Unlock-BitLocker
#
# Returns BitLockerVolume structures that describes the volumes which have been unlocked.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
# Protector - protector to use for unlocking
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Unlock-BitLocker
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint,
#
# Password Protector
#
[Parameter(Mandatory = $true, ParameterSetName="OnlyPasswordParameterSet")]
[Alias("pw")]
[System.Security.SecureString]
$Password,
#
# Recovery Password Protector
#
[Parameter(Mandatory = $true, ParameterSetName="OnlyRecoveryPasswordParameterSet")]
[ValidateNotNullOrEmpty()]
[Alias("rp")]
[String]
$RecoveryPassword,
#
# Recovery Key Protector
#
[Parameter(Mandatory = $true, ParameterSetName="OnlyRecoveryKeyParameterSet")]
[ValidateNotNullOrEmpty()]
[Alias("rk")]
[String]
$RecoveryKeyPath,
#
# Ad Account Or Group Protector
#
[Parameter(Mandatory = $true, ParameterSetName="OnlyAdAccountOrGroupParameterSet")]
[System.Management.Automation.SwitchParameter]
$AdAccountOrGroup
)
process
{
Write-Debug "Begin Unlock-BitLocker($MountPoint)"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point then
# the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
if ($PsCmdlet.ParameterSetName -eq "OnlyPasswordParameterSet")
{
$Result = Unlock-PasswordInternal $BitLockerVolumeInternal.MountPoint $Password
}
elseif ($PsCmdlet.ParameterSetName -eq "OnlyRecoveryPasswordParameterSet")
{
$Result = Unlock-RecoveryPasswordInternal $BitLockerVolumeInternal.MountPoint $RecoveryPassword
}
elseif ($PsCmdlet.ParameterSetName -eq "OnlyRecoveryKeyParameterSet")
{
$Result = Unlock-RecoveryKeyInternal $BitLockerVolumeInternal.MountPoint $RecoveryKeyPath
}
elseif ($PsCmdlet.ParameterSetName -eq "OnlyAdAccountOrGroupParameterSet")
{
$Result = Unlock-AdAccountOrGroupInternal $BitLockerVolumeInternal.MountPoint
}
if ($Result -ne 0)
{
Write-Debug "Unlock-BitLocker failed for $BitLockerVolumeInternal.MountPoint"
continue
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid mount point was provided that can be unlocked"
}
Write-Debug "End Unlock-BitLocker. Return $BitLockerVolume"
}
}
#########################################################################################
# Add-RecoveryPasswordProtectorInternal
#
# Returns BitLockerVolume structure that describes the volume with the new recovery password protector
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# RecoveryPassword - recovery password protector to add. Can be empty.
#
# Return: 0 for success
#########################################################################################
function Add-RecoveryPasswordProtectorInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Position = 1, Mandatory = $false)]
[string]
$RecoveryPassword,
[Parameter(Mandatory = $false)]
[System.Management.Automation.SwitchParameter]
$SuppressWarningMessage = $false
)
process
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
if ($RecoveryPassword -eq "")
{
$AddKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ProtectKeyWithNumericalPassword -Arguments @{FriendlyName = $null; NumericalPassword = $null}
}
else
{
$AddKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ProtectKeyWithNumericalPassword -Arguments @{FriendlyName = $null; NumericalPassword = $RecoveryPassword}
}
if ($AddKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $AddKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $AddKeyProtectorResult.ReturnValue
}
if (!$SuppressWarningMessage)
{
$KeyProtectorId = $AddKeyProtectorResult.VolumeKeyProtectorID
$RecoveryPasswordResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetKeyProtectorNumericalPassword -Arguments @{VolumeKeyProtectorID = $KeyProtectorId}
if ($RecoveryPasswordResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $RecoveryPasswordResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $RecoveryPasswordResult.ReturnValue
}
$RecoveryPassword = $RecoveryPasswordResult.NumericalPassword
Write-Debug "RecoveryPassword added"
$Message = [string]::Format($stringTable.WarningWriteDownRecoveryPassword, $RecoveryPassword, [Environment]::NewLine)
Write-Warning $Message
}
return 0
}
}
#########################################################################################
# Add-PasswordProtectorInternal
#
# Adds a passphrase protector to a volume
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# SecureString - password
#
# Return: 0 for success
#########################################################################################
function Add-PasswordProtectorInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Position = 1, Mandatory = $false)]
[System.Security.SecureString]
$Password
)
process
{
if ($Password -eq $null)
{
$Password = Read-UserSecretInternal -Message $stringTable.PasswordPrompt -ConfirmMessage $stringTable.ConfirmPasswordPrompt -NotMatchMessage $stringTable.NoMatchPassword
}
#
# Convert secure string to cleartext.
#
$ClearTextPassword = Decrypt-SecureStringInternal $Password
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$AddKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ProtectKeyWithPassphrase -Arguments @{FriendlyName = $null; PassPhrase = $ClearTextPassword}
# Clear the clear text password string
$ClearTextPassword = ""
if ($AddKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $AddKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $AddKeyProtectorResult.ReturnValue
}
return 0
}
}
#########################################################################################
# Remove-KeyProtectorByTypeInternal
#
# Deletes one key protector of the type specified by $ProtectorType
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# uint32 - protector type of protector that is to be deleted
#
# Return: 0 for success
#########################################################################################
function Remove-KeyProtectorByTypeInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true)]
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]
$ProtectorType
)
process
{
#
# Get key protectors of type $ProtectorType
#
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$KeyProtectorIdsResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetKeyProtectors -Arguments @{KeyProtectorType = [uint32]$ProtectorType}
if ($KeyProtectorIdsResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $KeyProtectorIdsResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $KeyProtectorIdsResult.ReturnValue
}
if ($KeyProtectorIdsResult.VolumeKeyProtectorID.Count -ne 1)
{
#
# Return success
#
return 0
}
$Result = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DeleteKeyProtector -Arguments @{VolumeKeyProtectorID = $KeyProtectorIdsResult.VolumeKeyProtectorID[0]}
if ($Result.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result.ReturnValue
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
return 0
}
}
#########################################################################################
# Add-TpmProtectorInternal
#
# Adds a TPM protector to a volume
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
#
# Return: 0 for success
#########################################################################################
function Add-TpmProtectorInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint
)
process
{
Write-Debug "Begin Add-TpmProtectorInternal"
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$AddKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ProtectKeyWithTPM -Arguments @{FriendlyName = $null; PlatformValidationProfile = $null}
if ($AddKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $AddKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $AddKeyProtectorResult.ReturnValue
}
#
# Delete all other TPM based protectors
#
$Result = Remove-KeyProtectorByTypeInternal $MountPoint TpmPin
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
$Result = Remove-KeyProtectorByTypeInternal $MountPoint TpmStartupKey
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
$Result = Remove-KeyProtectorByTypeInternal $MountPoint TpmPinStartupKey
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
Write-Debug "End Add-TpmProtectorInternal"
return 0
}
}
#########################################################################################
# Add-TpmAndPinProtectorInternal
#
# Adds a TPMAndPin protector to a volume
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# SecureString - Pin
#
# Return: 0 for success
#########################################################################################
function Add-TpmAndPinProtectorInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Position = 1, Mandatory = $false)]
[System.Security.SecureString]
$Pin
)
process
{
Write-Debug "Begin Add-TpmAndPinProtectorInternal"
if ($Pin -eq $null)
{
$Pin = Read-UserSecretInternal -Message $stringTable.PinPrompt -ConfirmMessage $stringTable.ConfirmPinPrompt -NotMatchMessage $stringTable.NoMatchPin
}
#
# Convert secure string to cleartext.
#
$ClearTextPin = Decrypt-SecureStringInternal $Pin
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$AddKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ProtectKeyWithTPMAndPin -Arguments @{FriendlyName = $null; PlatformValidationProfile = $null; PIN = $ClearTextPin}
# Clear the clear text pin
$ClearTextPin = ""
if ($AddKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $AddKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $AddKeyProtectorResult.ReturnValue
}
#
# Delete all other TPM based protectors
#
$Result = Remove-KeyProtectorByTypeInternal $MountPoint Tpm
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
$Result = Remove-KeyProtectorByTypeInternal $MountPoint TpmStartupKey
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
$Result = Remove-KeyProtectorByTypeInternal $MountPoint TpmPinStartupKey
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
Write-Debug "End Add-TpmAndPinProtectorInternal"
return 0
}
}
#########################################################################################
# Add-TpmAndStartupKeyProtectorInternal
#
# Adds a TPMAndStartupKey protector to a volume
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# String - Startup Key path
#
# Return: 0 for success
#########################################################################################
function Add-TpmAndStartupKeyProtectorInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true)]
[String]
$StartupKeyPath
)
process
{
Write-Debug "Begin Add-TpmAndStartupKeyProtectorInternal"
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$AddKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ProtectKeyWithTPMAndStartupKey -Arguments @{ExternalKey = $null; FriendlyName = $null; PlatformValidationProfile = $null}
if ($AddKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $AddKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $AddKeyProtectorResult.ReturnValue
}
$SaveExternalKeyResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName SaveExternalKeyToFile -Arguments @{VolumeKeyProtectorID = $AddKeyProtectorResult.VolumeKeyProtectorId; Path = $StartupKeyPath}
if ($SaveExternalKeyResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $SaveExternalKeyResult.ReturnValue
Write-Error -Exception $ExceptionForHr
#
# Remove previously added protector
#
$r = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DeleteKeyProtector -Arguments @{VolumeKeyProtectorID = $AddKeyProtectorResult.VolumeKeyProtectorID}
return $SaveExternalKeyResult.ReturnValue
}
#
# Delete all other TPM based protectors
#
$Result = Remove-KeyProtectorByTypeInternal $MountPoint Tpm
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
$Result = Remove-KeyProtectorByTypeInternal $MountPoint TpmPin
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
$Result = Remove-KeyProtectorByTypeInternal $MountPoint TpmPinStartupKey
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
Write-Debug "End Add-TpmAndStartupKeyProtectorInternal"
return 0
}
}
#########################################################################################
# Add-TpmAndPinAndStartupKeyProtectorInternal
#
# Adds a TPMAndPinAndStartupKey protector to a volume
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# SecureString - Pin
# String - Startup Key path
#
# Return: 0 for success
#########################################################################################
function Add-TpmAndPinAndStartupKeyProtectorInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true)]
[String]
$StartupKeyPath,
[Parameter(Position = 2, Mandatory = $false)]
[System.Security.SecureString]
$Pin
)
process
{
Write-Debug "Begin Add-TpmAndPinAndStartupKeyProtectorInternal"
if ($Pin -eq $null)
{
$Pin = Read-UserSecretInternal -Message $stringTable.PinPrompt -ConfirmMessage $stringTable.ConfirmPinPrompt -NotMatchMessage $stringTable.NoMatchPin
}
#
# Convert secure string to cleartext.
#
$ClearTextPin = Decrypt-SecureStringInternal $Pin
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$AddKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ProtectKeyWithTPMAndPinAndStartupKey -Arguments @{ExternalKey = $null; FriendlyName = $null; PIN = $ClearTextPin; PlatformValidationProfile = $null}
# Clear the clear text pin
$ClearTextPin = ""
if ($AddKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $AddKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $AddKeyProtectorResult.ReturnValue
}
$SaveExternalKeyResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName SaveExternalKeyToFile -Arguments @{VolumeKeyProtectorID = $AddKeyProtectorResult.VolumeKeyProtectorId; Path = $StartupKeyPath}
if ($SaveExternalKeyResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $SaveExternalKeyResult.ReturnValue
Write-Error -Exception $ExceptionForHr
#
# Remove previously added protector
#
$r = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DeleteKeyProtector -Arguments @{VolumeKeyProtectorID = $AddKeyProtectorResult.VolumeKeyProtectorID}
return $SaveExternalKeyResult.ReturnValue
}
#
# Delete all other TPM based protectors
#
$Result = Remove-KeyProtectorByTypeInternal $MountPoint Tpm
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
$Result = Remove-KeyProtectorByTypeInternal $MountPoint TpmPin
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
$Result = Remove-KeyProtectorByTypeInternal $MountPoint TpmStartupKey
if ($Result -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $Result
Write-Error -Exception $ExceptionForHr
return $Result.ReturnValue
}
Write-Debug "End Add-TpmAndPinAndStartupKeyProtectorInternal"
return 0
}
}
#########################################################################################
# Add-ExternalKeyProtectorInternal
#
# Adds an ExternalKey protector to a volume (Startup Key, Recovery Key)
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# String - External Key path
#
# Return: 0 for success
#########################################################################################
function Add-ExternalKeyProtectorInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true)]
[String]
$ExternalKeyPath
)
process
{
Write-Debug "Begin Add-ExternalKeyProtectorInternal"
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$AddKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ProtectKeyWithExternalKey -Arguments @{ExternalKey = $null; FriendlyName = $null}
if ($AddKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $AddKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $AddKeyProtectorResult.ReturnValue
}
$SaveExternalKeyResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName SaveExternalKeyToFile -Arguments @{VolumeKeyProtectorID = $AddKeyProtectorResult.VolumeKeyProtectorId; Path = $ExternalKeyPath}
if ($SaveExternalKeyResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $SaveExternalKeyResult.ReturnValue
Write-Error -Exception $ExceptionForHr
#
# Remove previously added protector
#
$r = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DeleteKeyProtector -Arguments @{VolumeKeyProtectorID = $AddKeyProtectorResult.VolumeKeyProtectorID}
return $SaveExternalKeyResult.ReturnValue
}
Write-Debug "End Add-ExternalKeyProtectorInternal"
return 0
}
}
#########################################################################################
# Add-SidProtectorInternal
#
# Adds a SID protector to a volume
#
# Input: String - volume name. Could be: drive letter or volume id or mounted directory
# String - SID
#
# Return: 0 for success
#########################################################################################
function Add-SidProtectorInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[String]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true)]
[String]
$Sid,
[Parameter(Position = 2, Mandatory = $true)]
[bool]
$Service
)
process
{
Write-Debug "Begin Add-SidProtectorInternal"
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$flags = 0
if ($Service -eq $true)
{
$flags = 1 # 1 means FVE_DPAPI_NG_FLAG_UNLOCK_AS_SERVICE_ACCOUNT
}
$User = [System.Security.Principal.NTAccount]($Sid)
try
{
$SidStr = $User.Translate([System.Security.Principal.SecurityIdentifier])
}
catch
{
#
# Failed to translate, so try to use what the user gave us
#
try
{
$SidStr = [System.Security.Principal.SecurityIdentifier]($Sid)
}
catch
{
Write-Error -Exception $_.Exception
return 1
}
}
$AddKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ProtectKeyWithAdSid -Arguments @{FriendlyName = $null; SidString = $SidStr.Value; Flags = [uint32]$flags}
if ($AddKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $AddKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $AddKeyProtectorResult.ReturnValue
}
Write-Debug "End Add-SidProtectorInternal"
return 0
}
}
#########################################################################################
# Add-BitLockerKeyProtector
#
# Returns BitLockerVolume structures that describe the volumes with the new protector.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
# KeyProtector - key protector to add
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Add-BitLockerKeyProtector
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint,
#
# Password Protector
#
[Parameter(Mandatory = $true, ParameterSetName="PasswordProtector")]
[Alias("pwp")]
[System.Management.Automation.SwitchParameter]
$PasswordProtector,
[Parameter(Mandatory = $false, ParameterSetName="PasswordProtector", Position = 1)]
[Alias("pw")]
[System.Security.SecureString]
$Password,
#
# Recovery Password Protector
#
[Parameter(Mandatory = $true, ParameterSetName="RecoveryPasswordProtector")]
[Alias("rpp")]
[System.Management.Automation.SwitchParameter]
$RecoveryPasswordProtector,
[Parameter(Mandatory = $false, ParameterSetName="RecoveryPasswordProtector", Position = 1)]
[ValidateNotNullOrEmpty()]
[Alias("rp")]
[String]
$RecoveryPassword,
#
# Startup Key Protector
#
[Parameter(Mandatory = $true, ParameterSetName="StartupKeyProtector")]
[Alias("skp")]
[System.Management.Automation.SwitchParameter]
$StartupKeyProtector,
[Parameter(Mandatory = $true, ParameterSetName="StartupKeyProtector", Position = 1)]
[Parameter(Mandatory = $true, ParameterSetName="TpmAndPinAndStartupKeyProtector", Position = 1)]
[Parameter(Mandatory = $true, ParameterSetName="TpmAndStartupKeyProtector", Position = 1)]
[Alias("sk")]
[String]
$StartupKeyPath,
#
# Sid Protector
#
[Parameter(Mandatory = $true, ParameterSetName="SidProtector")]
[Alias("sidp")]
[System.Management.Automation.SwitchParameter]
$ADAccountOrGroupProtector,
[Parameter(Mandatory = $true, ParameterSetName="SidProtector", Position = 1)]
[Alias("sid")]
[String]
$ADAccountOrGroup,
[Parameter(Mandatory = $false, ParameterSetName="SidProtector")]
[System.Management.Automation.SwitchParameter]
$Service,
#
# TPM And Pin And StartupKey Protector
#
[Parameter(Mandatory = $true, ParameterSetName="TpmAndPinAndStartupKeyProtector")]
[Alias("tpskp")]
[System.Management.Automation.SwitchParameter]
$TpmAndPinAndStartupKeyProtector,
# Defined in the StartupKeyProtector section above
# [Parameter(Mandatory = $true, ParameterSetName="TpmAndPinAndStartupKeyProtector", Position = 1)]
# [String]
# $StartupKeyPath,
[Parameter(Mandatory = $false, ParameterSetName="TpmAndPinAndStartupKeyProtector", Position = 2)]
[Parameter(Mandatory = $false, ParameterSetName="TpmAndPinProtector", Position = 1)]
[Alias("p")]
[System.Security.SecureString]
$Pin,
#
# TPM And Pin Protector
#
[Parameter(Mandatory = $true, ParameterSetName="TpmAndPinProtector")]
[Alias("tpp")]
[System.Management.Automation.SwitchParameter]
$TpmAndPinProtector,
# Defined in TPM And Pin And Startup Key Protector section above
# [Parameter(Mandatory = $false, ParameterSetName="TpmAndPinProtector", Position = 1)]
# [System.Security.SecureString]
# $Pin,
#
# TPM And StartupKey Protector
#
[Parameter(Mandatory = $true, ParameterSetName="TpmAndStartupKeyProtector")]
[Alias("tskp")]
[System.Management.Automation.SwitchParameter]
$TpmAndStartupKeyProtector,
# Defined in the StartupKeyProtector section above
# [Parameter(Mandatory = $true, ParameterSetName="TpmAndStartupKeyProtector", Position = 1)]
# [String]
# $StartupKeyPath,
#
# TPM Protector
#
[Parameter(Mandatory = $true, ParameterSetName="TpmProtector")]
[Alias("tpmp")]
[System.Management.Automation.SwitchParameter]
$TpmProtector,
#
# Recovery Key Protector
#
[Parameter(Mandatory = $true, ParameterSetName="RecoveryKeyProtector")]
[Alias("rkp")]
[System.Management.Automation.SwitchParameter]
$RecoveryKeyProtector,
[Parameter(Mandatory = $true, ParameterSetName="RecoveryKeyProtector", Position = 1)]
[Alias("rk")]
[String]
$RecoveryKeyPath
)
process
{
Write-Debug "Begin Add-BitLockerKeyProtector"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point then
# the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
if ($PsCmdlet.ParameterSetName -eq "RecoveryPasswordProtector")
{
$Result = Add-RecoveryPasswordProtectorInternal $BitLockerVolumeInternal.MountPoint $RecoveryPassword
}
elseif ($PsCmdlet.ParameterSetName -eq "PasswordProtector")
{
$Result = Add-PasswordProtectorInternal $BitLockerVolumeInternal.MountPoint $Password
}
elseif ($PsCmdlet.ParameterSetName -eq "TpmProtector")
{
$Result = Add-TpmProtectorInternal $BitLockerVolumeInternal.MountPoint
}
elseif ($PsCmdlet.ParameterSetName -eq "TpmAndPinProtector")
{
$Result = Add-TpmAndPinProtectorInternal $BitLockerVolumeInternal.MountPoint $Pin
}
elseif ($PsCmdlet.ParameterSetName -eq "TpmAndStartupKeyProtector")
{
$Result = Add-TpmAndStartupKeyProtectorInternal $BitLockerVolumeInternal.MountPoint $StartupKeyPath
}
elseif ($PsCmdlet.ParameterSetName -eq "TpmAndPinAndStartupKeyProtector")
{
$Result = Add-TpmAndPinAndStartupKeyProtectorInternal $BitLockerVolumeInternal.MountPoint $StartupKeyPath $Pin
}
elseif ($PsCmdlet.ParameterSetName -eq "StartupKeyProtector")
{
$Result = Add-ExternalKeyProtectorInternal $BitLockerVolumeInternal.MountPoint $StartupKeyPath
}
elseif ($PsCmdlet.ParameterSetName -eq "RecoveryKeyProtector")
{
$Result = Add-ExternalKeyProtectorInternal $BitLockerVolumeInternal.MountPoint $RecoveryKeyPath
}
elseif ($PsCmdlet.ParameterSetName -eq "SidProtector")
{
$Result = Add-SidProtectorInternal $BitLockerVolumeInternal.MountPoint $ADAccountOrGroup $Service
}
if ($Result -ne 0)
{
Write-Debug "Add-BitLockerKeyProtector failed for $BitLockerVolumeInternal.MountPoint"
continue
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid mount point was provided"
}
Write-Debug "End Add-BitLockerKeyProtector"
}
}
#########################################################################################
# Remove-BitLockerKeyProtector
#
# Returns BitLockerVolume structures that describe the volumes after the protector is deleted.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
# String - ID of key protector to be removed
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Remove-BitLockerKeyProtector
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[Alias("id")]
[string]
$KeyProtectorId
)
process
{
Write-Debug "Begin Remove-BitLockerKeyProtector($MountPoint, $KeyProtectorId)"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point then
# the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $BitLockerVolumeInternal.MountPoint
$DraKeyProtector = $BitLockerVolumeInternal.KeyProtector |
where {$_.KeyProtectorId -eq $KeyProtectorId -and
$_.KeyProtectorType -eq [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::PublicKey -and
[uint32]$_.KeyCertificateType -band [uint32][Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorCertificateTypes]::DataRecoveryAgent -eq [uint32][Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorCertificateTypes]::DataRecoveryAgent}
if ($DraKeyProtector -ne $null)
{
Write-Error -Message $stringTable.ErrorRemoveDraProtector
continue
}
$NkpProtector = $BitLockerVolumeInternal.KeyProtector |
where {$_.KeyProtectorId -eq $KeyProtectorId -and
$_.KeyProtectorType -eq [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::TpmNetworkKey}
if ($NkpProtector -ne $null)
{
Write-Error -Message $stringTable.ErrorRemoveNkpProtector
continue
}
$DeleteKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DeleteKeyProtector -Arguments @{VolumeKeyProtectorID = $KeyProtectorId}
if ($DeleteKeyProtectorResult.ReturnValue -eq $E_KEYREQUIRED)
{
$DisableKeyProtectorsResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DisableKeyProtectors
if ($DisableKeyProtectorsResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $DisableKeyProtectorsResult
Write-Error -Exception $ExceptionForHr
continue
}
$DeleteKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DeleteKeyProtector -Arguments @{VolumeKeyProtectorID = $KeyProtectorId}
}
if ($DeleteKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $DeleteKeyProtectorResult.ReturnValue
if ($DeleteKeyProtectorResult.ReturnValue -eq $E_VOLUMEBOUND)
{
$ErrorMessage = [string]::Format($stringTable.ErrorVolumeBoundAlready)
Write-Error -Exception $ExceptionForHr -Message $ErrorMessage
}
else
{
Write-Error -Exception $ExceptionForHr
}
continue
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid combination of mountpoint / protector id found"
}
Write-Debug "End Remove-BitLockerKeyProtector. Return $BitLockerVolume"
}
}
#########################################################################################
# Backup-BitLockerKeyProtector
#
# Returns BitLockerVolume structures that describe the volumes after the protector is backed up.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
# String - ID of key protector to be backed up
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Backup-BitLockerKeyProtector
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string]
$KeyProtectorId
)
process
{
Write-Debug "Begin Backup-BitLockerKeyProtector($MountPoint, $KeyProtectorId)"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point then
# the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $BitLockerVolumeInternal.MountPoint
$BackupKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName BackupRecoveryInformationToActiveDirectory -Arguments @{VolumeKeyProtectorID = $KeyProtectorId}
if ($BackupKeyProtectorResult.ReturnValue -eq $S_FALSE)
{
$ErrorMessage = [string]::Format($stringTable.ErrorGroupPolicyDisabledBackup)
Write-Error -Message $ErrorMessage
continue
}
elseif ($BackupKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $BackupKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid combination of mountpoint / protector id found"
}
Write-Debug "End Backup-BitLockerKeyProtector. Return $BitLockerVolume"
}
}
#########################################################################################
# BackupToAAD-BitLockerKeyProtector
#
# Returns BitLockerVolume structures that describe the volumes after the protector is backed up.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
# String - ID of key protector to be backed up
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function BackupToAAD-BitLockerKeyProtector
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string]
$KeyProtectorId
)
process
{
Write-Debug "Begin BackupToAAD-BitLockerKeyProtector($MountPoint, $KeyProtectorId)"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point then
# the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $BitLockerVolumeInternal.MountPoint
$BackupKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName BackupRecoveryInformationToCloudDomain -Arguments @{VolumeKeyProtectorID = $KeyProtectorId}
if ($BackupKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $BackupKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid combination of mountpoint / protector id found"
}
Write-Debug "End BackupToAAD-BitLockerKeyProtector. Return $BitLockerVolume"
}
}
#########################################################################################
# BackupToMSA-BitLockerKeyProtector
#
# Returns BitLockerVolume structures that describe the volumes after the protector is backed up.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
# String - ID of key protector to be backed up
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function BackupToMSA-BitLockerKeyProtector
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint,
[Parameter(Position = 1, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string]
$KeyProtectorId
)
process
{
Write-Debug "Begin BackupToMSA-BitLockerKeyProtector($MountPoint, $KeyProtectorId)"
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $BitLockerVolumeInternal.MountPoint
$BackupKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName BackupRecoveryInformationToMicrosoftAccount -Arguments @{VolumeKeyProtectorID = $KeyProtectorId}
if ($BackupKeyProtectorResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $BackupKeyProtectorResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid combination of mountpoint / protector id found"
}
Write-Debug "End BackupToMSA-BitLockerKeyProtector. Return $BitLockerVolume"
}
}
#########################################################################################
# Enable-BitLockerAutoUnlock
#
# Returns BitLockerVolume structures that describes the volumes which have auto unlock enabled.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Enable-BitLockerAutoUnlock
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint)
process
{
Write-Debug "Begin Enable-BitLockerAutoUnlock($MountPoint)"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point that can
# have auto unlock enabled then the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $BitLockerVolumeInternal.MountPoint
$IsAutoUnlockEnabledResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName IsAutoUnlockEnabled
if ($IsAutoUnlockEnabledResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $IsAutoUnlockEnabledResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
if ($IsAutoUnlockEnabledResult.IsAutoUnlockEnabled -eq $false)
{
$ProtectKeyWithExternalKeyResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ProtectKeyWithExternalKey
if ($ProtectKeyWithExternalKeyResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $ProtectKeyWithExternalKeyResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
Write-Debug ("Added Protector: " + $ProtectKeyWithExternalKeyResult.VolumeKeyProtectorID)
$EnableAutoUnlockResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName EnableAutoUnlock -Arguments @{VolumeKeyProtectorID = $ProtectKeyWithExternalKeyResult.VolumeKeyProtectorID}
if ($EnableAutoUnlockResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $EnableAutoUnlockResult.ReturnValue
$DeleteKeyProtectorResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DeleteKeyProtector -Arguments @{VolumeKeyProtectorID = $ProtectKeyWithExternalKeyResult.VolumeKeyProtectorID}
$ExceptionForDebug = Get-ExceptionForHrInternal -HrUInt32 $DeleteKeyProtectorResult.ReturnValue
Write-Debug ("Could not enable auto-unlock. Clean up result: " + $ExceptionForDebug)
Write-Error -Exception $ExceptionForHr
continue
}
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid mount point was provided that can have auto unlock enabled"
}
Write-Debug "End Enable-BitLockerAutoUnlock. Return $BitLockerVolume"
}
}
#########################################################################################
# Disable-BitLockerAutoUnlock
#
# Returns BitLockerVolume structures that describes the volumes which have auto unlock disabled.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Disable-BitLockerAutoUnlock
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint)
process
{
Write-Debug "Begin Disable-BitLockerAutoUnlock($MountPoint)"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point that can
# have auto unlock enabled then the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $BitLockerVolumeInternal.MountPoint
$IsAutoUnlockEnabledResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName IsAutoUnlockEnabled
if ($IsAutoUnlockEnabledResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $IsAutoUnlockEnabledResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
if ($IsAutoUnlockEnabledResult.IsAutoUnlockEnabled -eq $true)
{
$DisableAutoUnlockResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName DisableAutoUnlock
if ($DisableAutoUnlockResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $DisableAutoUnlockResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid mount point was provided that can have auto unlock enabled"
}
Write-Debug "End Disable-BitLockerAutoUnlock. Return $BitLockerVolume"
}
}
#########################################################################################
# Disable-BitLocker
#
# Returns BitLockerVolume structures that describe the volumes which have been disabled.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Disable-BitLocker
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint)
process
{
Write-Debug "Begin Disable-BitLocker($MountPoint)"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point that can
# have auto unlock enabled then the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if (!$BitLockerVolumeInternal)
{
$m = $MountPoint[$i]
Write-Debug "The following operation failed: Get-BitLockerVolumeInternal -MountPoint $m"
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $BitLockerVolumeInternal.MountPoint
if ($BitLockerVolumeInternal.VolumeType -eq [Microsoft.BitLocker.Structures.BitLockerVolumeType]::OperatingSystem)
{
$IsAutoUnlockKeyStoredResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName IsAutoUnlockKeyStored
if ($IsAutoUnlockKeyStoredResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $IsAutoUnlockKeyStoredResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
if ($IsAutoUnlockKeyStoredResult.IsAutoUnlockKeyStored -eq $true)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $E_AUTOUNLOCK_ENABLED
Write-Error -Exception $ExceptionForHr
continue
}
}
$DecryptResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName Decrypt
if ($DecryptResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $DecryptResult.ReturnValue
Write-Error -Exception $ExceptionForHr
continue
}
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
}
}
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid mount point was provided that can be decrypted"
}
Write-Debug "End Disable-BitLocker. Return $BitLockerVolume"
}
}
#########################################################################################
# Clear-BitLockerAutoUnlock
#
# Returns BitLockerVolume structure that describes the OS volume which has had auto unlock
# keys cleared.
#
# Input: None
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Clear-BitLockerAutoUnlock
{
[CmdletBinding()]
Param()
process
{
Write-Debug "Begin Clear-BitLockerAutoUnlock."
$OsBitLockerVolume = Get-BitLockerVolume | where {$_.VolumeType -eq [Microsoft.BitLocker.Structures.BitLockerVolumeType]::OperatingSystem}
if ($OsBitLockerVolume -eq $null)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $E_NOTFOUND
$ErrorMessage = [string]::Format($stringTable.ErrorOperatingSystemMountPointNotFound)
Write-Error -Exception $ExceptionForHr -Message $ErrorMessage
}
Write-Debug "Operating system volume to operate on: $OsBitLockerVolume."
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $OsBitLockerVolume.MountPoint
$ClearKeysResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName ClearAllAutoUnlockKeys
if ($ClearKeysResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $ClearKeysResult.ReturnValue
Write-Error -Exception $ExceptionForHr
$OsBitLockerVolume = $null
}
else
{
#
# Since we modified the OS Volume by clearing all auto unlock keys, we should
# get a fresh BitLockerVolume
#
$OsBitLockerVolume = Get-BitLockerVolume $OsBitLockerVolume
}
$OsBitLockerVolume
Write-Debug "End Clear-BitLockerAutoUnlock. Return $OsBitLockerVolume"
}
}
#########################################################################################
# Unlock-AdAccountOrGroupInternal
#
# Returns BitLockerVolume structure that describes an unlocked volume. The volume is unlocked
# based on the current user/machine token.
#
# Input: MountPoint
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume
#########################################################################################
function Unlock-AdAccountOrGroupInternal
{
Param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint)
process
{
Write-Debug "Begin Unlock-AdAccountOrGroupInternal($MountPoint)"
$BitLockerVolume = $null
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
$UnlockWithAdSidResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName UnlockWithAdSid
if ($UnlockWithAdSidResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $UnlockWithAdSidResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $UnlockWithAdSidResult.ReturnValue
}
return 0
Write-Debug "End Unlock-AdAccountOrGroupInternal. Return $BitLockerVolume"
}
}
#########################################################################################
# Test-SystemEntropyForBitLocker
#
# Returns true or false
#
# Input: None
#
# Return: $true or $false
#########################################################################################
function Test-SystemEntropyForBitLockerInternal
{
process
{
Write-Debug "Start Test-SystemEntropyForBitLockerInternal"
$IsWinPe = $false
$RegistyItem = Get-Item HKLM:\SYSTEM\CurrentControlSet\Control\MiniNT -ErrorAction SilentlyContinue
if ($RegistryItem -eq $null)
{
return $true
}
$IsWinPe = $true
Write-Debug "WinPe: $IsWinPe"
$Win32Tpm = Get-CimInstance -ClassName Win32_Tpm -Namespace "root\CIMV2\Security\MicrosoftTpm"
if ($Win32Tpm -eq $null)
{
Write-Debug "Tpm WMI object could not not be created"
return $false
}
$IsEnabled = $false
$IsActivated = $false
$IsEnabledResult = Invoke-CimMethod -InputObject $Win32Tpm -MethodName IsEnabled
if ($IsEnabledResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $IsEnabledResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $false
}
else
{
$IsEnabled = $IsEnabledResult.IsEnabled
}
$IsActivatedResult = Invoke-CimMethod -InputObject $Win32Tpm -MethodName IsActivated
if ($IsActivatedResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $IsActivatedResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $false
}
else
{
$IsActivated = $IsActivatedResult.IsActivated
}
Write-Debug "End Test-SystemEntropyForBitLockerInternal. IsEnabled: $IsEnabled IsActivated: $IsActivated"
return $IsEnabled -and $IsActivated
}
}
#########################################################################################
# Test-TpmProtectorNeededInternal
#
# Returns true or false
#
# Input: None
#
# Return: $true or $false
#########################################################################################
function Test-TpmProtectorNeededInternal
{
Param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$ParameterSetNameFromEnableBitLocker)
process
{
Write-Debug "Begin Test-TpmProtectorNeededInternal"
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint
if ($BitLockerVolumeInternal -eq $false)
{
Write-Debug "End Test-TpmProtectorNeededInternal. Return $false. BitLockerVolume not valid"
return $false
}
if ($BitLockerVolumeInternal.VolumeType -ne [Microsoft.BitLocker.Structures.BitLockerVolumeType]::OperatingSystem)
{
Write-Debug "End Test-TpmProtectorNeededInternal. Return $false. BitLockerVolume is not an OS volume"
return $false
}
$DoesPasswordProtectorExist = $BitLockerVolumeInternal.KeyProtector | where-object {$_.KeyProtectorType -eq [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::Password}
$IsTpmReady = Test-TpmForBitLockerInternal
if ($IsTpmReady -eq $true)
{
$AnyTpmKeyProtectorType = [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::Tpm,
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::TpmNetworkKey,
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::TpmPin,
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::TpmPinStartupKey,
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::TpmStartupKey
$DoesAnyTpmProtectorExist = $BitLockerVolumeInternal.KeyProtector | where-object {$AnyTpmKeyProtectorType -contains $_.KeyProtectorType}
#
# Check if we don't have the following:
# - Password protector
# - ANY Tpm protector
# - User trying to add a password protector
# - User trying to add ANY Tpm protector
#
if ($DoesPasswordProtectorExist -eq $null -and
$DoesAnyTpmProtectorExist -eq $null -and
$ParameterSetNameFromEnableBitLocker -ne "PasswordProtector" -and
$ParameterSetNameFromEnableBitLocker -ne "TpmProtector" -and
$ParameterSetNameFromEnableBitLocker -ne "TpmAndStartupKeyProtector" -and
$ParameterSetNameFromEnableBitLocker -ne "TpmAndPinProtector" -and
$ParameterSetNameFromEnableBitLocker -ne "TpmAndPinAndStartupKeyProtector")
{
Write-Debug "End Test-TpmProtectorNeededInternal. Return $true"
return $true
}
}
return $false
Write-Debug "End Test-TpmProtectorNeededInternal. Return $false"
}
}
#########################################################################################
# Test-TpmForBitLockerInternal
#
# Returns true or false
#
# Input: None
#
# Return: $true or $false
#########################################################################################
function Test-TpmForBitLockerInternal
{
process
{
Write-Debug "Begin Test-TpmForBitLockerInternal"
$IsEnabled = $false
$IsOwned = $false
$IsActivated = $false
$IsSrkAuthCompatible = $false
$Win32Tpm = Get-CimInstance -ClassName Win32_Tpm -Namespace "root\CIMV2\Security\MicrosoftTpm"
if ($Win32Tpm -eq $null)
{
Write-Debug "Tpm WMI object could not not be created"
return $false
}
$IsEnabledResult = Invoke-CimMethod -InputObject $Win32Tpm -MethodName IsEnabled
if ($IsEnabledResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $IsEnabledResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $false
}
else
{
$IsEnabled = $IsEnabledResult.IsEnabled
}
$IsOwnedResult = Invoke-CimMethod -InputObject $Win32Tpm -MethodName IsOwned
if ($IsOwnedResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $IsOwnedResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $false
}
else
{
$IsOwned = $IsOwnedResult.IsOwned
}
$IsActivatedResult = Invoke-CimMethod -InputObject $Win32Tpm -MethodName IsActivated
if ($IsActivatedResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $IsActivatedResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $false
}
else
{
$IsActivated = $IsActivatedResult.IsActivated
}
$IsSrkAuthCompatibleResult = Invoke-CimMethod -InputObject $Win32Tpm -MethodName IsSrkAuthCompatible
if ($IsSrkAuthCompatibleResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $IsSrkAuthCompatibleResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $false
}
else
{
$IsSrkAuthCompatible = $IsSrkAuthCompatibleResult.IsSrkAuthCompatible
}
Write-Debug "End Test-TpmForBitLockerInternal. IsEnabled: $IsEnabled IsOwned: $IsOwned IsActivated: $IsActivated IsSrkAuthCompatible: $IsSrkAuthCompatible"
return $IsEnabled -and $IsOwned -and $IsActivated -and $IsSrkAuthCompatible
}
}
function Enable-BitLockerInternal
{
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Mandatory = $false)]
[Microsoft.BitLocker.Structures.BitLockerVolumeEncryptionMethodOnEnable]
$EncryptionMethod,
[Parameter(Mandatory = $true)]
[bool]
$SkipHardwareTest,
[Parameter(Mandatory = $true)]
[bool]
$UsedSpaceOnly)
process
{
Write-Debug "Begin Enable-BitLockerInternal. MountPoint: $MountPoint EncryptionMethod: $EncryptionMethod SkipHardwareTest: $SkipHardwareTest UsedSpaceOnly: $UsedSpaceOnly"
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
if ($Win32EncryptableVolume -eq $null)
{
Write-Debug "Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint returned null"
return
}
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint
if ($BitLockerVolumeInternal -eq $null)
{
Write-Debug "Get-BitLockerVolumeInternal -MountPoint $MountPoint returned null"
return
}
$EncryptionFlags = 0
if ($UsedSpaceOnly -eq $true)
{
$EncryptionFlags = $FVE_CONV_FLAG_DATAONLY
}
$IntegerEncryptionMethod = 0 # None which means WMI layer picks encryption method
if ($EncryptionMethod -ne $null)
{
[int]$IntegerEncryptionMethod = $EncryptionMethod
}
if ($SkipHardwareTest -eq $true)
{
$EncryptResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName Encrypt -Arguments @{EncryptionMethod = [uint32]$IntegerEncryptionMethod; EncryptionFlags = [uint32]$EncryptionFlags}
if ($EncryptResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $EncryptResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
}
else
{
$EncryptResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName EncryptAfterHardwareTest -Arguments @{EncryptionMethod = [uint32]$IntegerEncryptionMethod; EncryptionFlags = [uint32]$EncryptionFlags}
if ($EncryptResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $EncryptResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
}
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint
$BitLockerVolumeInternal
Write-Debug "End Enable-BitLockerInternal. BitLockerVolumeInternal: $BitLockerVolumeInternal"
}
}
#########################################################################################
#
#########################################################################################
function Show-BitLockerRequiredActionsInternal
{
Param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Mandatory = $true)]
[bool]
$SkipHardwareTest)
process
{
Write-Debug "Begin Show-BitLockerRequiredActionsInternal. MountPoint: $MountPoint SkipHardwareTest: $SkipHardwareTest"
$HardwareTestStatus = $FVE_HARDWARE_TEST_NOT_FAILED_OR_PENDING
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint
if ($BitLockerVolumeInternal -eq $null)
{
Write-Debug "Get-BitLockerVolumeInternal -MountPoint $MountPoint returned null"
return
}
$AnyExternalKeyProtectorType = [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::ExternalKey,
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::TpmAndExternalKey,
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::TpmAndPinAndExternalKey
$RecoveryKeyProtector = $BitLockerVolumeInternal.KeyProtector | Where {$_.KeyProtectorType -eq [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::RecoveryPassword} | Select-Object -First 1
$AnyExternalKeyProtector = $BitLockerVolumeInternal.KeyProtector | Where {$AnyExternalKeyProtectorType -contains $_.KeyProtectorType} | Select-Object -First 1
if ($SkipHardwareTest -eq $false)
{
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
if ($Win32EncryptableVolume -eq $null)
{
Write-Debug "Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint returned null"
return
}
$HardwareTestStatusResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName GetHardwareTestStatus
if ($HardwareTestStatusResult.ReturnValue -ne 0)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $HardwareTestStatusResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return
}
$HardwareTestStatus = $HardwareTestStatusResult.TestStatus
}
if ($HardwareTestStatus -eq $FVE_HARDWARE_TEST_NOT_FAILED_OR_PENDING -and
$RecoveryKeyProtector -eq $null)
{
Write-Debug "End Show-BitLockerRequiredActionsInternal. HardwareTestStatus is not failed or pending"
return
}
if ($RecoveryKeyProtector -ne $null -and
$HardwareTestStatus -eq $FVE_HARDWARE_TEST_NOT_FAILED_OR_PENDING)
{
$Message = [string]::Format($stringTable.WarningWriteDownRecoveryPassword, $RecoveryKeyProtector.RecoveryPassword, [Environment]::NewLine)
Write-Warning $Message
}
elseif ($RecoveryKeyProtector -ne $null -and
$AnyExternalKeyProtector -ne $null -and
$HardwareTestStatus -eq $FVE_HARDWARE_TEST_PENDING)
{
$Message = [string]::Format($stringTable.WarningWriteDownRecoveryPasswordInsertExternalKeyRestart, $RecoveryKeyProtector.RecoveryPassword, [Environment]::NewLine)
Write-Warning $Message
}
elseif ($RecoveryKeyProtector -eq $null -and
$AnyExternalKeyProtector -ne $null -and
$HardwareTestStatus -eq $FVE_HARDWARE_TEST_PENDING)
{
$Message = [string]::Format($stringTable.WarningInsertExternalKeyRestart, [Environment]::NewLine)
Write-Warning $Message
}
elseif ($RecoveryKeyProtector -ne $null -and
$AnyExternalKeyProtector -eq $null -and
$HardwareTestStatus -eq $FVE_HARDWARE_TEST_PENDING)
{
$Message = [string]::Format($stringTable.WarningWriteDownRecoveryPasswordRestart, $RecoveryKeyProtector.RecoveryPassword, [Environment]::NewLine)
Write-Warning $Message
}
elseif ($RecoveryKeyProtector -eq $null -and
$AnyExternalKeyProtector -eq $null -and
$HardwareTestStatus -eq $FVE_HARDWARE_TEST_PENDING)
{
$Message = [string]::Format($stringTable.WarningRestart, [Environment]::NewLine)
Write-Warning $Message
}
elseif ($HardwareTestStatus -eq $FVE_HARDWARE_TEST_FAILED)
{
$Message = [string]::Format($StringTable.WarningHardwareTestFailed, [Environment]::NewLine)
Write-Warning $Message
}
}
}
#########################################################################################
#
#########################################################################################
function Get-RecoveryKeyProtectorsCountInternal
{
Param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint)
process
{
$RecoveryKeyProtectorTypes = [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::PublicKey,
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::Sid,
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::ExternalKey,
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::Password,
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::RecoveryPassword
[Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtector[]] $KeyProtectors = (Get-BitLockerVolumeInternal -MountPoint $MountPoint).KeyProtector | where {$RecoveryKeyProtectorTypes -contains $_.KeyProtectorType}
if ($KeyProtectors -eq $null)
{
return 0
}
return $KeyProtectors.Count
}
}
#########################################################################################
#
#########################################################################################
function Set-BitLockerVolumeInternal
{
Param(
[Parameter(Mandatory = $true)]
[ValidateNotNullOrEmpty()]
[string]
$MountPoint,
[Parameter(Mandatory = $true)]
[ValidateRange(0,2)] #[($FVE_FORCE_ENCRYPTION_TYPE_UNSPECIFIED,$FVE_FORCE_ENCRYPTION_TYPE_HARDWARE)]
[int]
$ForceEncryptionType,
[Parameter(Mandatory = $true)]
[bool]
$UsedSpaceOnly)
process
{
[int]$InitializationFlags = $ForceEncryptionType
$Win32EncryptableVolume = Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint
if ($Win32EncryptableVolume -eq $null)
{
Write-Debug "Get-Win32EncryptableVolumeInternal -MountPoint $MountPoint returned null"
return $null
}
if ($UsedSpaceOnly -eq $true)
{
$InitializationFlags += $FVE_PROVISIONING_MODIFIER_USED_SPACE;
}
$PrepareVolumeResult = Invoke-CimMethod -InputObject $Win32EncryptableVolume -MethodName PrepareVolumeEx -Arguments @{DiscoveryVolumeType = $DEFAULT_DISCOVERY_VOLUME_TYPE; InitializationFlags = [uint32]$InitializationFlags}
if ($PrepareVolumeResult.ReturnValue -ne 0)
{
if (($PrepareVolumeResult.ReturnValue -ne $FVE_E_NOT_DECRYPTED) -or
(($InitializationFlags -ne 0) -and
($InitializationFlags -ne $FVE_PROVISIONING_MODIFIER_USED_SPACE)))
{
#
# The volume may have been previously implicitly initialized
# through adding protectors. So we should not fail unless we
# were passing some explicit initialization flags.
# We also allow remapping on used-space flag because we are
# going to pass used-space flag later when starting conversion.
#
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $PrepareVolumeResult.ReturnValue
Write-Error -Exception $ExceptionForHr
return $null
}
}
Get-BitLockerVolumeInternal -MountPoint $MountPoint
}
}
#########################################################################################
# Enable-BitLocker
#
# Returns BitLockerVolume structures that describes volumes with bitlocker enabled.
#
# Input: String[] - array of volume names. Could be: drive letter or volume id or mounted directory
#
# Return: Microsoft.BitLocker.Structures.BitLockerVolume[]
#########################################################################################
#.ExternalHelp Bitlocker.psm1-help.xml
function Enable-BitLocker
{
[CmdletBinding(SupportsShouldProcess=$true)]
Param(
[Parameter(Position = 0, Mandatory = $true, ValueFromPipelineByPropertyName = $true, ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string[]]
$MountPoint,
[Parameter(Mandatory = $false)]
[Microsoft.BitLocker.Structures.BitLockerVolumeEncryptionMethodOnEnable]
$EncryptionMethod,
[Parameter(Mandatory = $false)]
[System.Management.Automation.SwitchParameter]
$HardwareEncryption = $false,
[Parameter(Mandatory = $false)]
[System.Management.Automation.SwitchParameter]
[Alias("s")]
$SkipHardwareTest = $false,
[Parameter(Mandatory = $false)]
[System.Management.Automation.SwitchParameter]
[Alias("qe")]
$UsedSpaceOnly = $false,
#
# Password Protector
#
[Parameter(Mandatory = $true, ParameterSetName="PasswordProtector")]
[Alias("pwp")]
[System.Management.Automation.SwitchParameter]
$PasswordProtector = $false,
[Parameter(Mandatory = $false, ParameterSetName="PasswordProtector", Position = 1)]
[Alias("pw")]
[System.Security.SecureString]
$Password,
#
# Recovery Password Protector
#
[Parameter(Mandatory = $true, ParameterSetName="RecoveryPasswordProtector")]
[Alias("rpp")]
[System.Management.Automation.SwitchParameter]
$RecoveryPasswordProtector = $false,
[Parameter(Mandatory = $false, ParameterSetName="RecoveryPasswordProtector", Position = 1)]
[ValidateNotNullOrEmpty()]
[Alias("rp")]
[String]
$RecoveryPassword,
#
# Startup Key Protector
#
[Parameter(Mandatory = $true, ParameterSetName="StartupKeyProtector")]
[Alias("skp")]
[System.Management.Automation.SwitchParameter]
$StartupKeyProtector = $false,
[Parameter(Mandatory = $true, ParameterSetName="StartupKeyProtector", Position = 1)]
[Parameter(Mandatory = $true, ParameterSetName="TpmAndPinAndStartupKeyProtector", Position = 1)]
[Parameter(Mandatory = $true, ParameterSetName="TpmAndStartupKeyProtector", Position = 1)]
[Alias("sk")]
[String]
$StartupKeyPath,
#
# Active Directory Account Or Group Protector
#
[Parameter(Mandatory = $true, ParameterSetName="AdAccountOrGroupProtector")]
[Alias("sidp")]
[System.Management.Automation.SwitchParameter]
$AdAccountOrGroupProtector = $false,
[Parameter(Mandatory = $false, ParameterSetName="AdAccountOrGroupProtector")]
[System.Management.Automation.SwitchParameter]
$Service = $false,
[Parameter(Mandatory = $true, ParameterSetName="AdAccountOrGroupProtector", Position = 1)]
[Alias("sid")]
[String]
$AdAccountOrGroup,
#
# TPM And Pin And StartupKey Protector
#
[Parameter(Mandatory = $true, ParameterSetName="TpmAndPinAndStartupKeyProtector")]
[Alias("tpskp")]
[System.Management.Automation.SwitchParameter]
$TpmAndPinAndStartupKeyProtector = $false,
# Defined in the StartupKeyProtector section above
# [Parameter(Mandatory = $true, ParameterSetName="TpmAndPinAndStartupKeyProtector", Position = 1)]
# [String]
# $StartupKeyPath,
[Parameter(Mandatory = $false, ParameterSetName="TpmAndPinAndStartupKeyProtector", Position = 2)]
[Parameter(Mandatory = $false, ParameterSetName="TpmAndPinProtector", Position = 1)]
[Alias("p")]
[System.Security.SecureString]
$Pin,
#
# TPM And Pin Protector
#
[Parameter(Mandatory = $true, ParameterSetName="TpmAndPinProtector")]
[Alias("tpp")]
[System.Management.Automation.SwitchParameter]
$TpmAndPinProtector = $false,
# Defined in TPM And Pin And Startup Key Protector section above
# [Parameter(Mandatory = $false, ParameterSetName="TpmAndPinProtector", Position = 1)]
# [System.Security.SecureString]
# $Pin,
#
# TPM And StartupKey Protector
#
[Parameter(Mandatory = $true, ParameterSetName="TpmAndStartupKeyProtector")]
[Alias("tskp")]
[System.Management.Automation.SwitchParameter]
$TpmAndStartupKeyProtector = $false,
# Defined in the StartupKeyProtector section above
# [Parameter(Mandatory = $true, ParameterSetName="TpmAndStartupKeyProtector", Position = 1)]
# [String]
# $StartupKeyPath,
#
# TPM Protector
#
[Parameter(Mandatory = $true, ParameterSetName="TpmProtector")]
[Alias("tpmp")]
[System.Management.Automation.SwitchParameter]
$TpmProtector = $false,
#
# Recovery Key Protector
#
[Parameter(Mandatory = $true, ParameterSetName="RecoveryKeyProtector")]
[Alias("rkp")]
[System.Management.Automation.SwitchParameter]
$RecoveryKeyProtector = $false,
[Parameter(Mandatory = $true, ParameterSetName="RecoveryKeyProtector", Position = 1)]
[Alias("rk")]
[String]
$RecoveryKeyPath)
process
{
Write-Debug "Begin Enable-BitLocker"
#########
# ValidMountPoint is a subset of the elements of MountPoint array.
# If MountPoint array contains an element that is not a valid mount point then
# the mount point is not part of ValidMountPoint
# Only those BitLockerVolume structures are returned that are part of ValidMountPoint
#
# If "-whatif" is used then ValidMountPoint is always $null
#########
[string[]]$ValidMountPoint = $null
if ($HardwareEncryption -eq $true -and $UsedSpaceOnly -eq $true)
{
$UsedSpaceOnly = $false
Write-Warning $stringTable.WarningUsedSpaceOnlyAndHardwareEncryption
}
for($i=0; $i -lt $MountPoint.Count; $i++)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
if ($BitLockerVolumeInternal -eq $null)
{
Write-Debug ("The following operation failed: Get-BitLockerVolumeInternal -MountPoint " + $MountPoint[$i])
continue
}
Write-Debug ("MountPoint: " + $BitLockerVolumeInternal.MountPoint)
$IsFullyDecrypted = $BitLockerVolumeInternal.VolumeStatus -eq [Microsoft.BitLocker.Structures.BitLockerVolumeStatus]::FullyDecrypted
$IsOsVolume = $BitLockerVolumeInternal.VolumeType -eq [Microsoft.BitLocker.Structures.BitLockerVolumeType]::OperatingSystem
if ($pscmdlet.ShouldProcess($BitLockerVolumeInternal.MountPoint))
{
if ($IsFullyDecrypted -eq $true)
{
$IsSystemEntropyReady = Test-SystemEntropyForBitLockerInternal
if ($IsSystemEntropyReady -eq $false)
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $TPM_E_DEACTIVATED
Write-Error -Exception $ExceptionForHr
continue
}
if ($HardwareEncryption -eq $true)
{
$BitLockerVolumeInternal = Set-BitLockerVolumeInternal -MountPoint $MountPoint[$i] -ForceEncryptionType $FVE_FORCE_ENCRYPTION_TYPE_HARDWARE -UsedSpaceOnly $false
}
else
{
$BitLockerVolumeInternal = Set-BitLockerVolumeInternal -MountPoint $MountPoint[$i] -ForceEncryptionType $FVE_FORCE_ENCRYPTION_TYPE_UNSPECIFIED -UsedSpaceOnly $UsedSpaceOnly
}
Write-Debug "Set-BitLockerVolumeInternal returned $BitLockerVolumeInternal"
if ($BitLockerVolumeInternal -eq $null)
{
continue
}
if ($IsOsVolume -eq $true)
{
$IsTpmReady = Test-TpmForBitLockerInternal
if ($IsTpmReady -eq $true)
{
$IsTpmProtectorNeeded = Test-TpmProtectorNeededInternal -MountPoint $MountPoint[$i] -ParameterSetNameFromEnableBitLocker $PsCmdlet.ParameterSetName
if ($IsTpmProtectorNeeded -eq $true)
{
$BitLockerVolumeInternal = Add-BitLockerKeyProtector -TpmProtector -MountPoint $BitLockerVolumeInternal
Write-Debug "Add-BitLockerKeyProtector returned $BitLockerVolumeInternal"
if ($BitLockerVolumeInternal -eq $null)
{
continue
}
}
}
else
{
$DoesPasswordProtectorExist = $BitLockerVolumeInternal.KeyProtector | where-object {$_.KeyProtectorType -eq [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::Password}
$DoesExternalKeyProtectorExist = $BitLockerVolumeInternal.KeyProtector | where-object {$_.KeyProtectorType -eq [Microsoft.BitLocker.Structures.BitLockerVolumeKeyProtectorType]::ExternalKey}
if ($DoesPasswordProtectorExist -eq $null -and
$DoesExternalKeyProtectorExist -eq $null -and
$PsCmdlet.ParameterSetName -ne "PasswordProtector" -and
$PsCmdlet.ParameterSetName -ne "StartupKeyProtector")
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $E_FAIL
Write-Error -Exception $ExceptionForHr -Message $stringTable.ErrorExternalKeyOrPasswordRequired
continue
}
}
if ($PsCmdlet.ParameterSetName -eq "AdAccountOrGroupProtector")
{
$RecoveryKeyProtectorCount = Get-RecoveryKeyProtectorsCountInternal -MountPoint $MountPoint[$i]
$IsTpmAvailable = Test-TpmForBitLockerInternal
if ( ($RecoveryKeyProtectorCount -lt $MINIMUM_REQUIRED_RECOVERY_PROTECTORS_WITH_TPM -and $IsTpmAvailable -eq $true) -or ($RecoveryKeyProtectorCount -lt $MINIMUM_REQUIRED_RECOVERY_PROTECTORS_WITHOUT_TPM -and $IsTpmAvailable -eq $false))
{
$ExceptionForHr = Get-ExceptionForHrInternal -HrUInt32 $E_FAIL
Write-Error -Exception $ExceptionForHr -Message $stringTable.ErrorSidProtectorRequiresAdditionalRecoveryProtector
continue
}
}
} # end if OS Volume
} #end if VolumeStatus -eq FullyDecrypted
if ($PsCmdlet.ParameterSetName -eq "PasswordProtector")
{
$BitLockerVolumeInternal = Add-BitLockerKeyProtector -MountPoint $MountPoint[$i] -PasswordProtector -Password $Password
}
elseif ($PsCmdlet.ParameterSetName -eq "RecoveryPasswordProtector")
{
#
# We call the internal add protector method because we
# don't want it to output the recovery password. This cmdlet will do it.
#
$nResult = 0
if ([string]::IsNullOrEmpty($RecoveryPassword))
{
$nResult = Add-RecoveryPasswordProtectorInternal $MountPoint[$i] -SuppressWarningMessage
}
else
{
$nResult = Add-RecoveryPasswordProtectorInternal $MountPoint[$i] $RecoveryPassword -SuppressWarningMessage
}
if ($nResult -eq 0)
{
$BitLockerVolumeInternal = Get-BitLockerVolumeInternal -MountPoint $MountPoint[$i]
}
}
elseif ($PsCmdlet.ParameterSetName -eq "StartupKeyProtector")
{
$BitLockerVolumeInternal = Add-BitLockerKeyProtector -MountPoint $MountPoint[$i] -StartupKeyProtector -StartupKeyPath $StartupKeyPath
}
elseif ($PsCmdlet.ParameterSetName -eq "AdAccountOrGroupProtector")
{
if ($Service -eq $false)
{
$BitLockerVolumeInternal = Add-BitLockerKeyProtector -MountPoint $MountPoint[$i] -AdAccountOrGroupProtector -AdAccountOrGroup $AdAccountOrGroup
}
else
{
$BitLockerVolumeInternal = Add-BitLockerKeyProtector -MountPoint $MountPoint[$i] -AdAccountOrGroupProtector -AdAccountOrGroup $AdAccountOrGroup -Service
}
}
elseif ($PsCmdlet.ParameterSetName -eq "TpmAndPinAndStartupKeyProtector")
{
$BitLockerVolumeInternal = Add-BitLockerKeyProtector -MountPoint $MountPoint[$i] -TpmAndPinAndStartupKeyProtector -StartupKeyPath $StartupKeyPath -Pin $Pin
}
elseif ($PsCmdlet.ParameterSetName -eq "TpmAndPinProtector")
{
$BitLockerVolumeInternal = Add-BitLockerKeyProtector -MountPoint $MountPoint[$i] -TpmAndPinProtector -Pin $Pin
}
elseif ($PsCmdlet.ParameterSetName -eq "TpmAndStartupKeyProtector")
{
$BitLockerVolumeInternal = Add-BitLockerKeyProtector -MountPoint $MountPoint[$i] -TpmAndStartupKeyProtector -StartupKeyPath $StartupKeyPath
}
elseif ($PsCmdlet.ParameterSetName -eq "TpmProtector")
{
$BitLockerVolumeInternal = Add-BitLockerKeyProtector -MountPoint $MountPoint[$i] -TpmProtector
}
elseif ($PsCmdlet.ParameterSetName -eq "RecoveryKeyProtector")
{
$BitLockerVolumeInternal = Add-BitLockerKeyProtector -MountPoint $MountPoint[$i] -RecoveryKeyProtector -RecoveryKeyPath $RecoveryKeyPath
}
if ($BitLockerVolumeInternal -eq $null)
{
Write-Debug ("Add-BitLockerKeyProtector did not return a bitlocker volume. ParameterSet: " + $PSCmdlet.ParameterSetName)
continue
}
if ($BitLockerVolumeInternal.VolumeType -eq [Microsoft.BitLocker.Structures.BitLockerVolumeType]::Data -or
$IsFullyDecrypted -ne $true)
{
$NeedHardwareTest = $false
}
else
{
$NeedHardwareTest = !$SkipHardwareTest
}
if ($EncryptionMethod -ne $null)
{
$BitLockerVolumeInternal = Enable-BitLockerInternal -MountPoint $BitLockerVolumeInternal -EncryptionMethod $EncryptionMethod -SkipHardwareTest (!$NeedHardwareTest) -UsedSpaceOnly $UsedSpaceOnly
}
else
{
$BitLockerVolumeInternal = Enable-BitLockerInternal -MountPoint $BitLockerVolumeInternal -SkipHardwareTest (!$NeedHardwareTest) -UsedSpaceOnly $UsedSpaceOnly
}
Write-Debug "Enable-BitLockerInternal returned $BitLockerVolumeInternal. EncryptionMethod: $EncryptionMethod NeedHardwareTest: $NeedHardwareTest UsedSpaceOnly: $UsedSpaceOnly"
if ($BitLockerVolumeInternal -eq $null)
{
Write-Debug ("Could not enable bitlocker on " + $MountPoint[$i])
continue
}
Show-BitLockerRequiredActionsInternal -MountPoint $BitLockerVolumeInternal -SkipHardwareTest (!$NeedHardwareTest)
$ValidMountPoint = $ValidMountPoint + $MountPoint[$i]
} #end ShouldProcess
} #end for each MountPoint
Write-Debug "ValidMountPoint: $ValidMountPoint"
if ($ValidMountPoint)
{
$BitLockerVolume = Get-BitLockerVolume -MountPoint $ValidMountPoint
$BitLockerVolume
}
else
{
Write-Debug "No valid mount point was provided that can have bitlocker enabled"
}
Write-Debug "End Enable-BitLocker $BitLockerVolume"
} #end process record
}