PowerShell and BitLocker: Part 1


Summary: Guest blogger, Stephane van Gulick, presents a practical hands-on post that shows how to use Windows PowerShell and BitLocker together.

Microsoft Scripting Guy, Ed Wilson, is here. Today we have a new guest blogger, Stephane van Gulick. Stephane was introduced to me by The Scripting Wife, she was browsing the Internet and found his blog. She thought he would be an excellent guest for the Hey, Scripting Guy! Blog, and I totally agreed. This is be a two-part blog series and there is a lot of information to share. Here is where you can find Stephane:

Website: PowerShell District
Twitter : @Stephanevg
Linked-In: Stéphane van Gulick

Howdy everybody,

Today is a perfect day to give you a good introduction to BitLocker. BitLocker is a Microsoft technology that allows you to encrypt a hard drive on a system. In today’s business world, many users are traveling and taking their laptops with them on their journeys. That laptop could potentially carry sensitive corporate data from clients or from their company. Having this data accessed by someone with bad intentions could be a real issue for the business if the laptop is stolen or forgotten somewhere (that can happen, yes!).

This is a risk that cannot be ignored, and it needs to be tackled by the IT department. This risk mitigation is handled by using BitLocker to encrypt the system drive of the computer.

A security mechanism can be implemented that will limit access to the computer with a PIN code that needs to be given each time the device is booted. Without this PIN, the data on the hard drive is encrypted and cannot be accessed.

Thus a thief cannot simply steal the laptop and plug the hard drive into his computer to access confidential information about the company.

The encryption mechanism can be done by using the GUI, but at the Hey, Scripting Guy! Blog, we are more interested in the scripting side of things.

In this post, I will guide you through the scripting steps to automate the encryption of drive C, which is very commonly the system drive. That is the drive that you need to be sure the thief does not have access to.

When you start to script BitLocker encryption, you might think, “Cool. I will use Windows PowerShell cmdlets.”

Well, that is true. But they only became available in systems with Windows PowerShell 4.0 (thus in Windows 8.1 and Windows Server 2012 R2). Luckily, there is WMI to help us!

The second difficulty you might bump in to is the logic. Indeed, to encrypt a volume, you do not only work with the hard drive, but also with the Trusted Platform Module (TPM). And a certain order needs to be respected before any encryption operation can be done.

The TPM is actually the microchip located on your motherboard that will encrypt your hard drive. So before you start to encrypt the hard drive, you need to do some specific TPM operations, which we will discuss in detail a bit later.

We need to take care of things such as taking ownership, clearing the TPM, and launching then encrypting the drive. What? Does it sound confusing? Yes! I agree. But do not worry—we will go through the logic and in a very short moment, and everything will become crystal clear.

The fun stuff

A lot of the following script examples come from a function I wrote called BitLockerSAK. It is a tool written in Windows PowerShell that makes BitLocker tasks easier to automate.

When we wanted to automate encryption prior to Windows PowerShell 4.0, we had to dig in to that good old WMI technology. WMI has indeed been here with us for a while, and it will most certainly be here longer. (The fact that the new “Nano Server” will only be administrable through WMI and Desired State Configuration proves it.)

The two main WMI classes you need to know about are:

  • Win32_TPM
  • Win32_EncryptableVolume

Win32_TPM contains methods and properties that we can use to automate TPM tasks on the local machine.

Win32_EncryptableVolume contains the methods and properties we can use to automate encryption tasks, such as the encryption of the drive and returning the percentage of the encryption. (Don’t worry—we will get there.) But first things first...

Let’s talk about the TPM and everything around it.

TPM ownership prerequisites

The TPM logic that needs to be respected has been simplified to the basics in this Visio flow chart:

Image of flow chart

Before starting to manipulate the encryption mechanisms, we need to handle the TPM. The TPM must meet three conditions before the encryption operations can start:

  • The TPM must be enabled.
  • The TPM must be activated.
  • The TPM must be owned.

If all three conditions are met, we can go further and run the encryption operations on the desired disk.

