QuantumSafe-TLS.ps1

<#PSScriptInfo
 
.VERSION 2.0.0
.GUID 62bb910b-2809-45d4-91b1-e44a79e3aab2
.AUTHOR Collin George
.COMPANYNAME
.COPYRIGHT
.LICENSEURI https://opensource.org/licenses/MIT
.PROJECTURI https://github.com/CollinGeorge/QuantumSafe-TLS
.TAGS TLS, QuantumSafe, Security, WindowsHardening, Crypto
.ICONURI
.EXTERNALMODULEDEPENDENCIES
.REQUIREDSCRIPTS
.EXTERNALSCRIPTDEPENDENCIES
.RELEASENOTES
- Enhanced error handling and validation
- Added comprehensive system analysis
- Improved enterprise logging and reporting
- Added rollback functionality
- Enhanced quantum readiness assessment
 
#>


<#
.DESCRIPTION
Enterprise-grade quantum-safe TLS hardening script with comprehensive audit, backup, and rollback capabilities
#>


<#
.SYNOPSIS
Disables legacy TLS and enables quantum-safe ciphers with enterprise-grade features
.DESCRIPTION
Quantum-safe TLS hardening for Windows with comprehensive audit, backup, and rollback capabilities
.PARAMETER VerifyOnly
Audit mode—performs comprehensive analysis without making changes
.PARAMETER Backup
Creates timestamped registry backup before hardening
.PARAMETER Rollback
Restores system from specified backup directory
.PARAMETER ReportPath
Path for detailed JSON/HTML compliance report generation
.PARAMETER Silent
Suppress interactive prompts for automation
.EXAMPLE
.\QuantumReadiness.ps1 -VerifyOnly -ReportPath "C:\Reports"
.EXAMPLE
.\QuantumReadiness.ps1 -Backup -Silent
.EXAMPLE
.\QuantumReadiness.ps1 -Rollback -BackupPath "C:\Temp\TLSSafeBackup-20241201-143022"
#>


param(
    [switch]$VerifyOnly,
    [switch]$Backup,
    [switch]$Rollback,
    [string]$BackupPath,
    [string]$ReportPath,
    [switch]$Silent
)

# Enhanced error handling
$ErrorActionPreference = "Stop"
$Global:LogEntries = @()
$Global:Issues = @()

# Privilege check with detailed messaging
if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Write-Error "ERROR: This script requires Administrator privileges. Please run PowerShell as Administrator and try again."
    exit 1
}

# Constants
$BasePath = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols"
$Legacy = @("SSL 2.0", "SSL 3.0", "TLS 1.0", "TLS 1.1")
$Enable = @("TLS 1.2", "TLS 1.3")
$NetVersions = @("v2.0.50727", "v4.0.30319")
$QuantumSafeCiphers = "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
$TLS13Ciphers = @("TLS_AES_256_GCM_SHA384", "TLS_AES_128_GCM_SHA256")

function Write-Log {
    param(
        [string]$Msg,
        [string]$Color = "White",
        [string]$Level = "INFO"
    )
    
    $timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    $logEntry = @{
        Timestamp = $timestamp
        Level = $Level
        Message = $Msg
    }
    $Global:LogEntries += $logEntry
    
    if (-not $Silent) {
        Write-Host "[$timestamp] [$Level] $Msg" -ForegroundColor $Color
    }
    
    # Log critical issues for reporting
    if ($Level -eq "ERROR" -or $Level -eq "WARNING") {
        $Global:Issues += $logEntry
    }
}

function Test-RegistryPath {
    param([string]$Path)
    try {
        return Test-Path $Path
    }
    catch {
        Write-Log "Registry path test failed: $Path" "Red" "ERROR"
        return $false
    }
}

function Get-SystemInfo {
    try {
        $os = Get-CimInstance -ClassName Win32_OperatingSystem
        $build = [Environment]::OSVersion.Version.Build
        
        return @{
            OSName = $os.Caption
            Version = $os.Version
            Build = $build
            Architecture = $os.OSArchitecture
            InstallDate = $os.InstallDate
            TLS13Supported = $build -ge 17763
        }
    }
    catch {
        Write-Log "Failed to get system information: $($_.Exception.Message)" "Red" "ERROR"
        throw
    }
}

