Functions/Get-IssuedCertificate.ps1

<#
    .SYNOPSIS
    Allows for Submission of a Certificate Request to a Certification Authority.
    Allows for retrieval of a previously issued Certificate from a Certification Authority.
 
    .PARAMETER CertificateRequest
    The BASE64 encoded Certificate Request to be submitted to the Certification Authority.
 
    .PARAMETER RequestId
    The Request Identifier that was given to a previously submitted Certificate Request.
 
    .PARAMETER ConfigString
    The Comnfiguration String for the Certificate Authority to connect to, either
    in the Form of "<Hostname>\<Common-Name-of-CA>" for a RPC/DCOM Enrollment or
    in for Form of "https://<Hostname>/<Common-Name-of-CA>_CES_<Authentication-Type>/service.svc/CES"
    for a WSTEP (Certificate Enrollment Web Service) Enrollment.
 
    .PARAMETER CertificateTemplate
    Optional: The name of the Certificate Template to request a Certificate from.
    Must be used if the Certificate does not contain this information.
 
    .PARAMETER Credential
    Credentials when performing a WSTEP Enrollment with Username/Password Authentication.
 
    .PARAMETER ClientCertificate
    Thumbprint of an authentication Certificate when performing a WSTEP Enrollment with Client Certificate Authentication.
 
    .OUTPUTS
    An object representing the Enrollment/Retrieval result.
#>