Now that we have our flow, we can script it when we have answered these questions:

  1. How do we identify if the TPM is enabled, activated, and owned?
  2. How do we remediate each step if the condition is not met?

The most difficult part of our job (in my opinion) is not really the scripting part (the Windows PowerShell scripting language really helps simplify things)—it is more about how and where to find the information we need. For this particular case (most likely, in all cases), you can find more information online and directly in Windows PowerShell by using Get-Member.

We already know that the TPM scripting-related activities are done through the Win32_TPM class, so we start our scripting operations by getting the TPM class:

$Tpm = Get-CIMClass -Namespace ROOT\CIMV2\Security\MicrosoftTpm -Class Win32_Tpm

If we add Get-Member to the TPM variable, we get the following list, where we can easily identify methods that can do the job (highlighted in red):

Image of command output

The other way to get that information is to go directly to the constructor’s webpage, and get a grip on the documentation of the Win32_TPM WMI class. (This is also a good way to get more information about methods that we have found using Get-Member).

We can very easily find the three methods that perfectly fit our tasks:

The Windows PowerShell code for each of them would be easy...

First, we have to load the WMI class into a variable:

$Tpm = Get-wmiobject -Namespace ROOT\CIMV2\Security\MicrosoftTpm -Class Win32_Tpm

Then we call the different methods like this:

#TPM enabled

 $Tpm.IsEnabled().isenabled

#TPM activation

 $Tpm.IsActivated().isactivated

#TPM owned

 $Tpm.IsOwned().isOwned

Each of these methods will return $true if the TPM is enabled, activated, or owned, or $false if not.

And what do we do to remediate these steps to make them answer $true if one of them returns $false? For the Enable and Activate methods, it is a piece of cake. By following the same searching methods as described earlier, we can simply use the following methods:

#TPM enable     $Tpm.Enable()

~ or to disable it:

#TPM disble     $Tpm.Disable() 

The activation is automatically done when the TPM setting is activated in the BIOS. 

Let’s take a minute and sum up all of that in our workflow:

Image of flow chart

There we go! We have the global logic, the methods that we need to verify the logic, and the remediation step methods.

Taking TPM ownership

This looks simple right? But actually, taking the ownership is a little bit less straightforward than what is described in the previous graphic. (That’s why I highlighted it in orange.) Plus, depending on the hardware you are using, you might encounter another behavior. Let me explain...

If you are not the owner of the TPM module, you have to clear the TPM module and then attempt to take ownership to finally have all the cards necessary for the encryption actions to start. But if there is already a TPM owner, you do not have to take the ownership, per se. The TPM ownership operations can succeed here without explicitly taking the ownership.

Let’s go further with the wish to take the ownership. Taking the ownership requires several steps for the process to complete successfully. I have summarized it for you in the following flow chart:

Image of flow chart

Now that we have the basic workflow diagram, let’s try to find how we could automate this. Let’s again look at the methods we have available in Win32_TPM with TPM | Get-Member, and identify the methods for this operation:

Image of command output

To clear the TPM, we can see that a method named Clear is available. Perfect. This exactly what we need!

To clear the TPM, we simply use the following command:

#TPM Clearing TPM owner

$Tpm.Clear()

It is important to know that you need to communicate with your domain controller to clear the TPM. Without a connection, this operation will fail and return a value of 2147942402.

We can also see a method named TakeOwnership that needs the OwnerAuth type as an entry.

When taking the TPM ownership, you actually have the possibility to provide a password so that the owner can be identified. This password is optional, and if used, it must be of the OwnerAuth type. Luckily, we can also see a method called ConverToOwnerAuth in the screenshot. We can use the following code to convert the password to the required format:

#TPM converting password

 $Password = “MyNameIsStephane”

 $TPMPAssword = Tpm.ConverToOwnerAuth($Password).OwnerAuth

And now to take ownership, we call the TakeOwnership() method with the password we previously generated:

Tpm.TakeOwnerShip($TPMPassword)

If you have a return value of 2150105108, it means that the TPM already has an owner. If you want to change the owner, you need to clear it. (Remember, if there is already an owner, you do not have to change the owner, but I recommend that you do it.)

