HP.Private.psm1
# # Copyright 2018-2021 HP Development Company, L.P. # All Rights Reserved. # # NOTICE: All information contained herein is, and remains the property of HP Development Company, L.P. # # The intellectual and technical concepts contained herein are proprietary to HP Development Company, L.P # and may be covered by U.S. and Foreign Patents, patents in process, and are protected by # trade secret or copyright law. Dissemination of this information or reproduction of this material # is strictly forbidden unless prior written permission is obtained from HP Development Company, L.P. $ErrorActionPreference = 'Stop' Set-StrictMode -Version 5.1 Add-Type -TypeDefinition @' using System; using System.Runtime.InteropServices; using System.Collections.Generic; public struct SureAdminSetting { public string Name; public string Value; public string AuthString; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct arr4k_t { [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = 4096)] public byte[] raw; }; public static class X509Utilities { [DllImport("dfmbios32.dll", EntryPoint = "get_public_key_from_pem", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] public static extern int get_public_key_from_pem32([In] string file, [In,Out] ref arr4k_t modulus, [In,Out] ref UInt32 modulus_size, [In,Out] ref UInt32 exponent); [DllImport("dfmbios64.dll", EntryPoint = "get_public_key_from_pem", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)] public static extern int get_public_key_from_pem64([In] string file, [In,Out] ref arr4k_t modulus, [In,Out] ref UInt32 modulus_size, [In,Out] ref UInt32 exponent); }; '@ function Get-HPPrivateReadINI { [CmdletBinding()] param( [Parameter(Mandatory = $True)] $file, [Parameter(Mandatory = $False)] [int]$maxRetries = 0 ) Write-Verbose "Reading INI style file '$file'" [System.IO.StreamReader]$streamReader = $null $CommentCount = 0 $name = $null $memoryStream = $null $webClient = $null try { if ($file.StartsWith("http://") -or $file.StartsWith("https://") -or $file.StartsWith("file://") -or $file.StartsWith("ftp://")) { Write-Verbose ("Reading network file: $file") $webClient = New-Object System.Net.WebClient if ($file.StartsWith("ftp://")) { $webClient.Credentials = New-Object -Type System.Net.NetworkCredential -ArgumentList "anonymous","anonymous" } else { $webClient.UseDefaultCredentials = $true; } $webClient.Proxy = [System.Net.WebRequest]::GetSystemWebProxy() [int]$retries = $maxRetries do { try { Write-Verbose "Downloading CVA file $file, try $($maxRetries-$retries) / $maxRetries" $data = $webClient.DownloadData($file) $retries = 0 } catch { $retries = $retries - 1 Write-Verbose ("Download failed: $($_.Exception)") if ($retries -le 0) { throw $_ } Start-Sleep 5 } } while ($retries -gt 0) $memoryStream = New-Object System.IO.MemoryStream ($data,[System.Text.Encoding]::Default) $streamReader = New-Object System.IO.StreamReader ($memoryStream) } else { Write-Verbose ("Reading filesystem file: $file") $streamReader = New-Object -TypeName System.IO.StreamReader -ArgumentList $file } $ini = @{} while (($line = $streamReader.ReadLine()) -ne $null) { switch -regex ($line) { "^\[(.+)\]$" { # Section $section = $matches[1] $ini[$section] = @{} $CommentCount = 0 } "^(;.*)$" { # Comment if (!(Test-Path variable:\section)) { $section = "No-Section" $ini[$section] = @{} } $value = $matches[1] $CommentCount = $CommentCount + 1 $name = "Comment" + $CommentCount $ini[$section][$name] = $value } "(.+?)\s*=\s*(.*)" { # Key if (!($section)) { $section = "No-Section" $ini[$section] = @{} } $name,$value = $matches[1..2] if ($ini[$section][$name]) { if ($ini[$section][$name] -is [string]) { $ini[$section][$name] = @($ini[$section][$name]) } $ini[$section][$name] += $value } else { $ini[$section][$name] = $value } continue } "^(?!(.*[=])).*" { # section text block if (!($section)) { $section = "No-Section" $ini[$section] = @{} } if ($ini[$section]["_body"] -eq $null) { $ini[$section]["_body"] = @() } $ini[$section]["_body"] += ($matches.Values | Where-Object { $_.StartsWith("[") -eq $false }) } } } } finally { if ($streamReader) { $streamReader.Close() $streamReader.Dispose() $streamReader = $null } if ($memoryStream) { $memoryStream.Close() $memoryStream.Dispose() $memoryStream = $null } if ($webClient) { $webClient.Dispose() $webClient = $null } } return $ini } # this is what the downloaded filename will be function Get-HPPrivateTemporaryFileName ($filename,[System.IO.DirectoryInfo]$cacheDir = [System.IO.Path]::GetTempPath() + "hp") { $cacheDir = Join-Path -Path $cacheDir -ChildPath $filename $cacheDir.FullName } function GetLockedStreamForWrite { [CmdletBinding()] param([string]$target,[int]$maxRetries = 10) Write-Verbose "Opening exclusive access to file $target with maximum retries of $maxRetries" $lock_wait = $false do { try { $lock_wait = $false $result = New-Object -TypeName System.IO.FileStream -ArgumentList $target,Create,Write,None } catch { Write-Verbose ("******* $($_ | fl)") $lock_wait = $true if ($maxRetries -gt 0) { Start-Sleep -Seconds 30 $maxRetries = $maxRetries - 1 } else { throw "Could not obtain exclusive access to file '$target' and all retries were exhausted." } } } while ($lock_wait -eq $true) $result } # check for collision with other processes function GetSharedFileInformation { [CmdletBinding()] param($file,[string]$mode,[switch]$wait,[int]$maxRetries,[switch]$progress,[switch]$skipSignatureCheck) $return = $true $length = 0 $sig = $false Write-Verbose ("Getting file information for file $file with access rights=$mode, wait = $wait, maxRetries=$maxRetries, skipAuthenticode=$($skipSignatureCheck.IsPresent)") if (-not $wait.IsPresent) { Write-Verbose ("This operation will not be retried.") $maxRetries = 0 } do { # file length try { $length = (Get-ChildItem -File $file -ErrorAction Stop).Length } catch { return (-1,$true,$skipSignatureCheck.IsPresent) } Write-Verbose ("Target file length on disk is $length bytes") try { $fs = [System.IO.File]::Open($file,"Open",$mode) $return = $true $fs.Close() $fs.Dispose() Write-Verbose "Able to read from file '$file', it doesn't seem locked." if ($skipSignatureCheck.IsPresent) { Write-Verbose "Not checking Authenticode signature for file $file" $sig = $true } else { $sig = Get-HPPrivateCheckSignature -File $file -Progress:$progress } break } catch [System.IO.FileNotFoundException]{ return (-1,$true,$skipSignatureCheck.IsPresent) } catch { Write-Verbose "Internal error: $_.Message" $return = $false if ($maxRetries -gt 0) { if ($progress) { Write-Progress -Activity "Blocked by another process, will retry for ($maxRetries) tries" } Write-Verbose ("Sleeping for 30 seconds since someone else has '$file' locked") Start-Sleep -Seconds 30 Write-Verbose ("Woke up") } $maxRetries = $maxRetries - 1 } } while ($maxRetries -gt 0) ($length,$return,$sig) } # download a file function Invoke-HPPrivateDownloadFile { [CmdletBinding()] param ( [string]$url, [string]$target, [bool]$progress, [string]$noclobber, [switch]$panic, [int]$maxRetries = 0, [switch]$skipSignatureCheck ) Write-Verbose ("Requesting to download $url to $target with progress: $progress and signatureCheckSkip: $skipSignatureCheck") [System.Net.ServicePointManager]::SecurityProtocol = Get-HPPrivateAllowedHttpsProtocols $targetStream = $null $responseStream = $null $response = $null try { if (Test-Path $target -PathType Leaf) { # target file exists switch ($noclobber) { "no" { if ($panic.IsPresent) { throw "File $target already exists, will not overwrite." } if ($progress) { Write-Host -ForegroundColor Magenta "File $target already exists, will not overwrite." } return } "yes" { if ($progress -eq $true) { Write-Verbose "Overwriting existing file $target" } } "skip" {} } } else { #create lead directory if needed $lead = Split-Path $target if (!(Test-Path $lead)) { Write-Verbose "Creating directory '$lead'" $tmp = New-Item -ItemType Directory -Force -Path $lead } } $uri = New-Object "System.Uri" "$url" $retries = $maxRetries do { $request = [System.Net.HttpWebRequest]::Create($uri) $request.set_Timeout(60000) if (-not $request -is [System.Net.FtpWebRequest]) { $request.set_UserAgent($LIBRARY_UA); } try { Write-Verbose "Executing query on $uri, try $($maxRetries-$retries) / $maxRetries" $response = $request.GetResponse() $retries = 0 } catch { $retries = $retries - 1 Write-Verbose ("Query failed $($_.Exception)") if ($retries -le 0) { throw } Start-Sleep 5 } } while ($retries -gt 0) $responseContentLength = $response.get_ContentLength() if ($responseContentLength -ge 1024) { $totalLength = [System.Math]::Floor($responseContentLength / 1024) } else { $totalLength = 1 } # Someone else may be downloading this file at this time, so we'll wait until they release the # lock and then we check the size Write-Verbose ("Target file is $target") $r = GetSharedFileInformation -File $target -Mode "Read" -Wait -maxRetries $maxRetries -Progress:$progress -skipSignatureCheck:$skipSignatureCheck if ($noclobber -eq "skip") { if (($r[0] -eq $response.get_ContentLength()) -and ($r[2] -eq $true)) { Write-Verbose "File already exists or another process has finished downloading this file for us." return } else { Write-Verbose ("Existing file $target doesn't seem correct (size=$($r[0]) vs expected $($response.get_ContentLength()), signature_check=$($r[2]), deleting it.") } } $responseStream = $response.GetResponseStream() $targetStream = GetLockedStreamForWrite -maxRetries $maxRetries -Target $target #try { $buffer = New-Object byte[] 10KB $count = $responseStream.Read($buffer,0,$buffer.Length) $downloadedBytes = $count #being too verbose with Write-Progress slows down the process $maxChunks = 20 $chunkSize = $totalLength / $maxChunks while ($chunkSize -gt 1024) { $maxChunks = $maxChunks * 2 $chunkSize = $totalLength / $maxChunks } if ($chunkSize -lt 16384) { $chunkSize = 16384 $maxChunks = 1 } $lastChunk = 0 while ($count -gt 0) { $targetStream.Write($buffer,0,$count) $count = $responseStream.Read($buffer,0,$buffer.Length) $downloadedBytes = $downloadedBytes + $count $thisChunk = [System.Math]::Floor(($downloadedBytes / 100) / $totalLength) if (($progress -eq $true) -and ($thisChunk -gt $lastChunk)) { $lastChunk = $thisChunk Write-Progress -Activity "Downloading file '$($url.split('/') | Select -Last 1)'" -Status "Downloaded ($([System.Math]::Floor($downloadedBytes/1024))K of $($totalLength)K): " -PercentComplete ((([System.Math]::Floor($downloadedBytes / 1024)) / $totalLength) * 100) } } if ($progress -eq $true) { Write-Verbose ("Finished downloading '$($url.split('/') | Select -Last 1)'") Write-Progress -Activity "Finished downloading file '$($url.split('/') | Select -Last 1)'" -Completed } } finally { if ($targetStream) { $targetStream.Flush() $targetStream.Close() $targetStream.Dispose() } if ($responseStream) { $responseStream.Close() $responseStream.Dispose() } if ($response) { $response.Close() } } } # perform an action after a SoftPaq download completed function Invoke-PostDownloadSoftpaqAction { [CmdletBinding()] param([string]$downloadedFile,[string]$action,[string]$number,$info,[string]$Destination) Write-Verbose 'Processing post-download action' $PostDownloadCmd = $null switch ($action) { "extract" { if (!$Destination) { $Destination = (Get-Item $downloadedFile).DirectoryName $Destination = Join-Path -Path $Destination -ChildPath (Get-Item $downloadedFile).BaseName } Write-Verbose -Message "Extracting $downloadedFile to: $Destination" Start-Process -Wait "$downloadedFile" -ArgumentList "-e -f `"$Destination`"","-s" } "install" { #$PostDownloadCmd = descendNodesAndGet $info -field "install" Start-Process -Wait "$downloadedFile" } "silentinstall" { # Get the silent install command from the metadata if (!$info) { $info = Get-SoftpaqMetadata $number } $PostDownloadCmd = $info | Out-SoftpaqField -Field "silentinstall" Start-Process -Wait "$downloadedFile" -ArgumentList "-s","-e cmd.exe","-a","/c $PostDownloadCmd" } } Write-Verbose 'Post-download action processing complete' } function Get-HPPrivateAllowedHttpsProtocols { [CmdletBinding()] param() $c = [System.Net.SecurityProtocolType]([System.Net.SecurityProtocolType].GetEnumNames() | Where-Object { $_ -ne "Ssl3" -and $_ -ne "Tls" -and $_ -ne "Tls11" }) Write-Verbose "Removing obsolete protocols SSL 3.0, TLS 1.0 and TLS 1.1, now supporting: $c" $c } function Get-HPPrivateCacheDirPath { [CmdletBinding()] param([System.IO.DirectoryInfo]$seed) if (-not $seed) { $seed = [System.IO.Path]::GetTempPath() + "hp" } Join-Path -Path $seed -ChildPath "cache" Write-Verbose "Local caching path is: $seed" } # check authenticode signature # check CVA and SoftPaq hash to determine download of the SoftPaq # # tests (remove these comments once we are happy with the function) # # PASS: Get-HPPrivateCheckSignature -file C:\windows\System32\notepad.exe -signedBy "Microsoft Windows" -Verbose # PASS: Get-HPPrivateCheckSignature -file C:\windows\System32\notepad.exe -Verbose # PASS: Get-HPPrivateCheckSignature -file .\sp99062.exe -CVAfile .\sp99062.cva -Verbose # PASS: Get-HPPrivateCheckSignature -file .\sp99062.exe -CVAfile .\sp99062.cva -Verbose -signedBy "HP Inc." function Get-HPPrivateCheckSignature { [CmdletBinding()] param( [Parameter(Position = 0,Mandatory = $true)] [string]$file, [Parameter(Mandatory = $false,Position = 1)] [string]$CVAfile = $null, [Parameter(Mandatory = $false,Position = 2)] [string]$signedBy = $null, [Parameter(Mandatory = $false,Position = 3)] [switch]$Progress ) if ($Progress.IsPresent) { Write-Progress -Activity "Checking integrity of $file" } try { $c = Get-AuthenticodeSignature -FilePath $file if ($c.Status -ne "Valid") { Write-Verbose ("$file is not signed or certificate is invalid.") return $false } if ($signedBy) { $signer = $c.SignerCertificate.Subject.Split(",")[0].trim().Split("=")[1] if ($signer -ne $signedBy) { Write-Verbose ("$file is not signed by $signedBy, it is signed by $signer, failing.") return $false } else { Write-Verbose ("$file is signed by $signedBy.") # return $true } } if ($CVAfile) { Write-Verbose "Verifying '$file' using '$CVAFile'" $targetFile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($file) $targetCVA = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($CVAFile) # Getting hash value of CVA $read_file = Get-HPPrivateReadINI -File $targetCVA $CVA_SHA256 = $read_file | Out-SoftpaqField -Field SoftPaqSHA256 $CVA_MD5 = $read_file | Out-SoftpaqField -Field SoftPaqMD5 Write-Verbose "CVA has MD5 hash '$CVA_MD5' and sha256 hash '$CVA_SHA256'" if ($CVA_SHA256 -and $CVA_SHA256.Length -eq 64) { Write-Verbose 'Checking SHA256 hash' $sha256match = return $CVA_SHA256 -eq (Get-FileHash -Path $targetFile -Algorithm SHA256).Hash Write-Verbose "SHA256 matched: $sha256match" return $sha256match } elseif ($CVA_MD5) { Write-Verbose 'Checking MD5 hash' $md5match = $CVA_MD5 -eq (Get-FileHash -Path $targetFile -Algorithm MD5).Hash Write-Verbose "MD5 matched: $md5match" return $md5match } else { Write-Verbose 'This CVA file has no checksum value' return $false } } # When only file is passed and it has valid signature return $true } catch { Write-Verbose "During signature check, had exception $_.Exception" return $false } finally { if ($Progress.IsPresent) { Write-Progress -Activity "Finished checking integrity of $file" -Completed } } } function Invoke-HPPrivateDeleteCachedItem { [CmdletBinding()] param([Parameter(Mandatory = $true)] $cab) Invoke-HPPrivateSafeRemove -Path $cab Invoke-HPPrivateSafeRemove -Path "$cab.dir" -Recurse } function Invoke-HPPrivateSafeRemove { [CmdletBinding()] param( [Parameter(Mandatory = $true,ValueFromPipelineByPropertyName = $true)] [string[]]$path, [Parameter(Mandatory = $false)] [switch]$recurse ) foreach ($p in $path) { if (Test-Path $p) { Write-Verbose "Removing $p" Remove-Item $p -Recurse:$recurse } } } function Invoke-HPPrivateExpandCAB { [CmdletBinding()] param( [Parameter(Mandatory = $true)] $cab, [Parameter(Mandatory = $true)] $expectedFile ) Write-Verbose "Expanding CAB $cab to $cab.dir" $target = "$cab.dir" Invoke-HPPrivateSafeRemove -Path $target -Recurse Write-Verbose "Expanding $cab to $target" $result = New-Item -Force $target -ItemType Directory Write-Verbose "Created folder $result" $shell = New-Object -ComObject "Shell.Application" try { if (!$?) { $(throw "unable to create $comObject object") } $sourceCab = $shell.Namespace($cab).items() $DestinationFolder = $shell.Namespace($target) $DestinationFolder.CopyHere($sourceCab) } finally { [System.Runtime.InteropServices.Marshal]::ReleaseComObject([System.__ComObject]$shell) | Out-Null [System.GC]::Collect() [System.GC]::WaitForPendingFinalizers() } $downloadedOk = Test-Path $expectedFile if ($downloadedOk -eq $false) { throw "Invalid cab file, did not find $expectedFile in contents" } return $expectedFile } # check if a download is needed, based on file existence and the remote last-modified time function Test-HPPrivateIsDownloadNeeded { [CmdletBinding()] param([Parameter(Mandatory = $true)] $url,[Parameter(Mandatory = $true)] $file) Write-Verbose "Checking if we need a new copy of $file" # $c = [System.Net.ServicePointManager]::SecurityProtocol # Write-Verbose ("Allowed HTTPS protocols: $c") [System.Net.ServicePointManager]::SecurityProtocol = Get-HPPrivateAllowedHttpsProtocols # need to validate if $header can be generated, in other words if $url is legitimate try { $headers = (Invoke-WebRequest -Uri $url -Method HEAD -UseBasicParsing).Headers [datetime]$offered = [string]$headers["Last-Modified"] Write-Verbose "File on server has timestamp $offered" } catch { Write-Verbose "data file not found on $url" throw } $exists = Test-Path -Path $file -PathType leaf if ($exists -eq $false) { Write-Verbose "Cached file $file does not exist, will need to download new file" $offered $true } else { [datetime]$have = (Get-Item $file).CreationTime $r = ($have -lt $offered) Write-Verbose "Cached file exist and it has timestamp $offered. Need to download: $r" $offered $r } } # check if the downloaded xml file is corrupted. function Test-HPPrivateIsValidXmlFile { [CmdletBinding()] param( [Parameter(Mandatory = $true)] $file ) if (-not (Test-Path -Path $file)) { Write-Verbose "File $file does not exist." return $false } # Check for Load or Parse errors when loading the XML file. $xml = New-Object System.Xml.XmlDocument try { $xml.Load($file) return $true } catch [System.Xml.XmlException]{ Write-Verbose "Invalid Xml file $file" return $false } } function Get-HPPrivateUserAgent () { "hpcmsl ($($MyInvocation.MyCommand.Module.Name); $($MyInvocation.MyCommand.Module.Version))" } # calculates CurrentOSVer function GetCurrentOSVer { [CmdletBinding()] param() try { $result = [string](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name DisplayVersion | Select-Object DisplayVersion).DisplayVersion if ($result -match '[0-9]{2}[hH][0-9]') { $bits = $result.substring(0,2) if ($bits -ge 21) { # for DisplayVersion >= 21XX, use the DisplayVersion as OSVer # convert OSVer to lower since the reference files have "21h1" in file name return $result.ToLower() } } } catch { Write-Verbose "Display Version not found. Fallback to ReleaseId." } # If DisplayVersion isn't found or DisplayVersion < 21XX, use ReleaseId instead $result = [string](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion' -Name ReleaseID | Select-Object ReleaseID).ReleaseId return $result } function validateWmiResult { [CmdletBinding()] param([int]$code,[int]$category = 0xff) Write-Verbose "Validating error code $code for facility $category" switch ($code) { 0 {} 0xea {} 6 { throw [NotSupportedException]"Operation could not be completed. Please ensure this is a supported HP system." } 5 { throw [ArgumentException]"Method called with invalid parameters." } 4 { throw [UnauthorizedAccessException]"The caller does not have permissions to perform this operation." } default { validateWmiResultInCategory -Category $category -code $code } } } function validateWmiResultInCategory { [CmdletBinding()] param([int]$category,[int]$code) switch ($category) { 1 { switch ($code) { 0x40 { throw [NotSupportedException]"This system does not support firmware logs." } 0x41 { throw [System.TimeoutException]"Call has timed out." } default { throw [SystemException]"An unknown error $code has occured." } } } 2 { switch ($code) { 0x0b { throw [UnauthorizedAccessException]"The caller does not have permissions to perform this operation." } 0x0e { throw [UnauthorizedAccessException]"The operation could not be completed, possibly due to a bios password mismatch?" } 0x0010 { throw [SystemException]"Invalid flash offset." } 0x0012 { throw [SystemException]"Invalid flash checksum" } 0x0013 { throw [InvalidOperationException]"Flash-in-progress error" } 0x0014 { throw [InvalidOperationException]"Flash-in-progress not set" } default { throw [SystemException]"An unknown error $code has occured." } } } 3 { switch ($code) { # this facility doesn't define specific codes default { throw [SystemException]"An unknown error $code has occured." } } } 4 { switch ($code) { 0x0b { throw [UnauthorizedAccessException]"The caller does not have permissions to perform this operation." } 0x03 { throw [NotSupportedException]"This system does not support HP Secure Platform or a hardware option is missing." } 0x1c { throw [SystemException]"The request was not accepted by the BIOS." } 0x1000 { throw [SystemException]"HP Secure Platform is not provisioned." } 0x1001 { throw [SystemException]"HP Secure Platform is already provisioned." } 0x1002 { throw [SystemException]"HP Secure Platform is in use. Deprovision all features that use the HP Secure Platform first." } default { throw [SystemException]"An unknown error $code has occured." } } } default { throw [SystemException]"An unknown error $code has occured." } } } function Test-HPPrivateCustomResult { [CmdletBinding()] param([int]$result,[int]$mi_result,[int]$category) Write-Verbose ("Checking result={0:x8}, mi_result={1:x8}, category={2:x4}" -f $result,$mi_result,$category) switch ($result) { 0 { Write-Verbose ("Operation succeeded.") } 0x80000711 { validateWmiResult -code $mi_result -Category $category } # E_DFM_FAILED_WITH_EXTENDED_ERROR 0x80000710 { throw [NotSupportedException]"Current platform does not support this operation." } # E_DFM_FEATURE_NOT_SUPPORTED 0x8000070b { throw [System.IO.IOException]"Firmware file could not be read." } # E_DFM_FILE_ACCESS_FAILURE 0x8000070e { throw [InvalidOperationException]"Firmware file is too long for expected flash type." } # E_DFM_FLASH_BUR_INPUT_DATA_TOO_LARGE 0x80000712 { throw [InvalidOperationException]"The firmware does not mach the target platform." } # E_DFM_WRONG_FLASH_FILE 0x80000714 { throw [OutOfMemoryException]"A memory allocation failed. The system may be out of memory." } # E_DFM_ALLOC_FAILED 0x80000715 { throw [InvalidOperationException]"Password length is not valid." } # E_DFM_PASSWORD_SIZE_INVALID 0x8000071a { throw [System.ArgumentException]"Invalid parameter for HP Sure View API" } 1392 { throw [System.IO.IOException]"Could not copy the file to the system partition." } # ERROR_FILE_CORRUPT 234 { Write-Verbose ("Operation succeeded.") } # MORE_DATA default { throw [ComponentModel.Win32Exception]$result } } } function Convert-HPPrivateObjectToBytes { [CmdletBinding()] param($obj) $mem = $null $length = 0 $bytes = $() Write-Verbose "Converting object of type $($obj.Gettype()) to byte array" try { $length = [System.Runtime.InteropServices.Marshal]::SizeOf($obj) $bytes = New-Object byte[] $length Write-Verbose "Converting object of type $($obj.Gettype()) is $length bytes" $mem = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($length) [System.Runtime.InteropServices.Marshal]::StructureToPtr($obj,$mem,$true) [System.Runtime.InteropServices.Marshal]::Copy($mem,$bytes,0,$length) ($bytes,$length) } finally { # Free the memory we allocated for the struct value if ($mem) { Write-Verbose "Freeing allocated memory" [System.Runtime.InteropServices.Marshal]::FreeHGlobal($mem) } } Write-Verbose "Conversion complete." } #region Cryptography function Get-HPPrivatePublicKeyCoalesce { [CmdletBinding()] param( [System.IO.FileInfo]$file, [psobject]$key ) if ($file) { $efile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($file) Write-Verbose "Coalescing to FILE PEM $efile" $modulus = New-Object arr4k_t $modulus_size = 4096 $exponent = 0 $mi_result = 0 $c = '[X509Utilities]::get_public_key_from_pem' + (Test-OSBitness) + '($efile,[ref]$modulus, [ref]$modulus_size, [ref]$exponent);' $result = Invoke-Expression -Command $c Test-HPPrivateCustomResult -result $result -mi_result $mi_result -Category 0x04 New-Object -TypeName PSObject -Property @{ Modulus = $modulus.raw[0..($modulus_size - 1)] Exponent = $exponent } } else { Write-Verbose "Coalescing to binary PEM" $key } } function Get-HPPrivateX509CertCoalesce { [CmdletBinding()] param( [System.IO.FileInfo]$file, [System.Security.Cryptography.X509Certificates.X509Certificate2]$cert, [string]$password ) $param = @{} if ($password) { $param.Add("Password",(ConvertTo-SecureString -AsPlainText -Force $password)) } if ($file) { $efile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($file) Write-Verbose "Coalescing to FILE certificate $efile" $param.Add("FileName",$efile) Get-HPPrivatePublicKeyCertificateFromPFX @param -Verbose:$VerbosePreference } else { Write-Verbose "Coalescing to binary certificate" $key = $cert.PublicKey.key $parameters = $key.ExportParameters($false); $mod_reversed = $parameters.Modulus [array]::Reverse($mod_reversed) New-Object -TypeName PSObject -Property @{ Full = $Cert Certificate = $cert.Export('Cert') Modulus = $mod_reversed Exponent = $parameters.Exponent } } } # get the PK from a PFX file function Get-HPPrivatePublicKeyCertificateFromPFX { [CmdletBinding(DefaultParameterSetName = "FF")] param( [Parameter(Mandatory = $true,Position = 0)] [string]$FileName, [Parameter(Mandatory = $false,Position = 1)] [securestring]$Password ) $certfile = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($FileName) if (-not (Test-Path -PathType leaf -Path $certfile)) { throw [System.IO.FileNotFoundException]"Certificate file '$certfile' could not be found" } Write-Verbose "Extracting public key from '$certfile'." try { $cert = New-Object -TypeName System.Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList ($certfile,$Password,'Exportable') $key = $cert.PublicKey.Key $parameters = $key.ExportParameters($false); $mod_reversed = $parameters.Modulus [array]::Reverse($mod_reversed) New-Object -TypeName PSObject -Property @{ Full = $cert Certificate = $cert.Export('Cert') Modulus = $mod_reversed Exponent = $parameters.Exponent } } finally { #$cert.Dispose(); #$cert = $null } } # sign a byte array with a certificate provided in $Filename function Invoke-HPPrivateSignData { [CmdletBinding()] param( [System.Security.Cryptography.X509Certificates.X509Certificate2]$Certificate, [byte[]]$Data ) $privKey = $Certificate.PrivateKey if ($null -eq $privKey) { Write-Error "Please provide an exportable key in the PFX file" } $params = $privKey.ExportParameters($true) $cspParams = New-Object System.Security.Cryptography.CspParameters (24,"Microsoft Enhanced RSA and AES Cryptographic Provider") $enhancedSignCsp = New-Object System.Security.Cryptography.RSACryptoServiceProvider ($cspParams) $enhancedSignCsp.ImportParameters($params) $result = $enhancedSignCsp.SignData($Data,[System.Security.Cryptography.HashAlgorithmName]::SHA256,[System.Security.Cryptography.RSASignaturePadding]::Pkcs1) [array]::Reverse($result) return $result } function Get-HPPrivateHash { [CmdletBinding()] param( [Parameter(Mandatory = $true,Position = 0)] [byte[]]$data, [Parameter(Mandatory = $false,Position = 1)] [string]$algo = "SHA256" ) $cp = [System.Security.Cryptography.HashAlgorithm]::Create($algo) try { $result = $cp.ComputeHash($data) } finally { $cp.Dispose() } $result } #endregion # Downloads files for when OfflineCacheMode is Enable # If -platform is present : Downloads Advisory Data Files (XXXX_cds.cab) where XXXX is platform ID. # also downloads the platform List function Get-HPPrivateOfflineCacheFiles { [CmdletBinding()] param( [string]$url, [string]$filename, [System.IO.DirectoryInfo]$cacheDirOffline = [System.IO.Path]::GetTempPath() + "hp", [switch]$expand ) $file = Get-HPPrivateTemporaryFileName -FileName $filename -cacheDir $cacheDirOffline $filename = $filename.Replace("cab","xml") $downloadedFile = "$file.dir\$filename" Write-Verbose "Checking if $url is available locally." try { $result = Test-HPPrivateIsDownloadNeeded -url $url -File $file -Verbose:$VerbosePreference } catch { throw [System.Net.WebException]"Could not find a data file for this platform." } if ($result[1] -eq $true) { Write-Verbose "$url is not local, or is out of date, will download." Write-Verbose "Cleaning cached data and downloading the data file." Invoke-HPPrivateDeleteCachedItem -cab $file Invoke-HPPrivateDownloadFile -url $url -Target $file -Verbose:$VerbosePreference (Get-Item $file).CreationTime = ($result[0]) (Get-Item $file).LastWriteTime = ($result[0]) } if ($expand.IsPresent) { # Need to make sure that the expanded data file exists and is not corrupted. # Otherwise, expand the cab file. if (-not (Test-Path $downloadedFile) -or (-not (Test-HPPrivateIsValidXmlFile -File $downloadedFile))) { Write-Verbose "Extracting the data file, looking for $downloadedFile." $file = Invoke-HPPrivateExpandCAB -cab $file -expectedFile $downloadedFile } } return $downloadedFile } # build URL for a remote item function Get-HPPrivateItemUrl ( [CmdletBinding()] [int]$Number, [string]$Ext, [string]$Url) { if ($url) { return "$url/sp$number.$ext" } [string]$baseNumber = $number.ToString() [int]$last3Value = [int]($baseNumber.substring($baseNumber.Length - 3)) [int]$blockStart = [int]($baseNumber.substring(0,$baseNumber.Length - 3)) [string]$block = "" [int]$blockEnd = $blockStart if ($last3Value -gt 500) { $blockEnd += 1 $block = "$($blockStart)501-$($blockEnd)000" } else { if ($last3Value -eq 0) { $blockStart -= 1 $block = "$($blockStart)501-$($blockEnd)000" } else { $block = "$($blockStart)001-$($blockStart)500" } } return "https://ftp.hp.com/pub/softpaq/sp$block/sp$number.$ext" } function biosErrorCodesToString ($code) { switch ($code) { 0 { return "OK" } 1 { return "Not Supported" } 2 { return "Unspecified error" } 3 { return "Operation timed out" } 4 { return "Operation failed or setting name is invalid" } 5 { return "Invalid parameter" } 6 { return "Access denied or incorrect password" } 7 { return "Bios user already exists" } 8 { return "Bios user not present" } 9 { return "Bios user name too long" } 10 { return "Password policy not met" } 11 { return "Invalid keyboard layout" } 12 { return "Too many users" } 32768 { return "Security or password policy not met" } default { return "Unknown error: $code" } } } function getBiosSettingInterface { [CmdletBinding(DefaultParameterSetName = 'nNwSession')] param( [Parameter(ParameterSetName = 'NewSession',Position = 0,Mandatory = $false)] [string]$Target = ".", [Parameter(ParameterSetName = 'ReuseSession',Position = 1,Mandatory = $true)] [CimSession]$CimSession ) $defaultAction = $ErrorActionPreference $ns = getNamespace $ErrorActionPreference = "Stop"; try { Write-Verbose "Getting BIOS interface from '$target' for namespace '$ns'" $params = @{ Namespace = $ns Class = "HPBIOS_BIOSSettingInterface" } if ($CimSession) { $params.Add("CimSession",$CimSession) } if ($Target -and ($target -ne ".") -and -not $CimSession) { $params.Add("ComputerName",$Target) } $result = Get-CimInstance @params -ErrorAction stop if (-not $result) { throw [System.EntryPointNotFoundException]"Setting interface not found" } } catch { Write-Error "Method failed: $($_.Exception.Message)" -ErrorAction stop } finally { $ErrorActionPreference = $defaultAction } $result } function getNamespace { [CmdletBinding()] param() [string]$c = [environment]::GetEnvironmentVariable("HP_BIOS_NAMESPACE","User") if (-not $c) { return "root\HP\InstrumentedBIOS" } Write-Verbose ("Default BIOS namespace is overwritten via HP_BIOS_NAMESPACE Variable, to $c. This should only happen during development.") return $c } function Get-HPPrivateFileContent { [CmdletBinding()] param([System.IO.FileInfo]$File) $f = $ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($File) [string]$content = Get-Content -Raw -Path $f -ErrorAction Stop return $content } function Get-HPPrivateSettingsFromPayload { [CmdletBinding()] param([string]$Content) $payload = $Content | ConvertFrom-Json if ($payload.purpose -ne "hp:sureadmin:biossettingslist") { throw "The payload should be generated by New-HPSureAdminBIOSSettingValuePayload function" } $data = [System.Text.Encoding]::UTF8.GetString($payload.Data) $settingsList = (Get-HPPrivateSettingsFromJson $data) return $settingsList } function Get-HPPrivateSettingsFromPayloadFile { [CmdletBinding()] param([System.IO.FileInfo]$File) $content = Get-HPPrivateFileContent $File return Get-HPPrivateSettingsFromPayload $content } function Get-HPPrivateSettingsFromJsonFile { [CmdletBinding()] param([System.IO.FileInfo]$File) [string]$content = Get-HPPrivateFileContent $File return (Get-HPPrivateSettingsFromJson $content) } function Get-HPPrivateSettingsFromJson { [CmdletBinding()] param([string]$Content) $list = $Content | ConvertFrom-Json $settingsList = New-Object System.Collections.Generic.List[SureAdminSetting] foreach ($item in $list) { $setting = New-Object -TypeName SureAdminSetting $setting.Name = $item.Name $setting.Value = $item.Value if ("AuthString" -in $item.PSObject.Properties.Name) { $setting.AuthString = $item.AuthString } $settingsList.Add($setting) } return $settingsList } function Get-HPPrivateSettingsFromBcuFile { [CmdletBinding()] param([System.IO.FileInfo]$File) $list = [ordered]@{} $auth = @{} $currset = "" Write-Verbose "Reading from file: $File" switch -regex -File $File { '^;Signature=<BEAM/>.*' { # keeping compatibility with BCU tool $c = $matches[0].trim() $auth[$currset] = $c.substring(11) } '^;AuthString=<BEAM/>.*' { $c = $matches[0].trim() $auth[$currset] = $c.substring(12) } '^\S.*$' { $currset = $matches[0].trim() if ($currset -ne "BIOSConfig 1.0" -and -not $currset.StartsWith(";")) { $list[$currset] = New-Object System.Collections.Generic.List[System.String] } } '^\s.*$' { # value (indented) $c = $matches[0].trim() $list[$currset].Add($c) } } $settingsList = New-Object System.Collections.Generic.List[SureAdminSetting] foreach ($s in $list.keys) { $setting = New-Object -TypeName SureAdminSetting $setting.Name = $s $setting.Value = Get-HPPrivateDesiredValue -Value $list[$s] if ($auth.ContainsKey($s)) { $setting.AuthString = $auth[$s] } $settingsList.Add($setting) } return $settingsList } function Get-HPPrivateDesiredValue { [CmdletBinding()] param($Value) $desired = $null $list = $Value -split ',' foreach ($v in $list) { if ($v.StartsWith("*")) { # enum $desired = $v.substring(1) break } } if (-not $desired) { # not an enum if ($list.Count -eq 1) { $desired = $list # a string or int } else { $desired = $list -join ',' # an ordered list } } return $desired } function Get-HPPrivateSettingsFromCsvFile { [CmdletBinding()] param([System.IO.FileInfo]$File) Write-Verbose "Reading CSV" $content = Get-HPPrivateFileContent $File $items = $content | ConvertFrom-Csv $settingsList = New-Object System.Collections.Generic.List[SureAdminSetting] foreach ($item in $items) { $setting = New-Object -TypeName SureAdminSetting $setting.Name = $item.Name $setting.Value = (Get-HPPrivateDesiredValue $item.CURRENT_VALUE) if ("AUTHSTRING" -in $item.PSObject.Properties.Name) { $setting.AuthString = $item.AuthString } $settingsList.Add($setting) } return $settingsList } function Get-HPPrivateSettingsFromXmlFile { [CmdletBinding()] param([System.IO.FileInfo]$File) Write-Verbose "Reading XML" $content = Get-HPPrivateFileContent $File try { $entries = ([xml]$content).ImagePal.BIOSSettings.BIOSSetting $settingsList = New-Object System.Collections.Generic.List[SureAdminSetting] foreach ($item in $entries) { $setting = New-Object -TypeName SureAdminSetting $setting.Name = $item.Name $setting.Value = $item.Value if ("AuthString" -in $item.PSObject.Properties.Name) { # The XML parser adds an unwanted space in the tag BEAM $setting.AuthString = $item.AuthString.InnerXml -replace "<BEAM />","<BEAM/>" } $settingsList.Add($setting) } } catch [System.Management.Automation.PropertyNotFoundException]{ throw [System.FormatException]'Invalid XML file.' } return $settingsList } function Get-HPPrivateSettingsFromFile { [CmdletBinding()] param( [System.IO.FileInfo]$FileName, [string]$Format ) [System.Collections.Generic.List[SureAdminSetting]]$settingsList = $null switch ($Format) { { $_ -eq 'csv' } { $settingsList = Get-HPPrivateSettingsFromCsvFile $FileName } { $_ -eq 'xml' } { $settingsList = Get-HPPrivateSettingsFromXmlFile $FileName } { $_ -eq 'json' } { $settingsList = Get-HPPrivateSettingsFromJsonFile $FileName } { $_ -eq 'bcu' } { $settingsList = Get-HPPrivateSettingsFromBcuFile $FileName } { $_ -eq 'payload' } { $settingsList = Get-HPPrivateSettingsFromPayloadFile $FileName } default { throw [System.FormatException]"Format specifier not provided, and could not determine format from file extension" } } return $settingsList } function Invoke-HPPrivateSetSetting { [CmdletBinding(DefaultParameterSetName = 'NewSession')] param( [Parameter(ParameterSetName = 'NewSession',Position = 0,Mandatory = $true)] [Parameter(ParameterSetName = 'ReuseSession',Position = 0,Mandatory = $true)] [SureAdminSetting]$Setting, [Parameter(ParameterSetName = 'NewSession',Position = 1,Mandatory = $false)] [Parameter(ParameterSetName = 'ReuseSession',Position = 1,Mandatory = $false)] [string]$Password, [Parameter(ParameterSetName = 'NewSession',Position = 2,Mandatory = $false)] [Parameter(ParameterSetName = 'ReuseSession',Position = 2,Mandatory = $false)] $ErrorHandling = 0, [Parameter(ParameterSetName = 'NewSession',Position = 3,Mandatory = $false)] [Parameter(ParameterSetName = 'ReuseSession',Position = 3,Mandatory = $false)] [Alias('Target')] [string]$ComputerName = ".", [Parameter(ParameterSetName = 'ReuseSession',Position = 4,Mandatory = $true)] [CimSession]$CimSession, [Parameter(ParameterSetName = 'NewSession',Position = 5,Mandatory = $false)] [Parameter(ParameterSetName = 'ReuseSession',Position = 5,Mandatory = $false)] [ref]$SingleSettingFailCounter ) $readOnly = 0 $notFound = 0 $alreadySet = 0 $localCounter = 0 $s = $null if (-not $CimSession) { $CimSession = newCimSession -Target $ComputerName } try { $s = Get-HPBIOSSetting -Name $Setting.Name -CimSession $CimSession -ErrorAction stop } catch { $notFound = 1 $SingleSettingFailCounter.Value = 0 #matching BCU, even if setting not found exit with 0 $err = $PSItem.ToString() Write-Verbose "'$Setting.Name': $err" switch ($ErrorHandling) { 0 { throw $err } 1 { Write-Warning -Message "$err" } 2 { Write-Verbose "Setting '$Setting.Name' could not be set, but ErrorHandling was set to 2 so error is quietly ignored" } } return $readOnly,$notFound,$alreadySet,$SingleSettingFailCounter.Value } if ($s) { switch ($s.CimClass.CimClassName) { "HPBIOS_BIOSEnumeration" { if ($s.CurrentValue -eq $Setting.Value) { $alreadySet = 1 Write-Host "Setting $($Setting.Name) is already set to $($Setting.Value)" } } default { if ($s.Value -eq $Setting.Value) { $alreadySet = 1 Write-Host "Setting $($Setting.Name) is already set to $($Setting.Value)" } } } if ($alreadySet -eq $false) { if ($s.IsReadOnly -eq 1) { $readOnly = 1 } else { if ($ErrorHandling -ne 1) { Set-HPPrivateBIOSSetting -Setting $setting -password $Password -CimSession $CimSession -SkipPrecheck $true -ErrorHandling $ErrorHandling -actualSetFailCounter ([ref]$localCounter) -Verbose:$VerbosePreference $SingleSettingFailCounter.Value = $localCounter } else { try { Set-HPPrivateBIOSSetting -Setting $setting -password $Password -CimSession $CimSession -SkipPrecheck $true -ErrorHandling $ErrorHandling -actualSetFailCounter ([ref]$localCounter) -Verbose:$VerbosePreference } catch { $SingleSettingFailCounter.Value = $localCounter $err = $PSItem.ToString() } } } } } return $readOnly,$notFound,$alreadySet,$SingleSettingFailCounter.Value } function Get-HPPrivateUseAuthString { [CmdletBinding()] param( [string]$SettingName ) if ((Get-HPPrivateIsSureAdminEnabled) -eq $true -or $SettingName -eq "Enhanced BIOS Authentication Mode") { return $true } return $false } function Set-HPPrivateBIOSSetting { [CmdletBinding()] param( $Setting, [string]$ComputerName = ".", [CimSession]$CimSession, [switch]$SkipPrecheck, [AllowEmptyString()] [string]$Password, $ErrorHandling, [Parameter(Mandatory = $false)] [ref]$actualSetFailCounter ) $localCounterForSet = 0 if ($CimSession -eq $null) { $CimSession = newCimSession -Target $ComputerName } $Name = $Setting.Name $Value = $Setting.Value if ($Setting.AuthString -and (Get-HPPrivateUseAuthString -SettingName $Name) -eq $true) { $authorization = $Setting.AuthString Write-Verbose "Using authorization string" } else { $authorization = "<utf-16/>" + $Password Write-Verbose "Using BIOS Setup password" } if ($SkipPrecheck.IsPresent) { Write-Verbose "Skipping pre-check" if ($Name -eq "Setup Password" -or $Name -eq "Power-On Password") { $type = 'HPBIOS_BIOSPassword' } else { $type = 'HPBIOS_Setting' } } else { $obj = Get-HPBIOSSetting -Name $name -CimSession $CimSession -ErrorAction stop $type = $obj.CimClass.CimClassName } $c = getBiosSettingInterface -CimSession $CimSession switch ($type) { { $_ -eq 'HPBIOS_BIOSPassword' } { Write-Verbose "Setting Password setting '$Name' on '$ComputerName'" $Arguments = @{ Name = $Name Value = "<utf-16/>" + [string]$Value Password = $authorization } $r = Invoke-CimMethod -InputObject $c -MethodName SetBiosSetting -Arguments $Arguments } default { Write-Verbose "Setting HP BIOS Setting '$Name' to value '$Value' on '$ComputerName'" $Arguments = @{ Name = $Name Value = [string]$Value Password = $authorization; } $r = Invoke-CimMethod -InputObject $c -MethodName SetBiosSetting -Arguments $Arguments } } if ($r.Return -eq 0) { $message = "HP BIOS Setting $Name successfully set" if ($Name -ne "Setup Password" -and $Name -ne "Power-On Password") { $message += " to $Value" } Write-Host -ForegroundColor Green $message } if ($r.Return -ne 0) { $localCounterForSet++ if ($r.Return -eq 5) { Write-Host -ForegroundColor Magenta "Operation failed. Please make sure that you are passing a valid value." Write-Host -ForegroundColor Magenta "Some variable names or values may be case sensitive." } $Err = "$(biosErrorCodesToString($r.Return))" if ($ErrorHandling -eq 1) { Write-Host -ForegroundColor Red "$($setting.Name) failed to set due to $Err" $actualSetFailCounter.Value = $localCounterForSet } throw $Err } } function Get-HPPrivateIsSureAdminEnabled { [CmdletBinding()] param() [boolean]$status = $false if ((Get-HPPrivateIsSureAdminSupported) -eq $true) { try { $mode = (Get-HPBIOSSettingValue -Name "Enhanced BIOS Authentication Mode") if ($mode -eq "Enable") { $status = $true } } catch {} } return $status } function Get-HPPrivateIsSureAdminSupported { [CmdletBinding()] param() [boolean]$status = $false try { $mode = (Get-HPBIOSSettingValue -Name "Enhanced BIOS Authentication Mode") $status = $true } catch {} return $status } function newCimSession () { [CmdletBinding()] param ( [Parameter(Position = 0)] $SkipTestConnection = $true, [Parameter(Position = 1)] $Protocol = 'DCOM', [Parameter(Position = 2)] $target = '.', [Parameter(Position = 3)] $SessionName = 'CMSLCimSession' ) Write-Verbose "Creating new CimSession (Protocol= $Protocol, Computer=$Target)" $opts = New-CimSessionOption -Protocol $Protocol $params = @{ Name = $SessionName SkipTestConnection = $SkipTestConnection SessionOption = $opts } if ($Target -and ($Target -ne ".")) { $params.Add("ComputerName",$target) } New-CimSession @params } function Set-HPPrivateBIOSSettingsList { [CmdletBinding()] param( [System.Collections.Generic.List[SureAdminSetting]]$settingsList, [string]$Password, [string]$ComputerName = ".", $ErrorHandling = 2, [CimSession]$CimSession, [switch]$NoSummary ) $failedToSet = 0 if (-not $CimSession) { $CimSession = newCimSession -Target $ComputerName } $counter = @(0,0,0,0,0) foreach ($setting in $SettingsList) { $counter[0]++ $refParameter = 0 $params = @{ Setting = $setting ErrorHandling = $ErrorHandling CimSession = $CimSession Password = $Password SingleSettingFailCounter = [ref]$refParameter } $c = Invoke-HPPrivateSetSetting @params -Verbose:$VerbosePreference $failedToSet += $refParameter $counter[1] += $c[0] $counter[2] += $c[1] $counter[3] += $c[2] } if ($counter -and (-not $NoSummary.IsPresent)) { $summary = "Total: $($counter[0]), not found: $($counter[2]), different but read-only: $($counter[1]), already set: $($counter[3])" Write-Output $summary } if ($ErrorHandling -eq 1) { if ($failedToSet -eq 0) { return 0 } else { return 13 } } } function Set-HPPrivateBIOSSettingsListPayload { [CmdletBinding()] param( [Parameter(ParameterSetName = 'Payload',Position = 0,Mandatory = $true,ValueFromPipeline = $true)] [string]$Payload, $ErrorHandling = 2 ) [System.Collections.Generic.List[SureAdminSetting]]$settingsList = Get-HPPrivateSettingsFromPayload -Content $Payload $params = @{ SettingsList = $settingsList ErrorHandling = $ErrorHandling } Set-HPPrivateBIOSSettingsList @params -Verbose:$VerbosePreference } # SIG # Begin signature block # MIIaygYJKoZIhvcNAQcCoIIauzCCGrcCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAIAVV5HEqdNbsK # y2TALaGrfLBvnJSnig7L+i8A6/8cm6CCCm8wggUwMIIEGKADAgECAhAECRgbX9W7 # ZnVTQ7VvlVAIMA0GCSqGSIb3DQEBCwUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK # EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV # BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0xMzEwMjIxMjAwMDBa # Fw0yODEwMjIxMjAwMDBaMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy # dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lD # ZXJ0IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3 # DQEBAQUAA4IBDwAwggEKAoIBAQD407Mcfw4Rr2d3B9MLMUkZz9D7RZmxOttE9X/l # qJ3bMtdx6nadBS63j/qSQ8Cl+YnUNxnXtqrwnIal2CWsDnkoOn7p0WfTxvspJ8fT # eyOU5JEjlpB3gvmhhCNmElQzUHSxKCa7JGnCwlLyFGeKiUXULaGj6YgsIJWuHEqH # CN8M9eJNYBi+qsSyrnAxZjNxPqxwoqvOf+l8y5Kh5TsxHM/q8grkV7tKtel05iv+ # bMt+dDk2DZDv5LVOpKnqagqrhPOsZ061xPeM0SAlI+sIZD5SlsHyDxL0xY4PwaLo # LFH3c7y9hbFig3NBggfkOItqcyDQD2RzPJ6fpjOp/RnfJZPRAgMBAAGjggHNMIIB # yTASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBhjATBgNVHSUEDDAK # BggrBgEFBQcDAzB5BggrBgEFBQcBAQRtMGswJAYIKwYBBQUHMAGGGGh0dHA6Ly9v # Y3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcwAoY3aHR0cDovL2NhY2VydHMuZGln # aWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNydDCBgQYDVR0fBHow # eDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJl # ZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDovL2NybDMuZGlnaWNlcnQuY29tL0Rp # Z2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBPBgNVHSAESDBGMDgGCmCGSAGG/WwA # AgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAK # BghghkgBhv1sAzAdBgNVHQ4EFgQUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHwYDVR0j # BBgwFoAUReuir/SSy4IxLVGLp6chnfNtyA8wDQYJKoZIhvcNAQELBQADggEBAD7s # DVoks/Mi0RXILHwlKXaoHV0cLToaxO8wYdd+C2D9wz0PxK+L/e8q3yBVN7Dh9tGS # dQ9RtG6ljlriXiSBThCk7j9xjmMOE0ut119EefM2FAaK95xGTlz/kLEbBw6RFfu6 # r7VRwo0kriTGxycqoSkoGjpxKAI8LpGjwCUR4pwUR6F6aGivm6dcIFzZcbEMj7uo # +MUSaJ/PQMtARKUT8OZkDCUIQjKyNookAv4vcn4c10lFluhZHen6dGRrsutmQ9qz # sIzV6Q3d9gEgzpkxYz0IGhizgZtPxpMQBvwHgfqL2vmCSfdibqFT+hKUGIUukpHq # aGxEMrJmoecYpJpkUe8wggU3MIIEH6ADAgECAhAFUi3UAAgCGeslOwtVg52XMA0G # CSqGSIb3DQEBCwUAMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJ # bmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0 # IFNIQTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0EwHhcNMjEwMzIyMDAwMDAw # WhcNMjIwMzMwMjM1OTU5WjB1MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZv # cm5pYTESMBAGA1UEBxMJUGFsbyBBbHRvMRAwDgYDVQQKEwdIUCBJbmMuMRkwFwYD # VQQLExBIUCBDeWJlcnNlY3VyaXR5MRAwDgYDVQQDEwdIUCBJbmMuMIIBIjANBgkq # hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtJ+rYUkseHcrB2M/GyomCEyKn9tCyfb+ # pByq/Jyf5kd3BGh+/ULRY7eWmR2cjXHa3qBAEHQQ1R7sX85kZ5sl2ukINGZv5jEM # 04ERNfPoO9+pDndLWnaGYxxZP9Y+Icla09VqE/jfunhpLYMgb2CuTJkY2tT2isWM # EMrKtKPKR5v6sfhsW6WOTtZZK+7dQ9aVrDqaIu+wQm/v4hjBYtqgrXT4cNZSPfcj # 8W/d7lFgF/UvUnZaLU5Z/+lYbPf+449tx+raR6GD1WJBAzHcOpV6tDOI5tQcwHTo # jJklvqBkPbL+XuS04IUK/Zqgh32YZvDnDohg0AEGilrKNiMes5wuAQIDAQABo4IB # xDCCAcAwHwYDVR0jBBgwFoAUWsS5eyoKo6XqcQPAYPkt9mV1DlgwHQYDVR0OBBYE # FD4tECf7wE2l8kA6HTvOgkbo33MvMA4GA1UdDwEB/wQEAwIHgDATBgNVHSUEDDAK # BggrBgEFBQcDAzB3BgNVHR8EcDBuMDWgM6Axhi9odHRwOi8vY3JsMy5kaWdpY2Vy # dC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNybDA1oDOgMYYvaHR0cDovL2NybDQu # ZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwSwYDVR0gBEQwQjA2 # BglghkgBhv1sAwEwKTAnBggrBgEFBQcCARYbaHR0cDovL3d3dy5kaWdpY2VydC5j # b20vQ1BTMAgGBmeBDAEEATCBhAYIKwYBBQUHAQEEeDB2MCQGCCsGAQUFBzABhhho # dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTgYIKwYBBQUHMAKGQmh0dHA6Ly9jYWNl # cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURDb2RlU2lnbmlu # Z0NBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQBZca1CZfgn # DucOwEDZk0RXqb8ECXukFiih/rPQ+T5Xvl3bZppGgPnyMyQXXC0fb94p1socJzJZ # fn7rEQ4tHxL1vpBvCepB3Jq+i3A8nnJFHSjY7aujglIphfGND97U8OUJKt2jwnni # EgsWZnFHRI9alEvfGEFyFrAuSo+uBz5oyZeOAF0lRqaRht6MtGTma4AEgq6Mk/iP # LYIIZ5hXmsGYWtIPyM8Yjf//kLNPRn2WeUFROlboU6EH4ZC0rLTMbSK5DV+xL/e8 # cRfWL76gd/qj7OzyJR7EsRPg92RQUC4RJhCrQqFFnmI/K84lPyHRgoctAMb8ie/4 # X6KaoyX0Z93PMYIPsTCCD60CAQEwgYYwcjELMAkGA1UEBhMCVVMxFTATBgNVBAoT # DERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UE # AxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUgU2lnbmluZyBDQQIQBVIt # 1AAIAhnrJTsLVYOdlzANBglghkgBZQMEAgEFAKB8MBAGCisGAQQBgjcCAQwxAjAA # MBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgor # BgEEAYI3AgEVMC8GCSqGSIb3DQEJBDEiBCDemA8mRrkL9MWQcjqXBE46mW6zrXYD # KUZz0NFgY3wldzANBgkqhkiG9w0BAQEFAASCAQAUallJGocQSY+I2mlo+NmDMq5d # U8OdnB4IAlqYoZnfGcrn2E+/HYB28bOX4M54259i+kMKr95WNotxhYDmYsPdjwOi # fJo6/Prrgtapw/xsXSbFP168WvCsJKjMe6NFEwwh8s7i3VCAyD4zmKQNLFX2LY+w # jomqduh2LCR+cTG29dMU9ISvN4Or+yufD2P0H/tMYA1YDIiFHrECpGia4/rfevIN # 9lExKYCEmc4vc5WnUXWRZqQ9xeWPMDUXqsvvIerjWmofAfflXHE1UQbJcuxarqiM # VV88BFRd19Uqmnh+fNzhZQgyhjiPYC4XiJrFg3rgc/Z5pF6IbMVnOeScfClzoYIN # fTCCDXkGCisGAQQBgjcDAwExgg1pMIINZQYJKoZIhvcNAQcCoIINVjCCDVICAQMx # DzANBglghkgBZQMEAgEFADB3BgsqhkiG9w0BCRABBKBoBGYwZAIBAQYJYIZIAYb9 # bAcBMDEwDQYJYIZIAWUDBAIBBQAEIN/hARZkPOm7agSR2u+hxCv5cSCirGwBepPZ # S/mJaNPjAhBAbdondCS+SR4bCBevwgPXGA8yMDIxMTEyMjE5MTkwM1qgggo3MIIE # /jCCA+agAwIBAgIQDUJK4L46iP9gQCHOFADw3TANBgkqhkiG9w0BAQsFADByMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQg # VGltZXN0YW1waW5nIENBMB4XDTIxMDEwMTAwMDAwMFoXDTMxMDEwNjAwMDAwMFow # SDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMuMSAwHgYDVQQD # ExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMTCCASIwDQYJKoZIhvcNAQEBBQADggEP # ADCCAQoCggEBAMLmYYRnxYr1DQikRcpja1HXOhFCvQp1dU2UtAxQtSYQ/h3Ib5Fr # DJbnGlxI70Tlv5thzRWRYlq4/2cLnGP9NmqB+in43Stwhd4CGPN4bbx9+cdtCT2+ # anaH6Yq9+IRdHnbJ5MZ2djpT0dHTWjaPxqPhLxs6t2HWc+xObTOKfF1FLUuxUOZB # OjdWhtyTI433UCXoZObd048vV7WHIOsOjizVI9r0TXhG4wODMSlKXAwxikqMiMX3 # MFr5FK8VX2xDSQn9JiNT9o1j6BqrW7EdMMKbaYK02/xWVLwfoYervnpbCiAvSwnJ # laeNsvrWY4tOpXIc7p96AXP4Gdb+DUmEvQECAwEAAaOCAbgwggG0MA4GA1UdDwEB # /wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsGAQUFBwMIMEEG # A1UdIAQ6MDgwNgYJYIZIAYb9bAcBMCkwJwYIKwYBBQUHAgEWG2h0dHA6Ly93d3cu # ZGlnaWNlcnQuY29tL0NQUzAfBgNVHSMEGDAWgBT0tuEgHf4prtLkYaWyoiWyyBc1 # bjAdBgNVHQ4EFgQUNkSGjqS6sGa+vCgtHUQ23eNqerwwcQYDVR0fBGowaDAyoDCg # LoYsaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC10cy5jcmww # MqAwoC6GLGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtdHMu # Y3JsMIGFBggrBgEFBQcBAQR5MHcwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRp # Z2ljZXJ0LmNvbTBPBggrBgEFBQcwAoZDaHR0cDovL2NhY2VydHMuZGlnaWNlcnQu # Y29tL0RpZ2lDZXJ0U0hBMkFzc3VyZWRJRFRpbWVzdGFtcGluZ0NBLmNydDANBgkq # hkiG9w0BAQsFAAOCAQEASBzctemaI7znGucgDo5nRv1CclF0CiNHo6uS0iXEcFm+ # FKDlJ4GlTRQVGQd58NEEw4bZO73+RAJmTe1ppA/2uHDPYuj1UUp4eTZ6J7fz51Kf # k6ftQ55757TdQSKJ+4eiRgNO/PT+t2R3Y18jUmmDgvoaU+2QzI2hF3MN9PNlOXBL # 85zWenvaDLw9MtAby/Vh/HUIAHa8gQ74wOFcz8QRcucbZEnYIpp1FUL1LTI4gdr0 # YKK6tFL7XOBhJCVPst/JKahzQ1HavWPWH1ub9y4bTxMd90oNcX6Xt/Q/hOvB46NJ # ofrOp79Wz7pZdmGJX36ntI5nePk2mOHLKNpbh6aKLzCCBTEwggQZoAMCAQICEAqh # JdbWMht+QeQF2jaXwhUwDQYJKoZIhvcNAQELBQAwZTELMAkGA1UEBhMCVVMxFTAT # BgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTEk # MCIGA1UEAxMbRGlnaUNlcnQgQXNzdXJlZCBJRCBSb290IENBMB4XDTE2MDEwNzEy # MDAwMFoXDTMxMDEwNzEyMDAwMFowcjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERp # Z2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMo # RGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIFRpbWVzdGFtcGluZyBDQTCCASIwDQYJ # KoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3QMu5LzY9/3am6gpnFOVQoV7YjSsQO # B0UzURB90Pl9TWh+57ag9I2ziOSXv2MhkJi/E7xX08PhfgjWahQAOPcuHjvuzKb2 # Mln+X2U/4Jvr40ZHBhpVfgsnfsCi9aDg3iI/Dv9+lfvzo7oiPhisEeTwmQNtO4V8 # CdPuXciaC1TjqAlxa+DPIhAPdc9xck4Krd9AOly3UeGheRTGTSQjMF287Dxgaqwv # B8z98OpH2YhQXv1mblZhJymJhFHmgudGUP2UKiyn5HU+upgPhH+fMRTWrdXyZMt7 # HgXQhBlyF/EXBu89zdZN7wZC/aJTKk+FHcQdPK/P2qwQ9d2srOlW/5MCAwEAAaOC # Ac4wggHKMB0GA1UdDgQWBBT0tuEgHf4prtLkYaWyoiWyyBc1bjAfBgNVHSMEGDAW # gBRF66Kv9JLLgjEtUYunpyGd823IDzASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud # DwEB/wQEAwIBhjATBgNVHSUEDDAKBggrBgEFBQcDCDB5BggrBgEFBQcBAQRtMGsw # JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBDBggrBgEFBQcw # AoY3aHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElE # Um9vdENBLmNydDCBgQYDVR0fBHoweDA6oDigNoY0aHR0cDovL2NybDQuZGlnaWNl # cnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDA6oDigNoY0aHR0cDov # L2NybDMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEUm9vdENBLmNybDBQ # BgNVHSAESTBHMDgGCmCGSAGG/WwAAgQwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93 # d3cuZGlnaWNlcnQuY29tL0NQUzALBglghkgBhv1sBwEwDQYJKoZIhvcNAQELBQAD # ggEBAHGVEulRh1Zpze/d2nyqY3qzeM8GN0CE70uEv8rPAwL9xafDDiBCLK938ysf # DCFaKrcFNB1qrpn4J6JmvwmqYN92pDqTD/iy0dh8GWLoXoIlHsS6HHssIeLWWywU # NUMEaLLbdQLgcseY1jxk5R9IEBhfiThhTWJGJIdjjJFSLK8pieV4H9YLFKWA1xJH # cLN11ZOFk362kmf7U2GJqPVrlsD0WGkNfMgBsbkodbeZY4UijGHKeZR+WfyMD+Nv # tQEmtmyl7odRIeRYYJu6DC0rbaLEfrvEJStHAgh8Sa4TtuF8QkIoxhhWz0E0tmZd # tnR79VYzIi8iNrJLokqV2PWmjlIxggKGMIICggIBATCBhjByMQswCQYDVQQGEwJV # UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu # Y29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgVGltZXN0YW1w # aW5nIENBAhANQkrgvjqI/2BAIc4UAPDdMA0GCWCGSAFlAwQCAQUAoIHRMBoGCSqG # SIb3DQEJAzENBgsqhkiG9w0BCRABBDAcBgkqhkiG9w0BCQUxDxcNMjExMTIyMTkx # OTAzWjArBgsqhkiG9w0BCRACDDEcMBowGDAWBBTh14Ko4ZG+72vKFpG1qrSUpiSb # 8zAvBgkqhkiG9w0BCQQxIgQglkGsx+epkhgXUqjIbIB/0XnUfWzku164Xnc6xODL # mbkwNwYLKoZIhvcNAQkQAi8xKDAmMCQwIgQgsxCQBrwK2YMHkVcp4EQDQVyD4ykr # YU8mlkyNNXHs9akwDQYJKoZIhvcNAQEBBQAEggEAqw7AicFYxDPTmR8wjPL70Gem # OP60vDdtNeuJOIvlhwVl4aAeP8d/ufvtNXi1Eqd5ybCePppRhuz7gL92N1V/YRtZ # vqbIgEcj3J7macr5qtT4raVTxr9YhABUbVscapyZZ8rYYRFf+28RaoWF1lae3uis # iUtML5enUi2LCM/f6szz7j7Dl10EfJ/d04s1Aw09/m+od6hq68o2GQ6nqnFUlYnL # 7mP2+krxEexkfRlM2siAQ6x7bvEuOAEQUAMeRsJX++7AzdwqpjI4z7CTFy6NmsxS # E7AmHaRuKti5GmmwMmUL6LKK9IFjZQP3Y3emlz6QT+sSRUMI+aUe1iEdcxO5hg== # SIG # End signature block |