Function Get-IssuedCertificate {

    [CmdletBinding()]
    param (

        [Parameter(
            ParameterSetName="Submit",
            Mandatory=$True,
            ValuefromPipeline=$True
            )]
        [ValidateNotNullOrEmpty()]
        [String]
        $CertificateRequest,

        [Parameter(
            ParameterSetName="Retrieve",
            Mandatory=$True
            )]
        [ValidateRange(1,4294967295)] # According to ADCS Database Schema, maximum should be 32 Bit
        [System.Uint32]
        $RequestId,

        [Parameter(Mandatory=$True)]
        [ValidateNotNullOrEmpty()]
        [String]
        $ConfigString,
    
        [Parameter(
            ParameterSetName="Submit",
            Mandatory=$False
            )]
        [ValidateNotNullOrEmpty()]
        [String]
        $CertificateTemplate,
        
        [Parameter(Mandatory=$False)]
        [System.Management.Automation.PSCredential]
        $Credential,

        [Parameter(Mandatory=$False)]
        [ValidatePattern("^[0-9a-fA-F]{40}$")]
        [String]
        $ClientCertificate
    )
    
    begin {}

    process {

        $CertRequest = New-Object -ComObject CertificateAuthority.Request

        # Configuring the Certificate Request Interface when using the WSTEP Protocol
        # https://docs.microsoft.com/en-us/windows/win32/api/certcli/nf-certcli-icertrequest3-setcredential
        If ($ConfigString.StartsWith("https://")) { 

            # WSTEP with Username and Password Authentication
            If ($ConfigString.EndsWith(
                "UsernamePassword/service.svc/CES", 
                [System.StringComparison]::OrdinalIgnoreCase
                )) {

                If ($Credential) {

                    $CertRequest.SetCredential(
                        [Int]$null, # no Window Handle
                        $X509EnrollmentAuthFlags.X509AuthUsername,
                        $Credential.UserName,
                        [Runtime.InteropServices.Marshal]::PtrToStringAuto(
                            [Runtime.InteropServices.Marshal]::SecureStringToBSTR($Credential.Password)
                        )
                    )

                }
                Else {
                    Write-Error -Message "You must provide Authentication Credentials."
                    return
                }
            }

            # WSTEP with Client Certificate Authentication
            If ($ConfigString.EndsWith(
                "Certificate/service.svc/CES", 
                [System.StringComparison]::OrdinalIgnoreCase
                )) {

                If ($ClientCertificate) {

                    $CertRequest.SetCredential(
                        [Int]$null, # no Window Handle
                        $X509EnrollmentAuthFlags.X509AuthCertificate,
                        $ClientCertificate,
                        [String]::Empty
                    )

                }
                Else {
                    Write-Error -Message "You must provide a Client Authentication Certificate Thumbprint."
                    return
                }
            }

            # WSTEP with Kerberos Authentication
            If ($ConfigString.EndsWith(
                "Kerberos/service.svc/CES", 
                [System.StringComparison]::OrdinalIgnoreCase
                )) {
    
                $CertRequest.SetCredential(
                    [Int]$null, # no Window Handle
                    $X509EnrollmentAuthFlags.X509AuthKerberos,
                    [String]::Empty,
                    [String]::Empty
                )

            }
        }

        # Submit a Certificate Request
        If ($CertificateRequest) {

            If ($CertificateTemplate) {
                $Attributes = "CertificateTemplate:$($CertificateTemplate)"
            }
            Else {
                $Attributes = [String]::Empty
            }

            Try {
                # https://docs.microsoft.com/en-us/windows/win32/api/certcli/nf-certcli-icertrequest-submit
                $Status = $CertRequest.Submit(
                    $RequestFlags.CR_IN_ENCODEANY,
                    $CertificateRequest,
                    $Attributes,
                    $ConfigString
                )
            }
            Catch {
                Write-Error -Message $PSItem.Exception.Message
                return
            }
        }

        # Retrieve a pending Certificate Request
        If ($RequestId) {

            Try {
                # https://docs.microsoft.com/en-us/windows/win32/api/certcli/nf-certcli-icertrequest-retrievepending
                $Status = $CertRequest.RetrievePending(
                    $RequestId,
                    $ConfigString
                )
            }
            Catch {
                Write-Error -Message $PSItem.Exception.Message
                return
            }
        }

        $StatusCode = "0x" + ('{0:x}' -f $CertRequest.GetLastStatus())
        $StatusMessage = (New-Object System.ComponentModel.Win32Exception($CertRequest.GetLastStatus())).Message

        # Process the Submission Result and return it
        Switch ($Status) {

            $DispositionType.CR_DISP_INCOMPLETE {

                [PSCustomObject]@{
                    RequestId = $CertRequest.GetRequestId()
                    Disposition = $Status
                    Result = "Request is incomplete"
                    StatusCode = $StatusCode
                    StatusMessage = $StatusMessage
                    Certificate = $null
                    RawCertificate = $null
                }
            }
           
            $DispositionType.CR_DISP_ERROR {

                [PSCustomObject]@{
                    RequestId = $CertRequest.GetRequestId()
                    Disposition = $Status
                    Result = "There was an error during submission"
                    StatusCode = $StatusCode
                    StatusMessage = $StatusMessage
                    Certificate = $null
                    RawCertificate = $null
                }
            }

            $DispositionType.CR_DISP_DENIED {

                [PSCustomObject]@{
                    RequestId = $CertRequest.GetRequestId()
                    Disposition = $Status
                    Result = "Request was denied"
                    StatusCode = $StatusCode
                    StatusMessage = $StatusMessage
                    Certificate = $null
                    RawCertificate = $null
                }
            }

            $DispositionType.CR_DISP_ISSUED {

                # https://docs.microsoft.com/en-us/windows/win32/api/certcli/nf-certcli-icertrequest-getcertificate
                # https://docs.microsoft.com/en-us/dotnet/api/system.security.cryptography.x509certificates.x509certificate2.import
                $CertificateObject = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
                $CertificateObject.Import(
                    [Convert]::FromBase64String(
                        $CertRequest.GetCertificate($RequestFlags.CR_OUT_BASE64)
                    )
                )

                [PSCustomObject]@{
                    RequestId = $CertRequest.GetRequestId()
                    Disposition = $Status
                    Result = "Certificate was issued"
                    StatusCode = $StatusCode
                    StatusMessage = $StatusMessage
                    Certificate = $CertificateObject
                    RawCertificate = $CertRequest.GetCertificate($RequestFlags.CR_OUT_BASE64HEADER)
                }
            }

            $DispositionType.CR_DISP_ISSUED_OUT_OF_BAND {

                [PSCustomObject]@{
                    RequestId = $CertRequest.GetRequestId()
                    Disposition = $Status
                    Result = "Certificate was issued out of band"
                    StatusCode = $StatusCode
                    StatusMessage = $StatusMessage
                    Certificate = $null
                    RawCertificate = $null
                }
            }

            $DispositionType.CR_DISP_UNDER_SUBMISSION {
                
                [PSCustomObject]@{
                    RequestId = $CertRequest.GetRequestId()
                    Disposition = $Status
                    Result = "Request was taken under submission"
                    StatusCode = $StatusCode
                    StatusMessage = $StatusMessage
                    Certificate = $null
                    RawCertificate = $null
                }
            }

            $DispositionType.CR_DISP_REVOKED {

                [PSCustomObject]@{
                    RequestId = $CertRequest.GetRequestId()
                    Disposition = $Status
                    Result = "Certificate has been revoked"
                    StatusCode = $StatusCode
                    StatusMessage = $StatusMessage
                    Certificate = $null
                    RawCertificate = $null
                }
            }

            # This should never happen, but just to be on the safe side
            default{
                Write-Error -Message "Retrieved unsupported Disposition Code $Status from the Certification Authority."
            }

        }

        [void]([System.Runtime.Interopservices.Marshal]::ReleaseComObject($CertRequest))

    }
    
    end {}
    
}
# SIG # Begin signature block
# MIIfUQYJKoZIhvcNAQcCoIIfQjCCHz4CAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUTCHnXJYM7E8kQ1sFmx69NsYq
# kySgghk4MIIFQDCCBCigAwIBAgIRAI8ql/xeLmzwWijNkBrZWykwDQYJKoZIhvcN
# AQELBQAwfDELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3Rl
# cjEQMA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQw
# IgYDVQQDExtTZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0EwHhcNMjAxMTIwMDAw
# MDAwWhcNMjMxMTIwMjM1OTU5WjCBhzELMAkGA1UEBhMCREUxDjAMBgNVBBEMBTkx
# NjAyMR0wGwYDVQQHDBREw7xycndhbmdlbiBIYWxzYmFjaDEVMBMGA1UECQwMV2Vp
# aGVyd2VnIDE1MRgwFgYDVQQKDA9Vd2UgR3JhZGVuZWdnZXIxGDAWBgNVBAMMD1V3
# ZSBHcmFkZW5lZ2dlcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOd8
# GJf9qC1WQbcxgVa4XpKLzh/oy12qkfG3K11BLRs2UuZoZXelefKJYirHWpzNlhkb
# RoGv3sNUCgKpRDtyz1kHf+jvk+nsB9SCctMccmb987BA8kq/togGWjqlHcQFfETr
# lv3zxiQkd560Ttrx9OO8/mgIvUubGW4jttet+AUV8PeHJeCQKwetoEn3obcgqjua
# AS41nc/f+NaX6wkD8iKGpXy+CrHbflhACasvUychBf/BlmxsZKP8sf6dZNN0I7TU
# 9kjO5A8NiWAp7J9oTz0tfKuHGurGaqlAMQUJdD9RNDzsz+CN1w/LjbkhfJawnoI8
# XR7g8nIBOH2df+YImPUCAwEAAaOCAa8wggGrMB8GA1UdIwQYMBaAFA7hOqhTOjHV
# ir7Bu61nGgOFrTQOMB0GA1UdDgQWBBQpnALCRSXWP6gLMr77GCxcPejdmjAOBgNV
# HQ8BAf8EBAMCB4AwDAYDVR0TAQH/BAIwADATBgNVHSUEDDAKBggrBgEFBQcDAzAR
# BglghkgBhvhCAQEEBAMCBBAwSgYDVR0gBEMwQTA1BgwrBgEEAbIxAQIBAwIwJTAj
# BggrBgEFBQcCARYXaHR0cHM6Ly9zZWN0aWdvLmNvbS9DUFMwCAYGZ4EMAQQBMEMG
# A1UdHwQ8MDowOKA2oDSGMmh0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1JT
# QUNvZGVTaWduaW5nQ0EuY3JsMHMGCCsGAQUFBwEBBGcwZTA+BggrBgEFBQcwAoYy
# aHR0cDovL2NydC5zZWN0aWdvLmNvbS9TZWN0aWdvUlNBQ29kZVNpZ25pbmdDQS5j
# cnQwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLnNlY3RpZ28uY29tMB0GA1UdEQQW
# MBSBEnV3ZUBncmFkZW5lZ2dlci5ldTANBgkqhkiG9w0BAQsFAAOCAQEAhEOjCx9s
# SaMpTP9RFRnJx8dcn0eDdCk6TGZlB3gyh24VWu+VECUXd/1svZJ6apPDRpz2kvFz
# TlIEfAORKDuXY72X6eCS7VFTjNvEyNFPmr67T6JUB7Qka6W9dpAqhufxOQ0DRS/a
# kytP3J4JF0BYiZ3IxfgAH1ji/uXuMyD1jFSWsDyhSMk+O0ugYw+TaKb4j8XCWN7k
# N8uVhaqXmDFi9XKTKQturbxEG3nCSxludZt5fDImj7cYnorhI3vGKZSXQTjgQ1Tv
# jUyb4YjoToTNjZ6fz3HamALoi6QHL9npHB6ekLLwVsUW8G9t5o54tQ4qbngap/fB
# Qk0JDQ0C2+ikbjCCBfUwggPdoAMCAQICEB2iSDBvmyYY0ILgln0z02owDQYJKoZI
# hvcNAQEMBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpOZXcgSmVyc2V5MRQw
# EgYDVQQHEwtKZXJzZXkgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3
# b3JrMS4wLAYDVQQDEyVVU0VSVHJ1c3QgUlNBIENlcnRpZmljYXRpb24gQXV0aG9y
# aXR5MB4XDTE4MTEwMjAwMDAwMFoXDTMwMTIzMTIzNTk1OVowfDELMAkGA1UEBhMC
# R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9y
# ZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQDExtTZWN0aWdvIFJT
# QSBDb2RlIFNpZ25pbmcgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
# AQCGIo0yhXoYn0nwli9jCB4t3HyfFM/jJrYlZilAhlRGdDFixRDtsocnppnLlTDA
# VvWkdcapDlBipVGREGrgS2Ku/fD4GKyn/+4uMyD6DBmJqGx7rQDDYaHcaWVtH24n
# lteXUYam9CflfGqLlR5bYNV+1xaSnAAvaPeX7Wpyvjg7Y96Pv25MQV0SIAhZ6DnN
# j9LWzwa0VwW2TqE+V2sfmLzEYtYbC43HZhtKn52BxHJAteJf7wtF/6POF6YtVbC3
# sLxUap28jVZTxvC6eVBJLPcDuf4vZTXyIuosB69G2flGHNyMfHEo8/6nxhTdVZFu
# ihEN3wYklX0Pp6F8OtqGNWHTAgMBAAGjggFkMIIBYDAfBgNVHSMEGDAWgBRTeb9a
# qitKz1SA4dibwJ3ysgNmyzAdBgNVHQ4EFgQUDuE6qFM6MdWKvsG7rWcaA4WtNA4w
# DgYDVR0PAQH/BAQDAgGGMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0lBBYwFAYI
# KwYBBQUHAwMGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0gADBQBgNVHR8ESTBH
# MEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQ2Vy
# dGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEEajBoMD8GCCsGAQUF
# BzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQWRkVHJ1
# c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20w
# DQYJKoZIhvcNAQEMBQADggIBAE1jUO1HNEphpNveaiqMm/EAAB4dYns61zLC9rPg
# Y7P7YQCImhttEAcET7646ol4IusPRuzzRl5ARokS9At3WpwqQTr81vTr5/cVlTPD
# oYMot94v5JT3hTODLUpASL+awk9KsY8k9LOBN9O3ZLCmI2pZaFJCX/8E6+F0ZXkI
# 9amT3mtxQJmWunjxucjiwwgWsatjWsgVgG10Xkp1fqW4w2y1z99KeYdcx0BNYzX2
# MNPPtQoOCwR/oEuuu6Ol0IQAkz5TXTSlADVpbL6fICUQDRn7UJBhvjmPeo5N9p8O
# Hv4HURJmgyYZSJXOSsnBf/M6BZv5b9+If8AjntIeQ3pFMcGcTanwWbJZGehqjSkE
# And8S0vNcL46slVaeD68u28DECV3FTSK+TbMQ5Lkuk/xYpMoJVcp+1EZx6ElQGqE
# V8aynbG8HArafGd+fS7pKEwYfsR7MUFxmksp7As9V1DSyt39ngVR5UR43QHesXWY
# DVQk/fBO4+L4g71yuss9Ou7wXheSaG3IYfmm8SoKC6W59J7umDIFhZ7r+YMp08Ys
# fb06dy6LN0KgaoLtO0qqlBCk4Q34F8W2WnkzGJLjtXX4oemOCiUe5B7xn1qHI/+f
# pFGe+zmAEc3btcSnqIBv5VPU4OOiwtJbGvoyJi1qV3AcPKRYLqPzW0sH3DJZ84en
# Gm1YMIIG7DCCBNSgAwIBAgIQMA9vrN1mmHR8qUY2p3gtuTANBgkqhkiG9w0BAQwF
# ADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcT
# C0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAs
# BgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcN
# MTkwNTAyMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjB9MQswCQYDVQQGEwJHQjEbMBkG
# A1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRgwFgYD
# VQQKEw9TZWN0aWdvIExpbWl0ZWQxJTAjBgNVBAMTHFNlY3RpZ28gUlNBIFRpbWUg
# U3RhbXBpbmcgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDIGwGv
# 2Sx+iJl9AZg/IJC9nIAhVJO5z6A+U++zWsB21hoEpc5Hg7XrxMxJNMvzRWW5+adk
# FiYJ+9UyUnkuyWPCE5u2hj8BBZJmbyGr1XEQeYf0RirNxFrJ29ddSU1yVg/cyeNT
# mDoqHvzOWEnTv/M5u7mkI0Ks0BXDf56iXNc48RaycNOjxN+zxXKsLgp3/A2UUrf8
# H5VzJD0BKLwPDU+zkQGObp0ndVXRFzs0IXuXAZSvf4DP0REKV4TJf1bgvUacgr6U
# nb+0ILBgfrhN9Q0/29DqhYyKVnHRLZRMyIw80xSinL0m/9NTIMdgaZtYClT0Bef9
# Maz5yIUXx7gpGaQpL0bj3duRX58/Nj4OMGcrRrc1r5a+2kxgzKi7nw0U1BjEMJh0
# giHPYla1IXMSHv2qyghYh3ekFesZVf/QOVQtJu5FGjpvzdeE8NfwKMVPZIMC1Pvi
# 3vG8Aij0bdonigbSlofe6GsO8Ft96XZpkyAcSpcsdxkrk5WYnJee647BeFbGRCXf
# BhKaBi2fA179g6JTZ8qx+o2hZMmIklnLqEbAyfKm/31X2xJ2+opBJNQb/HKlFKLU
# rUMcpEmLQTkUAx4p+hulIq6lw02C0I3aa7fb9xhAV3PwcaP7Sn1FNsH3jYL6uckN
# U4B9+rY5WDLvbxhQiddPnTO9GrWdod6VQXqngwIDAQABo4IBWjCCAVYwHwYDVR0j
# BBgwFoAUU3m/WqorSs9UgOHYm8Cd8rIDZsswHQYDVR0OBBYEFBqh+GEZIA/DQXdF
# KI7RNV8GEgRVMA4GA1UdDwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMBMG
# A1UdJQQMMAoGCCsGAQUFBwMIMBEGA1UdIAQKMAgwBgYEVR0gADBQBgNVHR8ESTBH
# MEWgQ6BBhj9odHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQ2Vy
# dGlmaWNhdGlvbkF1dGhvcml0eS5jcmwwdgYIKwYBBQUHAQEEajBoMD8GCCsGAQUF
# BzAChjNodHRwOi8vY3J0LnVzZXJ0cnVzdC5jb20vVVNFUlRydXN0UlNBQWRkVHJ1
# c3RDQS5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLnVzZXJ0cnVzdC5jb20w
# DQYJKoZIhvcNAQEMBQADggIBAG1UgaUzXRbhtVOBkXXfA3oyCy0lhBGysNsqfSoF
# 9bw7J/RaoLlJWZApbGHLtVDb4n35nwDvQMOt0+LkVvlYQc/xQuUQff+wdB+PxlwJ
# +TNe6qAcJlhc87QRD9XVw+K81Vh4v0h24URnbY+wQxAPjeT5OGK/EwHFhaNMxcyy
# UzCVpNb0llYIuM1cfwGWvnJSajtCN3wWeDmTk5SbsdyybUFtZ83Jb5A9f0VywRsj
# 1sJVhGbks8VmBvbz1kteraMrQoohkv6ob1olcGKBc2NeoLvY3NdK0z2vgwY4Eh0k
# hy3k/ALWPncEvAQ2ted3y5wujSMYuaPCRx3wXdahc1cFaJqnyTdlHb7qvNhCg0MF
# pYumCf/RoZSmTqo9CfUFbLfSZFrYKiLCS53xOV5M3kg9mzSWmglfjv33sVKRzj+J
# 9hyhtal1H3G/W0NdZT1QgW6r8NDT/LKzH7aZlib0PHmLXGTMze4nmuWgwAxyh8Fu
# TVrTHurwROYybxzrF06Uw3hlIDsPQaof6aFBnf6xuKBlKjTg3qj5PObBMLvAoGMs
# /FwWAKjQxH/qEZ0eBsambTJdtDgJK0kHqv3sMNrxpy/Pt/360KOE2See+wFmd7lW
# EOEgbsausfm2usg1XTN2jvF8IAwqd661ogKGuinutFoAsYyr4/kKyVRd1LlqdJ69
# SK6YMIIHBzCCBO+gAwIBAgIRAIx3oACP9NGwxj2fOkiDjWswDQYJKoZIhvcNAQEM
# BQAwfTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQ
# MA4GA1UEBxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSUwIwYD
# VQQDExxTZWN0aWdvIFJTQSBUaW1lIFN0YW1waW5nIENBMB4XDTIwMTAyMzAwMDAw
# MFoXDTMyMDEyMjIzNTk1OVowgYQxCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVh
# dGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3Rp
# Z28gTGltaXRlZDEsMCoGA1UEAwwjU2VjdGlnbyBSU0EgVGltZSBTdGFtcGluZyBT
# aWduZXIgIzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCRh0ssi8Hx
# HqCe0wfGAcpSsL55eV0JZgYtLzV9u8D7J9pCalkbJUzq70DWmn4yyGqBfbRcPlYQ
# gTU6IjaM+/ggKYesdNAbYrw/ZIcCX+/FgO8GHNxeTpOHuJreTAdOhcxwxQ177MPZ
# 45fpyxnbVkVs7ksgbMk+bP3wm/Eo+JGZqvxawZqCIDq37+fWuCVJwjkbh4E5y8O3
# Os2fUAQfGpmkgAJNHQWoVdNtUoCD5m5IpV/BiVhgiu/xrM2HYxiOdMuEh0FpY4G8
# 9h+qfNfBQc6tq3aLIIDULZUHjcf1CxcemuXWmWlRx06mnSlv53mTDTJjU67MximK
# IMFgxvICLMT5yCLf+SeCoYNRwrzJghohhLKXvNSvRByWgiKVKoVUrvH9Pkl0dPyO
# rj+lcvTDWgGqUKWLdpUbZuvv2t+ULtka60wnfUwF9/gjXcRXyCYFevyBI19UCTgq
# YtWqyt/tz1OrH/ZEnNWZWcVWZFv3jlIPZvyYP0QGE2Ru6eEVYFClsezPuOjJC77F
# hPfdCp3avClsPVbtv3hntlvIXhQcua+ELXei9zmVN29OfxzGPATWMcV+7z3oUX5x
# rSR0Gyzc+Xyq78J2SWhi1Yv1A9++fY4PNnVGW5N2xIPugr4srjcS8bxWw+StQ8O3
# ZpZelDL6oPariVD6zqDzCIEa0USnzPe4MQIDAQABo4IBeDCCAXQwHwYDVR0jBBgw
# FoAUGqH4YRkgD8NBd0UojtE1XwYSBFUwHQYDVR0OBBYEFGl1N3u7nTVCTr9X05rb
# nwHRrt7QMA4GA1UdDwEB/wQEAwIGwDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQM
# MAoGCCsGAQUFBwMIMEAGA1UdIAQ5MDcwNQYMKwYBBAGyMQECAQMIMCUwIwYIKwYB
# BQUHAgEWF2h0dHBzOi8vc2VjdGlnby5jb20vQ1BTMEQGA1UdHwQ9MDswOaA3oDWG
# M2h0dHA6Ly9jcmwuc2VjdGlnby5jb20vU2VjdGlnb1JTQVRpbWVTdGFtcGluZ0NB
# LmNybDB0BggrBgEFBQcBAQRoMGYwPwYIKwYBBQUHMAKGM2h0dHA6Ly9jcnQuc2Vj
# dGlnby5jb20vU2VjdGlnb1JTQVRpbWVTdGFtcGluZ0NBLmNydDAjBggrBgEFBQcw
# AYYXaHR0cDovL29jc3Auc2VjdGlnby5jb20wDQYJKoZIhvcNAQEMBQADggIBAEoD
# eJBCM+x7GoMJNjOYVbudQAYwa0Vq8ZQOGVD/WyVeO+E5xFu66ZWQNze93/tk7OWC
# t5XMV1VwS070qIfdIoWmV7u4ISfUoCoxlIoHIZ6Kvaca9QIVy0RQmYzsProDd6aC
# ApDCLpOpviE0dWO54C0PzwE3y42i+rhamq6hep4TkxlVjwmQLt/qiBcW62nW4SW9
# RQiXgNdUIChPynuzs6XSALBgNGXE48XDpeS6hap6adt1pD55aJo2i0OuNtRhcjwO
# hWINoF5w22QvAcfBoccklKOyPG6yXqLQ+qjRuCUcFubA1X9oGsRlKTUqLYi86q50
# 1oLnwIi44U948FzKwEBcwp/VMhws2jysNvcGUpqjQDAXsCkWmcmqt4hJ9+gLJTO1
# P22vn18KVt8SscPuzpF36CAT6Vwkx+pEC0rmE4QcTesNtbiGoDCni6GftCzMwBYj
# yZHlQgNLgM7kTeYqAT7AXoWgJKEXQNXb2+eYEKTx6hkbgFT6R4nomIGpdcAO39Bo
# lHmhoJ6OtrdCZsvZ2WsvTdjePjIeIOTsnE1CjZ3HM5mCN0TUJikmQI54L7nu+i/x
# 8Y/+ULh43RSW3hwOcLAqhWqxbGjpKuQQK24h/dN8nTfkKgbWw/HXaONPB3mBCBP+
# smRe6bE85tB4I7IJLOImYr87qZdRzMdEMoGyr8/fMYIFgzCCBX8CAQEwgZEwfDEL
# MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
# BxMHU2FsZm9yZDEYMBYGA1UEChMPU2VjdGlnbyBMaW1pdGVkMSQwIgYDVQQDExtT
# ZWN0aWdvIFJTQSBDb2RlIFNpZ25pbmcgQ0ECEQCPKpf8Xi5s8FoozZAa2VspMAkG
# BSsOAwIaBQCgeDAYBgorBgEEAYI3AgEMMQowCKACgAChAoAAMBkGCSqGSIb3DQEJ
# AzEMBgorBgEEAYI3AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEVMCMG
# CSqGSIb3DQEJBDEWBBQXivIO2LDEAy1cBQOmFIG7wZ6bdzANBgkqhkiG9w0BAQEF
# AASCAQDZVkF5t0qDZHJUQfug/d0l6C2/YNa5WrSlQj0vZzuVsS/xp3oysxO+Gqf+
# kDr37dLyjOeWOtkQ3pad3jc6tvYpNfLda5dkih5vgtwZMgSxQXnv/vDqz+MdzDvy
# tWpqbQwuf1bwN96cZT3R4CW7KAJN3g9oXHflQ2/JpejSx07h6IOU9ViQtjSy8voI
# 3d0S575JyPmU3A0Rhn9Pmm9D97r2xn3bQDvyv/ldYuQFXbkaV7Kj4SgvGK0KqxT9
# T1o53biGVu9vnWcuZPRE4OuSSfm+9prUNlq0WIYZLTXoR1jULIqHy8uuV2EinD9I
# fbZhGi8BTHFPOtlEPINlZhYZf+HLoYIDTDCCA0gGCSqGSIb3DQEJBjGCAzkwggM1
# AgEBMIGSMH0xCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0
# ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGDAWBgNVBAoTD1NlY3RpZ28gTGltaXRlZDEl
# MCMGA1UEAxMcU2VjdGlnbyBSU0EgVGltZSBTdGFtcGluZyBDQQIRAIx3oACP9NGw
# xj2fOkiDjWswDQYJYIZIAWUDBAICBQCgeTAYBgkqhkiG9w0BCQMxCwYJKoZIhvcN
# AQcBMBwGCSqGSIb3DQEJBTEPFw0yMTA1MDYxMTQ2NDhaMD8GCSqGSIb3DQEJBDEy
# BDBsab+kqYMgdow624PV/xIJlCjC8VeM5YxVu/Dkhf9fNeAipJN7gx8LW0LZfWlv
# 7QIwDQYJKoZIhvcNAQEBBQAEggIAfw6RiWsspzbPR6BDKbULZgpn5zd1iIEFH2AK
# YG4Pp+5DSnptVEkQblDYrzmjGuc4Aq89CwtJqcqpZQGP5e3zpVWSxBYaCuOtquXy
# Eyb61rMkHZcJmFcYqJ/acTx1hBkjdAEQKeGU9S5sy+EUbVqDRkydlOPQmuUTfL7b
# spwDTIOcxirMQkECitIF2THLEERiCZXRtsV6bX02eN4WZxwCeQk3FIzcz4ol7Zyj
# 4dLU7PDawDplP43bboTtUnXBGY44eRSHs+stfb5Rjh0MtK6LISJNK4ZfWa1c0A3M
# zTa3jQ/IVuJ5Je+RpWQ1wDhc+9Njr2FJQM0Fkvcly9RrF4htkLf7IZ6YVtkE6edL
# Jt6aZj0Ur22oSOM1F0guVB0glEwWAnOPhpYJKRmVIdiZRTlTZNZMVyJBUnSvk9eI
# GXYCqGt92HllUQr+ce2DrmIqGXopM0bXKrLJP5RpvlWdLdDI0ZYpfbCWTYYGagk5
# oAvto8Og1b+GjWhsIhpAUSDa5rRkHDw1mskbUGRsyFK+xHTqFdam0y5KAFj2nEk+
# Fl1p4v9Il9OFXL3E/TjuU9uw+jNSGkXWgAhwckcuCNShbTVnk7TgxvxsbUstPkDJ
# jL8h8DtiuqpwVVinDexPwj6NaP8SO0EImMr7WRiuX1V5PTr7ttsx38WvyBjPYG9q
# ja7MyRk=
# SIG # End signature block