Depending on the hardware that you are using, there could be an extra built-in security layer that would oblige you to have a physical presence at the computer when the TPM ownership is changed. This means, that somebody needs to be physically present during the next boot, and confirm by clicking Allow when asked for the BIOS change confirmation.

As scripters, I bet you see the issue that we could be facing here. However, this is important to know so that we can communicate it efficiently or simply avoid this situation. We can pretty easily identify if we need to have a physical presence at the computer after the TPM ownership has been taken. This can be done by using the method called GetPhysicalPresenceConfirmationStatus(5) from the Win32_tpmclass. The return value is an integer from 0 to 5. The following table explains their meanings.

Value

Meaning

0

Not implemented

1

BIOS only

2

Blocked for the operating system by the BIOS configuration

3

Allowed, and physically present user required

4

Allowed, and physically present user not required

If GetPhysicalPresenceConfirmationStatus(5) returns a 3, you will be obliged to be physically present at the computer to validate the TPM clear change. You might want to avoid taking ownership if you need to have a physical presence at the computer when the TPM ownership is taken.

If this is intended to be a remediation script (that you deploy through ConfigMgr, for example), the end user will be asked to validate the changes at the next boot. He most likely will not understand this screen, will end up frustrated, and will have to call the Help Desk. In most cases, it is better to avoid this type of situation.

Note  Taking ownership is not necessarily needed. If there is already an owner listed for the TPM on the system, you can bypass this option and attempt to encrypt the drive immediately.

Let’s summarize all of this in our flow chart so that we have a global vision of how this works:

Image of flow chart

Another method that can be pretty useful, but is not necessarily mandatory, is GetPhysicalPresenceTransition(). This method helps identify exactly where we are in the process of taking ownership. The returned values are as follows:

Value

Meaning

0

No user action is needed to perform a TPM physical presence operation.

1

To perform a TPM physical presence operation, the user must shut down the computer and then turn it on by using the power button. The user must be physically present at the computer to accept or reject the change when prompted by the BIOS.

2

To perform a TPM physical presence operation, the user must restart the computer by using a warm reboot. The user must be physically present at the computer to accept or reject the change when prompted by the BIOS.

3

The required user action is unknown.

This method tells you when you need to reboot or shut down the computer to confirm the ownership changes.

TPM ownership: The fast way

There is one more method I would like to highlight: SetphysicalPresenceRequest(). This method allows us to combine several of the steps I explained earlier, according to the value we provided. If we want to clear Enable and activate the TPM by generating a random password for us, we call the method like this:

 #TPM converting password

 $Tpm.SetPhysicalPresenceRequest(14)

I would represent it in a graphic like this:

Image of flow chart

Easy, right? You can simply assume that all the prerequisites for taking ownership of the TPM are met (clear + activate + enable).

There is a caveat though. Depending on the hardware you are using, when you perform this operation, you might be asked for a physical presence at the computer to validate the BIOS confirmation message.

TPM ownership: Complete overview

Now, if we put all of this together in one big visual representation, the global BitLocker ownership operations look like this:

Image of flow chart

SetPhysicalPresence(14) surely reduces the number of steps, but it also reduces the control of the process.

To summarize, the graphic shows two ways to take TPM ownership:

  • The controlled and longer path (green + red parts)
  • The more direct way (yellow section)

You will have to choose according to your needs.

Here is where you can find more information about the methods I have discussed:

~Stephane

Thank you, Stephane, for sharing your time and knowledge. That is all for today. Please join us tomorrow when Stephane will finish this exciting blog post.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy 