function Backup-TLSConfiguration {
    param([string]$BackupDirectory)
    
    try {
        Write-Log "Creating backup directory: $BackupDirectory" "Yellow" "INFO"
        New-Item $BackupDirectory -ItemType Directory -Force | Out-Null
        
        # Test write access
        $testFile = Join-Path $BackupDirectory "access_test.tmp"
        "test" | Out-File $testFile -Force
        Remove-Item $testFile -Force
        
        # Export registry keys
        Write-Log "Backing up SCHANNEL protocols..." "Yellow" "INFO"
        if (Test-RegistryPath $BasePath) {
            reg export "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL" "$BackupDirectory\SCHANNEL_backup.reg" /y | Out-Null
        }
        
        Write-Log "Backing up .NET Framework settings..." "Yellow" "INFO"
        reg export "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework" "$BackupDirectory\DotNet_backup.reg" /y | Out-Null
        
        # Backup cipher suite configuration
        $cipherPath = "HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002"
        if (Test-RegistryPath $cipherPath) {
            reg export "HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Cryptography" "$BackupDirectory\Cryptography_backup.reg" /y | Out-Null
        }
        
        # Create backup manifest
        $manifest = @{
            BackupDate = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            SystemInfo = Get-SystemInfo
            ScriptVersion = "2.0.0"
            BackupFiles = @(
                "SCHANNEL_backup.reg",
                "DotNet_backup.reg", 
                "Cryptography_backup.reg"
            )
        }
        
        $manifest | ConvertTo-Json -Depth 3 | Out-File "$BackupDirectory\backup_manifest.json" -Encoding UTF8
        
        Write-Log "Backup completed successfully: $BackupDirectory" "Green" "INFO"
        return $true
    }
    catch {
        Write-Log "Backup failed: $($_.Exception.Message)" "Red" "ERROR"
        return $false
    }
}

function Restore-TLSConfiguration {
    param([string]$BackupDirectory)
    
    try {
        $manifestPath = Join-Path $BackupDirectory "backup_manifest.json"
        if (-not (Test-Path $manifestPath)) {
            throw "Backup manifest not found. Invalid backup directory."
        }
        
        $manifest = Get-Content $manifestPath | ConvertFrom-Json
        Write-Log "Restoring from backup created: $($manifest.BackupDate)" "Yellow" "INFO"
        
        # Restore registry files
        foreach ($regFile in $manifest.BackupFiles) {
            $regPath = Join-Path $BackupDirectory $regFile
            if (Test-Path $regPath) {
                Write-Log "Restoring $regFile..." "Yellow" "INFO"
                reg import $regPath | Out-Null
            }
        }
        
        Write-Log "Configuration restored successfully. Reboot required." "Green" "INFO"
        return $true
    }
    catch {
        Write-Log "Restore failed: $($_.Exception.Message)" "Red" "ERROR"
        return $false
    }
}

