public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Laszlo Ersek" <lersek@redhat.com>
To: David Woodhouse <dwmw2@infradead.org>,
	"Wu, Jiaxin" <jiaxin.wu@intel.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>,
	"Wang, Jian J" <jian.j.wang@intel.com>,
	Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Richard Levitte <levitte@openssl.org>
Subject: Re: [edk2-devel] [PATCH v1 0/4] Support HTTPS HostName validation feature(CVE-2019-14553)
Date: Tue, 15 Oct 2019 18:56:53 +0200	[thread overview]
Message-ID: <7356801d-0b64-6059-a737-aa5ddd2d297b@redhat.com> (raw)
In-Reply-To: <72205ed7-e848-62a0-11d2-408d5b070cc7@redhat.com>

On 10/15/19 15:54, Laszlo Ersek wrote:
> On 10/15/19 13:03, David Woodhouse wrote:

>> The "app callback" in my OpenConnect example is set on the SSL_CTX not
>> the SSL object, and is called from the top-level
>> ssl_verify_cert_chain() function *instead* of X509_verify_cert().
>>
>> It is X509_verify_cert() which can do the hostname/IP checks for us, if
>> we can only tell it that we want it to. But the X509_VERIFY_PARAM
>> object is private to the SSL.
>>
>> As discussed, we have the SSL_set1_host() accessor function which lets
>> us set the hostname. The implementation really is a simple one-liner,
>> calling X509_VERIFY_PARAM_set1_host(s->param, …). But there's no way
>> for use to set the IP address from the outside, without an equivalent
>> accessor function for that (and without SSL_set1_host() spotting that
>> the string it's given is an IP address, and doing so).
>>
>> But what we can do is stash the target string in some ex_data hanging
>> off the SSL object, then have an app callback — which *can* reach the
>> underlying X509_VERIFY_PARAM — call X509_VERIFY_PARAM_set1_host() or
>> X509_VERIFY_PARAM_set1_ip_asc() accordingly, before just calling the
>> normal X509_verify_cert() function that it has overridden.
>>
>> Something like this... and instead of calling SSL_set1_host(ssl, host)
>> your own code now has to call
>> SSL_set_ex_data(ssl, ssl_target_idx, strdup(host));
>>
>> diff --git a/CryptoPkg/Library/TlsLib/TlsInit.c b/CryptoPkg/Library/TlsLib/TlsInit.c
>> index f9ad6f6b946c..add5810cc4bd 100644
>> --- a/CryptoPkg/Library/TlsLib/TlsInit.c
>> +++ b/CryptoPkg/Library/TlsLib/TlsInit.c
>> @@ -9,6 +9,49 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>>  
>>  #include "InternalTlsLib.h"
>>  
>> +/* You are lost in a twisty maze of SSL cert verify callbacks, all
>> + * alike.  All we really wanted to do was call SSL_set1_host() and
>> + * have it work for IP addresses too, which OpenSSL PR#9201 will do
>> + * for us. But until we update OpenSSL, that doesn't work. And we
>> + * can't get at the underlying X509_VERIFY_PARAM to set the IP address
>> + * for ourselves.
>> + *
>> + * So we install an app_verify_callback in the SSL_CTX (which is
>> + * different to the per-SSL callback wae can use, because it happens
>> + * sooner. All our callback does it set the hostname or IP address in
>> + * the X509_VERIFY_PARAM like we wanted to in the first place, and
>> + * then call X509_verify_param() which is the default function.
>> + *
>> + * How does it find the hostname/IP string? It's attached to the SSL
>> + * as ex_data, using this index:
>> + */
>> +static int ssl_target_idx;
>> +
>> +void ssl_target_free(void *parent, void *ptr, CRYPTO_EX_DATA *ad,
>> +		    int idx, long argl, void *argp)
>> +{
>> +	/* Free it */
>> +}
>> +
>> +int ssl_target_dup(CRYPTO_EX_DATA *to, const CRYPTO_EX_DATA *from,
>> +		   void *from_d, int idx, long argl, void *argp)
>> +{
>> +	/* strdup it */
>> +	return 0;
>> +}
>> +
>> +int app_verify_callback(X509_STORE_CTX *ctx, void *dummy)
>> +{
>> +	SSL *ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
>> +	char *hostname = SSL_get_ex_data(ssl, ssl_target_idx);
>> +	X509_VERIFY_PARAM *vpm = X509_STORE_CTX_get0_param(ctx);
>> +
>> +	if (hostname && !X509_VERIFY_PARAM_set1_ip_asc(vpm, hostname))
>> +		X509_VERIFY_PARAM_set1_host(vpm, hostname, 0);
>> +
>> +	return X509_verify_cert(ctx);
>> +}
>> +
>>  /**
>>    Initializes the OpenSSL library.
>>  
>> @@ -40,6 +83,9 @@ TlsInitialize (
>>      return FALSE;
>>    }
>>  
>> +  ssl_target_idx = SSL_get_ex_new_index(0, "TLS target hosthame/IP", NULL,
>> +					ssl_target_dup, ssl_target_free);
>> +
>>    //
>>    // Initialize the pseudorandom number generator.
>>    //
>> @@ -106,6 +152,10 @@ TlsCtxNew (
>>    //
>>    SSL_CTX_set_min_proto_version (TlsCtx, ProtoVersion);
>>  
>> +  /* SSL_CTX_set_cert_verify_callback. Not SSL_CTX_set_verify(), which
>> +   * we could have done as SSL_set_verify(). Twisty maze, remember? */
>> +  SSL_CTX_set_cert_verify_callback(TlsCtx, app_verify_callback, NULL);
>> +
>>    return (VOID *) TlsCtx;
>>  }