Comments (11)

  1. I’m getting a 404 for all image links.

  2. Very useful tip. Thanks

  3. ITGuy says:

    No images.

  4. Jason Zielke says:

    I have been looking for a way to enable TPM with an auto-generated password, and I was hoping this method would work.

    When using the SetPhysicalPresenceRequest(14) method, it does not take ownership. The site documentation for Win32_Tpm does not state that this actually takes ownership, only clear, enable, and activate. Has there been a change since this was written?

  5. Junz says:

    Very useful. I have a problem. I try to use $TPM.clear() or clear-TPM but always not working for me. It always prompt "The clear disable flag is set and all clear operations now require physical access." Anyone can help me this?

  6. Junz says:

    I use SetPhysicalPresenceRequest(14) method and it is working now. Thanks.

  7. d4rkcell says:

    Hello, when trying to run $tpm.enable() it doesn’t seem to like it. I get a "Not specified" method invocation exception. Is this method expecting some input? looking at get-member on the enable method is seems it wants a string OwnerAuth, whats the deal
    here?

  8. Jason Zielke says:

    @d4rkcell
    In order to enable the TPM, you have to have the ownership password (which is actually the ownership hash). You can retrieve this with $TPMPassword per the article, or if you have it stored in AD already, you can use dsa.msc to go in and find it.

    Alternatively, this code should find it for you:

    Import-Module ActiveDirectory (in case you are using v2)
    $tempcomps = (Read-host -Prompt "Please Enter Computer Names (separate with comma)").split(‘,’) | % {$_.trim()}
    if ($tempcomps -eq "")
    {$comp = $env:COMPUTERNAME}
    else {$comp = $tempcomps}
    $compObj = $comp | % {Get-ADComputer -Filter {cn -eq $_} -Properties Name, OperatingSystem, ‘msTPM-TpmInformationForComputer’, ‘msTPM-OwnerInformation’}
    $compObj | % {
    If ($_ -eq $null){Write-Output "Computer not found."};
    # Windows Vista and 7 stores the TPM owner password in the msTPM-OwnerInformation attribute, check that first.
    # If the key hasn’t been stored there, check the msTPM-TpmInformationForComputer object to see if it was backed up on a Win 8 or greater machine
    if($_.’msTPM-OwnerInformation’ -eq $null){
    #Check if the computer object has had the TPM info backed up to AD
    if($_.’msTPM-TpmInformationForComputer’ -ne $null){
    # Grab the TPM Owner Password from the msTPM-InformationObject
    $TPMObject = Get-ADObject -Identity $_.’msTPM-TpmInformationForComputer’ -Properties msTPM-OwnerInformation
    $TPMRecoveryKey = $TPMObject.’msTPM-OwnerInformation’
    }
    else{
    $TPMRecoveryKey = ”
    }
    }
    else{
    # Windows 7 and older OS TPM Owner Password
    $TPMRecoveryKey = $_.’msTPM-OwnerInformation’
    }
    $TPMRecoveryKey

    Or the short version:
    Get-ADObject -Filter * -SearchBase (Get-ADComputer -Identity ).DistinguishedName -Properties Name,’msTPM-OwnerInformation’,’msTPM-TpmInformationForComputer’,’msFVE-RecoveryPassword’ | Select
    Name,’msTPM-OwnerInformation’,’msTPM-TPMInformationForComputer’,’msFVE-RecoveryPassword’ | FL

  9. Jason Zielke says:

    @d4rkcell
    Then, to actually use that hash and enable your tpm, you’d use the method as follows:

    $tpm.Enable($TPMPassword) or $tpm.Enable($TPMRecoveryKey) depending on how you stored acquired the hash.

  10. Ev says:

    Typos:
    $TPMPAssword = Tpm.ConverToOwnerAuth($Password).OwnerAuth

    And now to take ownership, we call the TakeOwnership() method with the password we previously generated:

    Tpm.TakeOwnerShip($TPMPassword)

    Should be:
    $TPMPAssword = $TPM.ConverToOwnerAuth($Password).OwnerAuth

    And now to take ownership, we call the TakeOwnership() method with the password we previously generated:

    $TPM.TakeOwnerShip($TPMPassword)

  11. netlord says:

    Hi There

    two Questions:

    How can it be that the first answers (from anonymous) are 47 years ago?

    Is it possible to use this commands under windowsPE?
    If yes – out of the Box or do I have to install something first?

    thanks

Skip to main content