function Get-TLSAuditResults {
    $results = @{
        SystemInfo = Get-SystemInfo
        LegacyProtocols = @{}
        ModernProtocols = @{}
        NetFrameworkSecurity = @{}
        CipherSuites = @{}
        OverallScore = 0
        Issues = @()
        Recommendations = @()
    }
    
    Write-Log "=== COMPREHENSIVE TLS SECURITY AUDIT ===" "Cyan" "INFO"
    Write-Log "System: $($results.SystemInfo.OSName) Build $($results.SystemInfo.Build)" "Gray" "INFO"
    
    # Check legacy protocols
    Write-Log "`n--- Legacy Protocol Analysis ---" "Yellow" "INFO"
    $legacyEnabled = 0
    foreach ($proto in $Legacy) {
        $clientPath = "$BasePath\$proto\Client"
        $serverPath = "$BasePath\$proto\Server"
        
        $clientEnabled = $false
        $serverEnabled = $false
        
        if (Test-RegistryPath $clientPath) {
            $clientValue = (Get-ItemProperty $clientPath "Enabled" -EA SilentlyContinue).Enabled
            $clientEnabled = ($clientValue -eq 1)
        }
        
        if (Test-RegistryPath $serverPath) {
            $serverValue = (Get-ItemProperty $serverPath "Enabled" -EA SilentlyContinue).Enabled
            $serverEnabled = ($serverValue -eq 1)
        }
        
        $results.LegacyProtocols[$proto] = @{
            ClientEnabled = $clientEnabled
            ServerEnabled = $serverEnabled
            Secure = (-not $clientEnabled -and -not $serverEnabled)
        }
        
        if ($clientEnabled -or $serverEnabled) {
            Write-Log "$proto is ENABLED - HIGH RISK!" "Red" "ERROR"
            $results.Issues += "Legacy protocol $proto is enabled"
            $legacyEnabled++
        } else {
            Write-Log "$proto is properly disabled" "Green" "INFO"
        }
    }
    
    # Check modern protocols
    Write-Log "`n--- Modern Protocol Analysis ---" "Yellow" "INFO"
    foreach ($proto in $Enable) {
        $clientPath = "$BasePath\$proto\Client"
        $serverPath = "$BasePath\$proto\Server"
        
        $clientEnabled = $false
        $serverEnabled = $false
        
        if (Test-RegistryPath $clientPath) {
            $clientValue = (Get-ItemProperty $clientPath "Enabled" -EA SilentlyContinue).Enabled
            $clientEnabled = ($clientValue -eq 1)
        }
        
        if (Test-RegistryPath $serverPath) {
            $serverValue = (Get-ItemProperty $serverPath "Enabled" -EA SilentlyContinue).Enabled
            $serverEnabled = ($serverValue -eq 1)
        }
        
        $results.ModernProtocols[$proto] = @{
            ClientEnabled = $clientEnabled
            ServerEnabled = $serverEnabled
            Available = ($proto -eq "TLS 1.2" -or $results.SystemInfo.TLS13Supported)
        }
        
        if ($proto -eq "TLS 1.2") {
            if ($clientEnabled -and $serverEnabled) {
                Write-Log "TLS 1.2 is properly enabled" "Green" "INFO"
            } else {
                Write-Log "TLS 1.2 is not fully enabled - MEDIUM RISK" "Yellow" "WARNING"
                $results.Issues += "TLS 1.2 is not fully enabled"
            }
        }
        
        if ($proto -eq "TLS 1.3") {
            if ($results.SystemInfo.TLS13Supported) {
                if ($clientEnabled -and $serverEnabled) {
                    Write-Log "TLS 1.3 is enabled - EXCELLENT" "Green" "INFO"
                } else {
                    Write-Log "TLS 1.3 available but not enabled" "Yellow" "WARNING"
                    $results.Recommendations += "Enable TLS 1.3 for maximum security"
                }
            } else {
                Write-Log "TLS 1.3 not supported on this Windows version" "Gray" "INFO"
            }
        }
    }
    
    # Check .NET Framework security
    Write-Log "`n--- .NET Framework Security Analysis ---" "Yellow" "INFO"
    foreach ($version in $NetVersions) {
        $netPath = "HKLM:\SOFTWARE\Microsoft\.NETFramework\$version"
        $strongCrypto = $false
        
        if (Test-RegistryPath $netPath) {
            $cryptoValue = (Get-ItemProperty $netPath "SchUseStrongCrypto" -EA SilentlyContinue)."SchUseStrongCrypto"
            $strongCrypto = ($cryptoValue -eq 1)
        }
        
        $results.NetFrameworkSecurity[$version] = @{
            StrongCryptoEnabled = $strongCrypto
            Secure = $strongCrypto
        }
        
        if ($strongCrypto) {
            Write-Log ".NET ${version}: Strong cryptography enabled" "Green" "INFO"
        } else {
            Write-Log ".NET ${version}: Weak cryptography - MEDIUM RISK" "Yellow" "WARNING"
            $results.Issues += ".NET $version using weak cryptography"
        }
    }
    
    # Calculate overall security score
    $totalChecks = $Legacy.Count + $Enable.Count + $NetVersions.Count
    $secureConfigs = 0
    
    # Legacy protocols (should be disabled)
    $secureConfigs += ($Legacy.Count - $legacyEnabled)
    
    # Modern protocols (should be enabled)
    foreach ($proto in $Enable) {
        if ($results.ModernProtocols[$proto].ClientEnabled -and $results.ModernProtocols[$proto].ServerEnabled) {
            $secureConfigs++
        }
    }
    
    # .NET security
    foreach ($version in $NetVersions) {
        if ($results.NetFrameworkSecurity[$version].StrongCryptoEnabled) {
            $secureConfigs++
        }
    }
    
    $results.OverallScore = [math]::Round(($secureConfigs / $totalChecks) * 100)
    
    Write-Log "`n=== QUANTUM READINESS ASSESSMENT ===" "Magenta" "INFO"
    Write-Log "Security Score: $($results.OverallScore)%" $(if ($results.OverallScore -ge 90) { "Green" } elseif ($results.OverallScore -ge 75) { "Yellow" } else { "Red" }) "INFO"
    
    if ($results.OverallScore -eq 100) {
        Write-Log "QUANTUM-RESISTANT CONFIGURATION ACHIEVED!" "Green" "INFO"
        Write-Log "Your system uses current best-practice cryptography" "Green" "INFO"
    } elseif ($results.OverallScore -ge 90) {
        Write-Log "Excellent quantum readiness with minor improvements needed" "Yellow" "INFO"
    } elseif ($results.OverallScore -ge 75) {
        Write-Log "Good foundation, but hardening recommended" "Yellow" "WARNING"
    } else {
        Write-Log "Significant security improvements needed" "Red" "ERROR"
    }
    
    return $results
}