> (4) What happens if we call SSL_set_ex_data(), but a non-NULL value has
> already been stored for the same index?
> 
> Do we have to first fetch it with SSL_get_ex_data() and free it, or will
> it be automatically freed with "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.)

A similar question:

is it possible that app_verify_callback() is called more frequently than
SSL_set_ex_data() (in TlsSetVerify())?

Because that means that the frequency of SSL_set1_host() calls changes.
Previously we'd call SSL_set1_host() once per TlsSetVerify(), but now it
could be called multiple times per TlsSetVerify(). Is that the case?

If it is, is it OK?

To me the ownership of these strings (i.e., what component is
responsible for freeing the strings) is impenetrable. :(

Even the UEFI 2.8 spec doesn't explain whether EFI_TLS_SET_SESSION_DATA
saves the array of characters pointed-to by
"EFI_TLS_VERIFY_HOST.HostName", or just the pointer itself. :/

Laszlo

  parent reply	other threads:[~2019-10-15 16:56 UTC|newest]

Thread overview: 61+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-09-27  3:44 [PATCH v1 0/4] Support HTTPS HostName validation feature(CVE-2019-14553) Wu, Jiaxin
2019-09-27  3:44 ` [PATCH v1 1/4] MdePkg/Include/Protocol/Tls.h: Add the data type of EfiTlsVerifyHost(CVE-2019-14553) Wu, Jiaxin
2019-09-27  3:44 ` [PATCH v1 2/4] CryptoPkg/TlsLib: Add the new API "TlsSetVerifyHost"(CVE-2019-14553) Wu, Jiaxin
2019-09-27  3:44 ` [PATCH v1 3/4] NetworkPkg/TlsDxe: Add the support of host validation to TlsDxe driver(CVE-2019-14553) Wu, Jiaxin
2019-09-27  3:44 ` [PATCH v1 4/4] NetworkPkg/HttpDxe: Set the HostName for the verification(CVE-2019-14553) Wu, Jiaxin
2019-09-29  6:09 ` [edk2-devel] [PATCH v1 0/4] Support HTTPS HostName validation feature(CVE-2019-14553) Wang, Jian J
2019-09-30 23:21   ` Laszlo Ersek
2019-10-01  9:02     ` David Woodhouse
2019-10-08  6:19       ` Wu, Jiaxin
2019-10-09  7:53         ` David Woodhouse
2019-10-09 20:24           ` Laszlo Ersek
2019-10-09 20:34             ` David Woodhouse
2019-10-10  3:11               ` Wu, Jiaxin
2019-10-10  8:00               ` Laszlo Ersek
2019-10-10 15:45                 ` David Woodhouse
2019-10-10 18:03                   ` Laszlo Ersek
2019-10-11  2:24                     ` Wu, Jiaxin
2019-10-11  6:58                       ` David Woodhouse
2019-10-11  8:04                         ` Wu, Jiaxin
2019-10-11 10:55                       ` Laszlo Ersek
2019-10-11 11:16                         ` David Woodhouse
2019-10-11 15:36                           ` Laszlo Ersek
2019-10-11 16:01                             ` David Woodhouse
2019-10-14 16:15                               ` Laszlo Ersek
2019-10-14 16:20                                 ` Laszlo Ersek
2019-10-14 16:53                                 ` David Woodhouse
2019-10-15 11:03                                 ` David Woodhouse
2019-10-15 11:06                                   ` David Woodhouse
2019-10-15 13:54                                   ` Laszlo Ersek
2019-10-15 15:29                                     ` David Woodhouse
2019-10-15 16:56                                     ` Laszlo Ersek [this message]
2019-10-15 17:34                                       ` Laszlo Ersek
2019-10-16  9:40                                         ` David Woodhouse
2019-10-16 10:27                                           ` Laszlo Ersek
2019-10-15 15:57                     ` David Woodhouse
2019-10-15 17:28                       ` Laszlo Ersek
2019-10-10  2:45           ` Wu, Jiaxin
2019-10-09 15:54     ` Laszlo Ersek
2019-10-10  2:46       ` Wu, Jiaxin
2019-10-15 23:08 ` [RFC v1 5/4] CryptoPkg/TlsLib: accept peer certs via both DNS names and IP addresses Laszlo Ersek
2019-10-16  5:18   ` [edk2-devel] " Wu, Jiaxin
2019-10-16  7:36     ` Laszlo Ersek
2019-10-16  7:54       ` Laszlo Ersek
2019-10-16  7:56         ` David Woodhouse
2019-10-16  8:08       ` Laszlo Ersek
2019-10-16  9:19       ` David Woodhouse
2019-10-16 11:41         ` Laszlo Ersek
2019-10-16 13:35           ` David Woodhouse
2019-10-16 14:43             ` Laszlo Ersek
2019-10-16 15:25               ` David Woodhouse
2019-10-17 15:35                 ` Laszlo Ersek
2019-10-17 15:49                   ` David Woodhouse
2019-10-18 13:25                     ` Laszlo Ersek
2019-10-25  2:12                       ` Wu, Jiaxin
2019-10-25  8:14                         ` Laszlo Ersek
2019-10-24 19:47                     ` Laszlo Ersek
2019-10-25  2:13                       ` Wu, Jiaxin
2019-10-25  2:12               ` Wu, Jiaxin
2019-10-25  2:12           ` Wu, Jiaxin
2019-10-16  8:45     ` David Woodhouse
2019-10-16 11:01   ` David Woodhouse

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=7356801d-0b64-6059-a737-aa5ddd2d297b@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox