The CMS method described in Securing BIOS Passwords relies on a document encryption certificate. The BIOS password is encrypted to that certificate’s public key, and only devices holding the matching private key can decrypt it. This post is a companion to that one. It covers how to create and manage the certificate itself: choosing between a self-signed certificate and one issued from an enterprise PKI, and handling the full lifecycle from creation through distribution, rotation, and removal.
How the certificate is used
Before getting into the options, it helps to be clear about what this certificate actually does, because it is not used the way a typical certificate is.
CMS (Cryptographic Message Syntax) uses the certificate purely as an RSA key pair. Protect-CmsMessage encrypts the password to the public key, and Unprotect-CmsMessage decrypts it with the private key. That is the entire relationship. The certificate is a key container, not an identity.
Important
This means CMS does not validate a trust chain, an expiration date, or revocation. The certificate does not need to chain to a trusted root, it does not need to be “trusted” by the device, and decryption keeps working even after the certificate has expired. That one fact drives most of the decisions in this post, so it is worth keeping in mind throughout.
Self-signed or enterprise PKI?
Because CMS ignores trust and revocation, a self-signed certificate decrypts exactly as securely as one issued by a certificate authority. The choice between them is about operations and governance, not cryptographic strength.
| Factor | Enterprise PKI | Self-signed |
|---|---|---|
| CMS encrypt/decrypt strength | identical | identical |
| Trust chain / revocation relevance | none (CMS ignores it) | none |
| Lifecycle and expiry tracking | CA-managed | manual |
| Parameter correctness | template-enforced | per-command |
| Audit and governance | strong | ad hoc |
| Infrastructure needed | AD CS | none |
| Compromise remediation | rotate and re-encrypt | rotate and re-encrypt |
Enterprise PKI is the better choice if you already run AD CS. The benefits are operational: the CA tracks issuance and expiry, the template enforces the correct key size, EKU, and other parameters every time, and issuance is logged and auditable. Two of the usual PKI benefits do not really apply here though. Revocation does nothing for CMS, and auto-renewal does not help because you distribute a static copy of the private key to devices.
Self-signed is perfectly fine for labs, testing, small environments, or anywhere you do not have (or do not want to involve) a PKI. It’s one command and has no dependencies. The trade-off is that you own the entire lifecycle manually: tracking expiry, recreating the certificate, and getting the parameters right by hand.
The rest of this post covers both. The creation step differs, but everything after it (export, distribution, rotation, removal) is the same.
What the certificate needs
However you create it, the certificate has to have:
- Enhanced Key Usage: Document Encryption (OID
1.3.6.1.4.1.311.80.1). The CMS cmdlets require this EKU. - Key Usage: Key Encipherment (and Data Encipherment). CMS uses RSA key transport.
- Key algorithm: RSA, 2048-bit or larger. The CMS cmdlets will not use an ECC key for this.
- An exportable private key. The whole model is one certificate whose private key is exported and distributed to the fleet, so the key must be exportable at creation time.
Option 1 - Create a self-signed certificate
A single command on an admin workstation produces a certificate with all of the required properties:
$cert = New-SelfSignedCertificate -Subject "CN=BIOS Password Encryption" `
-KeyUsage KeyEncipherment,DataEncipherment -Type DocumentEncryptionCert `
-CertStoreLocation Cert:\CurrentUser\My -KeyExportPolicy Exportable
-Type DocumentEncryptionCert sets the Document Encryption EKU and the appropriate key usage for you. The default key is RSA 2048. -CertStoreLocation Cert:\CurrentUser\My places it in your user store, which is where the Export the certificate step below looks for it - skip ahead to it.
Option 2 - Issue the certificate from an enterprise PKI
There is no built-in Document Encryption template, so you duplicate one and configure it.
Create the template. On a machine with the Certificate Templates console (certtmpl.msc):
- Right-click the built-in User template and choose Duplicate Template.
- Compatibility: set to your environment’s standard.
- General: give it a name, set a validity period (see the expiration section below), and uncheck Publish certificate in Active Directory.
- Cryptography: Provider Category = Key Storage Provider; Algorithm = RSA; minimum key size 2048 or larger; request hash SHA256.
- Request Handling: Purpose = Encryption, and check Allow private key to be exported.
- Extensions - Application Policies: edit the list, remove what is there, and add Document Encryption.
- Extensions - Key Usage: select Key Usage and click Edit. In the Encryption section, choose Allow key exchange only with key encryption (key encipherment) and check Allow encryption of user data. Check Make this extension critical.
- Subject Name: Supply in the request, so you can set a fixed common name.
- Security: grant Read and Enroll to your own admin account or group only. Do not configure Autoenroll, and do not scope it to Domain Computers or Users. The devices never enroll this certificate, they receive the exported private key.
Then publish it: in the Certification Authority console (certsrv.msc), expand the CA, right-click Certificate Templates, and choose New > Certificate Template to Issue, then select the new template.
Enroll the certificate. On a secured admin workstation that can reach the CA, open certmgr.msc (Current User), go to Personal, and choose All Tasks - Request New Certificate. Select the new template, supply a common name such as BIOS Password Encryption when prompted, and enroll.
Export the certificate
From this point the process is the same for both options. You need two files: the public key for encrypting passwords, and the private key for the devices.
# Locate the certificate (adjust the store and subject to match where you created it)
$cert = Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.EnhancedKeyUsageList.ObjectId -contains '1.3.6.1.4.1.311.80.1' -and $_.Subject -eq 'CN=BIOS Password Encryption' }
# Public key - used to encrypt passwords (safe to share)
Export-Certificate -Cert $cert -FilePath .\BiosEnc.cer
# Private key - what the devices need (protect this file)
$pfxPw = Read-Host -AsSecureString -Prompt 'PFX password'
Export-PfxCertificate -Cert $cert -FilePath .\BiosEnc.pfx -Password $pfxPw
The .pfx is the sensitive file. Give it a strong export password, keep it in a restricted location, and lifecycle-manage it.
Distribute the private key to devices
The goal is for every target device to have the certificate and its private key in Cert:\LocalMachine\My, so the management script (running as SYSTEM) can decrypt at runtime. The import command, run elevated or as SYSTEM:
Import-PfxCertificate -FilePath .\BiosEnc.pfx -CertStoreLocation Cert:\LocalMachine\My -Password $pfxPw
Import-PfxCertificate imports the key as non-exportable by default, which is what you want. The certificate cannot then be re-exported off the machine. Do not add -Exportable.
Deliver the .pfx and that import step using whatever you already use for content and scripts:
- Configuration Manager - a package, application, or a “Run PowerShell Script” step that drops the file and runs the import.
- Intune - a Win32 app or a platform script that does the same.
Caution
One method that does not work for this is Group Policy. GPO can deploy public certificates to the Trusted Root or Trusted People stores, but it cannot deploy a
.pfxwith a private key intoCert:\LocalMachine\My. Use one of the options above for the private key.
Note that the import step has to supply the .pfx password, so that password lives in your deployment content; keep it restricted. It only protects the file in transit; once imported, the key is in the protected machine store.
Adding the certificate to a Configuration Manager boot image
WinPE’s certificate store is a RAM disk that is rebuilt on every boot. The key has to be placed into the store each time WinPE starts, which in practice means baking it into the boot image.
The Configuration Manager-native way to do this is a prestart command. In the boot image’s properties, on the Customization tab, enable a prestart command and use Include files for the prestart command to point at a folder containing the .pfx and a small import script. Configuration Manager injects those files into the boot image .wim, and the prestart command runs at WinPE startup, before the task sequence:
# ImportBiosCert.ps1 - included with the prestart command, run at WinPE startup
$pfxPw = ConvertTo-SecureString 'PfxPassword' -AsPlainText -Force
Import-PfxCertificate -FilePath "$PSScriptRoot\BiosEnc.pfx" -CertStoreLocation Cert:\LocalMachine\My -Password $pfxPw
After changing the boot image, update it to your distribution points so the new version is staged. A couple of things to keep in mind:
- The
.pfxis now embedded in the boot image, so the image itself becomes a sensitive object. Restrict access to it the same way you would the.pfx, and note that the prestart script carries the export password too. - If you would rather not carry that password in the image, you can instead service the boot image
.wimoffline (mount it with DISM and import the certificate into the mounted image’s store) so only the certificate, non-exportable, lives in the image. It is more involved but keeps the password out of the boot media.
Once the certificate is present in the WinPE store, Unprotect-CmsMessage and the -...CmsFile parameters work exactly as they do in the full OS.
Encrypt a password and use it
With the public key in hand and the private key on the devices, encrypt the password once and use it with the scripts. This is covered in more detail in Securing BIOS Passwords, but in short:
# Once, on the admin workstation - encrypt the BIOS password to the public key
Protect-CmsMessage -To .\BiosEnc.cer -Content 'TheBiosPassword' -OutFile .\BiosPw.cms
# On the device (as SYSTEM) - the script finds the private key and decrypts in memory
Manage-LenovoBiosSettings.ps1 -SetSettings -SupervisorPasswordCmsFile .\BiosPw.cms
The .cms file is ciphertext and is safe to store alongside your content.
Certificate expiration
Note
An expired certificate does not break decryption. CMS matches the recipient by issuer and serial number and uses the private key directly. It never checks the certificate’s expiration date. A device whose certificate has expired will keep decrypting
.cmsfiles without any issue. (In current Windows builds,Protect-CmsMessagewill even keep encrypting to an expired certificate.)
Expiration acts as a prompt to rotate, and a flag that audit and compliance tooling will raise, rather than something that stops the scripts from working.
That also changes the usual “shorter is more secure” calculation. For an identity or TLS certificate, a short validity period limits how long a stolen key is useful, because expiration and revocation eventually cut it off. That mechanism does not apply here. A leaked private key decrypts any .cms file it can reach regardless of the certificate’s expiration, and CMS ignores revocation. The only thing that neutralizes a compromised key is to rotate it and re-encrypt. A very short validity period buys little security while adding the effort of redeploying a new certificate to all devices every time it expires.
My recommendation is to size the validity period to a rotation cadence you will actually keep, rather than to the smallest number you can pick. Two to three years is a reasonable default, aligned with your BIOS password rotation policy. One year is fine if your security policy calls for tighter cycling.
Rotating the certificate
There are two different things that both get called “rotation”:
- Rotating the BIOS password does not require a new certificate. Just re-encrypt the new password to the existing certificate with
Protect-CmsMessageand ship the new.cmsfile. - Rotating the certificate is needed when it is nearing expiration or when the private key may have been exposed. Issue a new certificate, re-encrypt your passwords to it, distribute the new
.pfxto the devices, and once every device has the new key and all.cmsfiles have been re-encrypted, remove the old certificate (next section).
If you are rotating because of a suspected key compromise, also change the BIOS password itself. The old password may have been exposed along with the key, and re-encrypting an unchanged password to a new certificate does not help if the password is already known.
Removing the certificate
Once a certificate is retired and nothing depends on it any longer, clean it up.
On the devices, remove the old certificate from the machine store (run as SYSTEM, after the replacement is in place):
Get-ChildItem Cert:\LocalMachine\My | Where-Object Thumbprint -eq 'OLD_CERT_THUMBPRINT' | Remove-Item
On the source side, securely delete any exported .pfx and .cer files you no longer need, and remove the certificate from the admin workstation’s store if it is no longer used to encrypt.
If the certificate came from an enterprise PKI, you can revoke it as well. Keep in mind that revocation has no effect on CMS decryption (it will not stop a leaked private key from decrypting existing files) but it keeps your certificate inventory accurate and is good hygiene. Rotation and re-encryption, not revocation, are what actually retire the certificate’s usefulness.