Skip to main content

Generate and manage TPM-protected keys in Windows using PowerShell

Storing private keys in a Trusted Platform Module (TPM) is a secure and reliable way to protect cryptographic operations on a Windows 11 device.

This tutorial walks you through how to use TPM-backed key storage using PowerShell, with a focus on the Microsoft Platform Crypto Provider (PCP).

Why use TPM for key storage?

A TPM helps ensure that private keys are protected from theft or tampering. Once stored in the TPM, keys become non-exportable, and all operations using them must go through secure hardware-based access.

Windows provides two ways to interact with TPM hardware:

Each serves different needs depending on how deeply you want to work with TPM features.

PCP versus TBS: What's the Difference?

Table 1. PCP versus TBS

Feature

Platform Crypto Provider (PCP)

TPM Base Services (TBS)

Abstraction level

High-level API

Low-level TPM access

Primary use case

Key storage and cryptographic operations

Direct TPM command execution

Developer complexity

Easier to implement, less TPM-specific knowledge

Requires understanding of TPM commands

Integration

Tightly integrated with Windows features

Suited for custom security solutions


Microsoft Platform Crypto Provider (PCP)

PCP is typically used in scenarios where applications require secure key storage and cryptographic operations without the need for direct TPM command management. Key features include:

  • Key protection: Creates and stores cryptographic keys inside the TPM, ensuring private keys are non-exportable and protected from unauthorized access.

  • Integration with Windows Security Features: Integrates with Windows security features like BitLocker and Windows Hello for Business, enhancing security by leveraging TPM-backed keys.

  • Simplified API: Offers simplified APIs for secure key storage and cryptographic operations.

TPM Base Services (TBS)

TBS is a low-level system service that provides a standardized interface for applications to communicate directly with the TPM. TBS is suited for scenarios where applications require direct interaction with the TPM, such as custom security solutions or specialized hardware integrations. Its primary functions include:

  • Direct TPM command execution: Provides raw access to TPM command sets, offering granular control over TPM functionalities.

  • Resource management: Manages multiple app access to TPM resources, ensuring that TPM resources are used efficiently and without conflicts.

  • Support for custom TPM operations: Enables advanced or vendor-specific TPM functionality

Use PCP and PowerShell to generate a TPM-backed key and CSR

This example shows how to generate a TPM-backed key and create a certificate signing request (CSR) using PowerShell and PCP.

Before you begin

  • Install Windows 11 with a TPM2

  • Install PowerShell (should run as Administrator)

  1. Open PowerShell as an Administrator.

  2. Ensure a TPM is present by running the following PowerShell command:

    Get-Tpm

    Your output will resemble the example below:

    TpmPresent : True
    TpmReady   : True
    …
  3. Run the following PowerShell script:

    # Define key container and subject info
    $keyName = "TPMKey"
    $subject = "CN=My TPM CSR"
    
    # 1. Create a TPM-backed key pair using CNG
    Write-Host "Creating TPM-backed key..."
    $provider = "Microsoft Platform Crypto Provider"
    
    $key = New-Object System.Security.Cryptography.CngKeyCreationParameters
    $key.Provider = $provider
    $key.KeyCreationOptions = [System.Security.Cryptography.CngKeyCreationOptions]::OverwriteExistingKey
    $key.ExportPolicy = [System.Security.Cryptography.CngExportPolicies]::None
    $key.KeyUsage = [System.Security.Cryptography.CngKeyUsages]::Signing
    
    [System.Security.Cryptography.CngKey]::Create("RSA", $keyName, $key)
    
    Write-Host "TPM key created with name: $keyName"
    
    # 2. Create an INF file for CSR generation
    $infPath = "$env:TEMP\csr.inf"
    $csrPath = "$env:TEMP\csr.req"
    
    $infContent = @"
    [Version]
    Signature="$Windows NT$"
    
    [NewRequest]
    Subject = "$subject"
    KeySpec = 1
    KeyLength = 2048
    Exportable = FALSE
    MachineKeySet = TRUE
    ProviderName = "$provider"
    KeyContainer = "$keyName"
    HashAlgorithm = sha256
    RequestType = PKCS10
    
    [Extensions]
    2.5.29.17 = "{text}"
    _continue_ = "dns=example.com&"
    _continue_ = "dns=www.example.com"
    
    [RequestAttributes]
    CertificateTemplate = User
    "@
    
    Set-Content -Path $infPath -Value $infContent -Encoding ASCII
    
    # 3. Generate the CSR
    Write-Host "Generating CSR..."
    certreq.exe -new $infPath $csrPath
    
    if (Test-Path $csrPath) {
        Write-Host "CSR successfully created at: $csrPath"
        Get-Content $csrPath
    } else {
        Write-Error "CSR generation failed."
    }
    
    # Cleanup temporary files (optional)
    # Remove-Item $infPath
    
  4. Submit the CSR to a certificate authority.

    Submit the generated CSR (csr.req) to DigiCert® Device Trust Manager over any of the Certificate management methods, such as REST, EST, SCEP, CMPv2 or ACME to obtain a signed certificate. See:

  5. Install the issued certificate.

    Once you receive the signed certificate (for example, tpm_certificate.cer), install it by running the following command:

    certreq -accept tpm_certificate.cer 

    This command associates the certificate with the existing TPM-protected private key.

Cleanup

To delete the TPM-backed key created with the Microsoft Platform Crypto Provider in Windows (for example, named TPMKey), you can use the PowerShell and the Windows CNG APIs.

Run the following PowerShell command:

$keyName = "TPMKey" 
$provider = "Microsoft Platform Crypto Provider"  

# Attempt to open and delete the key 
try {     
  $key = [System.Security.Cryptography.CngKey]::Open($keyName, $provider)    
  $key.Delete()     
  Write-Host "Key '$keyName' successfully deleted from TPM." 
} catch {     
  Write-Warning "Failed to delete key '$keyName'. It may not exist or is not accessible." 
}

If you used the key to enroll a certificate, you might want to remove that certificate as well:

# Remove certs that reference the TPM key by container name 
Get-ChildItem Cert:\LocalMachine\My | Where-Object {  
  $_.PrivateKey.CspKeyContainerInfo.KeyContainerName -eq "TPMKey" 
} | Remove-Item

See How Windows uses the Trusted Platform Module for information.