From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) by mx.groups.io with SMTP id smtpd.web10.4118.1571153356435045705 for ; Tue, 15 Oct 2019 08:29:17 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@infradead.org header.s=bombadil.20170209 header.b=R5eYSDbC; spf=none, err=permanent DNS error (domain: bombadil.srs.infradead.org, ip: 198.137.202.133, mailfrom: batv+75f0ce7eb89552d200dd+5896+infradead.org+dwmw2@bombadil.srs.infradead.org) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=Mime-Version:Content-Type:References: In-Reply-To:Date:Cc:To:From:Subject:Message-ID:Sender:Reply-To: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=YgaRNAXSaYkZghbBUoZlq0fXf1PU8MlBuDNb3AuQ0iQ=; b=R5eYSDbCElagb14tT9e/hZAp6 yo5SenjahQriwItY2ucpWy9hvHJIi5F6FKXeV8i/UiE4eh/XCItdF7skxf4A1Q4QCqG2y9Y2lmu1A F9wuDQLPZbkefqNs/r4j5sB/2StVdUz60XAUQPc46i2ZYUXlwity0faUxfQCMkJ8PngoY+tVkfyQr uVntRwbxse3qFS1BGPlJGKWnbTxRUu3Y1cQgqXfPWALmnLMlJ3m5Qf9ycD675H1MBrGQW+JeaLfQe UWL6svOhjv2Jy35f3QWVVzLPkELs6enCA0l8cZtsqcTqzwIsZzyRR+S0BIa2/jprQ3B70QBOnag4U JY2Bf8nww==; Received: from 54-240-197-233.amazon.com ([54.240.197.233] helo=freeip.amazon.com) by bombadil.infradead.org with esmtpsa (Exim 4.92.3 #3 (Red Hat Linux)) id 1iKOl3-0001lr-SO; Tue, 15 Oct 2019 15:29:13 +0000 Message-ID: <2957070b198f4a6d3756e9e407fb766da9283ccb.camel@infradead.org> Subject: Re: [edk2-devel] [PATCH v1 0/4] Support HTTPS HostName validation feature(CVE-2019-14553) From: "David Woodhouse" To: Laszlo Ersek , "Wu, Jiaxin" , "devel@edk2.groups.io" , "Wang, Jian J" , Bret Barkelew Cc: Richard Levitte Date: Tue, 15 Oct 2019 16:29:07 +0100 In-Reply-To: <72205ed7-e848-62a0-11d2-408d5b070cc7@redhat.com> References: <20190927034441.3096-1-Jiaxin.wu@intel.com> <69774fe6-ea00-44b9-5468-c092dea6cd36@redhat.com> <8106467c9f4132c831d0aa604e897fe9d4dda12a.camel@infradead.org> <895558F6EA4E3B41AC93A00D163B727416F5D921@SHSMSX107.ccr.corp.intel.com> <777053db79600eb90a19945700293d14f4978344.camel@infradead.org> <6bb5d2f6-ec6f-1766-e19b-03fd45c1bc12@redhat.com> <9A4966EE-76CD-465C-A6CA-70DD9E38D834@infradead.org> <850a81a8-2cdc-0708-4ff7-db9825fdaedc@redhat.com> <23699ae3-10c2-037c-b3f5-ac8f5bea1fb7@redhat.com> <895558F6EA4E3B41AC93A00D163B727416F7E4AB@SHSMSX107.ccr.corp.intel.com> <6939ba4e-6c77-0769-4ac2-c3ba1ea9a0b7@redhat.com> <44468659be80e9bf1886e7b6f8f3aa77044b5fd6.camel@infradead.org> <5bbadb29-36f2-1054-fd41-5577d59c9290@redhat.com> <5c33b6c2-c8b0-aa64-a85f-06bdc3c69843@redhat.com> <1400b3e6c04f3422a1ba0bef844664aa84c6ff33.camel@infradead.org> <72205ed7-e848-62a0-11d2-408d5b070cc7@redhat.com> X-Mailer: Evolution 3.28.5-0ubuntu0.18.04.1 Mime-Version: 1.0 X-SRS-Rewrite: SMTP reverse-path rewritten from by bombadil.infradead.org. See http://www.infradead.org/rpr.html X-Groupsio-MsgNum: 49015 Content-Type: multipart/signed; micalg="sha-256"; protocol="application/x-pkcs7-signature"; boundary="=-Kfep3WPydCLMi2vaGmZs" --=-Kfep3WPydCLMi2vaGmZs Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Tue, 2019-10-15 at 15:54 +0200, Laszlo Ersek wrote: > On 10/15/19 13:03, David Woodhouse wrote: > > On Mon, 2019-10-14 at 18:15 +0200, Laszlo Ersek wrote: > > > My understanding is that a fix purely in edk2 -- that is, without > > > advancing our openssl submodule reference at once -- is possible, bas= ed > > > on your comment > > >=20 > > > https://bugzilla.tianocore.org/show_bug.cgi?id=3D960#c32 > > >=20 > > > Namely, edk2 commit 9396cdfeaa7a ("CryptoPkg: Add new TlsLib library"= , > > > 2016-12-22) added a SSL_set_verify() call (in function TlsSetVerify()= ). > > > The last argument of that call is currently NULL. > > >=20 > > > We should change that, to a callback function that implements what > > > ssl_app_verify_callback() and match_cert_hostname() do, in your sourc= e file > > >=20 > > > http://git.infradead.org/users/dwmw2/openconnect.git/blob/HEAD:/opens= sl.c > >=20 > >=20 > > Hm, you are lost in a twisty maze of verify callbacks, all alike. >=20 > Definitely. >=20 > > Actually the one you can set with SSL_set_verify() isn't the one you > > want. That's a low-level one, called from within the generic > > X509_verify_cert() function. >=20 > Well, above I referred to SSL_set_verify() only because you had named > that function in : Yeah, I was wrong. You were the one who called me an expert; I didn't :) > Thank you very much for this code. >=20 > To me it seems like this patch should be squashed into patch#2 (which > modifies TlsLib), after adapting it to the edk2 coding style. >=20 > I have some comments / questions. >=20 >=20 > (1) In TlsSetVerifyHost(), you mention that SSL_set1_host() should be > replaced with SSL_set_ex_data(). OK. >=20 > In case the client does not use the TlsSetVerifyHost() function, > SSL_set_ex_data() would not be called. However, app_verify_callback() > would still be called. >=20 > Is my understanding correct that "hostname" (from SSL_get_ex_data()) > would be NULL in that case, and therefore both > X509_VERIFY_PARAM_set1_ip_asc() and X509_VERIFY_PARAM_set1_host() would > be omitted? >=20 > (I mean this looks like the correct behavior to me; just asking if that > is indeed the intent of the code.) Yep. In the case where there's no such ex_data attached to the SSL object, our own app_verify_callback() function would do nothing special, just call through to the standard X509_verify_cert() function that would have been called if we hadn't registered our own override. You may call this "correct". I think you're right, in the context you meant it. But I suggest there is a conversation to be had about whether it's ever "correct" for a crypto library to silently accept any bloody certificate it sees, regardless of what the Subject of that certificate is. Or whether perhaps it ought to fail safe, and require you to jump through extra hoops if you *really* want to accept any certificate. In a world where crypto libraries made it hard for the users to Do The Wrong Thing, CVE-2019-14553 would never have happened. But we digress. Is it late enough in the day for me to start drinking yet? > (2) The documentation of the APIs seems a bit strange. I've found the > following "directory" web pages: >=20 > https://www.openssl.org/docs/man1.0.2/man3/ > https://www.openssl.org/docs/man1.1.0/man3/ > https://www.openssl.org/docs/man1.1.1/man3/ >=20 > edk2 currently consumes "OpenSSL_1_1_1b", so I thought I should only > look at the last page. However, SSL_get_ex_new_index() is only > documented in the first page. >=20 > Is my understanding correct that each OpenSSL API should be looked up in > the latest documentation directory that appears to describe it? >=20 > In other words: assuming I look for SSL_get_ex_new_index() in the 1.1.1 > manual, and fail to find it, does that mean that the API is deprecated, > or only that I should look at an earlier release of the manual? I was just looking at the code. I happened to be looking at OpenSSL HEAD but the sconnect demo I showed in my second email works with 1.1.1. >=20 > (3) Anyway, SSL_get_ex_new_index() seems like a thin wrapper around > CRYPTO_get_ex_new_index(). >=20 > https://www.openssl.org/docs/man1.0.2/man3/SSL_get_ex_new_index.html > https://www.openssl.org/docs/man1.1.1/man3/CRYPTO_get_ex_new_index.html >=20 > Based on that, I think the second ("argp") parameter of our > SSL_get_ex_new_index() call should be NULL, as the "argp" parameters of > the "free" and "dup" functions are unused. >=20 > Do you agree? Yeah, I had just cargo-culted that from elsewhere, and was assuming it was performing some kind of de-duplication or alternative lookup functionality. It does look like you can leave it NULL and it doesn't matter. >=20 > (4) What happens if we call SSL_set_ex_data(), but a non-NULL value has > already been stored for the same index? >=20 > Do we have to first fetch it with SSL_get_ex_data() and free it, or will > it be automatically freed with "free_func"? It will be automatically freed with free_func. Note that this doesn't work in the sconnect.c patch I sent, but only because I'd forgotten to actually add the call to SSL_get_ex_new_index(). After I fixed that and wasn't just using an index of zero, I saw the printf() that I'd added in my free_func. > (Note: I think that, if we used a "new_func" for allocating anything, > this question could be relevant the very first time SSL_set_ex_data() > were called.) I believe new_func is only for when a new SSL object is created. We don't need that. > (5) The most confusing part... If I look at the 1.0.2 documentation, it > says about "dup_func": >=20 > > dup_func() is called when a structure is being copied. [...] The > > from_d parameter is passed a pointer to the source application data > > when the function is called, when the function returns the value is > > copied to the destination: the application can thus modify the data > > pointed to by from_d and have different values in the source and > > destination >=20 > This makes no sense: I wouldn't want to modify the source application > data in-place, just to give the new parent object a modified instance of = it! >=20 > Also, how would OpenSSL know how many bytes to copy? >=20 > So I looked at the code, and it turns out dup_func is called with a > (void**), not a (void*): >=20 > if (!storage[i]->dup_func(to, from, &ptr, i, > storage[i]->argl, storage[i]->argp)= ) >=20 > The 1.1.1 documentation is more accurate; it says: >=20 > https://www.openssl.org/docs/man1.1.1/man3/CRYPTO_get_ex_new_index.html >=20 > > The from_d parameter needs to be cast to a void **pptr as the API has > > currently the wrong signature; that will be changed in a future > > version. The *pptr is a pointer to the source exdata. When the > > dup_func() returns, the value in *pptr is copied to the destination > > ex_data. If the pointer contained in *pptr is not modified by the > > dup_func(), then both to and from will point to the same data Yes, I think dup_func wants to do something like: int ssl_target_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from, void *from_d, int idx, long argl, void *argp) { char **p =3D from_d; if (*p) { *p =3D strdup(*p); return !!*p; } return 1; } > So let me summarize the documentation status: >=20 > - SSL_get_ex_new_index is not documented in 1.1.1, >=20 > - SSL_get_ex_new_index is not documented in 1.1.0, >=20 > - SSL_get_ex_new_index has a "shim" documentation in 1.0.2, and it > refers the reader to RSA_get_ex_new_index(), >=20 > - RSA_get_ex_new_index is documented in 1.0.2 *incorrectly* (with regard > to dup_func), >=20 > - the valid documentation is in 1.1.1, under CRYPTO_get_ex_new_index -- > but for learning about that function, I had to look at the library > source code. >=20 > When you suggested the IP checking would be easy to imlement, you were > joking, right? :) I confess I hadn't realised that we needed to jump through ex_data hoops to even get the hostname information to the right place in the callback. But I don't think I actually said "easy", did I? Only that it would take less typing than we'd already expended in trying to make excuses for the regression. I also said you could manage it, which you seem to have proved by working out the details I had... erm... left as an exercise for you :) > (6) Given that we are introducing callbacks (from > CryptoPkg/Library/OpensslLib to CryptoPkg/Library/TlsLib), and OpenSSL > does not declare these function prototypes with EFIAPI, the callbacks > too must be defined with "native" (not EFIAPI) calling convention. Yes, that makes sense. --=-Kfep3WPydCLMi2vaGmZs Content-Type: application/x-pkcs7-signature; name="smime.p7s" Content-Disposition: attachment; filename="smime.p7s" Content-Transfer-Encoding: base64 MIAGCSqGSIb3DQEHAqCAMIACAQExDzANBglghkgBZQMEAgEFADCABgkqhkiG9w0BBwEAAKCCECow ggUcMIIEBKADAgECAhEA4rtJSHkq7AnpxKUY8ZlYZjANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxPTA7BgNVBAMTNENPTU9ETyBSU0EgQ2xpZW50IEF1dGhl bnRpY2F0aW9uIGFuZCBTZWN1cmUgRW1haWwgQ0EwHhcNMTkwMTAyMDAwMDAwWhcNMjIwMTAxMjM1 OTU5WjAkMSIwIAYJKoZIhvcNAQkBFhNkd213MkBpbmZyYWRlYWQub3JnMIIBIjANBgkqhkiG9w0B AQEFAAOCAQ8AMIIBCgKCAQEAsv3wObLTCbUA7GJqKj9vHGf+Fa+tpkO+ZRVve9EpNsMsfXhvFpb8 RgL8vD+L133wK6csYoDU7zKiAo92FMUWaY1Hy6HqvVr9oevfTV3xhB5rQO1RHJoAfkvhy+wpjo7Q cXuzkOpibq2YurVStHAiGqAOMGMXhcVGqPuGhcVcVzVUjsvEzAV9Po9K2rpZ52FE4rDkpDK1pBK+ uOAyOkgIg/cD8Kugav5tyapydeWMZRJQH1vMQ6OVT24CyAn2yXm2NgTQMS1mpzStP2ioPtTnszIQ Ih7ASVzhV6csHb8Yrkx8mgllOyrt9Y2kWRRJFm/FPRNEurOeNV6lnYAXOymVJwIDAQABo4IB0zCC Ac8wHwYDVR0jBBgwFoAUgq9sjPjF/pZhfOgfPStxSF7Ei8AwHQYDVR0OBBYEFLfuNf820LvaT4AK xrGK3EKx1DE7MA4GA1UdDwEB/wQEAwIFoDAMBgNVHRMBAf8EAjAAMB0GA1UdJQQWMBQGCCsGAQUF BwMEBggrBgEFBQcDAjBGBgNVHSAEPzA9MDsGDCsGAQQBsjEBAgEDBTArMCkGCCsGAQUFBwIBFh1o dHRwczovL3NlY3VyZS5jb21vZG8ubmV0L0NQUzBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3Js LmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDbGllbnRBdXRoZW50aWNhdGlvbmFuZFNlY3VyZUVtYWls Q0EuY3JsMIGLBggrBgEFBQcBAQR/MH0wVQYIKwYBBQUHMAKGSWh0dHA6Ly9jcnQuY29tb2RvY2Eu Y29tL0NPTU9ET1JTQUNsaWVudEF1dGhlbnRpY2F0aW9uYW5kU2VjdXJlRW1haWxDQS5jcnQwJAYI KwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmNvbW9kb2NhLmNvbTAeBgNVHREEFzAVgRNkd213MkBpbmZy YWRlYWQub3JnMA0GCSqGSIb3DQEBCwUAA4IBAQALbSykFusvvVkSIWttcEeifOGGKs7Wx2f5f45b nv2ghcxK5URjUvCnJhg+soxOMoQLG6+nbhzzb2rLTdRVGbvjZH0fOOzq0LShq0EXsqnJbbuwJhK+ PnBtqX5O23PMHutP1l88AtVN+Rb72oSvnD+dK6708JqqUx2MAFLMevrhJRXLjKb2Mm+/8XBpEw+B 7DisN4TMlLB/d55WnT9UPNHmQ+3KFL7QrTO8hYExkU849g58Dn3Nw3oCbMUgny81ocrLlB2Z5fFG Qu1AdNiBA+kg/UxzyJZpFbKfCITd5yX49bOriL692aMVDyqUvh8fP+T99PqorH4cIJP6OxSTdxKM MIIFHDCCBASgAwIBAgIRAOK7SUh5KuwJ6cSlGPGZWGYwDQYJKoZIhvcNAQELBQAwgZcxCzAJBgNV BAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAY BgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMT0wOwYDVQQDEzRDT01PRE8gUlNBIENsaWVudCBBdXRo ZW50aWNhdGlvbiBhbmQgU2VjdXJlIEVtYWlsIENBMB4XDTE5MDEwMjAwMDAwMFoXDTIyMDEwMTIz NTk1OVowJDEiMCAGCSqGSIb3DQEJARYTZHdtdzJAaW5mcmFkZWFkLm9yZzCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBALL98Dmy0wm1AOxiaio/bxxn/hWvraZDvmUVb3vRKTbDLH14bxaW /EYC/Lw/i9d98CunLGKA1O8yogKPdhTFFmmNR8uh6r1a/aHr301d8YQea0DtURyaAH5L4cvsKY6O 0HF7s5DqYm6tmLq1UrRwIhqgDjBjF4XFRqj7hoXFXFc1VI7LxMwFfT6PStq6WedhROKw5KQytaQS vrjgMjpICIP3A/CroGr+bcmqcnXljGUSUB9bzEOjlU9uAsgJ9sl5tjYE0DEtZqc0rT9oqD7U57My ECIewElc4VenLB2/GK5MfJoJZTsq7fWNpFkUSRZvxT0TRLqznjVepZ2AFzsplScCAwEAAaOCAdMw ggHPMB8GA1UdIwQYMBaAFIKvbIz4xf6WYXzoHz0rcUhexIvAMB0GA1UdDgQWBBS37jX/NtC72k+A CsaxitxCsdQxOzAOBgNVHQ8BAf8EBAMCBaAwDAYDVR0TAQH/BAIwADAdBgNVHSUEFjAUBggrBgEF BQcDBAYIKwYBBQUHAwIwRgYDVR0gBD8wPTA7BgwrBgEEAbIxAQIBAwUwKzApBggrBgEFBQcCARYd aHR0cHM6Ly9zZWN1cmUuY29tb2RvLm5ldC9DUFMwWgYDVR0fBFMwUTBPoE2gS4ZJaHR0cDovL2Ny bC5jb21vZG9jYS5jb20vQ09NT0RPUlNBQ2xpZW50QXV0aGVudGljYXRpb25hbmRTZWN1cmVFbWFp bENBLmNybDCBiwYIKwYBBQUHAQEEfzB9MFUGCCsGAQUFBzAChklodHRwOi8vY3J0LmNvbW9kb2Nh LmNvbS9DT01PRE9SU0FDbGllbnRBdXRoZW50aWNhdGlvbmFuZFNlY3VyZUVtYWlsQ0EuY3J0MCQG CCsGAQUFBzABhhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wHgYDVR0RBBcwFYETZHdtdzJAaW5m cmFkZWFkLm9yZzANBgkqhkiG9w0BAQsFAAOCAQEAC20spBbrL71ZEiFrbXBHonzhhirO1sdn+X+O W579oIXMSuVEY1LwpyYYPrKMTjKECxuvp24c829qy03UVRm742R9Hzjs6tC0oatBF7KpyW27sCYS vj5wbal+TttzzB7rT9ZfPALVTfkW+9qEr5w/nSuu9PCaqlMdjABSzHr64SUVy4ym9jJvv/FwaRMP gew4rDeEzJSwf3eeVp0/VDzR5kPtyhS+0K0zvIWBMZFPOPYOfA59zcN6AmzFIJ8vNaHKy5QdmeXx RkLtQHTYgQPpIP1Mc8iWaRWynwiE3ecl+PWzq4i+vdmjFQ8qlL4fHz/k/fT6qKx+HCCT+jsUk3cS jDCCBeYwggPOoAMCAQICEGqb4Tg7/ytrnwHV2binUlYwDQYJKoZIhvcNAQEMBQAwgYUxCzAJBgNV BAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAY BgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMSswKQYDVQQDEyJDT01PRE8gUlNBIENlcnRpZmljYXRp b24gQXV0aG9yaXR5MB4XDTEzMDExMDAwMDAwMFoXDTI4MDEwOTIzNTk1OVowgZcxCzAJBgNVBAYT AkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAYBgNV BAoTEUNPTU9ETyBDQSBMaW1pdGVkMT0wOwYDVQQDEzRDT01PRE8gUlNBIENsaWVudCBBdXRoZW50 aWNhdGlvbiBhbmQgU2VjdXJlIEVtYWlsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC AQEAvrOeV6wodnVAFsc4A5jTxhh2IVDzJXkLTLWg0X06WD6cpzEup/Y0dtmEatrQPTRI5Or1u6zf +bGBSyD9aH95dDSmeny1nxdlYCeXIoymMv6pQHJGNcIDpFDIMypVpVSRsivlJTRENf+RKwrB6vcf WlP8dSsE3Rfywq09N0ZfxcBa39V0wsGtkGWC+eQKiz4pBZYKjrc5NOpG9qrxpZxyb4o4yNNwTqza aPpGRqXB7IMjtf7tTmU2jqPMLxFNe1VXj9XB1rHvbRikw8lBoNoSWY66nJN/VCJv5ym6Q0mdCbDK CMPybTjoNCQuelc0IAaO4nLUXk0BOSxSxt8kCvsUtQIDAQABo4IBPDCCATgwHwYDVR0jBBgwFoAU u69+Aj36pvE8hI6t7jiY7NkyMtQwHQYDVR0OBBYEFIKvbIz4xf6WYXzoHz0rcUhexIvAMA4GA1Ud DwEB/wQEAwIBhjASBgNVHRMBAf8ECDAGAQH/AgEAMBEGA1UdIAQKMAgwBgYEVR0gADBMBgNVHR8E RTBDMEGgP6A9hjtodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9SU0FDZXJ0aWZpY2F0aW9u QXV0aG9yaXR5LmNybDBxBggrBgEFBQcBAQRlMGMwOwYIKwYBBQUHMAKGL2h0dHA6Ly9jcnQuY29t b2RvY2EuY29tL0NPTU9ET1JTQUFkZFRydXN0Q0EuY3J0MCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz cC5jb21vZG9jYS5jb20wDQYJKoZIhvcNAQEMBQADggIBAHhcsoEoNE887l9Wzp+XVuyPomsX9vP2 SQgG1NgvNc3fQP7TcePo7EIMERoh42awGGsma65u/ITse2hKZHzT0CBxhuhb6txM1n/y78e/4ZOs 0j8CGpfb+SJA3GaBQ+394k+z3ZByWPQedXLL1OdK8aRINTsjk/H5Ns77zwbjOKkDamxlpZ4TKSDM KVmU/PUWNMKSTvtlenlxBhh7ETrN543j/Q6qqgCWgWuMAXijnRglp9fyadqGOncjZjaaSOGTTFB+ E2pvOUtY+hPebuPtTbq7vODqzCM6ryEhNhzf+enm0zlpXK7q332nXttNtjv7VFNYG+I31gnMrwfH M5tdhYF/8v5UY5g2xANPECTQdu9vWPoqNSGDt87b3gXb1AiGGaI06vzgkejL580ul+9hz9D0S0U4 jkhJiA7EuTecP/CFtR72uYRBcunwwH3fciPjviDDAI9SnC/2aPY8ydehzuZutLbZdRJ5PDEJM/1t yZR2niOYihZ+FCbtf3D9mB12D4ln9icgc7CwaxpNSCPt8i/GqK2HsOgkL3VYnwtx7cJUmpvVdZ4o gnzgXtgtdk3ShrtOS1iAN2ZBXFiRmjVzmehoMof06r1xub+85hFQzVxZx5/bRaTKTlL8YXLI8nAb R9HWdFqzcOoB/hxfEyIQpx9/s81rgzdEZOofSlZHynoSMYIDyjCCA8YCAQEwga0wgZcxCzAJBgNV BAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNVBAcTB1NhbGZvcmQxGjAY BgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMT0wOwYDVQQDEzRDT01PRE8gUlNBIENsaWVudCBBdXRo ZW50aWNhdGlvbiBhbmQgU2VjdXJlIEVtYWlsIENBAhEA4rtJSHkq7AnpxKUY8ZlYZjANBglghkgB ZQMEAgEFAKCCAe0wGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMTkx MDE1MTUyOTA3WjAvBgkqhkiG9w0BCQQxIgQgd8uN9JghJHRpkmbyRPU+LlnQ9mDnvYLs5dl2Ji9S K3Mwgb4GCSsGAQQBgjcQBDGBsDCBrTCBlzELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIg TWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQx PTA7BgNVBAMTNENPTU9ETyBSU0EgQ2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBTZWN1cmUgRW1h aWwgQ0ECEQDiu0lIeSrsCenEpRjxmVhmMIHABgsqhkiG9w0BCRACCzGBsKCBrTCBlzELMAkGA1UE BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxPTA7BgNVBAMTNENPTU9ETyBSU0EgQ2xpZW50IEF1dGhl bnRpY2F0aW9uIGFuZCBTZWN1cmUgRW1haWwgQ0ECEQDiu0lIeSrsCenEpRjxmVhmMA0GCSqGSIb3 DQEBAQUABIIBAFZN/pz0Fa7LhkYSPmEtez+xNCgIIMm5PRWrZc3kgzGfXe5Lz2cc6/difFbgBYEy P+TzymKQ2hEyFSnUl6i04X9clQFFvm94D8b/3DuM+bPFWj3GRs1V8eBWxnpJrVbJsk8aHnI43IaJ FqdIsQR5lF97sMWHbcJ9GGLFwXHTCSYEo47/EPdVtpNP0P+FeWUwGkNd3ukO549bHMp+RIKLPFOt Nokt//rwjz9n0amX8XFGOcrvx3zSKqEeZXkb3hMbwiViA1cA9cTANdvkRpE0HTOqPXIV4Ffm9N8Z P+HqTuwWSVyTGZhaC0ZNONrJPzIzCKeFLXiAkuQS93hAXbIC0zsAAAAAAAA= --=-Kfep3WPydCLMi2vaGmZs--