Bonus Post – Managing BIOS/UEFI Passwords from Configuration Manager

If you have not yet, give my Managing BIOS/UEFI Settings from Configuration Manager series a quick read as a primer for this post.

When working on the previous UEFI settings series, I ran in to a scenario where a customer had a few different UEFI passwords in their environment. I have seen this scenario before where somewhere along the line it is decided to start using a different password but nobody goes back to change previous systems.

I started with my existing TS.

I then added two additional password variables, treating the initial variable as my desired password. I stuck with three total due to Lenovo locking out after either 3 or 6 depending on model.

I then wrote a short script per manufacturer to check if a password is set, and if one is, cycle through the three passwords to ensure the desired password is set. I added a restart variable to enforce a restart should the password be changed. This puts the new password in to effect and allows me to carry on with the additional settings.

If no password is set, I do not set one. Lenovo prevents an initial password to be set programmatically, you must touch the system. I wanted to keep logic uniform between the three manufacturers, so I followed the same rules for HP and Dell too.

I entered these directly in the TS, no application or package required to house the scripts. Each script step is conditioned to only run on the applicable manufacturer’s systems.

Dell:

$TS = New-Object -ComObject Microsoft.SMS.TSEnvironment
$desiredPW = $TS.Value('UEFIPassword')
$oldpw1 = $TS.Value('oldUEFIPassword1')
$oldpw2 = $TS.Value('oldUEFIPassword2')

$passwords = @()
$passwords += $oldpw1
$passwords += $oldpw2
$passwords += $desiredPW

get-command -module DellBIOSProvider | out-null

if((Get-Item -Path DellSmbios:\Security\IsAdminPasswordSet).currentvalue){
    ForEach($password in $passwords){
        $UEFIError = $NULL
        Set-Item -Path DellSmbios:\Security\AdminPassword $desiredPW -Password $password -ErrorVariable UEFIError
        $password
        if($password -ne $desiredPW -and !($UEFIError)){
            $TS.Value('RESTART1') = 1
            break
        }
        elseif(!($UEFIError)){break}
    }    
}

HP:

$TS = New-Object -ComObject Microsoft.SMS.TSEnvironment
$desiredPW = $TS.Value('UEFIPassword')
$oldpw1 = $TS.Value('oldUEFIPassword1')
$oldpw2 = $TS.Value('oldUEFIPassword2')

$passwords = @()
$passwords += $oldpw1
$passwords += $oldpw2
$passwords += $desiredPW

if((Get-CIMInstance -Namespace root/hp/instrumentedBIOS -ClassName HP_BIOSSettingInterface) -eq 1){
    ForEach($password in $passwords){
        $value = "<utf-16/>" + $desiredPW
        $formattedpassword = "<utf-16/>" + $password
        $return = (Invoke-CimMethod -InputObject (Get-CimInstance -classname HP_BIOSSettingInterface -namespace root/hp/instrumentedBIOS) -MethodName setbiossetting -Arguments @{ Name = $Setting; Value = $value; Password = $formattedpassword }).Return
        if($password -ne $desiredPW -and $return -eq 0){
            TS.Value('RESTART1') = 1
            break
        }
        elseif($return -eq 0){break}
    }
}

Lenovo:

$TS = New-Object -ComObject Microsoft.SMS.TSEnvironment
$desiredPW = $TS.Value('UEFIPassword')
$oldpw1 = $TS.Value('oldUEFIPassword1')
$oldpw2 = $TS.Value('oldUEFIPassword2')

$passwords = @()
$passwords += $oldpw1
$passwords += $oldpw2
$passwords += $desiredPW
$Setting = "Setup Password"

if((Get-CIMInstance -Namespace root\wmi -ClassName Lenovo_BiosPasswordSettings).PasswordState -in @(2,3,6,7)){
    ForEach($password in $passwords){
        $return = (Invoke-CimMethod -InputObject (Get-CimInstance -classname Lenovo_SetBiosPassword -namespace root\wmi) -MethodName SetBiosPassword -Arguments @{ Parameter = "pap,$password,$desiredPW,ascii,us" }).Return
        $password
        $return
        if($password -ne $desiredPW -and $return -eq "SUCCESS"){
            $TS.Value('RESTART1') = 1
            break
        }
        elseif($return -eq "SUCCESS"){break}
    }
}

I added a reboot after the scripts conditioned on the “RESTART1” variable I created. From there on, I could continue to setting the rest of the UEFI settings I wanted to in my application.