function Apply-TLSHardening {
    Write-Log "=== APPLYING QUANTUM-SAFE CONFIGURATION ===" "Cyan" "INFO"
    
    try {
        # Disable legacy protocols
        foreach ($proto in $Legacy) {
            foreach ($role in @("Client", "Server")) {
                $path = "$BasePath\$proto\$role"
                if (-not (Test-RegistryPath $path)) {
                    New-Item $path -Force | Out-Null
                }
                Set-ItemProperty $path "Enabled" 0 -Type DWord -Force
                Set-ItemProperty $path "DisabledByDefault" 1 -Type DWord -Force
                Write-Log "Disabled $proto ($role)" "Green" "INFO"
            }
        }
        
        # Enable modern protocols
        foreach ($proto in $Enable) {
            foreach ($role in @("Client", "Server")) {
                $path = "$BasePath\$proto\$role"
                if (-not (Test-RegistryPath $path)) {
                    New-Item $path -Force | Out-Null
                }
                Set-ItemProperty $path "Enabled" 1 -Type DWord -Force
                Set-ItemProperty $path "DisabledByDefault" 0 -Type DWord -Force
                Write-Log "Enabled $proto ($role)" "Green" "INFO"
            }
        }
        
        # Configure cipher suites
        $cipherPath = "HKLM:\SOFTWARE\Policies\Microsoft\Cryptography\Configuration\SSL\00010002"
        if (-not (Test-RegistryPath $cipherPath)) {
            New-Item $cipherPath -Force | Out-Null
        }
        Set-ItemProperty $cipherPath "Functions" $QuantumSafeCiphers -Type String -Force
        Write-Log "Configured quantum-safe cipher suite ordering" "Green" "INFO"
        
        # Enable TLS 1.3 ciphers if supported
        $sysInfo = Get-SystemInfo
        if ($sysInfo.TLS13Supported) {
            foreach ($suite in $TLS13Ciphers) {
                try {
                    Enable-TlsCipherSuite $suite -Position 0 | Out-Null
                    Write-Log "Enabled TLS 1.3 cipher: $suite" "Green" "INFO"
                }
                catch {
                    Write-Log "TLS 1.3 cipher $suite configuration skipped: $($_.Exception.Message)" "Gray" "INFO"
                }
            }
        }
        
        # Harden .NET Framework
        foreach ($version in $NetVersions) {
            $path = "HKLM:\SOFTWARE\Microsoft\.NETFramework\$version"
            if (-not (Test-RegistryPath $path)) {
                New-Item $path -Force | Out-Null
            }
            Set-ItemProperty $path "SchUseStrongCrypto" 1 -Type DWord -Force
            Set-ItemProperty $path "SystemDefaultTlsVersions" 1 -Type DWord -Force
            Write-Log "Hardened .NET Framework $version" "Green" "INFO"
        }
        
        return $true
    }
    catch {
        Write-Log "Hardening failed: $($_.Exception.Message)" "Red" "ERROR"
        return $false
    }
}

