Functions/Get-SCEPCertificate.ps1
|
<#
.SYNOPSIS Requests a Certificate from an SCEP Server via the SCEP Protocol. This works on Windows 8.1 and newer Operating Systems. .PARAMETER ComputerName Specifies the Host Name or IP Address of the SCEP Server. If using SSL, this must match the SCEP Server's identity as specified in its SSL Server Certificate. .PARAMETER MachineContext By default, the Key for Certificate Request gets created in the current User's Context. By specifying this Parameter, it will be created as a Machine Key. You must execute the Command with Elevation (Run as Administrator) then. .PARAMETER Subject Specifies the Subject DN for the Certificate. May be left empty if you specify a DnsName, Upn or IP instead. .PARAMETER Dns Specifies one or more DNS Names to be written into the Subject Alternative Name (SAN) Extension of the Certificate Request. May be left Empty if you specify a Subject, Upn or IP instead. .PARAMETER Upn Specifies one or more User Principal Names to be written into the Subject Alternative Name (SAN) Extension of the Certificate Request. May be left Empty if you specify a Subject, DnsName or IP instead. .PARAMETER Email Specifies one or more E-Mail addresses (RFC 822) to be written into the Subject Alternative Name (SAN) Extension of the Certificate Request. May be left Empty if you specify a Subject, DnsName, Upn or IP instead. .PARAMETER IP Specifies or more IP Addresses to be written into the Subject Alternative Name (SAN) Extension of the Certificate Request. May be left Empty if you specify a Subject, DnsName or Upn instead. .PARAMETER CertificateTemplate Specifies the Object Identifier of a Certificate Template to be written into the Certificate Template Information Extension of the Certificate Request. .PARAMETER Eku Specifies one or more Enhanced Key Usages to be included in the Certificate Request. They get identified by their Friendly Name. .PARAMETER AppPolicy Specifies one or more Application Policies to be included in the Certificate Request. They get identified by their Friendly Name. .PARAMETER KeyUsage Specifies the Key Usage to be included in the Certificate Request. Unlike New-CertificateRequest, no Key Usage Extension is included unless specified. .PARAMETER Smime Specifies the S/MIME Capabilities the requestor supports. .PARAMETER Sid Specifies a Security Identifier to be written into the szOID_NTDS_CA_SECURITY_EXT Extension of the Certificate Request. .PARAMETER ChallengePassword Specifies the Challenge Password used to authenticate to the SCEP Server. Not necessary if the SCEP Server doesn't require a Password, or if you specify a SigningCert. .PARAMETER SigningCert Specifies the Signing Certificate used to sign the SCEP Certificate Request. Can be passed to the Command via the Pipeline. Use this when you already have a Certificate issued by the SCEP Server and just want to renew it. Subject Information will be taken from this Certificate as otherwise NDES would deny the Request if there is a mismatch. .PARAMETER Ksp Specifies the Cryptographic Service Provider (CSP) or Key Storage Provider (KSP) to be used for the Private Key of the Certificate. You can specify any CSP or KSP that is installed on the System. Defaults to the Microsoft Software Key Storage Provider. .PARAMETER KeyAlgorithm Specifies the Algorithm to be used when creating the Key Pair. Defaults to "RSA". .PARAMETER KeyLength Specifies the Key Length for the Key pair of the Certificate. Gets applied only when KeyAlgorithm is "RSA". Defaults to 3072 Bits. .PARAMETER PrivateKeyExportable Specifies if the Private Key of the Certificate shall be marked as exportable. Defaults to the Key being not marked as exportable. .PARAMETER UseSSL Forces the connection to use SSL Encryption. Not necessary from a security perspective, as the SCEP Message's confidential partsd are encrypted with the NDES RA Certificates anyway. .PARAMETER Port Specifies the Network Port of the SCEP Server to be used. Only necessary if your SCEP Server is running on a non-default Port for some reason. Defaults to Port 80 without SSL and 443 with SSL. .PARAMETER Method Specifies if the Certificate Submission shall be done with HTTP "GET" or "POST". Defaults to "POST". .NOTES CertificateTemplate, Eku, AppPolicy, KeyUsage, Smime and Sid only add Extensions to the Certificate Request. Whether they make it into the issued Certificate is up to the SCEP Server and the CA behind it. They cannot be combined with SigningCert, as a Renewal inherits its Extensions from that Certificate. .OUTPUTS System.Security.Cryptography.X509Certificates.X509Certificate. Returns the issued Certificate returned by the SCEP Server. #> Function Get-SCEPCertificate { [cmdletbinding()] [Alias("Get-NDESCertificate")] param( [Parameter(Mandatory=$True)] [String] $ComputerName, [Alias("Machine")] [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [Switch] $MachineContext, [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [ValidateNotNullOrEmpty()] [String] $Subject, [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [Alias("DnsName")] [ValidateNotNullOrEmpty()] [ValidateScript({ $_ | ForEach-Object -Process { [System.Uri]::CheckHostName($_) -eq [System.UriHostnameType]::Dns } })] [String[]] $Dns, [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [Alias("UserPrincipalName")] [ValidateNotNullOrEmpty()] [mailaddress[]] $Upn, [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [Alias("RFC822Name")] [Alias("E-Mail")] [ValidateNotNullOrEmpty()] [mailaddress[]] $Email, [Alias("IPAddress")] [Parameter(Mandatory=$False)] [ValidateNotNullOrEmpty()] [System.Net.IPAddress[]] $IP, [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [ValidatePattern("^([0-2])((\.0)|(\.[1-9][0-9]*))*$")] [String] $CertificateTemplate, [Alias("EnhancedKeyUsage")] [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [ValidateSet( "EnrollmentAgent", "ClientAuthentication", "CodeSigning", "LifeTimeSigning", "DocumentSigning", "DocumentEncryption", "EncryptingFileSystem", "FileRecovery", "IPSecEndSystem", "IPSecIKEIntermediate", "IPSecTunnelEndpoint", "IPSecUser", "KeyRecovery", "KDCAuthentication", "SecureEmail", "ServerAuthentication", "SmartCardLogon", "TimeStamping", "OCSPSigning", "RemoteDesktopAuthentication", "PrivateKeyArchival" )] [String[]] $Eku, [Alias("ApplicationPolicy")] [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [ValidateSet( "EnrollmentAgent", "ClientAuthentication", "CodeSigning", "LifeTimeSigning", "DocumentSigning", "DocumentEncryption", "EncryptingFileSystem", "FileRecovery", "IPSecEndSystem", "IPSecIKEIntermediate", "IPSecTunnelEndpoint", "IPSecUser", "KeyRecovery", "KDCAuthentication", "SecureEmail", "ServerAuthentication", "SmartCardLogon", "TimeStamping", "OCSPSigning", "RemoteDesktopAuthentication", "PrivateKeyArchival" )] [String[]] $AppPolicy, [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [ValidateSet( "CrlSign", "DataEncipherment", "DecipherOnly", "DigitalSignature", "EncipherOnly", "KeyAgreement", "KeyCertSign", "KeyEncipherment", "None", "NonRepudiation" )] [String[]] $KeyUsage, [Alias("SmimeCapabilities")] [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [ValidateSet( "des", "des3", "rc2", "rc4", "des3wrap", "rc2wrap", "aes128", "aes192", "aes256", "aes128wrap", "aes192wrap", "aes256wrap", "md5", "sha1", "sha256", "sha384", "sha512" )] [String[]] $Smime, [Alias("SecurityIdentifier")] [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [ValidateNotNullOrEmpty()] [ValidatePattern("^S-1-5-21-[0-9]*-[0-9]*-[0-9]*-[0-9]*$")] [String] $Sid, [Parameter( ParameterSetName="NewRequest", Mandatory=$False )] [ValidateNotNullOrEmpty()] [String] $ChallengePassword, [Parameter( ParameterSetName="RenewalRequest", ValuefromPipeline = $True, Mandatory=$False )] [ValidateScript({($_.HasPrivateKey) -and ($null -ne $_.PSParentPath)})] [Security.Cryptography.X509Certificates.X509Certificate2] $SigningCert, [Alias("KeyStorageProvider")] [Parameter(Mandatory=$False)] [ValidateScript({ $Ksp = $_ [bool](Get-KeyStorageProvider | Where-Object { $_.Name -eq $Ksp })} )] [String] $Ksp = "Microsoft Software Key Storage Provider", [Parameter(Mandatory=$False)] [ValidateSet( "RSA", "ECDSA_P256", "ECDSA_P384", "ECDSA_P521", "ECDH_P256", "ECDH_P384", "ECDH_P521", "ML-DSA:44", "ML-DSA:65", "ML-DSA:87" )] [String] $KeyAlgorithm = "RSA", [Alias("KeySize")] [Parameter(Mandatory=$False)] [ValidateSet(512,1024,2048,3072,4096,8192)] [Int] $KeyLength = 3072, [Alias("Exportable")] [Parameter(Mandatory=$False)] [Switch] $PrivateKeyExportable = $False, [Alias("SSL")] [Parameter(Mandatory=$False)] [Switch] $UseSSL = $False, [Parameter(Mandatory=$False)] [ValidateRange(1,65535)] [Int] $Port, [Parameter(Mandatory=$False)] [ValidateSet("GET","POST")] [String] $Method = "POST", [Parameter(Mandatory=$False)] [ValidateNotNullOrEmpty()] [String] $Suffix = "certsrv/mscep/mscep.dll", [Parameter(Mandatory=$False)] [ValidateScript({$_.Subject -eq $_.Issuer})] [System.Security.Cryptography.X509Certificates.X509Certificate] $RootCaCert, [ValidateSet( "POSTPKIOperation", "Renewal", "SHA-512", "SHA-256", "SHA-1", "AES", "DES3")] [String[]] $CaCapabilites ) begin { # This hides the Status Indicators of the Invoke-WebRequest Calls later on $ProgressPreference = "SilentlyContinue" # Assembling the Configuration String, which is the SCEP URL in this Case If ($UseSSL) { $Protocol = "https" } Else { $Protocol = "http" } If ($Port) { $PortString = ":$($Port)" } Else { $PortString = [String]::Empty } $ConfigString = "$($Protocol)://$($ComputerName)$($PortString)/$($Suffix)/pkiclient.exe" Write-Verbose -Message "Configuration String: $ConfigString" # SCEP GetCACaps Operation if ($CaCapabilites) { $GetCACaps = $CaCapabilites -join [Environment]::NewLine } Else { Try { $GetCACaps = (Invoke-WebRequest -Uri "$($ConfigString)?operation=GetCACaps" -UseBasicParsing).Content } Catch { Write-Error -Message $PSItem.Exception.Message return } } # SCEP GetCACert Operation Try { $GetCACert = (Invoke-WebRequest -Uri "$($ConfigString)?operation=GetCACert" -UseBasicParsing).Content # Decoding the CMS (PKCS#7 Message that was returned from the SCEP Server) $Pkcs7CaCert = New-Object -TypeName Security.Cryptography.Pkcs.SignedCms $Pkcs7CaCert.Decode($GetCACert) } Catch { Write-Error -Message $PSItem.Exception.Message return } } process { # Skip pipeline processing if the preparation steps failed If (-not $GetCACaps) { return } If (-not $Pkcs7CaCert.Certificates) { return } # Ensuring we work with Elevation when messing with the Computer Certificate Store # As we want to inherit Key Settings from the Signing Certificate, we must also check its Certificate Store If ($MachineContext.IsPresent -or ($SigningCert -and ($SigningCert.PSParentPath -match "Machine"))) { If (-not ( [Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")) { Write-Error -Message "This must be run with Elevation (Run as Administrator) when using the Machine Context!" return } } $CertificateRequestPkcs10 = New-Object -ComObject "X509Enrollment.CX509CertificateRequestPkcs10" # Determining if we create an entirely new Certificate Request or inherit Settings from an old one If ($SigningCert) { # Certificate Renewal Request If ($GetCACaps -match "Renewal") { $InheritOptions = $X509RequestInheritOptions.InheritDefault $InheritOptions += $X509RequestInheritOptions.InheritSubjectAltNameFlag $InheritOptions += $X509RequestInheritOptions.InheritExtensionsFlag $InheritOptions += $X509RequestInheritOptions.InheritSubjectFlag $CertificateRequestPkcs10.InitializeFromCertificate( [int]($SigningCert.PSParentPath -match "Machine")+1, [Convert]::ToBase64String($SigningCert.RawData), $EncodingType.XCN_CRYPT_STRING_BASE64, $InheritOptions ) $CertificateRequestPkcs10.PrivateKey.Length = $KeyLength $CertificateRequestPkcs10.PrivateKey.ExportPolicy = [int]($PrivateKeyExportable.IsPresent) $CertificateRequestPkcs10.PrivateKey.ProviderName = $Ksp <# RFC 8894 A client that is performing certificate renewal as per Appendix D SHOULD send an empty challenge password (i.e. use the empty string as the challenge password) but MAY send the originally distributed challenge password in the challengePassword attribute. #> $CertificateRequestPkcs10.ChallengePassword = [String]::Empty } Else { Write-Error -Message "The Server does not support Renewal!" return } } Else { # New Certificate Request If ((-not $Dns) -and (-not $Upn) -and (-not $Email) -and (-not $IP) -and (-not $Subject)) { Write-Error -Message "You must provide an Identity, either in Form ob a Subject or Subject Alternative Name!" return } $PrivateKey = New-Object -ComObject X509Enrollment.CX509PrivateKey $PrivateKey.ProviderName = $Ksp $PrivateKey.MachineContext = [int]($MachineContext.IsPresent) $PrivateKey.ExportPolicy = [int]($PrivateKeyExportable.IsPresent) If ($KeyAlgorithm -ne "RSA") { $Algorithm = New-Object -ComObject X509Enrollment.CObjectId $Algorithm.InitializeFromAlgorithmName( $ObjectIdGroupId.XCN_CRYPT_PUBKEY_ALG_OID_GROUP_ID, $ObjectIdPublicKeyFlags.XCN_CRYPT_OID_INFO_PUBKEY_ANY, $AlgorithmFlags.AlgorithmFlagsNone, $KeyAlgorithm ) $PrivateKey.Algorithm = $Algorithm [void]([System.Runtime.Interopservices.Marshal]::ReleaseComObject($Algorithm)) } # Key Length is only relevant when Key Type is "RSA" If ($KeyAlgorithm -eq "RSA") { $PrivateKey.Length = $KeyLength } Try { $PrivateKey.Create() } Catch { [void]([System.Runtime.Interopservices.Marshal]::ReleaseComObject($PrivateKey)) Write-Error -Message $PSItem.Exception.Message return } $CertificateRequestPkcs10.InitializeFromPrivateKey( [int]($MachineContext.IsPresent)+1, $PrivateKey, [String]::Empty ) Try { # To Do: implement Validation of the Subject RDN $SubjectDnObject = New-Object -ComObject "X509Enrollment.CX500DistinguishedName" $SubjectDnObject.Encode($Subject) $CertificateRequestPkcs10.Subject = $SubjectDnObject } Catch { Write-Error -Message "Invalid Subject DN supplied!" return } # Set the Subject Alternative Names Extension if specified as Argument If ($Upn -or $Email -or $Dns -or $IP) { $SubjectAlternativeNamesExtension = New-Object -ComObject X509Enrollment.CX509ExtensionAlternativeNames $Sans = New-Object -ComObject X509Enrollment.CAlternativeNames Foreach ($Entry in $Upn) { $AlternativeNameObject = New-Object -ComObject X509Enrollment.CAlternativeName $AlternativeNameObject.InitializeFromString( $AlternativeNameType.XCN_CERT_ALT_NAME_USER_PRINCIPLE_NAME, $Entry ) $Sans.Add($AlternativeNameObject) [void]([System.Runtime.Interopservices.Marshal]::ReleaseComObject($AlternativeNameObject)) } Foreach ($Entry in $Email) { $AlternativeNameObject = New-Object -ComObject X509Enrollment.CAlternativeName $AlternativeNameObject.InitializeFromString( $AlternativeNameType.XCN_CERT_ALT_NAME_RFC822_NAME, $Entry ) $Sans.Add($AlternativeNameObject) [void]([System.Runtime.Interopservices.Marshal]::ReleaseComObject($AlternativeNameObject)) } Foreach ($Entry in $Dns) { $AlternativeNameObject = New-Object -ComObject X509Enrollment.CAlternativeName $AlternativeNameObject.InitializeFromString( $AlternativeNameType.XCN_CERT_ALT_NAME_DNS_NAME, $Entry ) $Sans.Add($AlternativeNameObject) [void]([System.Runtime.Interopservices.Marshal]::ReleaseComObject($AlternativeNameObject)) } Foreach ($Entry in $IP) { $AlternativeNameObject = New-Object -ComObject X509Enrollment.CAlternativeName $AlternativeNameObject.InitializeFromRawData( $AlternativeNameType.XCN_CERT_ALT_NAME_IP_ADDRESS, $EncodingType.XCN_CRYPT_STRING_BASE64, [Convert]::ToBase64String($Entry.GetAddressBytes()) ) $Sans.Add($AlternativeNameObject) [void]([System.Runtime.Interopservices.Marshal]::ReleaseComObject($AlternativeNameObject)) } $SubjectAlternativeNamesExtension.Critical = $True $SubjectAlternativeNamesExtension.InitializeEncode($Sans) # Adding the Extension to the Certificate $CertificateRequestPkcs10.X509Extensions.Add($SubjectAlternativeNamesExtension) } $X509Extensions = @{} If ($CertificateTemplate) { $X509Extensions.Add($Oid.szOID_CERTIFICATE_TEMPLATE, $(New-TemplateExtension -ObjectIdentifier $CertificateTemplate)) } If ($KeyUsage) { $X509Extensions.Add($Oid.szOID_KEY_USAGE, $(New-KeyUsageExtension -KeyUsage $KeyUsage)) } If ($Eku) { $X509Extensions.Add($Oid.XCN_OID_ENHANCED_KEY_USAGE, $(New-ExtendedKeyUsageExtension -Eku $Eku)) } If ($AppPolicy) { $X509Extensions.Add($Oid.szOID_APPLICATION_CERT_POLICIES, $(New-ApplicationPoliciesExtension -ApplicationPolicies $AppPolicy)) } If ($Smime) { $X509Extensions.Add($Oid.SmimeCapabilities, $(New-SmimeCapabilitiesExtension -Smime $Smime)) } If ($Sid) { $X509Extensions.Add($Oid.szOID_NTDS_CA_SECURITY_EXT, $(New-SidExtension -Sid $Sid)) } $X509Extensions.GetEnumerator() | ForEach-Object -Process { $X509Extension = New-Object -ComObject X509Enrollment.CX509Extension $X509ExtensionOid = New-Object -ComObject X509Enrollment.CObjectId try { $X509ExtensionOid.InitializeFromValue($_.Key) $X509Extension.Critical = $False $X509Extension.Initialize($X509ExtensionOid, $EncodingType.XCN_CRYPT_STRING_BASE64, $_.Value) $CertificateRequestPkcs10.X509Extensions.Add($X509Extension) } finally { $X509Extension | Unregister-ComObject $X509ExtensionOid | Unregister-ComObject } } If ($ChallengePassword) { <# RFC 8894 PKCS#10 [RFC2986] specifies a PKCS#9 [RFC2985] challengePassword attribute to be sent as part of the enrollment request. Inclusion of the challengePassword by the SCEP client is OPTIONAL and allows for unauthenticated authorization of enrollment requests. #> $CertificateRequestPkcs10.ChallengePassword = $ChallengePassword } } <# Identify the Root CA Certificate that was delivered with the Chain A certificate is self-issued if the same DN appears in the subject and issuer fields #> if ($null -eq $RootCaCert) { $RootCaCert = $Pkcs7CaCert.Certificates | Where-Object { $_.Subject -eq $_.Issuer } } else { # This is a workaround for the case where the SCEP server doesnt provide the Root CA certificate. In this case we must fool the Microsoft API and inject the user-provided one. $CertificateCollection = $Pkcs7CaCert.Certificates [void]$CertificateCollection.Add([System.Security.Cryptography.X509Certificates.X509Certificate2]::New($RootCaCert.RawData)) $GetCACert = $CertificateCollection.Export(5) } # Initialize the IX509SCEPEnrollment Interface $SCEPEnrollmentInterface = New-Object -ComObject "X509Enrollment.CX509SCEPEnrollment" # Let's try to build a SCEP Enrollment Message now... Try { $SCEPEnrollmentInterface.Initialize( $CertificateRequestPkcs10, (Get-Hash -Bytes $RootCaCert.RawData -HashAlgorithm "MD5"), $EncodingType.XCN_CRYPT_STRING_HEX, [Convert]::ToBase64String($GetCACert), $EncodingType.XCN_CRYPT_STRING_BASE64 ) } Catch { Write-Error -Message $PSItem.Exception.Message return } # Sets the preferred hash and encryption algorithms for the request. # If you do not set this property, then the default hash and encryption algorithms will be used. $SCEPEnrollmentInterface.ServerCapabilities = $GetCACaps <# RFC 8894 If the requester does not have an appropriate existing certificate, then a locally generated self-signed certificate MUST be used instead. The self-signed certificate MUST use the same subject name as in the PKCS#10 request. To create a renewal request, you must set this property prior to calling the CreateRequestMessage method. Otherwise, the CreateRequestMessage method will create a new request and generate a self-signed certificate using the same private key as the inner PKCSV10 reqeust. #> If ($SigningCert) { $SignerCertificate = New-Object -ComObject X509Enrollment.CSignerCertificate $SignerCertificate.Initialize( [int]($SigningCert.PSParentPath -match "Machine"), $X509PrivateKeyVerify.VerifyNone, # We did this already during Parameter Validation $EncodingType.XCN_CRYPT_STRING_BASE64, [Convert]::ToBase64String($SigningCert.RawData) ) $SCEPEnrollmentInterface.SignerCertificate = $SignerCertificate } # Building the PKCS7 Message for the SCEP Enrollment $SCEPRequestMessage = $SCEPEnrollmentInterface.CreateRequestMessage( $EncodingType.XCN_CRYPT_STRING_BASE64 ) # Submission to the SCEP Server Try { If ($Method -eq "POST") { If ($GetCACaps -match "POSTPKIOperation") { $SCEPResponse = Invoke-WebRequest ` -Body ([Convert]::FromBase64String($SCEPRequestMessage)) ` -Method 'POST' ` -Uri "$($ConfigString)?operation=PKIOperation" ` -Headers @{'Content-Type' = 'application/x-pki-message'} ` -UseBasicParsing } Else { Write-Warning -Message "The Server indicates that it doesnt support the 'POST' Method. Falling back to 'GET'." $Method = "GET" } } If ($Method -eq "GET") { $SCEPResponse = Invoke-WebRequest ` -Method 'GET' ` -Uri "$($ConfigString)?operation=PKIOperation&message=$([uri]::EscapeDataString($SCEPRequestMessage))" ` -Headers @{'Content-Type' = 'application/x-pki-message'} ` -UseBasicParsing } $SCEPResponse = [Convert]::ToBase64String($ScepResponse.Content) } Catch { Write-Error -Message $PSItem.Exception.Message return } Try { # Process a response message and return the disposition of the message. $Disposition = $SCEPEnrollmentInterface.ProcessResponseMessage( $SCEPResponse, $EncodingType.XCN_CRYPT_STRING_BASE64 ) Switch ($Disposition) { $X509SCEPDisposition.SCEPDispositionFailure { $ErrorMessage = '' $ErrorMessage += "The SCEP Server rejected the Certificate Request!`n" $FailInfo = ($SCEPFailInfo | Where-Object { $_.Code -eq $SCEPEnrollmentInterface.FailInfo() }) $ErrorMessage += "SCEP Failure Information: $($FailInfo.Message) ($($FailInfo.Code)) $($FailInfo.Description)`n" $ErrorMessage += "Additional Information returned by the Server: $($SCEPEnrollmentInterface.Status().Text)`n" If ($SCEPEnrollmentInterface.Status().Text -match $NDESErrorCode.CERT_E_WRONG_USAGE) { $ErrorMessage += "Possible reason(s): The Challenge Password has been used already." } If ($SCEPEnrollmentInterface.Status().Text -match $NDESErrorCode.TRUST_E_CERT_SIGNATURE) { $ErrorMessage += "Possible reason(s): The SCEP Server requires a Challenge Password but none was supplied." } If ($SCEPEnrollmentInterface.Status().Text -match $NDESErrorCode.ERROR_NOT_FOUND) { $ErrorMessage += "Possible reason(s): The Challenge Password supplied is unknown to the SCEP Server, or it has been used already." } If ($SCEPEnrollmentInterface.Status().Text -match $NDESErrorCode.CERTSRV_E_BAD_REQUESTSUBJECT) { $ErrorMessage += "Possible reason(s): The CA denied your request because an invalid Subject was requested." } If ($SCEPEnrollmentInterface.Status().Text -match $NDESErrorCode.RPC_S_SERVER_UNAVAILABLE) { $ErrorMessage += "Possible reason(s): The SCEP Server was unable to contact the Certification Authority." } Write-Error -Message $ErrorMessage } $X509SCEPDisposition.SCEPDispositionPending { Write-Warning -Message "The Enrollment was successful with Status ScepDispositionPending, which is not yet implemented!" } $X509SCEPDisposition.SCEPDispositionPendingChallenge { Write-Warning -Message "The Enrollment was successful with Status ScepDispositionPendingChallenge, which is not yet implemented!" } $X509SCEPDisposition.SCEPDispositionUnknown { Write-Error -Message "The Enrollment failed for an unknown Reason." } $X509SCEPDisposition.SCEPDispositionSuccess { # We load the Certificate into an X509Certificate2 Object $CertificateObject = [Security.Cryptography.X509Certificates.X509Certificate2]::new([Convert]::FromBase64String( $SCEPEnrollmentInterface.Certificate($EncodingType.XCN_CRYPT_STRING_BASE64))) # Return the resulting Certificate If ($MachineContext.IsPresent -or ($SigningCert -and ($SigningCert.PSParentPath -match "Machine"))) { Get-ChildItem -Path "Cert:\LocalMachine\My\$($CertificateObject.Thumbprint)" } Else { Get-ChildItem -Path "Cert:\CurrentUser\My\$($CertificateObject.Thumbprint)" } } } } Catch { Write-Error -Message $PSItem.Exception.Message return } # Cleaning up the COM Objects, avoiding any User Errors to be reported $CertificateRequestPkcs10, $SubjectDnObject, $SubjectAlternativeNamesExtension, $Sans, $SCEPEnrollmentInterface, $SignerCertificate | ForEach-Object -Process { Try { [void]([System.Runtime.Interopservices.Marshal]::ReleaseComObject($_)) } Catch { # we don't want to return anything here } } } end {} } # SIG # Begin signature block # MIInYwYJKoZIhvcNAQcCoIInVDCCJ1ACAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCCMO/NAx3z3P5V4 # 8YHZwEvtZTm6vYxlgJLOfon2Cwd6L6CCIBMwggZCMIIEKqADAgECAhBpEmNtaQD5 # xRtKmVz7/u/QMA0GCSqGSIb3DQEBCwUAMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQK # ExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2Rl # IFNpZ25pbmcgMjAyMSBDQTAeFw0yNjAzMTgwNzQ5NDRaFw0yNzA2MjAwNzQ5NDNa # MGgxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCYXllcm4xFDASBgNVBAcMC0TDvHJy # d2FuZ2VuMRgwFgYDVQQKDA9Vd2UgR3JhZGVuZWdnZXIxGDAWBgNVBAMMD1V3ZSBH # cmFkZW5lZ2dlcjCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBAM2hKwhe # E1F2z3bW4sx0w3zQoHm6QC3uXPWzhQ9slqAzgu4PHaIRE22OqlABXYtXq+iu2kh6 # PZxkim0QEdq1vtuHOKBnD1XEOBUx/NIi+PxZ02AaRulDO685tLUOrnupohxaG4qq # 6C/Seyab8/7tXzMEhv/PsOGl1N4m3YOLJjUslMVhkLoNc12T/PzF6qTZThBRiKeD # N0tlQo5EraLhghZ3jFKkpCH6ckGEVolBNwqg0BBJiT6mQtVlcZmlJK2c1rNq9Apw # IvN9bA+5A/w9T3yhbIlz0nuoIqdTaFq0DUH2SFQdXZP6xEPuAICJCDaDrc3hL4WF # gLc4Tw5SzwVKLawFeYhzCbq22CvA6+c4dGgMyLY99UXtIiHB52UQEmL50tkMRxWw # Hsonxy2/H380mrVQus2/lM1X9xYcQrxHcjoDjQSi4JCClZekVYPUxgd9lxYQBd8+ # PpdRucjAzKmOx0uc5+tddVRzMYYoc/xQSWj06aTr2zDQu+dpchWFJHEirQIDAQAB # o4IBeDCCAXQwDAYDVR0TAQH/BAIwADA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8v # Y2NzY2EyMDIxLmNybC5jZXJ0dW0ucGwvY2NzY2EyMDIxLmNybDBzBggrBgEFBQcB # AQRnMGUwLAYIKwYBBQUHMAGGIGh0dHA6Ly9jY3NjYTIwMjEub2NzcC1jZXJ0dW0u # Y29tMDUGCCsGAQUFBzAChilodHRwOi8vcmVwb3NpdG9yeS5jZXJ0dW0ucGwvY2Nz # Y2EyMDIxLmNlcjAfBgNVHSMEGDAWgBTddF1MANt7n6B0yrFu9zzAMsBwzTAdBgNV # HQ4EFgQUwj1KxaiWz3BWxuN8zTWx+dWip28wSwYDVR0gBEQwQjAIBgZngQwBBAEw # NgYLKoRoAYb2dwIFAQQwJzAlBggrBgEFBQcCARYZaHR0cHM6Ly93d3cuY2VydHVt # LnBsL0NQUzATBgNVHSUEDDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8EBAMCB4AwDQYJ # KoZIhvcNAQELBQADggIBADrSbHhlYMa9ixnpIWBgVhL76qdlK5iPN35rlMHgK89n # O9afz8EYTK7UExehOZxHtpLqO/hJu4eIQmjzC+tyUDii/3+IPoL1R9NlxAgoPxMc # 3voLsX0xwTkl+R6dO6Q8RM3EDsknyUtVpjBggCPZ0pZsNumV1BXdIPPzdA1Rxm3F # 6zcOGaXAJH37EWtbnc2e3X4EIxRFPm2EP5oiEYVEi90B3lcmo5p3iJG6zNSr+apG # neN4AWuoGMbYBT7Ms5CdmbaM6uhuq73OqP6x47VjyeXpfuEVxvLSBfL24AI73//3 # 8sq2gH//j4qE8Ic4hV8NIBsHLvHuFH06z2EqWoEI0dKz2C92S86hqw+OGAcgLTVE # StRppJXgtJwwxusm9OiJPIfDFY7kQxSGRq4B1YR1GGaUm1p4s2+819H8sYM+RGbM # MCrY4C8EQNeCJedXZeCIXyWFDRizK7BB6B24DC0a7XR7cedQOMwMy/m9kZRsSt6X # 7c84iOhCEL3Degnv8V4/KJSDtaOMVQUm6vRyFdQEfkVCHCaOuM6i4lQwKu38nOx+ # vNkCOSm3LWrYJGMxk1/KcPL5T+nR8WIR9SaS2vEGEvZmie71Q6qdug8cmPibxIs6 # N8wM2NJ+fDBHhoZl6as2VmDvLhqkbJaC0Piz82UWi6lGAfrhs4sLjOPIRvSauJTe # MIIGuTCCBKGgAwIBAgIRAJmjgAomVTtlq9xuhKaz6jkwDQYJKoZIhvcNAQEMBQAw # gYAxCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBT # LkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJDAi # BgNVBAMTG0NlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EgMjAeFw0yMTA1MTkwNTMy # MThaFw0zNjA1MTgwNTMyMThaMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3Nl # Y28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25p # bmcgMjAyMSBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAJ0jzwQw # IzvBRiznM3M+Y116dbq+XE26vest+L7k5n5TeJkgH4Cyk74IL9uP61olRsxsU/WB # AElTMNQI/HsE0uCJ3VPLO1UufnY0qDHG7yCnJOvoSNbIbMpT+Cci75scCx7UsKK1 # fcJo4TXetu4du2vEXa09Tx/bndCBfp47zJNsamzUyD7J1rcNxOw5g6FJg0ImIv7n # CeNn3B6gZG28WAwe0mDqLrvU49chyKIc7gvCjan3GH+2eP4mYJASflBTQ3HOs6JG # driSMVoD1lzBJobtYDF4L/GhlLEXWgrVQ9m0pW37KuwYqpY42grp/kSYE4BUQrbL # gBMNKRvfhQPskDfZ/5GbTCyvlqPN+0OEDmYGKlVkOMenDO/xtMrMINRJS5SY+jWC # i8PRHAVxO0xdx8m2bWL4/ZQ1dp0/JhUpHEpABMc3eKax8GI1F03mSJVV6o/nmmKq # DE6TK34eTAgDiBuZJzeEPyR7rq30yOVw2DvetlmWssewAhX+cnSaaBKMEj9O2GgY # kPJ16Q5Da1APYO6n/6wpCm1qUOW6Ln1J6tVImDyAB5Xs3+JriasaiJ7P5KpXeiVV # /HIsW3ej85A6cGaOEpQA2gotiUqZSkoQUjQ9+hPxDVb/Lqz0tMjp6RuLSKARsVQg # ETwoNQZ8jCeKwSQHDkpwFndfCceZ/OfCUqjxAgMBAAGjggFVMIIBUTAPBgNVHRMB # Af8EBTADAQH/MB0GA1UdDgQWBBTddF1MANt7n6B0yrFu9zzAMsBwzTAfBgNVHSME # GDAWgBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0l # BAwwCgYIKwYBBQUHAwMwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL2NybC5jZXJ0 # dW0ucGwvY3RuY2EyLmNybDBsBggrBgEFBQcBAQRgMF4wKAYIKwYBBQUHMAGGHGh0 # dHA6Ly9zdWJjYS5vY3NwLWNlcnR1bS5jb20wMgYIKwYBBQUHMAKGJmh0dHA6Ly9y # ZXBvc2l0b3J5LmNlcnR1bS5wbC9jdG5jYTIuY2VyMDkGA1UdIAQyMDAwLgYEVR0g # ADAmMCQGCCsGAQUFBwIBFhhodHRwOi8vd3d3LmNlcnR1bS5wbC9DUFMwDQYJKoZI # hvcNAQEMBQADggIBAHWIWA/lj1AomlOfEOxD/PQ7bcmahmJ9l0Q4SZC+j/v09CD2 # csX8Yl7pmJQETIMEcy0VErSZePdC/eAvSxhd7488x/Cat4ke+AUZZDtfCd8yHZgi # kGuS8mePCHyAiU2VSXgoQ1MrkMuqxg8S1FALDtHqnizYS1bIMOv8znyJjZQESp9R # T+6NH024/IqTRsRwSLrYkbFq4VjNn/KV3Xd8dpmyQiirZdrONoPSlCRxCIi54vQc # qKiFLpeBm5S0IoDtLoIe21kSw5tAnWPazS6sgN2oXvFpcVVpMcq0C4x/CLSNe0Xc # kmmGsl9z4UUguAJtf+5gE8GVsEg/ge3jHGTYaZ/MyfujE8hOmKBAUkVa7NMxRSB1 # EdPFpNIpEn/pSHuSL+kWN/2xQBJaDFPr1AX0qLgkXmcEi6PFnaw5T17UdIInA58r # Tu3mefNuzUtse4AgYmxEmJDodf8NbVcU6VdjWtz0e58WFZT7tST6EWQmx/OoHPel # E77lojq7lpsjhDCzhhp4kfsfszxf9g2hoCtltXhCX6NqsqwTT7xe8LgMkH4hVy8L # 1h2pqGLT2aNCx7h/F95/QvsTeGGjY7dssMzq/rSshFQKLZ8lPb8hFTmiGDJNyHga # 5hZ59IGynk08mHhBFM/0MLeBzlAQq1utNjQprztZ5vv/NJy8ua9AGbwkMWkOMIIF # yTCCBLGgAwIBAgIQG7WPJSrfIwBJKMmuPX7tJzANBgkqhkiG9w0BAQwFADB+MQsw # CQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEn # MCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIwIAYDVQQD # ExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMB4XDTIxMDUzMTA2NDMwNloXDTI5 # MDkxNzA2NDMwNlowgYAxCzAJBgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRl # Y2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBB # dXRob3JpdHkxJDAiBgNVBAMTG0NlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EgMjCC # AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL35ePjm1YAMZJ2GG5ZkZz8i # Oh51AX3v+1xnjMnMXGupkea5QuUgS5vam3u5mV3Zm4BL14RAKyfT6Lowuz4JGqdJ # le8rQCTCl8en7psl76gKAJeFWqqd3CnJ4jUH63BNStbBs1a4oUE4m9H7MX+P4F/h # sT8PjhZJYNcGjRj5qiYQqyrT0NFnjRtGvkcw1S5y0cVj2udjeUR+S2MkiYYuND8p # TFKLKqfA4pEoibnAW/kd2ecnrf+aApfBxlCSmwIsvam5NFkKv4RK/9/+s5/r2Z7g # mCPspmt3FirbzK07HKSH3EZzXhliaEVX5JCCQrtC1vBh4MGjPWajXfQY7ojJjRdF # KZkydQIx7ikmyGsC5rViRX83FVojaInUPt5OJ7DwQAy8TRfLTaKzHtAGWt32k89X # dZn1+oYaZ3izv5b+NNy951JW5bPldXvXQZEF3F1p45UNQ7n8g5Y5lXtsgFpPE3LG # 130pekS6UqQq1UFGCSD+IqC2WzCNvIkM1ddw+IdS/drvrFEuB7NO/tAJ2nDvmPpW # 5m3btVdL3OUsJRXIni54TvjanJ6GLMpX8xrlyJKLGoKWesO8UBJp2A5aRos66yb6 # I8m2sIG+QgCk+Nb+MC7H0kb25Y51/fLMudCHW8wGEGC7gzW3XmfeR+yZSPGkoRX+ # rYxijjlVTzkWubFjnf+3AgMBAAGjggE+MIIBOjAPBgNVHRMBAf8EBTADAQH/MB0G # A1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAfBgNVHSMEGDAWgBQIds3LB/8k # 9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYwLwYDVR0fBCgwJjAkoCKgIIYe # aHR0cDovL2NybC5jZXJ0dW0ucGwvY3RuY2EuY3JsMGsGCCsGAQUFBwEBBF8wXTAo # BggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3AtY2VydHVtLmNvbTAxBggrBgEF # BQcwAoYlaHR0cDovL3JlcG9zaXRvcnkuY2VydHVtLnBsL2N0bmNhLmNlcjA5BgNV # HSAEMjAwMC4GBFUdIAAwJjAkBggrBgEFBQcCARYYaHR0cDovL3d3dy5jZXJ0dW0u # cGwvQ1BTMA0GCSqGSIb3DQEBDAUAA4IBAQBRwqFYFiIQi/yGMdTCMtNc+EuiL2o+ # TfirCB7t1ej65wgN7LfGHg6ydQV6sQv613RqAAYfpM6q8mt92BHAEQjUDk1hxTqo # +rHh45jq4mP9QfWTfQ28XZI7kZplutBfTL5MjWgDEBbV8dAEioUz+TfnWy4maUI8 # us281HrpTZ3a50P7Y1KAhQTEJZVV8H6nnwHFWyj44M6GcKYnOzn7OC6YU2UidS3X # 9t0iIpGW691o7T+jGZfTOyWI7DYSPal+zgKNBZqSpyduRbKcYoY3DaQzjteoTtBK # F0NMxfGnbNIeWGwUUX6KVKH27595el2BmhaQD+G78UoA+fndvu2q7M4KMIIGuTCC # BKGgAwIBAgIRAOf/acc7Nc5LkSbYdHxopYcwDQYJKoZIhvcNAQEMBQAwgYAxCzAJ # BgNVBAYTAlBMMSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScw # JQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJDAiBgNVBAMT # G0NlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EgMjAeFw0yMTA1MTkwNTMyMDdaFw0z # NjA1MTgwNTMyMDdaMFYxCzAJBgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0 # YSBTeXN0ZW1zIFMuQS4xJDAiBgNVBAMTG0NlcnR1bSBUaW1lc3RhbXBpbmcgMjAy # MSBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAOkSHwQ17bldesWm # lUG+imV/TnfRbSV102aO2/hhKH9/t4NAoVoipzu0ePujH67y8iwlmWuhqRR4xLeL # dPxolEL55CzgUXQaq+Qzr5Zk7ySbNl/GZloFiYwuzwWS2AVgLPLCZd5DV8QTF+V5 # 7Y6lsdWTrrl5dEeMfsxhkjM2eOXabwfLy6UH2ZHzAv9bS/SmMo1PobSx+vHWST7c # 4aiwVRvvJY2dWRYpTipLEu/XqQnqhUngFJtnjExqTokt4HyzOsr2/AYOm8YOcoJQ # xgvc26+LAfXHiBkbQkBdTfHak4DP3UlYolICZHL+XSzSXlsRgqiWD4MypWGU4A13 # xiHmaRBZowS8FET+QAbMiqBaHDM3Y6wohW07yZ/mw9ZKu/KmVIAEBhrXesxifPB+ # DTyeWNkeCGq4IlgJr/Ecr1px6/1QPtj66yvXl3uauzPPGEXUk6vUym6nZyE1IGXI # 45uGVI7XqvCt99WuD9LNop9Kd1LmzBGGvxucOo0lj1M3IRi8FimAX3krunSDguC5 # HgD75nWcUgdZVjm/R81VmaDPEP25Wj+C1reicY5CPckLGBjHQqsJe7jJz1CJXBMU # tZs10cVKMEK3n/xD2ku5GFWhx0K6eFwe50xLUIZD9GfT7s/5/MyBZ1Ep8Q6H+GMu # udDwF0mJitk3G8g6EzZprfMQMc3DAgMBAAGjggFVMIIBUTAPBgNVHRMBAf8EBTAD # AQH/MB0GA1UdDgQWBBS+VAIvv0Bsc0POrAklTp5DRBru4DAfBgNVHSMEGDAWgBS2 # oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYI # KwYBBQUHAwgwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL2NybC5jZXJ0dW0ucGwv # Y3RuY2EyLmNybDBsBggrBgEFBQcBAQRgMF4wKAYIKwYBBQUHMAGGHGh0dHA6Ly9z # dWJjYS5vY3NwLWNlcnR1bS5jb20wMgYIKwYBBQUHMAKGJmh0dHA6Ly9yZXBvc2l0 # b3J5LmNlcnR1bS5wbC9jdG5jYTIuY2VyMDkGA1UdIAQyMDAwLgYEVR0gADAmMCQG # CCsGAQUFBwIBFhhodHRwOi8vd3d3LmNlcnR1bS5wbC9DUFMwDQYJKoZIhvcNAQEM # BQADggIBALiTWXfJTBX9lAcIoKd6oCzwQZOfARQkt0OmiQ390yEqMrStHmpfycgg # fPGlBHdMDDYhHDVTGyvY+WIbdsIWpJ1BNRt9pOrpXe8HMR5sOu71AWOqUqfEIXaH # WOEs0UWmVs8mJb4lKclOHV8oSoR0p3GCX2tVO+XF8Qnt7E6fbkwZt3/AY/C5KYzF # ElU7TCeqBLuSagmM0X3Op56EVIMM/xlWRaDgRna0hLQze5mYHJGv7UuTCOO3wC1b # zeZWdlPJOw5v4U1/AljsNLgWZaGRFuBwdF62t6hOKs86v+jPIMqFPwxNJN/ou22D # qzpP+7TyYNbDocrThlEN9D2xvvtBXyYqA7jhYY/fW9edUqhZUmkUGM++Mvz9lyT/ # nBdfaKqM5otK0U5H8hCSL4SGfjOVyBWbbZlUIE8X6XycDBRRKEK0q5JTsaZksoKa # bFAyRKJYgtObwS1UPoDGcmGirwSeGMQTJSh+WR5EXZaEWJVA6ZZPBlGvjgjFYaQ0 # kLq1OitbmuXZmX7Z70ks9h/elK0A8wOg8oiNVd3o1bb59ms1QF4OjZ45rkWfsGuz # 8ctB9/leCuKzkx5Rt1WAOsXy7E7pws+9k+jrePrZKw2DnmlNaT19QgX2I+hFtvhC # 6uOhj/CgjVEA4q1i1OJzpoAmre7zdEg+kZcFIkrDHgokA5mcIMK1MIIGgjCCBGqg # AwIBAgIQKPB3wRw2vf5fdDJHcCcuAzANBgkqhkiG9w0BAQwFADBWMQswCQYDVQQG # EwJQTDEhMB8GA1UEChMYQXNzZWNvIERhdGEgU3lzdGVtcyBTLkEuMSQwIgYDVQQD # ExtDZXJ0dW0gVGltZXN0YW1waW5nIDIwMjEgQ0EwHhcNMjYwMzExMDczNDU0WhcN # MzYwMjI3MDczNDU0WjBQMQswCQYDVQQGEwJQTDEhMB8GA1UECgwYQXNzZWNvIERh # dGEgU3lzdGVtcyBTLkEuMR4wHAYDVQQDDBVDZXJ0dW0gVGltZXN0YW1wIDIwMjYw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC4vc3wcPsSNdoYthfbjUAT # Tkk5EyItd37odw4lsmyOd/dmwXycOrTu8w7O1Kj/63o1X+MRU1N1zTj7LjhZD+Uj # xbJ1sJ91SS/jYTYbLro72LELWkJ7zaNcJOOq3k4MLNS/DhRHSmsYMqk+MzkMfNZi # 8DWUqlzVPUa2/aACViReDMnc/gtXm7tA9Pr4DN7agEPE1NtN36oCgj6iHR5aGhah # /XskfvLZ6ZstoZ5zefWTrZrLh3kcH+YkzoZYX9Hf6qqrizkiBj4BlS9R4+VwVKMd # jhO7UEa/pf8cTWy+jrsATuAGthG7sWIN+3KV7+Ytv5Uy+DQEgf3bn/VuH4wN0aPh # j/mwueJ9jmIjNwqvM/dno8fBeR1jtnuP++XgveQfbTMP3qu9dPRg8ltvtrreQZ9K # PDFyUxEZMsrLVm6nJ1JKJgPe6n4gwsL6VrjjHX0zpLF3vUvsQ8TiWgm4sk4r4D7p # cXE/rX0E0Vwa+VMLT73PiDZ2nzhIpc1RwNdbb/qR3Mpa8sQXNPHFIoX/7bapGUtG # 5sd1cUGsvLqIWk6dP/xAgPb2BludUinSTCYV7ysiHQS8vFmDXIU7fMkSE7/QHcYP # Sahro4fk5z9W1t2kIxbZRJe0s4DXiPDlQPwiQFllLkU9wLvU6DqR8v35a65J4TeI # XhMO/+iCzL+B0rI9GGeKLQIDAQABo4IBUDCCAUwwdQYIKwYBBQUHAQEEaTBnMDsG # CCsGAQUFBzAChi9odHRwOi8vc3ViY2EucmVwb3NpdG9yeS5jZXJ0dW0ucGwvY3Rz # Y2EyMDIxLmNlcjAoBggrBgEFBQcwAYYcaHR0cDovL3N1YmNhLm9jc3AtY2VydHVt # LmNvbTAfBgNVHSMEGDAWgBS+VAIvv0Bsc0POrAklTp5DRBru4DAMBgNVHRMBAf8E # AjAAMDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9zdWJjYS5jcmwuY2VydHVtLnBs # L2N0c2NhMjAyMS5jcmwwFgYDVR0lAQH/BAwwCgYIKwYBBQUHAwgwDgYDVR0PAQH/ # BAQDAgeAMCIGA1UdIAQbMBkwCAYGZ4EMAQQCMA0GCyqEaAGG9ncCBQELMB0GA1Ud # DgQWBBQjOWooq5oSp6Sn8h/5RZq/jf6CAzANBgkqhkiG9w0BAQwFAAOCAgEAZv6T # m6wL3k6mBTwkrYcTVcAR01uE37gUGNihgnTJR+gC41T2H9lwETRjE10nEdCUNv3N # i8S6aBx4UcMRX93fd9w4RUteua2I+oj0kCpuNa3PQDKUwozHZmotWivaPO9KTs08 # y0YVhVSMZvuUH/reFec9eLT6FLAFnX0Sg9Wc7833uQB5RPa8TmXBkTolC8bNxHX+ # 2SfEWSNI8w/Y7o9qBF9l0uwVSrjQitVtIdZo2qb9NvMqqPFLWYef9SG+PGMqfPAQ # 2EoYeT0hlFLkubWF1X3HbiDwXtz3TU2EWHU+VTcZMC4IzMyHK/+kh9n3oxSQ45ws # Y71y7mqxKyYPyHSPoV3RiAQ1Thr9c65BeJLaELxWSKeQyAGIdBsMlIXPO6qp+VGm # E49vosogQ0jYe2hgq5LgJ6oO0Ie364V/kITBnifUqS6Zxu+qjfOYS8o72EeoEWIi # 04/BuH8Y6leNNP27j8NKwaPciWcqv/HBnQjizzmH/aqXn03K2SnjvaYPlCR8fFAA # W2k6os0cZvLFEhMnHHAghYSIrdwCP98BrkjgA3ogOu+jXEO/nbD9OGL873Te6U2T # coOu9lqQQyXYNHiLR5eMqJrzXiDlodarOEKjlukyPDnLIuLkg0y6K8S1A5wU8CkM # 86cXdWFHLRIEYd9kdCfRZBZHhK7iVPeEZYxa9bgxggamMIIGogIBATBqMFYxCzAJ # BgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAi # BgNVBAMTG0NlcnR1bSBDb2RlIFNpZ25pbmcgMjAyMSBDQQIQaRJjbWkA+cUbSplc # +/7v0DANBglghkgBZQMEAgEFAKCBiDAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIB # BDAcBgkqhkiG9w0BCQUxDxcNMjYxMDA3MTQyMTU0WjAcBgorBgEEAYI3AgELMQ4w # DAYKKwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgB9E56ChZWvAN7Co5gqZP8k5K # sTdHSIsRQopvcyMNdBwwDQYJKoZIhvcNAQEBBQAEggGAbq5P40GrzfE9k7lZ6V8v # unCBibowNRzsoeuny6hAb0pNXoYsW2emYw7Hmu2DpLlf/UiE+8+qEpWepd1vUQ+U # WzCgWrqEnqHy2eNbNiT+I3NaIyRv8LYyPJkChLPY5SDDl7i8H/QNI69Y5+6MwTU7 # WfcJS+HKNs3QUKLb6n8ZiNr/IbaG8qMqpVa6UJlSY/JQYRHzgzEHhET+Ba+JrDxD # MOKKlER5pZ3YOnNhCHXIqgwEjHIVSf9y3ykD00PFDheTOD/HgMNYDRTqYW33TTKp # CxaBc2jQ4wNg+0TsQJBrdvQxnrdlRvD1nHUZfepiLsQHyWfwQ4Dq4vHkXqbXISxh # awzcntptsYjarGWwB1kusjIPYTYpBNQ3+QHpfb4cS/p8ZWcbhazaha5iMOql5+kj # zSPjRRf1eilHvtZxk/DKgRKuM7nUQqLk9gFSGZfIfZtgmWDBHey8xo07J34eJmtR # hRmtHWeML+FNSZDZ2yVRkJ9KsAw1iznMehxeCxquEgtzoYIEAjCCA/4GCSqGSIb3 # DQEJBjGCA+8wggPrAgEBMGowVjELMAkGA1UEBhMCUEwxITAfBgNVBAoTGEFzc2Vj # byBEYXRhIFN5c3RlbXMgUy5BLjEkMCIGA1UEAxMbQ2VydHVtIFRpbWVzdGFtcGlu # ZyAyMDIxIENBAhAo8HfBHDa9/l90MkdwJy4DMA0GCWCGSAFlAwQCAgUAoIIBVjAa # BgkqhkiG9w0BCQMxDQYLKoZIhvcNAQkQAQQwHAYJKoZIhvcNAQkFMQ8XDTI2MTAw # NzE0MjE1NVowNwYLKoZIhvcNAQkQAi8xKDAmMCQwIgQghb6Q4QrSQ418ySi2r0iw # mrIIF3zs+LASbFjTkQUlxDwwPwYJKoZIhvcNAQkEMTIEMAu1uwwFOLXFy4KYzLHo # Pv4pOFrGGmPii2doOw4laboMZDkwZaqD26Z+/O9ldLvZBjCBnwYLKoZIhvcNAQkQ # AgwxgY8wgYwwgYkwgYYEFFcUaEEMqFrzQk75FkpRNhD0042YMG4wWqRYMFYxCzAJ # BgNVBAYTAlBMMSEwHwYDVQQKExhBc3NlY28gRGF0YSBTeXN0ZW1zIFMuQS4xJDAi # BgNVBAMTG0NlcnR1bSBUaW1lc3RhbXBpbmcgMjAyMSBDQQIQKPB3wRw2vf5fdDJH # cCcuAzANBgkqhkiG9w0BAQEFAASCAgBK50Y2IMoBuUmPGdeNLupRpk0ikzXm+iDN # qEGCBx4q1zx1YpdsSMJo7OFMv4gB7yLnzwA4g/nOeO+QtHHqO6QUc6xQZvS45i+2 # iI374NA1ce3Wr4OHmY7kDWk1dGFLv6nvudmTxzmf8XKfrqXqNzYtJZcAkVwE8gtZ # jVprvaSe8+W1XKZZLoPDzEkAoRGTvFuPtfCTDw/AimwUO32tMG5CRWbpedCzjh0X # W/I8QvK0SWsoILZL51knl2KpS7utfGYZC7p+H8JKSiJi98bT7oyUJpqPI/YymIjf # 0B0gSxlburqoyrbDtfsNvPoqUAhwpgGc6jEYwG5Od2KdDCMjUA7EbJ7OzUGhDjW+ # AdfmvcuHfw2nvPTDgyryMt+78QtCOvV/OPU2O3uQ9eplT+VDcSGmiMGmO4unzScc # wrs2f7fuEhCLBkp4GPAjisRsN+QNM1ky6lywYt3xcSC+w2Q5VN8PSidFlqBZC9iQ # jtTellQI++vpFr8h0PsFNmwIcefVlt7cvXxRLcU8yLdQsF+8hbzxlLP8hdLAdP+q # pu+/09R7J00NRyFMB/MrLSZmUZUXC1TV6t1tt1RHq5ne7cWxO4/zmVelqiLEKTRi # jC7AjfZ4t+G6BE0Z9a62VmZvebVDTQ4psp+ZggaSw6Yt98UezfGbu9sCVuW1LUOR # KQqQY7GsYg== # SIG # End signature block |