Get-ADWHfBKeyFromValue.ps1
|
# # Get_ADWhfbKeyFromValue.ps1 # # Copyright 2019 Microsoft. All rights reserved. # function Get-ADWHfBKeyFromValue { <#.SYNOPSIS Parses a WHfB key from a msdsKeyCredentialLink dn-binary value. .DESCRIPTION Parses a WHfB key from a msdsKeyCredentialLink dn-binary value. .PARAMETER RawValue The raw value of the msdsKeyCredentialLink dn-binary attribute as queried via LDAP. .PARAMETER Logging This switch will enable additional diagnostic logging to a file. #> [CmdletBinding()] param ( [Parameter( Mandatory=$true )] [string]$RawValue, [Parameter( Mandatory=$false )] [bool]$Logging ) Process { $memStream = $null; $binReader = $null; try { $parsedLink = $RawValue.Split(':'); if($parsedLink.Length -ne 4) { if ($Logging) { $output = "Key has unexpected number of elements: $parsedLink.Length" DiagLog $output -logOnly } Write-Output $null; return; } $valueCount = [Convert]::ToInt32($parsedLink[1]); if ($parsedLink[2].Length -ne $valueCount) { if ($Logging) { $output = "Key has unexpected valueCount: $parsedLink[2].Length $valueCount" DiagLog $output -logOnly } Write-Output $null; return; } $keyBytes = Get-ByteArrayFromHexString -HexString $parsedLink[2]; $memStream = New-Object System.IO.MemoryStream (,[byte[]]$keyBytes) $binReader = New-Object System.IO.BinaryReader $memStream; $key = Get-ADWHfBKeyFromRawValueBinary -Reader $binReader if($null -eq $key) { Write-Output $null; return; } $key.KeyLinkTargetDN = $parsedLink[3]; $key.KeyRawLDAPValue = $RawValue; Write-Output $key; } catch { $output = "Get-ADWHfBKeyFromValue caught exception: " + $_.Exception.ToString() DiagLog $output -logOnly Write-Output $null } finally { if($null -ne $binReader) { $binReader.Close(); $binReader.Dispose(); } if($null -ne $memStream) { $memStream.Close(); $memStream.Dispose(); } } } } <# Get-ADWHfBKeyFromRawValueBinary #> function Get-ADWHfBKeyFromRawValueBinary { <#.SYNOPSIS Parses a WHfB key from a msdsKeyCredentialLink dn-binary binary value. .DESCRIPTION Parses a WHfB key from a msdsKeyCredentialLink dn-binary binary value. .PARAMETER Reader The binary value loaded into a binary reader object. .PARAMETER Logging This switch will enable additional diagnostic logging to a file. #> [CmdletBinding()] param ( [Parameter( Mandatory=$true)] [System.IO.BinaryReader]$Reader, [Parameter( Mandatory=$false )] [bool]$Logging ) Process { # Create empty key object with all fields $Key = [PSCustomObject]@{ UserDomain = "" UserSamAccountName = "" UserDistinguishedName = "" KeyVersion = -1 KeyId = "" KeyMaterial = $null KeySource = "" KeyUsage = "" KeyDeviceId = "" KeyApproximateLastLogonTimestamp = "" KeyCreationTime = "" CustomKeyInformation = $null KeyLinkTargetDN = "" ROCAVulnerable = "Unknown" OrphanedKey = "Unknown" KeyRawLDAPValue = "" } $keySourceString = [String]::Empty; $keySource = @(1); $lastReadKeyId = [KEY_OBJECT_ATTR_TYPE]::KeyObjectValueIdMsDsKeyVersion; # First four bytes is the key version $KeyVersionBytes = 0; $KeyVersionBytes = $Reader.ReadUInt32(); switch($KeyVersionBytes) { 0 { if ($Logging) { $output = "Key has zero (0) version : $parsedLink[2].Length $valueCount" DiagLog $output -logOnly } return $null }; 0x100 { $Key.KeyVersion = 1; break; }; 0x200 { $Key.KeyVersion = 2; break; } default { if ($Logging) { $output = "Key has unrecognized version: " + $KeyVersionBytes.ToString() DiagLog $output -logOnly } return $null; } } # Each set in this stream is in the form of: # { keyValueCount (2bytes), keyId (1byte), keyValue (keyValueCount bytes) } do { # Read the keyValueCount $keyValueCount = $Reader.ReadUInt16(); # Read the keyId $keyId = $Reader.ReadByte(); if ($keyId -ge 10 -or $keyId -lt 0) { if ($Logging) { $output = "Key value has unrecognized id: $keyId" DiagLog $output -logOnly } return $null } $readKeyId = [KEY_OBJECT_ATTR_TYPE]$keyId; if ($lastReadKeyId -ge $readKeyId) { if ($Logging) { $output = "Key has duplicated key id value" DiagLog $output -logOnly } return $null } # Read the actual keyValue. $keyValue = $Reader.ReadBytes($keyValueCount); switch($readKeyId) { "KeyObjectValueIdMsDsKeyUsage" { if ($keyValueCount -eq 1) { switch ($keyValue[0]) { 0 { $Key.KeyUsage = "AdminKey" } 1 { $Key.KeyUsage = "NGC" } 2 { $Key.KeyUsage = "STK" } 3 { $Key.KeyUsage = "BitlockerRecovery" } default { $Key.KeyUsage = "Unknown" } } } else { $Key.KeyUsage = [System.Text.Encoding.UTF8]::GetString($keyValue); } break; } "KeyObjectValueIdMsDsKeyId" { $keyIdBytes = @(); $keyIdBytes = $keyValue; if($Key.KeyVersion -eq 1) { # Version 1 keys had a guid in this field $Key.KeyId = [System.BitConverter]::ToString($keyIdBytes).Replace("-", ""); } else { # Version 2 keys have a SHA256 hash of the key material here $Key.KeyId = [System.Convert]::ToBase64String($keyIdBytes); } break; } "KeyObjectValueIdMsDsKeyHash" { # Do nothing. break; } "KeyObjectValueIdMsDsKeyMaterial" { $Key.KeyMaterial = [System.Convert]::ToBase64String($keyValue); break; } "KeyObjectValueIdMsDsKeySource" { $keySource = $keyValue; if($Key.KeyVersion -le 1) { $Key.KeySource = "NA"; } elseif($keySource[0]-eq 0) { $Key.KeySource = "AD"; } elseif($keySource[0]-eq 1) { $Key.KeySource = "AzureAD"; } else { $Key.KeySource = "Unknown"; } break; } "KeyObjectValueIdMsDsDeviceId" { $deviceId = New-Object System.Guid (,$keyValue) $Key.KeyDeviceId = $deviceId.ToString() break; } "KeyObjectValueIdMsDsCustomKeyInformation" { $Key.CustomKeyInformation = [System.Convert]::ToBase64String($keyValue); break; } "KeyObjectValueIdMsDsKeyApproximateLastLogonTimeStamp" { $Key.KeyApproximateLastLogonTimestamp = Get-KeyTimeFromBytes ` -TimeData $keyValue ` -KeySource $keySource[0]` -KeyVersion $Key.KeyVersion; break; } "KeyObjectValueIdMsDsKeyCreationTime" { $Key.KeyCreationTime = Get-KeyTimeFromBytes ` -TimeData $keyValue ` -KeySource $keySource[0]` -KeyVersion $Key.KeyVersion; break; } default { $output = "Ignoring unrecognized key entry id: $readKeyId" DiagLog $output -logOnly } } } while($Reader.BaseStream.Position -lt $Reader.BaseStream.Length); return $Key } } <# Get-KeyTimeFromBytes #> function Get-KeyTimeFromBytes { <#.SYNOPSIS Parse time from byte array. The time format is inferred from the key source and version. .DESCRIPTION Parse time from byte array. The time format is inferred from the key source and version. .PARAMETER TimeData Byte array containing the time information. .PARAMETER KeySource The time source (AD or AAD). .PARAMETER KeyVersion The WHfB key version #> [CmdletBinding()] param ( [Parameter( Mandatory=$true, Position=0)] [byte[]]$TimeData, [Parameter( Mandatory=$true, Position=1)] [int]$KeySource, [Parameter( Mandatory=$true, Position=2)] [int]$KeyVersion ) PROCESS { $dateTime64 = [System.BitConverter]::ToInt64($TimeData, 0); if ($dateTime64 -eq 0) { $time = [DateTime]::MinValue } elseif (($KeyVersion -le 1) -or ($KeySource -eq 1)) { $time = [DateTime]::FromBinary($dateTime64); } elseif ($KeySource -eq 0) { $time = [DateTime]::FromFileTime($dateTime64); } else { throw New-Object System.Exception -ArgumentList "Unexpected time format."; } Write-Output $time.ToString("o"); } } # SIG # Begin signature block # MIIoCQYJKoZIhvcNAQcCoIIn+jCCJ/YCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCD9PSpjJKruAPsO # y4vS6PE/zIqzm9jn1NHXRYF1CVZ1LaCCEXAwggiCMIIHaqADAgECAhM2AAAA6Gad # G0hCpUxFAAEAAADoMA0GCSqGSIb3DQEBCwUAMEExEzARBgoJkiaJk/IsZAEZFgNH # QkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxFTATBgNVBAMTDEFNRSBDUyBDQSAwMTAe # Fw0xOTAzMjUxMzE3MTBaFw0yMDAzMjQxMzE3MTBaMC8xLTArBgNVBAMTJE1pY3Jv # c29mdCBBenVyZSBEZXBlbmRlbmN5IENvZGUgU2lnbjCCASIwDQYJKoZIhvcNAQEB # BQADggEPADCCAQoCggEBANzmuspUXRFHozpraZYcR8lLf8oaCK27bhl7agSI00Vc # GZy2slaHQ8JZ+Bqiao7e2hpEVxeJ0s9lfIUe30ye3RwDa7oNloC8u8fa/W0QusGD # T7p4c7wwbRJ5MrXowwB/nSgsOKtoCoJMpk6LDpRhgwhn4va4PjVrajBxrxN1eVIP # Kw1GPkzh3qkLQ0SIhuiYUlZur4HSG6Mdkl7jYk1ifVtNupf+FO4Nflw+ZRsczZUg # jo74fVEoBI9qzrZSkCg5wku1qGsTXrd9DtRgOQEEp96NruISfEb22ZZtpMrJg71H # p/oAEqqlOBN5FIjzWi+mxznE1CNMBNFCbtsZOvHVSJMCAwEAAaOCBYMwggV/MCkG # CSsGAQQBgjcVCgQcMBowDAYKKwYBBAGCN1sCATAKBggrBgEFBQcDAzA9BgkrBgEE # AYI3FQcEMDAuBiYrBgEEAYI3FQiGkOMNhNW0eITxiz6Fm90Wzp0SgWCE2K5IhaaW # JgIBZAIBDTCCAnYGCCsGAQUFBwEBBIICaDCCAmQwYgYIKwYBBQUHMAKGVmh0dHA6 # Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2lpbmZyYS9DZXJ0cy9CWTJQS0lDU0NBMDEu # QU1FLkdCTF9BTUUlMjBDUyUyMENBJTIwMDEoMSkuY3J0MFIGCCsGAQUFBzAChkZo # dHRwOi8vY3JsMS5hbWUuZ2JsL2FpYS9CWTJQS0lDU0NBMDEuQU1FLkdCTF9BTUUl # MjBDUyUyMENBJTIwMDEoMSkuY3J0MFIGCCsGAQUFBzAChkZodHRwOi8vY3JsMi5h # bWUuZ2JsL2FpYS9CWTJQS0lDU0NBMDEuQU1FLkdCTF9BTUUlMjBDUyUyMENBJTIw # MDEoMSkuY3J0MFIGCCsGAQUFBzAChkZodHRwOi8vY3JsMy5hbWUuZ2JsL2FpYS9C # WTJQS0lDU0NBMDEuQU1FLkdCTF9BTUUlMjBDUyUyMENBJTIwMDEoMSkuY3J0MFIG # CCsGAQUFBzAChkZodHRwOi8vY3JsNC5hbWUuZ2JsL2FpYS9CWTJQS0lDU0NBMDEu # QU1FLkdCTF9BTUUlMjBDUyUyMENBJTIwMDEoMSkuY3J0MIGtBggrBgEFBQcwAoaB # oGxkYXA6Ly8vQ049QU1FJTIwQ1MlMjBDQSUyMDAxLENOPUFJQSxDTj1QdWJsaWMl # MjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1Db25maWd1cmF0aW9uLERD # PUFNRSxEQz1HQkw/Y0FDZXJ0aWZpY2F0ZT9iYXNlP29iamVjdENsYXNzPWNlcnRp # ZmljYXRpb25BdXRob3JpdHkwHQYDVR0OBBYEFMhZoWfS7cerFd3KJYxV4M3+DOEi # MA4GA1UdDwEB/wQEAwIHgDBQBgNVHREESTBHpEUwQzEpMCcGA1UECxMgTWljcm9z # b2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xFjAUBgNVBAUTDTIzNjE2OSs0NTMz # NzQwggHUBgNVHR8EggHLMIIBxzCCAcOgggG/oIIBu4Y8aHR0cDovL2NybC5taWNy # b3NvZnQuY29tL3BraWluZnJhL0NSTC9BTUUlMjBDUyUyMENBJTIwMDEuY3Jshi5o # dHRwOi8vY3JsMS5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEuY3Jshi5o # dHRwOi8vY3JsMi5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEuY3Jshi5o # dHRwOi8vY3JsMy5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEuY3Jshi5o # dHRwOi8vY3JsNC5hbWUuZ2JsL2NybC9BTUUlMjBDUyUyMENBJTIwMDEuY3JshoG6 # bGRhcDovLy9DTj1BTUUlMjBDUyUyMENBJTIwMDEsQ049QlkyUEtJQ1NDQTAxLENO # PUNEUCxDTj1QdWJsaWMlMjBLZXklMjBTZXJ2aWNlcyxDTj1TZXJ2aWNlcyxDTj1D # b25maWd1cmF0aW9uLERDPUFNRSxEQz1HQkw/Y2VydGlmaWNhdGVSZXZvY2F0aW9u # TGlzdD9iYXNlP29iamVjdENsYXNzPWNSTERpc3RyaWJ1dGlvblBvaW50MB8GA1Ud # IwQYMBaAFBtmohn8m+ul2oSPGJjpEKTDe5K9MB8GA1UdJQQYMBYGCisGAQQBgjdb # AgEGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IBAQCVZn2MgvVx6Lix7aYfjSp6 # t9NYHifbtXl3VxQk20PyxzmNbXoXHQMtgWioOWP4SaQ0Jpw23TgpczqPCS/BWy0E # t2iZ12XatAQRPqrsU4YKcTTExKEPa/gdOz63Okmi+5GQH78d53M5I39DJWzPja7d # RdZgASuswapduSUZMAFJJOslCFtBYAuzrJDy+UH2k7NZQ4+ExtFuuwZZA16c1IbQ # O9JwjGdYna9ZlNtWIc2RSDeNjX8St40y7hhxxrszktg13D1oGZX8+oeQBsPyzigY # U+5JuPoUWGkFBUL8LKR6z3wddTWFZWrW5zfy2aQTxSYOpRYNcUmuAYfLBVhSNI/j # MIII5jCCBs6gAwIBAgITHwAAABS0xR/G8oC+cQAAAAAAFDANBgkqhkiG9w0BAQsF # ADA8MRMwEQYKCZImiZPyLGQBGRYDR0JMMRMwEQYKCZImiZPyLGQBGRYDQU1FMRAw # DgYDVQQDEwdhbWVyb290MB4XDTE2MDkxNTIxMzMwM1oXDTIxMDkxNTIxNDMwM1ow # QTETMBEGCgmSJomT8ixkARkWA0dCTDETMBEGCgmSJomT8ixkARkWA0FNRTEVMBMG # A1UEAxMMQU1FIENTIENBIDAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC # AQEA1VeBAtb5+tD3G4C53TfNJNxmYfzhiXKtKQzSGxuav660bTS1VEeDDjSnFhsm # nlb6GkPCeYmCJwWgZGs+3oWJ8yad3//VoP99bXG8azzTJmT2PFM1yKxUXUJgi7I9 # y3C4ll/ATfBwbGGRXD+2PdkdlVpxKWzeNEPVwbCtxWjUhHr6Ecy9R6O23j+2/RSZ # SgfzYctDzDWhNf0PvGPflm31PSk4+ozca337/Ozu0+naDKg5i/zFHhfSJZkq5dPP # G6C8wDrdiwHh6G5IGrMd2QXnmvEfjtpPqE+G8MeWbszaWxlxEjQJQC6PBwn+8Qt4 # Vqlc0am3Z3fBw8kzRunOs8Mn/wIDAQABo4IE2jCCBNYwEAYJKwYBBAGCNxUBBAMC # AQEwIwYJKwYBBAGCNxUCBBYEFJH8M85CnvaT5uJ9VNcIGLu413FlMB0GA1UdDgQW # BBQbZqIZ/JvrpdqEjxiY6RCkw3uSvTCCAQQGA1UdJQSB/DCB+QYHKwYBBQIDBQYI # KwYBBQUHAwEGCCsGAQUFBwMCBgorBgEEAYI3FAIBBgkrBgEEAYI3FQYGCisGAQQB # gjcKAwwGCSsGAQQBgjcVBgYIKwYBBQUHAwkGCCsGAQUFCAICBgorBgEEAYI3QAEB # BgsrBgEEAYI3CgMEAQYKKwYBBAGCNwoDBAYJKwYBBAGCNxUFBgorBgEEAYI3FAIC # BgorBgEEAYI3FAIDBggrBgEFBQcDAwYKKwYBBAGCN1sBAQYKKwYBBAGCN1sCAQYK # KwYBBAGCN1sDAQYKKwYBBAGCN1sFAQYKKwYBBAGCN1sEAQYKKwYBBAGCN1sEAjAZ # BgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwEgYDVR0TAQH/ # BAgwBgEB/wIBADAfBgNVHSMEGDAWgBQpXlFeZK40ueusnA2njHUB0QkLKDCCAWgG # A1UdHwSCAV8wggFbMIIBV6CCAVOgggFPhiNodHRwOi8vY3JsMS5hbWUuZ2JsL2Ny # bC9hbWVyb290LmNybIYxaHR0cDovL2NybC5taWNyb3NvZnQuY29tL3BraWluZnJh # L2NybC9hbWVyb290LmNybIYjaHR0cDovL2NybDIuYW1lLmdibC9jcmwvYW1lcm9v # dC5jcmyGI2h0dHA6Ly9jcmwzLmFtZS5nYmwvY3JsL2FtZXJvb3QuY3JshoGqbGRh # cDovLy9DTj1hbWVyb290LENOPUFNRVJPT1QsQ049Q0RQLENOPVB1YmxpYyUyMEtl # eSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRpb24sREM9QU1F # LERDPUdCTD9jZXJ0aWZpY2F0ZVJldm9jYXRpb25MaXN0P2Jhc2U/b2JqZWN0Q2xh # c3M9Y1JMRGlzdHJpYnV0aW9uUG9pbnQwggGrBggrBgEFBQcBAQSCAZ0wggGZMDcG # CCsGAQUFBzAChitodHRwOi8vY3JsMS5hbWUuZ2JsL2FpYS9BTUVST09UX2FtZXJv # b3QuY3J0MEcGCCsGAQUFBzAChjtodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtp # aW5mcmEvY2VydHMvQU1FUk9PVF9hbWVyb290LmNydDA3BggrBgEFBQcwAoYraHR0 # cDovL2NybDIuYW1lLmdibC9haWEvQU1FUk9PVF9hbWVyb290LmNydDA3BggrBgEF # BQcwAoYraHR0cDovL2NybDMuYW1lLmdibC9haWEvQU1FUk9PVF9hbWVyb290LmNy # dDCBogYIKwYBBQUHMAKGgZVsZGFwOi8vL0NOPWFtZXJvb3QsQ049QUlBLENOPVB1 # YmxpYyUyMEtleSUyMFNlcnZpY2VzLENOPVNlcnZpY2VzLENOPUNvbmZpZ3VyYXRp # b24sREM9QU1FLERDPUdCTD9jQUNlcnRpZmljYXRlP2Jhc2U/b2JqZWN0Q2xhc3M9 # Y2VydGlmaWNhdGlvbkF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAKLdKhpqP # H6QBaM3CAOqQi8oA4WQeZLW3QOXNmWm7UA018DQEa1yTqEQbuD5OlR1Wu/F289Dm # XNTdsZM4GTKEaZehIiVaMoLvEJtu5h6CTyfWqPetNyOJqR1sGqod0Xwn5/G/zcTY # Sxn5K3N8KdlcDrZAIyfq3yaEJYHGnA9eJ/f1RrfbJgeo/RAhICctOONwfpsBXcgi # TuTmlD/k0DqogvzJgPq9GOkIyX/dxk7IkPzX/n484s0zHR4IKU58U3G1oPSQmZ5O # HAvgHaEASkdN5E20HyJv5zN7du+QY08fI+VIci6pagLfXHYaTX3ZJ/MUM9XU+oU5 # y4qMLzTj1JIG0LVfuHK8yoB7h2inyTe7bn6h2G8NxZ02aKZ0xa+n/JnoXKNsaVPG # 1SoTuItMsXV5pQtIShsBqnXqFjY3bJMlMhIofMcjiuOwRCW+prZ+PoYvE2P+ML7g # s3L65GZ9BdKF3fSW3TvmpOujPQ23rzSle9WGxFJ02fNbaF9C7bG44uDzMoZU4P+u # vQaB7KE4OMqAvYYfFy1tv1dpVIN/qhx0H/9oNiOJpuZZ39ZibLt9DXbsq5qwyHmd # JXaisxwB53wJshUjc1i76xqFPUNGb8EZQ3aFKl2w9B47vfBi+nU3sN0tpnLPtew4 # LHWq4LBD5uiNZVBOYosZ6BKhSlk1+Y/0y1IxghXvMIIV6wIBATBYMEExEzARBgoJ # kiaJk/IsZAEZFgNHQkwxEzARBgoJkiaJk/IsZAEZFgNBTUUxFTATBgNVBAMTDEFN # RSBDUyBDQSAwMQITNgAAAOhmnRtIQqVMRQABAAAA6DANBglghkgBZQMEAgEFAKCB # rjAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgELMQ4wDAYK # KwYBBAGCNwIBFTAvBgkqhkiG9w0BCQQxIgQgLwGCNYHH04VTe3dz78azxGeGHpi7 # MFlQ9SL0mPG+oiUwQgYKKwYBBAGCNwIBDDE0MDKgFIASAE0AaQBjAHIAbwBzAG8A # ZgB0oRqAGGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbTANBgkqhkiG9w0BAQEFAASC # AQA/2dm8YsAkdmuN74EDnLTwSSfBZFo6JlAG/Uteat04b0KKk76CQc7KrLn5ROgM # +U8wcA5SSAtS2wG6qk8JRyYYSXFyMJij6pFTeIJIOmQX/HjlZ1AK6GhbCc4Tn3YO # xY+OeZLzGNZbSD7T4wSNeQiZOPj/Zfax30YIukUNYqijyqz4a/2YASMtUSBHC++X # TER3tM5buV6XplsladjS0jPVRTX5Gs4DUhj/dhmxUkn35xKC1hbq/UFtE8tx63YD # TKpnZLGmXn7Q+mRldNU228HIWqLWNsW9hfEqUmTo3+0BUV3SsOzRf0E+gSC+V8EG # MK5yk/N3gp5CoEMjths3G4VpoYITtzCCE7MGCisGAQQBgjcDAwExghOjMIITnwYJ # KoZIhvcNAQcCoIITkDCCE4wCAQMxDzANBglghkgBZQMEAgEFADCCAVgGCyqGSIb3 # DQEJEAEEoIIBRwSCAUMwggE/AgEBBgorBgEEAYRZCgMBMDEwDQYJYIZIAWUDBAIB # BQAEIEwfwnR0gSXNIt3W0buy24uyd+w36YO/1MawY32gFOJZAgZd5nWE7+YYEzIw # MTkxMjA0MDgyNDM4LjkwNFowBwIBAYACAfSggdSkgdEwgc4xCzAJBgNVBAYTAlVT # MRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQK # ExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVy # YXRpb25zIFB1ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpCMUI3 # LUY2N0YtRkVDMjElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2Vydmlj # ZaCCDx8wggT1MIID3aADAgECAhMzAAABA+pOK3i2KieTAAAAAAEDMA0GCSqGSIb3 # DQEBCwUAMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYD # VQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAk # BgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMB4XDTE5MDkwNjIw # NDExN1oXDTIwMTIwNDIwNDExN1owgc4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpX # YXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQg # Q29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1ZXJ0 # byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpCMUI3LUY2N0YtRkVDMjEl # MCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZTCCASIwDQYJKoZI # hvcNAQEBBQADggEPADCCAQoCggEBALCRV96uFMhQPoeefQrvxbzOW3Y7LKElUOxY # oMR9HW2+DOgS3ECplmsQJZbcXZJ1686/7CV7skdSO95rG7k9cnI9tvX4OW0WDRjt # caFOvmDdENyBUYmIf+kuPHwA8Edbzeg7OPkBCtvM5nUJ5xVnQuiT9R5NF9axjwoY # kHaIcaj9GWQgW5h+awLofbWyY0rWyXYk8GndPVK3MkT3FnFPWLGY6OB2lRMEgpBL # w1uKpCUHqp4Fpff5gnvb93EVSliLr11lwfYwEF5RjNDegi9P39MjpnuXGwI2LjGK # UsF66VGaVw4rdaUKQlPKJ0P/h/b9LCcVZyBVfwAD/XapWoo2JEsCAwEAAaOCARsw # ggEXMB0GA1UdDgQWBBTiNi2Y/aGPja1lJu2PPODMEW9aCDAfBgNVHSMEGDAWgBTV # YzpcijGQ80N7fEYbxTNoWoVtVTBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3Js # Lm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNUaW1TdGFQQ0FfMjAx # MC0wNy0wMS5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1RpbVN0YVBDQV8yMDEwLTA3 # LTAxLmNydDAMBgNVHRMBAf8EAjAAMBMGA1UdJQQMMAoGCCsGAQUFBwMIMA0GCSqG # SIb3DQEBCwUAA4IBAQB8Naig5oqAZfKHIUhs99mL2pqtVa6yca9TwUyeM9yC/Sod # uk4CXbtGtn+/j7yMpQldXXFefBh9PIg3bdlLchCtL8RXVxdmxDQYcjyxYtEmxCxx # S+6EOBfl9I1ouXDj8Aq8wGZZ9PbAraJDeqxgVqd9W/YCrC4la3tg4HzF1hot6L0o # xNlTnu+RyXmZ7f6f/Vq6KZAZPyaKbI5P6qHBG3REPAgr45+GySpbWAQhZjUNZ9pJ # 3NcePbuaa8N2xiIJsc9t8/FTSCj1xoiK9q2YvXoA64/hkyUIn/fBFY3BD6meMnQC # G500ruiAm0GujHYOmZxAbosMOxtLPahmQUkcbQCPMIIGcTCCBFmgAwIBAgIKYQmB # KgAAAAAAAjANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT # Cldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29m # dCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNh # dGUgQXV0aG9yaXR5IDIwMTAwHhcNMTAwNzAxMjEzNjU1WhcNMjUwNzAxMjE0NjU1 # WjB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSYwJAYDVQQD # Ex1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMDCCASIwDQYJKoZIhvcNAQEB # BQADggEPADCCAQoCggEBAKkdDbx3EYo6IOz8E5f1+n9plGt0VBDVpQoAgoX77Xxo # SyxfxcPlYcJ2tz5mK1vwFVMnBDEfQRsalR3OCROOfGEwWbEwRA/xYIiEVEMM1024 # OAizQt2TrNZzMFcmgqNFDdDq9UeBzb8kYDJYYEbyWEeGMoQedGFnkV+BVLHPk0yS # wcSmXdFhE24oxhr5hoC732H8RsEnHSRnEnIaIYqvS2SJUGKxXf13Hz3wV3WsvYpC # TUBR0Q+cBj5nf/VmwAOWRH7v0Ev9buWayrGo8noqCjHw2k4GkbaICDXoeByw6ZnN # POcvRLqn9NxkvaQBwSAJk3jN/LzAyURdXhacAQVPIk0CAwEAAaOCAeYwggHiMBAG # CSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBTVYzpcijGQ80N7fEYbxTNoWoVtVTAZ # BgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/ # BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8E # TzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9k # dWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBM # MEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRz # L01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDCBoAYDVR0gAQH/BIGVMIGSMIGP # BgkrBgEEAYI3LgMwgYEwPQYIKwYBBQUHAgEWMWh0dHA6Ly93d3cubWljcm9zb2Z0 # LmNvbS9QS0kvZG9jcy9DUFMvZGVmYXVsdC5odG0wQAYIKwYBBQUHAgIwNB4yIB0A # TABlAGcAYQBsAF8AUABvAGwAaQBjAHkAXwBTAHQAYQB0AGUAbQBlAG4AdAAuIB0w # DQYJKoZIhvcNAQELBQADggIBAAfmiFEN4sbgmD+BcQM9naOhIW+z66bM9TG+zwXi # qf76V20ZMLPCxWbJat/15/B4vceoniXj+bzta1RXCCtRgkQS+7lTjMz0YBKKdsxA # QEGb3FwX/1z5Xhc1mCRWS3TvQhDIr79/xn/yN31aPxzymXlKkVIArzgPF/UveYFl # 2am1a+THzvbKegBvSzBEJCI8z+0DpZaPWSm8tv0E4XCfMkon/VWvL/625Y4zu2Jf # mttXQOnxzplmkIz/amJ/3cVKC5Em4jnsGUpxY517IW3DnKOiPPp/fZZqkHimbdLh # nPkd/DjYlPTGpQqWhqS9nhquBEKDuLWAmyI4ILUl5WTs9/S/fmNZJQ96LjlXdqJx # qgaKD4kWumGnEcua2A5HmoDF0M2n0O99g/DhO3EJ3110mCIIYdqwUB5vvfHhAN/n # MQekkzr3ZUd46PioSKv33nJ+YWtvd6mBy6cJrDm77MbL2IK0cs0d9LiFAR6A+xuJ # KlQ5slvayA1VmXqHczsI5pgt6o3gMy4SKfXAL1QnIffIrE7aKLixqduWsqdCosnP # GUFN4Ib5KpqjEWYw07t0MkvfY3v1mYovG8chr1m1rtxEPJdQcdeh0sVV42neV8HR # 3jDA/czmTfsNv11P6Z0eGTgvvM9YBS7vDaBQNdrvCScc1bN+NR4Iuto229Nfj950 # iEkSoYIDrTCCApUCAQEwgf6hgdSkgdEwgc4xCzAJBgNVBAYTAlVTMRMwEQYDVQQI # EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv # ZnQgQ29ycG9yYXRpb24xKTAnBgNVBAsTIE1pY3Jvc29mdCBPcGVyYXRpb25zIFB1 # ZXJ0byBSaWNvMSYwJAYDVQQLEx1UaGFsZXMgVFNTIEVTTjpCMUI3LUY2N0YtRkVD # MjElMCMGA1UEAxMcTWljcm9zb2Z0IFRpbWUtU3RhbXAgU2VydmljZaIlCgEBMAkG # BSsOAwIaBQADFQBrXDo2eDr68GRJRlXYVs3aqGzas6CB3jCB26SB2DCB1TELMAkG # A1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQx # HjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEpMCcGA1UECxMgTWljcm9z # b2Z0IE9wZXJhdGlvbnMgUHVlcnRvIFJpY28xJzAlBgNVBAsTHm5DaXBoZXIgTlRT # IEVTTjo0REU5LTBDNUUtM0UwOTErMCkGA1UEAxMiTWljcm9zb2Z0IFRpbWUgU291 # cmNlIE1hc3RlciBDbG9jazANBgkqhkiG9w0BAQUFAAIFAOGRuvIwIhgPMjAxOTEy # MDQxMjU2MThaGA8yMDE5MTIwNTEyNTYxOFowdDA6BgorBgEEAYRZCgQBMSwwKjAK # AgUA4ZG68gIBADAHAgEAAgIjCjAHAgEAAgIXjDAKAgUA4ZMMcgIBADA2BgorBgEE # AYRZCgQCMSgwJjAMBgorBgEEAYRZCgMBoAowCAIBAAIDFuNgoQowCAIBAAIDB6Eg # MA0GCSqGSIb3DQEBBQUAA4IBAQBIXllBeEox4PM1V7Usrc++goLL7nvk8cpL5Ff/ # BCylRyT5rwHQEFeS1SAcWuAWTinXtAFVraR6GtW2m+n99qH2Db3/c5fWQzX/WA25 # 6AlJeDias/dgdMTc8aV3kPCcPU919jnzNod6VB0/Yx0FOoM+P91czipGJjvWgMHA # Jw4gE1FNfApYeh1NOtG23A2O4GBdKfv5vjpPT7esf7XuZ5disGm4QZH6VwtArZBM # wFkvMUWYsxSudHrLzWgJcGLAYklVln48iSlc/9LscEeJy9vqGzneIvaoqKh3gLLl # V0fuR2scX5Vvflk9+OEb8zR2eV95FwM7GviYeMK++ZRZ5csCMYIC9TCCAvECAQEw # gZMwfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE # AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAED6k4reLYqJ5MA # AAAAAQMwDQYJYIZIAWUDBAIBBQCgggEyMBoGCSqGSIb3DQEJAzENBgsqhkiG9w0B # CRABBDAvBgkqhkiG9w0BCQQxIgQgnjKS7lpEfSI0da2+7IA+SF38WAEjSfLNEvV5 # rw2DGtowgeIGCyqGSIb3DQEJEAIMMYHSMIHPMIHMMIGxBBRrXDo2eDr68GRJRlXY # Vs3aqGzaszCBmDCBgKR+MHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5n # dG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9y # YXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwAhMz # AAABA+pOK3i2KieTAAAAAAEDMBYEFDOmp8mqbV5A967ie0+lA+2SGQ8KMA0GCSqG # SIb3DQEBCwUABIIBACV2anr8IUztrqtxeUy+nNm4xYwUe6Nfe4YI9f/FdheslP9b # qqTyZAHclbegHrpe5ImYul8/IZm0lEem1vl1Mld4lvi/d1bR8SyT8S9+m2AHjss0 # 6IfkUldeJuvxIqUxUv+kXO0RqxZUKyGP72PSNCRDUjnE9njgO580n5c6oAj38PGx # u+UYisHUShc6ivDgju3cjnCvmmhecEmKqQYEvV5MC2NIbtSqgEOOIEaYTbWanxzt # xfmC1H1YZFLx0f6dx+hroTlM3DtzRaK1XbZvvhTLKuaKHB9+2h7JzRFp+hCE/C6A # YRTpWYRrbgnv2fCnPkxwfTF2DdPUWsTdxNlIxOY= # SIG # End signature block |