function Export-ComplianceReport {
    param(
        [object]$AuditResults,
        [string]$ReportPath
    )
    
    try {
        if (-not (Test-Path $ReportPath)) {
            New-Item $ReportPath -ItemType Directory -Force | Out-Null
        }
        
        $timestamp = Get-Date -Format "yyyyMMdd-HHmmss"
        
        # JSON Report
        $jsonPath = Join-Path $ReportPath "TLS_Audit_Report_$timestamp.json"
        $reportData = @{
            GeneratedOn = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
            ScriptVersion = "2.0.0"
            AuditResults = $AuditResults
            LogEntries = $Global:LogEntries
        }
        $reportData | ConvertTo-Json -Depth 5 | Out-File $jsonPath -Encoding UTF8
        
        # HTML Report
        $htmlPath = Join-Path $ReportPath "TLS_Audit_Report_$timestamp.html"
        $html = @"
<!DOCTYPE html>
<html>
<head>
    <title>TLS Security Audit Report</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        .header { background: #2c3e50; color: white; padding: 20px; }
        .score { font-size: 24px; font-weight: bold; }
        .good { color: #27ae60; }
        .warning { color: #f39c12; }
        .error { color: #e74c3c; }
        table { border-collapse: collapse; width: 100%; margin: 20px 0; }
        th, td { border: 1px solid #ddd; padding: 12px; text-align: left; }
        th { background-color: #f2f2f2; }
    </style>
</head>
<body>
    <div class="header">
        <h1>TLS Security Audit Report</h1>
        <p>Generated: $(Get-Date -Format "yyyy-MM-dd HH:mm:ss")</p>
        <p>System: $($AuditResults.SystemInfo.OSName)</p>
        <p class="score">Security Score: $($AuditResults.OverallScore)%</p>
    </div>
     
    <h2>Executive Summary</h2>
    <p>This system has achieved a security score of $($AuditResults.OverallScore)% based on quantum-readiness criteria.</p>
     
    <h2>Protocol Analysis</h2>
    <table>
        <tr><th>Protocol</th><th>Status</th><th>Security Level</th></tr>
"@

        
        foreach ($proto in $Legacy) {
            $status = if ($AuditResults.LegacyProtocols[$proto].Secure) { "Disabled" } else { "Enabled" }
            $class = if ($AuditResults.LegacyProtocols[$proto].Secure) { "good" } else { "error" }
            $html += "<tr><td>$proto</td><td class='$class'>$status</td><td>Legacy (Vulnerable)</td></tr>"
        }
        
        foreach ($proto in $Enable) {
            $enabled = $AuditResults.ModernProtocols[$proto].ClientEnabled -and $AuditResults.ModernProtocols[$proto].ServerEnabled
            $status = if ($enabled) { "Enabled" } else { "Disabled" }
            $class = if ($enabled) { "good" } else { "warning" }
            $html += "<tr><td>$proto</td><td class='$class'>$status</td><td>Modern (Secure)</td></tr>"
        }
        
        $html += @"
    </table>
     
    <h2>Issues Found</h2>
    <ul>
"@

        
        foreach ($issue in $AuditResults.Issues) {
            $html += "<li class='error'>$issue</li>"
        }
        
        if ($AuditResults.Issues.Count -eq 0) {
            $html += "<li class='good'>No security issues detected</li>"
        }
        
        $html += @"
    </ul>
     
    <h2>Recommendations</h2>
    <ul>
"@

        
        foreach ($rec in $AuditResults.Recommendations) {
            $html += "<li>$rec</li>"
        }
        
        if ($AuditResults.Recommendations.Count -eq 0) {
            $html += "<li class='good'>System is optimally configured</li>"
        }
        
        $html += @"
    </ul>
</body>
</html>
"@

        
        $html | Out-File $htmlPath -Encoding UTF8
        
        Write-Log "Reports generated:" "Green" "INFO"
        Write-Log " JSON: $jsonPath" "Gray" "INFO"
        Write-Log " HTML: $htmlPath" "Gray" "INFO"
        
        return $true
    }
    catch {
        Write-Log "Report generation failed: $($_.Exception.Message)" "Red" "ERROR"
        return $false
    }
}

# Main execution logic
try {
    Write-Log "QuantumReadiness v2.0.0 - Enterprise TLS Hardening" "Magenta" "INFO"
    Write-Log "Copyright (c) Collin George - Licensed under MIT" "Gray" "INFO"
    
    # Handle rollback request
    if ($Rollback) {
        if (-not $BackupPath) {
            throw "BackupPath parameter required for rollback operation"
        }
        
        if (-not (Test-Path $BackupPath)) {
            throw "Backup directory not found: $BackupPath"
        }
        
        $restored = Restore-TLSConfiguration -BackupDirectory $BackupPath
        if ($restored) {
            Write-Log "System restored successfully. Reboot required to apply changes." "Green" "INFO"
            if (-not $Silent) {
                $reboot = Read-Host "Reboot now? (Y/N)"
                if ($reboot -eq "Y" -or $reboot -eq "y") {
                    Restart-Computer -Force
                }
            }
        }
        exit 0
    }
    
    # Perform comprehensive audit
    $auditResults = Get-TLSAuditResults
    
    # Generate compliance report if requested
    if ($ReportPath) {
        Export-ComplianceReport -AuditResults $auditResults -ReportPath $ReportPath
    }
    
    # Exit if verify-only mode
    if ($VerifyOnly) {
        Write-Log "`nAudit completed. Use -ReportPath to generate detailed compliance reports." "Cyan" "INFO"
        exit 0
    }
    
    # Create backup if requested
    if ($Backup) {
        $backupDir = "$env:TEMP\TLSSafeBackup-$(Get-Date -f 'yyyyMMdd-HHmmss')"
        $backupSuccess = Backup-TLSConfiguration -BackupDirectory $backupDir
        if (-not $backupSuccess) {
            throw "Backup failed - aborting hardening process"
        }
    }
    
    # Apply hardening
    $hardeningSuccess = Apply-TLSHardening
    if (-not $hardeningSuccess) {
        throw "TLS hardening failed"
    }
    
    Write-Log "`n=== CONFIGURATION COMPLETE ===" "Magenta" "INFO"
    Write-Log "Your system now uses quantum-resistant TLS configuration" "Green" "INFO"
    Write-Log "A system reboot is required to activate all changes" "Yellow" "WARNING"
    
    # Reboot prompt
    if (-not $Silent) {
        Write-Log "`nReboot recommended to activate all TLS changes." "Yellow" "INFO"
        $reboot = Read-Host "Reboot now? (Y/N)"
        if ($reboot -eq "Y" -or $reboot -eq "y") {
            Write-Log "Rebooting system..." "Yellow" "INFO"
            Start-Sleep 3
            Restart-Computer -Force
        }
    }
    
    exit 0
}
catch {
    Write-Log "FATAL ERROR: $($_.Exception.Message)" "Red" "ERROR"
    Write-Log "Stack trace: $($_.ScriptStackTrace)" "Red" "ERROR"
    exit 1
}