NOTE: I used Sapien's PowerShellStudio to write this script that significantly simplified the process!
I have wrestled with the issue of encrypting a system using Bitlocker during a build. The issue I have had is that not all of the process can be automated. The steps of turning on the TPM, and activating it can be automated. The portion where the TPM is cleared is a forced, manual process. If you put this in the build, then the build is stopped at the when the TPM is cleared upon the reboot waiting for a user to hit F12 to confirm the clearing of the TPM.
I have wrestled with the issue of encrypting a system using Bitlocker during a build. The issue I have had is that not all of the process can be automated. The steps of turning on the TPM, and activating it can be automated. The portion where the TPM is cleared is a forced, manual process. If you put this in the build, then the build is stopped at the when the TPM is cleared upon the reboot waiting for a user to hit F12 to confirm the clearing of the TPM.
To get around this pause in the build, we decided to make the steps of turning on, clearing, and activating the TPM a manual process before the build process is started. I wrote the script below, integrating the BitLockerSAK function written by Stéphane vg, to verify TPM is on, TPM is cleared, and TPM is activated. If it is not, the script pops up a window saying the build failed due to the TPM not being ready. It says to turn on the TPM, clear the TPM, and activate the TPM. When OK is clicked, the build fails.
The function I wrote uses Dell's CCTK.exe file to check the status of the TPM. I have this executing in WinPE, before the operating system is laid down. To do this, you will need to run three command line tasks.
The first will map the drive to the folder location of that contains the CCTK.exe. I arbitrarily selected T: as the drive letter to use. You enter:
net use t: \\<network location of CCTK.exe>\ /user:<domain>\username Password
The second task sequence is to install CCTK on the X: drive, which is the drive letter of the WinPE. The following command line should be exactly what you need to copy the files to x:\CCTK\:
xcopy.exe "t:\*.*" "x:\CCTK\" /E /C /I /H /R /Y /V
The third step is to enable HAPI, which is also present in the X:\CCTK\ directory. The following command line should do this with no issues:
x:\CCTK\HAPI\hapint -i -k C-C-T-K -p X:\CCTK\HAPI\
Of course you will need to limit the task sequences to only machines which need to be bitlockered.
Now is the time to enter another task sequence that will execute the BitlockerSAK_CheckTPM.ps1 file. You will need to specify the executionpolicy since this is being executed in WinPE. The command line for this that I used was the following with the Start in also populated with the location of the script:
powershell.exe -executionpolicy bypass -file BitlockerSAK_CheckTPM.ps1
If the script detects the TPM is not turned on, not activated, and/or is owned, it will return an exit code of 1. This will cause the build to fail. It will also display the following window alerting the technician of the issue:
If the script detects the TPM is not turned on, not activated, and/or is owned, it will return an exit code of 1. This will cause the build to fail. It will also display the following window alerting the technician of the issue:
You can download the script from here.
1: <#
2: .NOTES
3: ===========================================================================
4: Created with: SAPIEN Technologies, Inc., PowerShell Studio 2015 v4.2.99
5: Created on: 1/28/2016 1:55 PM
6: Created by: Mick Pletcher
7: Organization:
8: Filename: BitlockerSAK_CheckTPM.ps1
9: ===========================================================================
10: .DESCRIPTION
11: This script will test if bitlocker is turned on, cleared, and
12: activated. It uses the BitLockerSAK function wirtten by Stéphane vg to
13: check the ownership of Bitlocker. It also uses CCTK for testing
14: the status of TPM.
15: #>
16:
17: Function BitLockerSAK {
18: <#
19: .SYNOPSIS
20: Get and set Bitlocker related information.
21:
22: .DESCRIPTION
23: Based on WMI classes, this function can achiev the following tasks :
24:
25: --TPM operations---
26: -TPM activation state.
27: -If the TPM is enabled or not.
28: -If a TPM OwnerShip is Allowed.
29: -If the TPM is currently owned.
30: -The possibility to take the ownerShip
31:
32: --Encryption possibilities ---
33: - Retrieves the current encryption method.
34: - Get the current protection status.
35: - The current protection state.
36: - The possibility to encrypt a Drive.
37: - The possibility to Resume an encryption that has been paused.
38: - Possibility to return the current protector ID's.
39: - Possibility to return the current protector type(s).
40: - Retrieves the Volume key protector Passwords
41:
42:
43: .PARAMETER isTPMActivated
44: Returns activation state of the TPM:
45: Returns true if activated and false if not.
46:
47: .PARAMETER isTPMEnabled
48: Returns the enabled state of the TPM:
49: Returns true if activated and false if not.
50:
51: .PARAMETER IsTPMOwnerShipAllowed
52: Returns if the TPM ownership is allowed.
53: Returns true if allowed, false if not.
54:
55: .PARAMETER ResumeEncryption
56: Will resume an paused encryption.
57:
58: .PARAMETER GetEncryptionState
59: Returns the current encurrent state in an object as wolled :
60:
61: .PARAMETER GetProtectionStatus
62: Returns the current protection status. It will return "Protected" if the drive is 100% encrypted, and "Unprotected" if anything else then "100% encrypted".
63:
64: .PARAMETER Encrypt
65: Will encrypt a drive.
66:
67: .PARAMETER TakeTPMOwnerShip
68: Returns true if allowed, false if not
69:
70: .PARAMETER pin
71: Is needed in order to take the ownership and to encrypt the drive.
72:
73: .PARAMETER IsTPMOwned
74: Returns true if owned, false if not
75:
76: .PARAMETER GetKeyProtectorIds
77: Returns all the protector id's available on the machine.
78:
79: .PARAMETER GetKeyProtectorType
80: Returns the type of protector that is currently in use.
81:
82: .PARAMETER GetEncryptionMethod
83: REturns the current encryption method that is in use.
84:
85: .PARAMETER GetKeyProtectorNumericalPassword
86: Returns a given numerical password based on a Protector ID value.
87: The ProtectorID value is mandatory, and must be passed using the parameter VolumeKeyProtectorID.
88:
89: .PARAMETER VolumeKeyProtectorID
90: This parameter will work only in conjunction with GetKeyProtectorNumericalPassword switch.
91: It must contain the ProtectorID from which the desired Numerical Password will be returned.
92:
93: .PARAMETER GetKeyProtectorTypeAndID
94: The GetKeyProtectorTypeAndID switch will return all the existing key protector ID's and their type of the Keys existing on the machine.
95:
96:
97: .PARAMETER Whatif
98: Permits to launch this script in "draft" mode. This means it will only show the results without really making generating the files.
99:
100: .PARAMETER Verbose
101: Allow to run the script in verbose mode for debbuging purposes.
102:
103: .EXAMPLE
104:
105: BitLockerSAK
106:
107: Returns the current status of the drives.
108:
109: IsTPMOwned : True
110: EncryptionMethod : AES_128
111: IsTPMOwnerShipAllowed : True
112: IsTPMActivated : True
113: IsTPMEnabled : True
114: CurrentEncryptionPercentage : 100
115: EncryptionState : FullyEncrypted
116: ProtectorIds : {{FFC19381-6E75-4D1E-94E9-D6E0D3E681FA}, {65AF5A93-9846-47AC-B3B1-D8DE6F06B780}}
117: KeyProtectorType : {Numerical password, Trusted Platform Module (TPM)}
118:
119: .EXAMPLE
120:
121: BitLockerSAK -GetProtectionStatus
122:
123: Returns the current protection status : Protected or unprotected
124:
125: .EXAMPLE
126:
127: BitLockerSAK -GetEncryptionState
128:
129: CurrentEncryptionProgress is express in percentage.
130:
131: CurrentEncryptionProgress EncryptionState
132: ------------------------- ---------------
133: 100 FullyEncrypted
134:
135: .EXAMPLE
136:
137: Get all the key protectors and their respective ID's and protector types from the current machine.
138:
139: BitLockerSAK -GetKeyProtectorTypeAndID
140:
141: KeyProtectorID KeyProtectorType
142: -------------- ----------------
143: {AB1535D4-ECB3-49D6-8AB1-E334A4F60579} Numerical password
144: {B1BDF8CD-55F2-4532-A93F-4B1AF4F22B55} Trusted Platform Module (TPM)
145:
146: .EXAMPLE
147:
148: Get the numerical password from a specefic Key using the ID.
149:
150: BitLockerSAK -GetKeyProtectorNumericalPassword -VolumeKeyProtectorID "{AB1535D4-ECB3-49D6-8AB1-E334A4F60579}"
151:
152: Message KeyProtectorNumericalPassword VolumeKeyProtectorID
153: ------- ----------------------------- --------------------
154: The method was successful. 242968-693319-295251-477840-704451-214225-550055-383229 {AB1535D4-ECB3-49D6-8AB1-E334A4F60579}
155:
156: .NOTES
157: -Author: Stephane van Gulick
158: -Email :
159: -CreationDate: 13-01-2014
160: -LastModifiedDate: 11.06.2015
161: -Version: 1.5
162: -History:
163: #0.1 : Created function
164: #1.1 : 20140901 Added GetProtectorIds
165: #1.2 : 20140909 Rewrote function
166: Added GetKeyprotectorType
167: Added EncryptionMethod
168: #1.3 : 20141003 Added TPM conditions.
169: #1.4 : Possiblity to select drive letter, added RemoveKeyProtectors.
170: --> GetKeyProtectorTypeAndID,
171: --> DeleteKeyProtectors,
172: --> ProtectorIDs,
173: --> DeleteKeyProtector,
174: --> PauseEncryption,
175: --> PauseDecryption,
176: --> Decrytp
177: #1.4.1 --> updated help with GetKeyPRotectedID instead of KeyProtectedID parameter
178: #1.5 Added GetKeyProtectorNumericalPassword and VolumeKeyProtectorID parameters.
179:
180: .LINK
181: www.PowerShellDistrict.com
182:
183: #>
184: [cmdletBinding()]
185: Param (
186: [Switch]$IsTPMActivated,
187: [Switch]$IsTPMEnabled,
188: [Switch]$IsTPMOwnerShipAllowed,
189: [Switch]$ResumeEncryption,
190: [Switch]$GetEncryptionState,
191: [Switch]$GetProtectionStatus,
192: [switch]$Encrypt,
193: [Parameter(ParameterSetName = 'OwnerShip')][switch]$TakeTPMOwnerShip,
194: [Parameter(ParameterSetName = 'OwnerShip')][int]$pin,
195: [switch]$IsTPMOwned,
196: [Switch]$GetKeyProtectorIds,
197: [switch]$GetEncryptionMethod,
198: [ValidateScript({
199: if ($_ -match '^[A-Z]{1}[:]') {
200: return $true
201: } else {
202: Write-Warning 'The drive letter parameter has to respect the following case: DriverLetter+Colomn EG: --> C: --> D: --> E: '
203: return $false
204: }
205: })][string]$DriveLetter = 'C:',
206: [switch]$GetKeyProtectorTypeAndID,
207: [switch]$DeleteKeyProtectors,
208: #Acceptvaluefrompipelinebyname
209: [String[]]$ProtectorIDs,
210: [switch]$DeleteKeyProtector,
211: [switch]$PauseEncryption,
212: [switch]$PauseDecryption,
213: [switch]$Decrytp,
214: [Parameter(ParameterSetName = 'NumericalPassword')][Switch]$GetKeyProtectorNumericalPassword,
215: [Parameter(ParameterSetName = 'NumericalPassword', Mandatory = $true)][String]$VolumeKeyProtectorID
216:
217: )
218: Begin {
219: try {
220: $Tpm = Get-WmiObject -Namespace ROOT\CIMV2\Security\MicrosoftTpm -Class Win32_Tpm -ErrorAction Stop
221: } catch [System.Management.ManagementException]{
222:
223: write-warning 'Could not access the WMI methods. Verify that you run the script with elevated rights and try again.'
224: continue
225:
226:
227: }
228: }
229: Process {
230: ##Add switch to verify if enough place is present on HD (6gig are need, 10 recommended).
231:
232:
233: switch ($PSBoundParameters.keys) {
234:
235: 'IsTPMActivated'{ $return = if ($Tpm) { $tpm.IsActivated().isactivated }; break }
236: 'IsTPMEnabled'{ $return = if ($Tpm) { $tpm.IsEnabled().isenabled }; break }
237: 'IsTPMOwnerShipAllowed'{ $return = if ($Tpm) { $tpm.IsOwnerShipAllowed().IsOwnerShipAllowed }; break }
238: 'IsTPMOwned'{ $return = if ($Tpm) { $Tpm.isowned().isowned }; break }
239: 'GetEncryptionState'{
240: write-verbose "Getting the encryptionstate of drive $($driveletter)"
241: #http://msdn.microsoft.com/en-us/library/aa376433(VS.85).aspx
242: #We only want to work on the C: drive.
243: $EncryptionData = Get-WmiObject -Namespace ROOT\CIMV2\Security\Microsoftvolumeencryption -Class Win32_encryptablevolume -Filter "DriveLetter = '$DriveLetter'"
244: $protectionState = $EncryptionData.GetConversionStatus()
245: $CurrentEncryptionProgress = $protectionState.EncryptionPercentage
246:
247: switch ($ProtectionState.Conversionstatus) {
248:
249: '0' {
250:
251: $Properties = @{ 'EncryptionState' = 'FullyDecrypted'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }
252: $Return = New-Object psobject -Property $Properties
253:
254: }
255:
256: '1' {
257:
258: $Properties = @{ 'EncryptionState' = 'FullyEncrypted'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }
259: $Return = New-Object psobject -Property $Properties
260:
261: }
262: '2' {
263:
264: $Properties = @{ 'EncryptionState' = 'EncryptionInProgress'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }
265: $Return = New-Object psobject -Property $Properties
266: }
267: '3' {
268:
269: $Properties = @{ 'EncryptionState' = 'DecryptionInProgress'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }
270: $Return = New-Object psobject -Property $Properties
271: }
272: '4' {
273:
274: $Properties = @{ 'EncryptionState' = 'EncryptionPaused'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }
275: $Return = New-Object psobject -Property $Properties
276: }
277: '5' {
278:
279: $Properties = @{ 'EncryptionState' = 'DecryptionPaused'; 'CurrentEncryptionProgress' = $CurrentEncryptionProgress }
280: $Return = New-Object psobject -Property $Properties
281: }
282: default {
283: write-verbose "Couldn't retrieve an encryption state."
284: $Properties = @{ 'EncryptionState' = $false; 'CurrentEncryptionProgress' = $false }
285: $Return = New-Object psobject -Property $Properties
286: }
287: }
288: }
289: 'ResumeEncryption'{
290: write-verbose 'Resuming encryption'
291: $ProtectionState = Get-WmiObject -Namespace ROOT\CIMV2\Security\Microsoftvolumeencryption -Class Win32_encryptablevolume -Filter "DriveLetter = '$DriveLetter'"
292:
293: $Ret = $protectionState.ResumeConversion()
294: $ReturnCode = $ret.ReturnValue
295:
296: switch ($ReturnCode) {
297:
298: ('0') { $Message = 'The Method Resume Conversion was called succesfully.' }
299: ('2150694912') { $message = 'The volume is locked' }
300: default { $message = 'The resume operation failed with an uknowned return code.' }
301: }
302:
303: $Properties = @{ 'ReturnCode' = $ReturnCode; 'ErrorMessage' = $message }
304: $Return = New-Object psobject -Property $Properties
305: } #EndResumeEncryption
306: 'GetProtectionStatus'{
307: #http://msdn.microsoft.com/en-us/library/windows/desktop/aa376448(v=vs.85).aspx
308: $ProtectionState = Get-WmiObject -Namespace ROOT\CIMV2\Security\Microsoftvolumeencryption -Class Win32_encryptablevolume -Filter "DriveLetter = '$DriveLetter'"
309: write-verbose 'Gathering BitLocker protection status infos.'
310:
311: switch ($ProtectionState.GetProtectionStatus().protectionStatus) {
312:
313: ('0') { $return = 'Unprotected' }
314: ('1') { $return = 'Protected' }
315: ('2') { $return = 'Uknowned' }
316: default { $return = 'NoReturn' }
317: } #EndSwitch
318: } #EndGetProtection
319: 'Encrypt'{
320: #http://msdn.microsoft.com/en-us/library/windows/desktop/aa376432(v=vs.85).aspx
321: $ProtectionState = Get-WmiObject -Namespace ROOT\CIMV2\Security\Microsoftvolumeencryption -Class Win32_encryptablevolume -Filter "DriveLetter = '$DriveLetter'"
322: write-verbose 'Launching drive encryption.'
323:
324: $ProtectorKey = $protectionState.ProtectKeyWithTPMAndPIN('ProtectKeyWithTPMAndPin', '', $pin)
325: Start-Sleep -Seconds 3
326: $NumericalPasswordReturn = $protectionState.ProtectKeyWithNumericalPassword()
327:
328: $Return = $protectionState.Encrypt()
329: $returnCode = $return.returnvalue
330: switch ($ReturnCode) {
331:
332: ('0') { $message = 'Operation successfully started.' }
333: ('2147942487') { $message = 'The EncryptionMethod parameter is provided but is not within the known range or does not match the current Group Policy setting.' }
334: ('2150694958') { $message = 'No encryption key exists for the volume' }
335: ('2150694957') { $message = 'The provided encryption method does not match that of the partially or fully encrypted volume.' }
336: ('2150694942') { $message = 'The volume cannot be encrypted because this computer is configured to be part of a server cluster.' }
337: ('2150694956') { $message = 'No key protectors of the type Numerical Password are specified. The Group Policy requires a backup of recovery information to Active Directory Domain Services' }
338: default {
339: $message = 'An unknown status was returned by the Encryption action.'
340:
341: }
342: }
343:
344: $Properties = @{ 'ReturnCode' = $ReturnCode; 'ErrorMessage' = $message }
345: $Return = New-Object psobject -Property $Properties
346: }
347: 'GetKeyProtectorIds'{
348: $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"
349: $return = $BitLocker.GetKeyProtectors('0').VolumeKeyProtectorID
350: }
351: 'GetEncryptionMethod'{
352: $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"
353: $EncryptMethod = $BitLocker.GetEncryptionMethod().encryptionmethod
354: switch ($EncryptMethod) {
355: '0'{ $Return = 'None'; break }
356: '1'{ $Return = 'AES_128_WITH_DIFFUSER'; break }
357: '2'{ $Return = 'AES_256_WITH_DIFFUSER'; break }
358: '3'{ $Return = 'AES_128'; break }
359: '4'{ $Return = 'AES_256'; break }
360: '5'{ $Return = 'HARDWARE_ENCRYPTION'; break }
361: default { $Return = 'UNKNOWN'; break }
362: }
363:
364: }
365: 'GetKeyProtectorTypeAndID'{
366:
367: $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"
368: $ProtectorIds = $BitLocker.GetKeyProtectors('0').volumekeyprotectorID
369:
370: $return = @()
371:
372: foreach ($ProtectorID in $ProtectorIds) {
373:
374: $KeyProtectorType = $BitLocker.GetKeyProtectorType($ProtectorID).KeyProtectorType
375: $keyType = ''
376: switch ($KeyProtectorType) {
377:
378: '0'{ $Keytype = 'Unknown or other protector type'; break }
379: '1'{ $Keytype = 'Trusted Platform Module (TPM)'; break }
380: '2'{ $Keytype = 'External key'; break }
381: '3'{ $Keytype = 'Numerical password'; break }
382: '4'{ $Keytype = 'TPM And PIN'; break }
383: '5'{ $Keytype = 'TPM And Startup Key'; break }
384: '6'{ $Keytype = 'TPM And PIN And Startup Key'; break }
385: '7'{ $Keytype = 'Public Key'; break }
386: '8'{ $Keytype = 'Passphrase'; break }
387: '9'{ $Keytype = 'TPM Certificate'; break }
388: '10'{ $Keytype = 'CryptoAPI Next Generation (CNG) Protector'; break }
389:
390: } #endSwitch
391:
392: $Properties = @{ 'KeyProtectorID' = $ProtectorID; 'KeyProtectorType' = $Keytype }
393: $Return += New-Object -TypeName psobject -Property $Properties
394: } #EndForeach
395:
396: } #EndGetKeyProtectorType
397: 'DeleteKeyProtectors'{
398: $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"
399: $Return = $BitLocker.DeleteKeyProtectors()
400:
401: }
402: 'TakeTPMOwnerShip'{
403: $Tpm.takeOwnership()
404: }
405: 'DeleteKeyProtector'{
406:
407: if ($PSBoundParameters.ContainsKey('ProtectorIDs')) {
408: $Return = @()
409: $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"
410:
411: foreach ($ProtID in $ProtectorIDs) {
412: $Return += $BitLocker.DeleteKeyProtector($ProtID)
413: }
414: } else {
415: write-warning 'Could not delete the key protector. Missing ProtectorID parameter.'
416: $Return = 'Could not delete the key protector. Missing ProtectorID parameter.'
417:
418: }
419: }
420: 'PauseEncryption'{
421: $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"
422: $ReturnCode = $BitLocker.PauseConversion()
423:
424: switch ($ReturnCode.ReturnValue) {
425: '0'{ $Return = 'Paused sucessfully.'; break }
426: '2150694912'{ $Return = 'The volume is locked.'; Break }
427: default { $Return = 'Uknown return code.'; break }
428: }
429: }
430: 'PauseDecryption'{
431: $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"
432: $ReturnCode = $BitLocker.PauseConversion()
433:
434: switch ($ReturnCode.ReturnValue) {
435: '0'{ $Return = 'Paused sucessfully.'; break }
436: '2150694912'{ $Return = 'The volume is locked.'; Break }
437: default { $Return = 'Uknown return code.'; break }
438: }
439: }
440: 'Decrytp'{
441: $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"
442: $ReturnCode = $BitLocker.Decrypt()
443:
444: switch ($ReturnCode.ReturnValue) {
445: '0'{ $Return = 'Uncryption started successfully.'; break }
446: '2150694912'{ $Return = 'The volume is locked.'; Break }
447: '2150694953' { $Return = 'This volume cannot be decrypted because keys used to automatically unlock data volumes are available.'; Break }
448: default { $Return = 'Uknown return code.'; break }
449: }
450:
451: }
452: 'GetKeyProtectorNumericalPassword'{
453: $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"
454: $Return = @()
455:
456:
457: $KeyProtectorReturn = $BitLocker.GetKeyProtectorNumericalPassword($VolumeKeyProtectorID)
458:
459: switch ($KeyProtectorReturn.ReturnValue) {
460: '0' { $msg = 'The method was successful.' }
461: '2150694912' { $msg = 'The volume is locked.'; Break }
462: '2147942487' { $msg = "The VolumeKeyProtectorID parameter does not refer to a key protector of the type 'Numerical Password'."; Break }
463: '2150694920' { $msg = 'BitLocker is not enabled on the volume. Add a key protector to enable BitLocker.'; Break }
464: default { $msg = "Unknown return value: $($KeyProtectorReturn.ReturnValue)" }
465: } #EndSwitch
466:
467: $Properties = @{ 'KeyProtectorNumericalPassword' = $KeyProtectorReturn.NumericalPassword; 'VolumeKeyProtectorID' = $VolumeKeyProtectorID; 'Message' = $msg }
468: $Return += New-Object -TypeName psobject -Property $Properties
469:
470:
471: }
472: } #endSwitch
473:
474:
475: if ($PSBoundParameters.Keys.Count -eq 0) {
476: #Returning info on all drives.
477: write-verbose 'Returning bitlocker main status'
478: $Tpm = Get-WmiObject -Namespace ROOT\CIMV2\Security\MicrosoftTpm -Class Win32_Tpm
479: $BitLocker = Get-WmiObject -Namespace 'Root\cimv2\Security\MicrosoftVolumeEncryption' -Class 'Win32_EncryptableVolume' -Filter "DriveLetter = '$DriveLetter'"
480:
481: #If no TPM module is present
482: if ($tpm) {
483: $TpmActivated = $tpm.IsActivated().isactivated
484: $TPMEnabled = $tpm.IsEnabled().isenabled
485: $TPMOwnerShipAllowed = $Tpm.IsOwnershipAllowed().IsOwnerShipAllowed
486: $TPMOwned = $Tpm.isowned().isowned
487:
488: }
489:
490: $ProtectorIds = $BitLocker.GetKeyProtectors('0').volumekeyprotectorID
491: $CurrentEncryptionState = BitLockerSAK -GetEncryptionState
492: $EncryptionMethod = BitLockerSAK -GetEncryptionMethod
493: $KeyProtectorTypeAndID = BitLockerSAK -GetKeyProtectorTypeAndID
494:
495: $properties = @{
496: 'IsTPMActivated' = $TpmActivated;`
497: 'IsTPMEnabled' = $TPMEnabled;`
498: 'IsTPMOwnerShipAllowed' = $TPMOwnerShipAllowed;`
499: 'IsTPMOwned' = $TPMOwned;`
500: 'CurrentEncryptionPercentage' = $CurrentEncryptionState.CurrentEncryptionProgress;`
501: 'EncryptionState' = $CurrentEncryptionState.encryptionState; `
502: 'EncryptionMethod' = $EncryptionMethod;`
503: 'KeyProtectorTypesAndIDs' = $KeyProtectorTypeAndID
504: }
505:
506: $Return = New-Object psobject -Property $Properties
507: }
508:
509: }
510: End {
511: return $return
512: }
513:
514: }
515:
516: function Get-BiosStatus {
517: param ([String]$Option)
518:
519: #Declare Local Variables
520: Set-Variable -Name Argument -Scope Local -Force
521: Set-Variable -Name CCTK -Value "x:\cctk\cctk.exe" -Scope Local -Force
522: Set-Variable -Name Output -Scope Local -Force
523:
524: $Argument = "--" + $Option
525: $Output = [string] (& $CCTK $Argument)
526: $Output = $Output.Split('=')
527: Return $Output[1]
528:
529: #Cleanup Local Variables
530: Remove-Variable -Name Argument -Scope Local -Force
531: Remove-Variable -Name CCTK -Scope Local -Force
532: Remove-Variable -Name Output -Scope Local -Force
533: }
534:
535: #Declare Local Variables
536: Set-Variable -Name oShell -Scope Local -Force
537: Set-Variable -Name TPMActivated -Scope Local -Force
538: Set-Variable -Name TPMEnabled -Scope Local -Force
539: Set-Variable -Name TPMOwned -Scope Local -Force
540: Set-Variable -Name TPMOwnershipAllowed -Scope Local -Force
541:
542: cls
543:
544: $TPMEnabled = Get-BiosStatus -Option "tpm"
545: Write-Host "TPM Enabled:"$TPMEnabled
546: $TPMActivated = Get-BiosStatus -Option "tpmactivation"
547: Write-Host "TPM Activated:"$TPMActivated
548: $TPMOwnershipAllowed = BitLockerSAK -IsTPMOwnerShipAllowed
549: Write-Host "TPM Ownership Allowed:"$TPMOwnershipAllowed
550: $TPMOwned = BitLockerSAK -IsTPMOwned
551: Write-Host "TPM Owned:"$TPMOwned
552: Write-Host
553: If (($TPMEnabled -eq "on") -and ($TPMActivated -eq "activate") -and ($TPMOwnershipAllowed -eq $true) -and ($TPMOwned -eq $false)) {
554: Write-Host "TPM Ready for Bitlocker"
555: Exit 0
556: } else {
557: Write-Host "TPM Not Ready for Bitlocker"
558: $oShell = New-Object -ComObject Wscript.Shell
559: $oShell.Popup("TPM Not Ready for Bitlocker." + [char]13 + [char]13 + "Turn On, Clear, and Activate TPM, then restart image.", 0, "TPM Failure", 0x0)
560: Exit 1
561: }
562:
563: #Cleanup Local Variables
564: Remove-Variable -Name oShell -Scope Local -Force
565: Remove-Variable -Name TPMActivated -Scope Local -Force
566: Remove-Variable -Name TPMEnabled -Scope Local -Force
567: Remove-Variable -Name TPMOwned -Scope Local -Force
568: Remove-Variable -Name TPMOwnershipAllowed -Scope Local -Force
569:
0 comments:
Post a Comment