From 970b5f67512e00fb26765a14b4a1cb8a8a04276d Mon Sep 17 00:00:00 2001 From: Laszlo Ersek Date: Mon, 2 Dec 2019 12:31:57 +0100 Subject: [PATCH 6/9] CryptoPkg/TlsLib: TlsSetVerifyHost: parse IP address literals as such (CVE-2019-14553) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit RH-Author: Laszlo Ersek Message-id: <20191117220052.15700-7-lersek@redhat.com> Patchwork-id: 92452 O-Subject: [RHEL-8.2.0 edk2 PATCH 6/9] CryptoPkg/TlsLib: TlsSetVerifyHost: parse IP address literals as such (CVE-2019-14553) Bugzilla: 1536624 RH-Acked-by: Philippe Mathieu-Daudé RH-Acked-by: Vitaly Kuznetsov Using the inet_pton() function that we imported in the previous patches, recognize if "HostName" is an IP address literal, and then parse it into binary representation. Passing the latter to OpenSSL for server certificate validation is important, per RFC-2818 : > In some cases, the URI is specified as an IP address rather than a > hostname. In this case, the iPAddress subjectAltName must be present in > the certificate and must exactly match the IP in the URI. Note: we cannot use X509_VERIFY_PARAM_set1_ip_asc() because in the OpenSSL version that is currently consumed by edk2, said function depends on sscanf() for parsing IPv4 literals. In "CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c", we only provide an empty -- always failing -- stub for sscanf(), however. Cc: David Woodhouse Cc: Jian J Wang Cc: Jiaxin Wu Cc: Sivaraman Nainar Cc: Xiaoyu Lu Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=960 CVE: CVE-2019-14553 Suggested-by: David Woodhouse Signed-off-by: Laszlo Ersek Acked-by: Jian J Wang Reviewed-by: Jiaxin Wu (cherry picked from commit 1e72b1fb2ec597caedb5170079bb213f6d67f32a) --- CryptoPkg/Library/TlsLib/TlsConfig.c | 28 ++++++++++++++++++++++++---- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/CryptoPkg/Library/TlsLib/TlsConfig.c b/CryptoPkg/Library/TlsLib/TlsConfig.c index 2bf5aee..307eb57 100644 --- a/CryptoPkg/Library/TlsLib/TlsConfig.c +++ b/CryptoPkg/Library/TlsLib/TlsConfig.c @@ -517,7 +517,11 @@ TlsSetVerifyHost ( IN CHAR8 *HostName ) { - TLS_CONNECTION *TlsConn; + TLS_CONNECTION *TlsConn; + X509_VERIFY_PARAM *VerifyParam; + UINTN BinaryAddressSize; + UINT8 BinaryAddress[MAX (NS_INADDRSZ, NS_IN6ADDRSZ)]; + INTN ParamStatus; TlsConn = (TLS_CONNECTION *) Tls; if (TlsConn == NULL || TlsConn->Ssl == NULL || HostName == NULL) { @@ -526,11 +530,27 @@ TlsSetVerifyHost ( SSL_set_hostflags(TlsConn->Ssl, Flags); - if (SSL_set1_host(TlsConn->Ssl, HostName) == 0) { - return EFI_ABORTED; + VerifyParam = SSL_get0_param (TlsConn->Ssl); + ASSERT (VerifyParam != NULL); + + BinaryAddressSize = 0; + if (inet_pton (AF_INET6, HostName, BinaryAddress) == 1) { + BinaryAddressSize = NS_IN6ADDRSZ; + } else if (inet_pton (AF_INET, HostName, BinaryAddress) == 1) { + BinaryAddressSize = NS_INADDRSZ; } - return EFI_SUCCESS; + if (BinaryAddressSize > 0) { + DEBUG ((DEBUG_VERBOSE, "%a:%a: parsed \"%a\" as an IPv%c address " + "literal\n", gEfiCallerBaseName, __FUNCTION__, HostName, + (UINTN)((BinaryAddressSize == NS_IN6ADDRSZ) ? '6' : '4'))); + ParamStatus = X509_VERIFY_PARAM_set1_ip (VerifyParam, BinaryAddress, + BinaryAddressSize); + } else { + ParamStatus = X509_VERIFY_PARAM_set1_host (VerifyParam, HostName, 0); + } + + return (ParamStatus == 1) ? EFI_SUCCESS : EFI_ABORTED; } /** -- 1.8.3.1