Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 15 additions & 11 deletions bssl-compat/source/SSL_CTX_set_select_certificate_cb.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ typedef enum ssl_select_cert_result_t (*select_certificate_cb_t)(const SSL_CLIEN
* in_select_certificate_cb(ssl) function to query whether or not we are
* executing within a SSL_CTX_set_select_certificate_cb() callback for that SSL
* object, or not.
*
* This mechanism is used by the SSL_get_servername() function to provide a
* different implementation depending on it's invocation context.
*
* This mechanism is used by SSL_get_servername() & SSL_set_ocsp_response()
* to provide different behavior depending on invocation context.
*/
class ActiveSelectCertificateCb {
public:
Expand All @@ -26,14 +26,14 @@ class ActiveSelectCertificateCb {
~ActiveSelectCertificateCb() {
SSL_set_ex_data(ssl_, index(), nullptr);
}
static bool isActive(const SSL *ssl) {
return SSL_get_ex_data(ssl, index()) != nullptr;
}
private:
static int index() {
static int index = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr,
+[](void *, void *ptr, CRYPTO_EX_DATA *, int, long, void*) {
if (ptr) ossl_OPENSSL_free(ptr);
});
static int index = SSL_get_ex_new_index(0, nullptr, nullptr, nullptr, nullptr);
return index;
}
private:
SSL *ssl_;
};

Expand All @@ -42,7 +42,7 @@ class ActiveSelectCertificateCb {
* callback invocation for the specified SSL object.
*/
bool in_select_certificate_cb(const SSL *ssl) {
return SSL_get_ex_data(ssl, ActiveSelectCertificateCb::index()) != nullptr;
return ActiveSelectCertificateCb::isActive(ssl);
}


Expand Down Expand Up @@ -100,15 +100,19 @@ static int ssl_ctx_client_hello_cb(SSL *ssl, int *alert, void *arg) {
return ossl_SSL_CLIENT_HELLO_ERROR;
}

// Ensure extensions are freed even if the callback throws
std::unique_ptr<uint8_t, decltype(&OPENSSL_free)> cleanup(
const_cast<uint8_t*>(client_hello.extensions),
OPENSSL_free
);

enum ssl_select_cert_result_t result;

{
ActiveSelectCertificateCb active(ssl);
result = callback(&client_hello);
}

OPENSSL_free((void*)client_hello.extensions);

switch (result) {
case ssl_select_cert_success: return ossl_SSL_CLIENT_HELLO_SUCCESS;
case ssl_select_cert_retry: return ossl_SSL_CLIENT_HELLO_RETRY;
Expand Down
36 changes: 23 additions & 13 deletions bssl-compat/source/SSL_set_ocsp_response.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,12 @@
#include "SSL_CTX_set_select_certificate_cb.h"


typedef std::pair<void*,size_t> OcspResponse;
typedef std::pair<std::unique_ptr<void, decltype(&OPENSSL_free)>,size_t> OcspResponse;

static int index() {
static int index {ossl.ossl_SSL_get_ex_new_index(0, nullptr, nullptr, nullptr,
+[](void *, void *ptr, CRYPTO_EX_DATA *, int, long, void*) {
if(ptr) {
OcspResponse *resp {reinterpret_cast<OcspResponse*>(ptr)};
ossl.ossl_OPENSSL_free(resp->first);
if(OcspResponse *resp = reinterpret_cast<OcspResponse*>(ptr)) {
delete resp;
}
})};
Expand All @@ -44,10 +42,11 @@ static int ssl_apply_deferred_ocsp_response_cb(SSL *ssl, void *arg) {

if (resp) {
ossl.ossl_SSL_set_ex_data(ssl, index(), nullptr);
if (ossl.ossl_SSL_set_tlsext_status_ocsp_resp(ssl, resp->first, resp->second) == 0) {
return ossl_SSL_TLSEXT_ERR_ALERT_FATAL;
if (ossl.ossl_SSL_set_tlsext_status_ocsp_resp(ssl, resp->first.get(), resp->second) == 1) {
resp->first.release(); // ossl_SSL_set_tlsext_status_ocsp_resp() took ownership
return ossl_SSL_TLSEXT_ERR_OK;
}
return ossl_SSL_TLSEXT_ERR_OK;
return ossl_SSL_TLSEXT_ERR_ALERT_FATAL;
}

return ossl_SSL_TLSEXT_ERR_NOACK;
Expand All @@ -60,7 +59,12 @@ static int ssl_apply_deferred_ocsp_response_cb(SSL *ssl, void *arg) {
* ossl_SSL_CTX_set_tlsext_status_cb() later on.
*/
extern "C" int SSL_set_ocsp_response(SSL *ssl, const uint8_t *response, size_t response_len) {
if (void *response_copy {ossl.ossl_OPENSSL_memdup(response, response_len)}) {
std::unique_ptr<void, decltype(&OPENSSL_free)> response_copy(
ossl.ossl_OPENSSL_memdup(response, response_len),
OPENSSL_free
);

if (response_copy) {
if (in_select_certificate_cb(ssl)) {

SSL_CTX *ctx {ossl.ossl_SSL_get_SSL_CTX(ssl)};
Expand All @@ -84,15 +88,21 @@ extern "C" int SSL_set_ocsp_response(SSL *ssl, const uint8_t *response, size_t r
// squirreled away already. If so, delete it first, so we don't just
// overwrite it and create a leak.
if(OcspResponse *prev = reinterpret_cast<OcspResponse*>(ossl.ossl_SSL_get_ex_data(ssl, index()))) {
ossl.ossl_OPENSSL_free(prev->first);
delete prev;
}

// Store the OCSP response bytes for the callback to pick up later
return ossl.ossl_SSL_set_ex_data(ssl, index(), new OcspResponse(response_copy, response_len));
// Store the OcspResponse bytes for the callback to pick up later
std::unique_ptr<OcspResponse> resp = std::make_unique<OcspResponse>(std::move(response_copy), response_len);
if (ossl.ossl_SSL_set_ex_data(ssl, index(), resp.get()) == 1) {
resp.release(); // ossl_SSL_set_ex_data() took ownership
return 1;
}
}
else {
return ossl.ossl_SSL_set_tlsext_status_ocsp_resp(ssl, response_copy, response_len);
else { // We're not in a select certificate callback, so we set it directly
if (ossl.ossl_SSL_set_tlsext_status_ocsp_resp(ssl, response_copy.get(), response_len) == 1) {
response_copy.release(); // ossl_SSL_set_tlsext_status_ocsp_resp() took ownership
return 1;
}
}
}

Expand Down
32 changes: 16 additions & 16 deletions bssl-compat/source/test/certs/client_1_cert.pem
Original file line number Diff line number Diff line change
@@ -1,27 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEjjCCA3agAwIBAgIUFo1jXwKCIORrRQ/OBgIzxW2RsPYwDQYJKoZIhvcNAQEL
MIIEjjCCA3agAwIBAgIUaiKtqqxi9QAugmGrmbc7MwnbaMYwDQYJKoZIhvcNAQEL
BQAwgYoxCzAJBgNVBAYTAkdCMRYwFAYDVQQIDA1UeW5lIGFuZCBXZWFyMRwwGgYD
VQQHDBNOZXdjYXN0bGUgdXBvbiBUeW5lMRAwDgYDVQQKDAdSZWQgSGF0MRwwGgYD
VQQLDBNSZWQgSGF0IEVuZ2luZWVyaW5nMRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0Ew
HhcNMjMwNDE5MTg0MTQ2WhcNMjUwNDE4MTg0MTQ2WjCBizELMAkGA1UEBhMCR0Ix
HhcNMjUxMjE5MTEwNTI0WhcNMjcxMjE5MTEwNTI0WjCBizELMAkGA1UEBhMCR0Ix
FjAUBgNVBAgMDVR5bmUgYW5kIFdlYXIxHDAaBgNVBAcME05ld2Nhc3RsZSB1cG9u
IFR5bmUxEDAOBgNVBAoMB1JlZCBIYXQxHDAaBgNVBAsME1JlZCBIYXQgRW5naW5l
ZXJpbmcxFjAUBgNVBAMMDVRlc3QgQ2xpZW50IDEwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDKgSU1fHjw2YG7nf4LApxQf6JOVBISJCSOkNBbVsmQWs5B
DejbhINFdHrxGwpm1OguYGtNcDIsrfTIPAIbkquUtDjRkQy5D2W9JmzAa4Easqtk
hJ7RM/lLvA27eoFPh+ERHCr8gVtFBG/n+bpfF/MpZrkyYnwcwZMSHmHCyRvKNj/p
lP0Y+g/9imN0klOCG+yczG71MtV6W7Q14ESMbrLYr2fOPoppveL7y8hom9BWEi4M
1OVG/yGyDszkLYXVzcvWFL3tITWC6xgh8decKi47rMcLzsgZm3V1In6tJ6AYi6W9
aNGiBl5yAHdKwRQG09LAxgpKPeRyQO64Rc0/uTU/AgMBAAGjgegwgeUwDAYDVR0T
A4IBDwAwggEKAoIBAQC2Bruv9yzCz8+wbrQZOuPXW7/ZV6FY+Nn9OCiZNXiP3KLZ
sXo76NIqJFE4nngTm+lq11rmqHcE+gjolN7/Z8IT9MB9yeOR3Po35aFEuXhu5bk+
sjInphX6aL3clyUYIur00SsBDjKoV4gM2VFQCDZWFHI1QtreD+BerVvaHBRJpsln
9R3hpFVaOtePlbhuRwUaXsbCoIdn7p8SPTpqKmkJuldfGnXsHAAqaMuPrGZPuvbX
arqZ/wGoze2/lYgddvGAZLkxTUsTQM1FCB0biGu/TORaMYZDFE4pFpBONi0gE9aK
yUWMwEj9h135J/nx3tS3gvtfSYgt2YG2slunnbdNAgMBAAGjgegwgeUwDAYDVR0T
AQH/BAIwADALBgNVHQ8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF
BwMBMGkGA1UdEQRiMGCGIXNwaWZmZTovL3JlZGhhdC5jb20vdGVzdC1jbGllbnQt
MYYfaHR0cDovL3Rlc3QtY2xpZW50LTEucmVkaGF0LmNvbYIKcmVkaGF0LmNvbYIO
d3d3LnJlZGhhdC5jb20wHQYDVR0OBBYEFJxz2EplABwgpSLysJIM2+lTusviMB8G
A1UdIwQYMBaAFFG0cchLrL8gNr/H1YkrXoKcRfeUMA0GCSqGSIb3DQEBCwUAA4IB
AQAQmKvu4XHggQ5bNqo/UHz115MReBq0khPk+p3zFJ1EAY6V9l66g79pWPYGsG0L
zbJ1HUwb/854CMcv1kHJdF0CnsBYMBsBWu6+8hBTNoc8xU+v9fUQEWymDEFNxuB8
4ZW8xuREyVxwFPFnJz3t5PHnicciAe3ymkIhL26RScviR74yEoqoteMEd+h48YgG
+LYPR16R9kRvAbAPI4KGUWEYlD/zHFu+5SuZSRTbGAKAC21qnFEgZpuPKsuL/gOr
ioWUMGF2TeQUL7xw1EyxYQl6DXR6b87Y2BZBJ90VaTwcruZVYPowHrURmkAOtXP9
pSNa9XFCTq54MxA1ww7vAXfF
d3d3LnJlZGhhdC5jb20wHQYDVR0OBBYEFHqjBoUIHBF0g0htfUMUIl1r973yMB8G
A1UdIwQYMBaAFOf12l7WdUN4dZUwZrfJm84VSwgTMA0GCSqGSIb3DQEBCwUAA4IB
AQAMePd+cDw6OglgJxuLIcWYzeyaBySlOgW+6dTvA24IdJN7ERZ69yVk6hVGPCAk
xOwfREvXWxWm1/d14o+PnSQdIbnckO/p3SH+PNApd3s9crfpSR4ThAFSYQ4Qg2wM
VXB5ZFcmsiCkyrrMC25L7mbVkVn5VNXAOVKN0/MpyrA+x72HwNqt/ZmRGy1LJMuq
C0wokMzkYOIIfvuKOL499Ty0iUKvzq8fTzldsePZM6U3rXtoW8yC2/3EgfYWRRj+
HeiGvD08RTPntBLIepQuu5hYcvuMMvwahM9OeqKoVw5XXkBTSmsICUCUKH2Vgahd
hDn9K87FpCVrjAnYdmqv7pTR
-----END CERTIFICATE-----
32 changes: 16 additions & 16 deletions bssl-compat/source/test/certs/client_1_cert.pem.h
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
static const char client_1_cert_pem_str[] = R"""(-----BEGIN CERTIFICATE-----
MIIEjjCCA3agAwIBAgIUFo1jXwKCIORrRQ/OBgIzxW2RsPYwDQYJKoZIhvcNAQEL
MIIEjjCCA3agAwIBAgIUaiKtqqxi9QAugmGrmbc7MwnbaMYwDQYJKoZIhvcNAQEL
BQAwgYoxCzAJBgNVBAYTAkdCMRYwFAYDVQQIDA1UeW5lIGFuZCBXZWFyMRwwGgYD
VQQHDBNOZXdjYXN0bGUgdXBvbiBUeW5lMRAwDgYDVQQKDAdSZWQgSGF0MRwwGgYD
VQQLDBNSZWQgSGF0IEVuZ2luZWVyaW5nMRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0Ew
HhcNMjMwNDE5MTg0MTQ2WhcNMjUwNDE4MTg0MTQ2WjCBizELMAkGA1UEBhMCR0Ix
HhcNMjUxMjE5MTEwNTI0WhcNMjcxMjE5MTEwNTI0WjCBizELMAkGA1UEBhMCR0Ix
FjAUBgNVBAgMDVR5bmUgYW5kIFdlYXIxHDAaBgNVBAcME05ld2Nhc3RsZSB1cG9u
IFR5bmUxEDAOBgNVBAoMB1JlZCBIYXQxHDAaBgNVBAsME1JlZCBIYXQgRW5naW5l
ZXJpbmcxFjAUBgNVBAMMDVRlc3QgQ2xpZW50IDEwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDKgSU1fHjw2YG7nf4LApxQf6JOVBISJCSOkNBbVsmQWs5B
DejbhINFdHrxGwpm1OguYGtNcDIsrfTIPAIbkquUtDjRkQy5D2W9JmzAa4Easqtk
hJ7RM/lLvA27eoFPh+ERHCr8gVtFBG/n+bpfF/MpZrkyYnwcwZMSHmHCyRvKNj/p
lP0Y+g/9imN0klOCG+yczG71MtV6W7Q14ESMbrLYr2fOPoppveL7y8hom9BWEi4M
1OVG/yGyDszkLYXVzcvWFL3tITWC6xgh8decKi47rMcLzsgZm3V1In6tJ6AYi6W9
aNGiBl5yAHdKwRQG09LAxgpKPeRyQO64Rc0/uTU/AgMBAAGjgegwgeUwDAYDVR0T
A4IBDwAwggEKAoIBAQC2Bruv9yzCz8+wbrQZOuPXW7/ZV6FY+Nn9OCiZNXiP3KLZ
sXo76NIqJFE4nngTm+lq11rmqHcE+gjolN7/Z8IT9MB9yeOR3Po35aFEuXhu5bk+
sjInphX6aL3clyUYIur00SsBDjKoV4gM2VFQCDZWFHI1QtreD+BerVvaHBRJpsln
9R3hpFVaOtePlbhuRwUaXsbCoIdn7p8SPTpqKmkJuldfGnXsHAAqaMuPrGZPuvbX
arqZ/wGoze2/lYgddvGAZLkxTUsTQM1FCB0biGu/TORaMYZDFE4pFpBONi0gE9aK
yUWMwEj9h135J/nx3tS3gvtfSYgt2YG2slunnbdNAgMBAAGjgegwgeUwDAYDVR0T
AQH/BAIwADALBgNVHQ8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF
BwMBMGkGA1UdEQRiMGCGIXNwaWZmZTovL3JlZGhhdC5jb20vdGVzdC1jbGllbnQt
MYYfaHR0cDovL3Rlc3QtY2xpZW50LTEucmVkaGF0LmNvbYIKcmVkaGF0LmNvbYIO
d3d3LnJlZGhhdC5jb20wHQYDVR0OBBYEFJxz2EplABwgpSLysJIM2+lTusviMB8G
A1UdIwQYMBaAFFG0cchLrL8gNr/H1YkrXoKcRfeUMA0GCSqGSIb3DQEBCwUAA4IB
AQAQmKvu4XHggQ5bNqo/UHz115MReBq0khPk+p3zFJ1EAY6V9l66g79pWPYGsG0L
zbJ1HUwb/854CMcv1kHJdF0CnsBYMBsBWu6+8hBTNoc8xU+v9fUQEWymDEFNxuB8
4ZW8xuREyVxwFPFnJz3t5PHnicciAe3ymkIhL26RScviR74yEoqoteMEd+h48YgG
+LYPR16R9kRvAbAPI4KGUWEYlD/zHFu+5SuZSRTbGAKAC21qnFEgZpuPKsuL/gOr
ioWUMGF2TeQUL7xw1EyxYQl6DXR6b87Y2BZBJ90VaTwcruZVYPowHrURmkAOtXP9
pSNa9XFCTq54MxA1ww7vAXfF
d3d3LnJlZGhhdC5jb20wHQYDVR0OBBYEFHqjBoUIHBF0g0htfUMUIl1r973yMB8G
A1UdIwQYMBaAFOf12l7WdUN4dZUwZrfJm84VSwgTMA0GCSqGSIb3DQEBCwUAA4IB
AQAMePd+cDw6OglgJxuLIcWYzeyaBySlOgW+6dTvA24IdJN7ERZ69yVk6hVGPCAk
xOwfREvXWxWm1/d14o+PnSQdIbnckO/p3SH+PNApd3s9crfpSR4ThAFSYQ4Qg2wM
VXB5ZFcmsiCkyrrMC25L7mbVkVn5VNXAOVKN0/MpyrA+x72HwNqt/ZmRGy1LJMuq
C0wokMzkYOIIfvuKOL499Ty0iUKvzq8fTzldsePZM6U3rXtoW8yC2/3EgfYWRRj+
HeiGvD08RTPntBLIepQuu5hYcvuMMvwahM9OeqKoVw5XXkBTSmsICUCUKH2Vgahd
hDn9K87FpCVrjAnYdmqv7pTR
-----END CERTIFICATE-----
)""";
64 changes: 32 additions & 32 deletions bssl-compat/source/test/certs/client_1_cert_chain.pem
Original file line number Diff line number Diff line change
@@ -1,51 +1,51 @@
-----BEGIN CERTIFICATE-----
MIIEjjCCA3agAwIBAgIUFo1jXwKCIORrRQ/OBgIzxW2RsPYwDQYJKoZIhvcNAQEL
MIIEjjCCA3agAwIBAgIUaiKtqqxi9QAugmGrmbc7MwnbaMYwDQYJKoZIhvcNAQEL
BQAwgYoxCzAJBgNVBAYTAkdCMRYwFAYDVQQIDA1UeW5lIGFuZCBXZWFyMRwwGgYD
VQQHDBNOZXdjYXN0bGUgdXBvbiBUeW5lMRAwDgYDVQQKDAdSZWQgSGF0MRwwGgYD
VQQLDBNSZWQgSGF0IEVuZ2luZWVyaW5nMRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0Ew
HhcNMjMwNDE5MTg0MTQ2WhcNMjUwNDE4MTg0MTQ2WjCBizELMAkGA1UEBhMCR0Ix
HhcNMjUxMjE5MTEwNTI0WhcNMjcxMjE5MTEwNTI0WjCBizELMAkGA1UEBhMCR0Ix
FjAUBgNVBAgMDVR5bmUgYW5kIFdlYXIxHDAaBgNVBAcME05ld2Nhc3RsZSB1cG9u
IFR5bmUxEDAOBgNVBAoMB1JlZCBIYXQxHDAaBgNVBAsME1JlZCBIYXQgRW5naW5l
ZXJpbmcxFjAUBgNVBAMMDVRlc3QgQ2xpZW50IDEwggEiMA0GCSqGSIb3DQEBAQUA
A4IBDwAwggEKAoIBAQDKgSU1fHjw2YG7nf4LApxQf6JOVBISJCSOkNBbVsmQWs5B
DejbhINFdHrxGwpm1OguYGtNcDIsrfTIPAIbkquUtDjRkQy5D2W9JmzAa4Easqtk
hJ7RM/lLvA27eoFPh+ERHCr8gVtFBG/n+bpfF/MpZrkyYnwcwZMSHmHCyRvKNj/p
lP0Y+g/9imN0klOCG+yczG71MtV6W7Q14ESMbrLYr2fOPoppveL7y8hom9BWEi4M
1OVG/yGyDszkLYXVzcvWFL3tITWC6xgh8decKi47rMcLzsgZm3V1In6tJ6AYi6W9
aNGiBl5yAHdKwRQG09LAxgpKPeRyQO64Rc0/uTU/AgMBAAGjgegwgeUwDAYDVR0T
A4IBDwAwggEKAoIBAQC2Bruv9yzCz8+wbrQZOuPXW7/ZV6FY+Nn9OCiZNXiP3KLZ
sXo76NIqJFE4nngTm+lq11rmqHcE+gjolN7/Z8IT9MB9yeOR3Po35aFEuXhu5bk+
sjInphX6aL3clyUYIur00SsBDjKoV4gM2VFQCDZWFHI1QtreD+BerVvaHBRJpsln
9R3hpFVaOtePlbhuRwUaXsbCoIdn7p8SPTpqKmkJuldfGnXsHAAqaMuPrGZPuvbX
arqZ/wGoze2/lYgddvGAZLkxTUsTQM1FCB0biGu/TORaMYZDFE4pFpBONi0gE9aK
yUWMwEj9h135J/nx3tS3gvtfSYgt2YG2slunnbdNAgMBAAGjgegwgeUwDAYDVR0T
AQH/BAIwADALBgNVHQ8EBAMCBeAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF
BwMBMGkGA1UdEQRiMGCGIXNwaWZmZTovL3JlZGhhdC5jb20vdGVzdC1jbGllbnQt
MYYfaHR0cDovL3Rlc3QtY2xpZW50LTEucmVkaGF0LmNvbYIKcmVkaGF0LmNvbYIO
d3d3LnJlZGhhdC5jb20wHQYDVR0OBBYEFJxz2EplABwgpSLysJIM2+lTusviMB8G
A1UdIwQYMBaAFFG0cchLrL8gNr/H1YkrXoKcRfeUMA0GCSqGSIb3DQEBCwUAA4IB
AQAQmKvu4XHggQ5bNqo/UHz115MReBq0khPk+p3zFJ1EAY6V9l66g79pWPYGsG0L
zbJ1HUwb/854CMcv1kHJdF0CnsBYMBsBWu6+8hBTNoc8xU+v9fUQEWymDEFNxuB8
4ZW8xuREyVxwFPFnJz3t5PHnicciAe3ymkIhL26RScviR74yEoqoteMEd+h48YgG
+LYPR16R9kRvAbAPI4KGUWEYlD/zHFu+5SuZSRTbGAKAC21qnFEgZpuPKsuL/gOr
ioWUMGF2TeQUL7xw1EyxYQl6DXR6b87Y2BZBJ90VaTwcruZVYPowHrURmkAOtXP9
pSNa9XFCTq54MxA1ww7vAXfF
d3d3LnJlZGhhdC5jb20wHQYDVR0OBBYEFHqjBoUIHBF0g0htfUMUIl1r973yMB8G
A1UdIwQYMBaAFOf12l7WdUN4dZUwZrfJm84VSwgTMA0GCSqGSIb3DQEBCwUAA4IB
AQAMePd+cDw6OglgJxuLIcWYzeyaBySlOgW+6dTvA24IdJN7ERZ69yVk6hVGPCAk
xOwfREvXWxWm1/d14o+PnSQdIbnckO/p3SH+PNApd3s9crfpSR4ThAFSYQ4Qg2wM
VXB5ZFcmsiCkyrrMC25L7mbVkVn5VNXAOVKN0/MpyrA+x72HwNqt/ZmRGy1LJMuq
C0wokMzkYOIIfvuKOL499Ty0iUKvzq8fTzldsePZM6U3rXtoW8yC2/3EgfYWRRj+
HeiGvD08RTPntBLIepQuu5hYcvuMMvwahM9OeqKoVw5XXkBTSmsICUCUKH2Vgahd
hDn9K87FpCVrjAnYdmqv7pTR
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIEBzCCAu+gAwIBAgIUNT7DdWdpRF5GXsgldAUwg/w9ofMwDQYJKoZIhvcNAQEL
MIIEBzCCAu+gAwIBAgIUXT9QJkjeC4IRCxS3/CT7yaDXrx0wDQYJKoZIhvcNAQEL
BQAwgYoxCzAJBgNVBAYTAkdCMRYwFAYDVQQIDA1UeW5lIGFuZCBXZWFyMRwwGgYD
VQQHDBNOZXdjYXN0bGUgdXBvbiBUeW5lMRAwDgYDVQQKDAdSZWQgSGF0MRwwGgYD
VQQLDBNSZWQgSGF0IEVuZ2luZWVyaW5nMRUwEwYDVQQDDAxUZXN0IFJvb3QgQ0Ew
HhcNMjMwNDE5MTg0MTQ1WhcNMjUwNDE4MTg0MTQ1WjCBijELMAkGA1UEBhMCR0Ix
HhcNMjUxMjE5MTEwNTI0WhcNMjcxMjE5MTEwNTI0WjCBijELMAkGA1UEBhMCR0Ix
FjAUBgNVBAgMDVR5bmUgYW5kIFdlYXIxHDAaBgNVBAcME05ld2Nhc3RsZSB1cG9u
IFR5bmUxEDAOBgNVBAoMB1JlZCBIYXQxHDAaBgNVBAsME1JlZCBIYXQgRW5naW5l
ZXJpbmcxFTATBgNVBAMMDFRlc3QgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQAD
ggEPADCCAQoCggEBAMxXI2ABGv7MVb/vLKtgR6PJQzLIXsQHnIb80JuWAAbDujwO
a6YuYypjpbF5sZaxNK2KHZH7IuBRNy8asiz8xjt/BK3+xneAIWYGGYtIR+l2teho
eRCBdoIGruVzrHuE+FWJqt7f5eiOtbzzAeoKXMLiTwX8CF9NA0ugDjLZRlSzRS3d
chKdgq542sOQ0vwiDtdTovmZT/5RweGumZ1uvAUP8DynrxKdzffv0c30nEpcCbOI
SqSRgDUwOwCL2dXshJM3EBV0Ycn+yvvqCvDlWtqILvStw9gTHNdo+fn7g2v+/GZb
OnOx1Yp9JlzcN5JchKd47QwvX7Llk7WV4rniv3ECAwEAAaNjMGEwDwYDVR0TAQH/
BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFFG0cchLrL8gNr/H1Ykr
XoKcRfeUMB8GA1UdIwQYMBaAFFG0cchLrL8gNr/H1YkrXoKcRfeUMA0GCSqGSIb3
DQEBCwUAA4IBAQBonfu+Om04XKWQU6PQlAPoz3vxYec9UYSdL32wYiMEBj8OO/Sv
7a9aYRpahkX27pT7J0erL9jR+p+gAtmvCWl7SYzfb0LQzUgPPImb5bcEZ/Q80+Uv
IffCl3ChWEqErg0JJdMSc5qj1WpTU9+Y4YXMddviYsQgVNDea7w1v+hFAp4BlyKP
OE8h9TQDQErkxI+3kulc2X7OSvGFUDVJpSTPdYd68uSuW4pf7E9l2SbNDaTqNKFI
EyhYYl6v/HUBYNiPnRUPHdkz+Ypt/9+YxkdNc680q0mGDjU1tWZX0/XVE3pETp52
tysI3R1cdVCam29BtNXUHfhBxjfxtH+zvhjK
ggEPADCCAQoCggEBAM2fT1zuSOJVpa7n20toUuFCBIZPiPOHwx1L3RnYH7B8CtH/
JkzDCtI96fwbd5WabPZERF7MBHHkvykEsk+htAyE2jBfEOFTl9xuXu2b+m6l25jZ
XMbcRqMir/7oq5b+9fXEHMusgishHnuPuQgmLj994/iDLuGfWhs1+rtl2RuhjjIy
15quQVXu/artpeU1pRl+mpZ7SS9ZFK7vyzBUdG5YkURDoeMv+VH69VTrPFPbACJs
D8SZNMrtm+vK5AZ9QUO//j+VrtrB0LfcimH8jUyiXtRMYPVN028Ut6X8dKKOehD4
SttfU8mh1/6UKhrm/udFUhHO0Q9GcV+UaXRs+MECAwEAAaNjMGEwDwYDVR0TAQH/
BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFOf12l7WdUN4dZUwZrfJ
m84VSwgTMB8GA1UdIwQYMBaAFOf12l7WdUN4dZUwZrfJm84VSwgTMA0GCSqGSIb3
DQEBCwUAA4IBAQDD/w2m3SME30IwnT3gVOgtehni9RtMeuL1WMoX/nGVAlGmRYi5
AuP3cptuhyJMLKTRupnNDLIJNphj4gicb9VopEk/5pCfrQUxhoRU4kwAs/oQUMay
rxxKe1M17oFy2vy30FL2x9dx9D/bWG0bFIgkBBVuE4z6sWB1Pd4GgrFEs75xHGmv
FbAHtRX3sSFO/A/g5f/Pa8Yev1tjysHy8defVbD0aVDLnFZR0aVZbLpdiaHUuHrM
my1xv2Ycq9Updj6q/9o+mXqGtgtl7DqRTqEarBtNUj1UJnbhSG01tPYQGuELzYla
uDnMY3qfno72HDgo/68ddhm82ZaNeqb96qLS
-----END CERTIFICATE-----
Loading