From: "Wu, Jiaxin" <jiaxin.wu@intel.com>
To: "Fu, Siyuan" <siyuan.fu@intel.com>,
"edk2-devel@lists.01.org" <edk2-devel@lists.01.org>
Cc: "Ye, Ting" <ting.ye@intel.com>,
"Zhang, Lubo" <lubo.zhang@intel.com>,
"Long, Qin" <qin.long@intel.com>,
Thomas Palmer <thomas.palmer@hpe.com>
Subject: Re: [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6
Date: Thu, 15 Dec 2016 07:14:53 +0000 [thread overview]
Message-ID: <895558F6EA4E3B41AC93A00D163B72741627F514@SHSMSX103.ccr.corp.intel.com> (raw)
In-Reply-To: <B1FF2E9001CE9041BD10B825821D5BC58A88641B@SHSMSX151.ccr.corp.intel.com>
Good suggestion, I will change the flag to "https://" before commit the patch.
Even we have a library to get the URI scheme, we still need check whether it's http or https.
Thanks,
Jiaxin
> -----Original Message-----
> From: Fu, Siyuan
> Sent: Thursday, December 15, 2016 10:39 AM
> To: Wu, Jiaxin <jiaxin.wu@intel.com>; edk2-devel@lists.01.org
> Cc: Ye, Ting <ting.ye@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>;
> Long, Qin <qin.long@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>
> Subject: RE: [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4
> and IPv6
>
> Hi, Jiaxin
>
> In function IsHttpsUrl(), I suggest to search string "https://" instead of only
> "https", in case of some incorrect scheme like "httpsabc://".
> However, since there is already code to parse the URL by using
> HttpParseUrl(), the scheme should already been known by the Http url
> parser, I think it better to add a new function to the HttpLib like
> HttpUrlGetScheme().
>
> Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>
>
>
> -----Original Message-----
> From: Wu, Jiaxin
> Sent: 2016年12月14日 15:34
> To: edk2-devel@lists.01.org
> Cc: Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang,
> Lubo <lubo.zhang@intel.com>; Long, Qin <qin.long@intel.com>; Thomas
> Palmer <thomas.palmer@hpe.com>; Wu, Jiaxin <jiaxin.wu@intel.com>
> Subject: [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and
> IPv6
>
> This patch is used to enable HTTPS feature. HttpDxe driver
> will consume TlsDxe driver. It can both support http and https
> feature, that’s depended on the information of URL, the HTTP
> instance can be able to determine whether to use http or https.
>
> Cc: Ye Ting <ting.ye@intel.com>
> Cc: Fu Siyuan <siyuan.fu@intel.com>
> Cc: Zhang Lubo <lubo.zhang@intel.com>
> Cc: Long Qin <qin.long@intel.com>
> Cc: Thomas Palmer <thomas.palmer@hpe.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com>
> ---
> NetworkPkg/HttpDxe/HttpDriver.h | 10 +-
> NetworkPkg/HttpDxe/HttpDxe.inf | 12 +-
> NetworkPkg/HttpDxe/HttpImpl.c | 252 +++++-
> NetworkPkg/HttpDxe/HttpProto.c | 464 +++++++---
> NetworkPkg/HttpDxe/HttpProto.h | 65 +-
> NetworkPkg/HttpDxe/HttpsSupport.c | 1692
> +++++++++++++++++++++++++++++++++++++
> NetworkPkg/HttpDxe/HttpsSupport.h | 260 ++++++
> 7 files changed, 2601 insertions(+), 154 deletions(-)
> create mode 100644 NetworkPkg/HttpDxe/HttpsSupport.c
> create mode 100644 NetworkPkg/HttpDxe/HttpsSupport.h
>
> diff --git a/NetworkPkg/HttpDxe/HttpDriver.h
> b/NetworkPkg/HttpDxe/HttpDriver.h
> index fa2372c..93a412a 100644
> --- a/NetworkPkg/HttpDxe/HttpDriver.h
> +++ b/NetworkPkg/HttpDxe/HttpDriver.h
> @@ -22,10 +22,11 @@
>
> //
> // Libraries
> //
> #include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> #include <Library/MemoryAllocationLib.h>
> #include <Library/BaseLib.h>
> #include <Library/UefiLib.h>
> #include <Library/DebugLib.h>
> #include <Library/NetLib.h>
> @@ -48,17 +49,23 @@
> #include <Protocol/Tcp6.h>
> #include <Protocol/Dns4.h>
> #include <Protocol/Dns6.h>
> #include <Protocol/Ip4Config2.h>
> #include <Protocol/Ip6Config.h>
> +#include <Protocol/Tls.h>
> +#include <Protocol/TlsConfig.h>
>
> -
> +#include <Guid/ImageAuthentication.h>
> //
> // Produced Protocols
> //
> #include <Protocol/Http.h>
>
> +#include <Guid/TlsAuthentication.h>
> +
> +#include <IndustryStandard/Tls1.h>
> +
> //
> // Driver Version
> //
> #define HTTP_DRIVER_VERSION 0xa
>
> @@ -77,10 +84,11 @@ extern EFI_HTTP_UTILITIES_PROTOCOL
> *mHttpUtilities;
> // Include files with function prototypes
> //
> #include "ComponentName.h"
> #include "HttpImpl.h"
> #include "HttpProto.h"
> +#include "HttpsSupport.h"
> #include "HttpDns.h"
>
> typedef struct {
> EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
> UINTN NumberOfChildren;
> diff --git a/NetworkPkg/HttpDxe/HttpDxe.inf
> b/NetworkPkg/HttpDxe/HttpDxe.inf
> index bf2cbee..1118181 100644
> --- a/NetworkPkg/HttpDxe/HttpDxe.inf
> +++ b/NetworkPkg/HttpDxe/HttpDxe.inf
> @@ -1,9 +1,9 @@
> ## @file
> # Implementation of EFI HTTP protocol interfaces.
> #
> -# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
> +# Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
> #
> # This program and the accompanying materials
> # are licensed and made available under the terms and conditions of the
> BSD License
> # which accompanies this distribution. The full text of the license may be
> found at
> # http://opensource.org/licenses/bsd-license.php.
> @@ -24,10 +24,11 @@
> MODULE_UNI_FILE = HttpDxe.uni
>
> [Packages]
> MdePkg/MdePkg.dec
> MdeModulePkg/MdeModulePkg.dec
> + NetworkPkg/NetworkPkg.dec
>
> [Sources]
> ComponentName.h
> ComponentName.c
> HttpDns.h
> @@ -36,14 +37,17 @@
> HttpDriver.c
> HttpImpl.h
> HttpImpl.c
> HttpProto.h
> HttpProto.c
> + HttpsSupport.h
> + HttpsSupport.c
>
> [LibraryClasses]
> UefiDriverEntryPoint
> UefiBootServicesTableLib
> + UefiRuntimeServicesTableLib
> MemoryAllocationLib
> BaseLib
> UefiLib
> DebugLib
> NetLib
> @@ -62,8 +66,14 @@
> gEfiDns4ProtocolGuid ## SOMETIMES_CONSUMES
> gEfiDns6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES
> gEfiDns6ProtocolGuid ## SOMETIMES_CONSUMES
> gEfiIp4Config2ProtocolGuid ## SOMETIMES_CONSUMES
> gEfiIp6ConfigProtocolGuid ## SOMETIMES_CONSUMES
> + gEfiTlsServiceBindingProtocolGuid ## SOMETIMES_CONSUMES
> + gEfiTlsProtocolGuid ## SOMETIMES_CONSUMES
> + gEfiTlsConfigurationProtocolGuid ## SOMETIMES_CONSUMES
> +
> +[Guids]
> + gEfiTlsCaCertificateGuid ## CONSUMES ## GUID
>
> [UserExtensions.TianoCore."ExtraFiles"]
> HttpDxeExtra.uni
> \ No newline at end of file
> diff --git a/NetworkPkg/HttpDxe/HttpImpl.c
> b/NetworkPkg/HttpDxe/HttpImpl.c
> index 6fcb0b7..77aa64a 100644
> --- a/NetworkPkg/HttpDxe/HttpImpl.c
> +++ b/NetworkPkg/HttpDxe/HttpImpl.c
> @@ -239,10 +239,11 @@ EfiHttpRequest (
> UINTN HostNameSize;
> UINT16 RemotePort;
> HTTP_PROTOCOL *HttpInstance;
> BOOLEAN Configure;
> BOOLEAN ReConfigure;
> + BOOLEAN TlsConfigure;
> CHAR8 *RequestMsg;
> CHAR8 *Url;
> UINTN UrlLen;
> CHAR16 *HostNameStr;
> HTTP_TOKEN_WRAP *Wrap;
> @@ -258,10 +259,11 @@ EfiHttpRequest (
> HostName = NULL;
> RequestMsg = NULL;
> HostNameStr = NULL;
> Wrap = NULL;
> FileUrl = NULL;
> + TlsConfigure = FALSE;
>
> if ((This == NULL) || (Token == NULL)) {
> return EFI_INVALID_PARAMETER;
> }
>
> @@ -343,10 +345,36 @@ EfiHttpRequest (
> HttpInstance->Url = Url;
> }
>
>
> UnicodeStrToAsciiStrS (Request->Url, Url, UrlLen);
> +
> + //
> + // From the information in Url, the HTTP instance will
> + // be able to determine whether to use http or https.
> + //
> + HttpInstance->UseHttps = IsHttpsUrl (Url);
> +
> + //
> + // Check whether we need to create Tls child and open the TLS protocol.
> + //
> + if (HttpInstance->UseHttps && HttpInstance->TlsChildHandle == NULL) {
> + //
> + // Use TlsSb to create Tls child and open the TLS protocol.
> + //
> + HttpInstance->TlsChildHandle = TlsCreateChild (
> + HttpInstance->Service->ImageHandle,
> + &(HttpInstance->Tls),
> + &(HttpInstance->TlsConfiguration)
> + );
> + if (HttpInstance->TlsChildHandle == NULL) {
> + return EFI_DEVICE_ERROR;
> + }
> +
> + TlsConfigure = TRUE;
> + }
> +
> UrlParser = NULL;
> Status = HttpParseUrl (Url, (UINT32) AsciiStrLen (Url), FALSE, &UrlParser);
> if (EFI_ERROR (Status)) {
> goto Error1;
> }
> @@ -357,11 +385,15 @@ EfiHttpRequest (
> goto Error1;
> }
>
> Status = HttpUrlGetPort (Url, UrlParser, &RemotePort);
> if (EFI_ERROR (Status)) {
> - RemotePort = HTTP_DEFAULT_PORT;
> + if (HttpInstance->UseHttps) {
> + RemotePort = HTTPS_DEFAULT_PORT;
> + } else {
> + RemotePort = HTTP_DEFAULT_PORT;
> + }
> }
> //
> // If Configure is TRUE, it indicates the first time to call Request();
> // If ReConfigure is TRUE, it indicates the request URL is not same
> // with the previous call to Request();
> @@ -374,13 +406,17 @@ EfiHttpRequest (
> // Request() is called the first time.
> //
> ReConfigure = FALSE;
> } else {
> if ((HttpInstance->RemotePort == RemotePort) &&
> - (AsciiStrCmp (HttpInstance->RemoteHost, HostName) == 0)) {
> + (AsciiStrCmp (HttpInstance->RemoteHost, HostName) == 0) &&
> + (!HttpInstance->UseHttps || (HttpInstance->UseHttps &&
> + !TlsConfigure &&
> + HttpInstance->TlsSessionState ==
> EfiTlsSessionDataTransferring))) {
> //
> // Host Name and port number of the request URL are the same with
> previous call to Request().
> + // If Https protocol used, the corresponding SessionState is
> EfiTlsSessionDataTransferring.
> // Check whether previous TCP packet sent out.
> //
>
> if (EFI_ERROR (NetMapIterate (&HttpInstance->TxTokens,
> HttpTcpNotReady, NULL))) {
> //
> @@ -480,10 +516,20 @@ EfiHttpRequest (
> if (!HttpInstance->LocalAddressIsIPv6) {
> ASSERT (HttpInstance->Tcp4 != NULL);
> } else {
> ASSERT (HttpInstance->Tcp6 != NULL);
> }
> +
> + if (HttpInstance->UseHttps && !TlsConfigure) {
> + Status = TlsCloseSession (HttpInstance);
> + if (EFI_ERROR (Status)) {
> + goto Error1;
> + }
> +
> + TlsCloseTxRxEvent (HttpInstance);
> + }
> +
> HttpCloseConnection (HttpInstance);
> EfiHttpCancel (This, NULL);
> }
>
> //
> @@ -498,17 +544,22 @@ EfiHttpRequest (
> Wrap->HttpToken = Token;
> Wrap->HttpInstance = HttpInstance;
> if (Request != NULL) {
> Wrap->TcpWrap.Method = Request->Method;
> }
> -
> - Status = HttpInitTcp (HttpInstance, Wrap, Configure);
> +
> + Status = HttpInitSession (
> + HttpInstance,
> + Wrap,
> + Configure || ReConfigure,
> + TlsConfigure
> + );
> if (EFI_ERROR (Status)) {
> goto Error2;
> - }
> + }
>
> - if (!Configure) {
> + if (!Configure && !ReConfigure && !TlsConfigure) {
> //
> // For the new HTTP token, create TX TCP token events.
> //
> Status = HttpCreateTcpTxEvent (Wrap);
> if (EFI_ERROR (Status)) {
> @@ -591,13 +642,18 @@ Error4:
> if (RequestMsg != NULL) {
> FreePool (RequestMsg);
> }
>
> Error3:
> - HttpCloseConnection (HttpInstance);
> + if (HttpInstance->UseHttps) {
> + TlsCloseSession (HttpInstance);
> + TlsCloseTxRxEvent (HttpInstance);
> + }
>
> Error2:
> + HttpCloseConnection (HttpInstance);
> +
> HttpCloseTcpConnCloseEvent (HttpInstance);
> if (NULL != Wrap->TcpWrap.Tx4Token.CompletionToken.Event) {
> gBS->CloseEvent (Wrap->TcpWrap.Tx4Token.CompletionToken.Event);
> Wrap->TcpWrap.Tx4Token.CompletionToken.Event = NULL;
> }
> @@ -729,26 +785,34 @@ HttpCancel (
> } else {
> return Status;
> }
> }
>
> - //
> - // Then check the tokens queued by EfiHttpResponse().
> - //
> - Status = NetMapIterate (&HttpInstance->RxTokens, HttpCancelTokens,
> Token);
> - if (EFI_ERROR (Status)) {
> - if (Token != NULL) {
> - if (Status == EFI_ABORTED) {
> - return EFI_SUCCESS;
> + if (!HttpInstance->UseHttps) {
> + //
> + // Then check the tokens queued by EfiHttpResponse(), except for Https.
> + //
> + Status = NetMapIterate (&HttpInstance->RxTokens, HttpCancelTokens,
> Token);
> + if (EFI_ERROR (Status)) {
> + if (Token != NULL) {
> + if (Status == EFI_ABORTED) {
> + return EFI_SUCCESS;
> + } else {
> + return EFI_NOT_FOUND;
> + }
> } else {
> - return EFI_NOT_FOUND;
> + return Status;
> }
> + }
> + } else {
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + HttpInstance->Tcp4->Cancel (HttpInstance->Tcp4, &HttpInstance-
> >Tcp4TlsRxToken.CompletionToken);
> } else {
> - return Status;
> + HttpInstance->Tcp6->Cancel (HttpInstance->Tcp6, &HttpInstance-
> >Tcp6TlsRxToken.CompletionToken);
> }
> }
> -
> +
> return EFI_SUCCESS;
> }
>
>
> /**
> @@ -880,10 +944,11 @@ HttpResponseWorker (
> HTTP_PROTOCOL *HttpInstance;
> EFI_HTTP_TOKEN *Token;
> NET_MAP_ITEM *Item;
> HTTP_TOKEN_WRAP *ValueInItem;
> UINTN HdrLen;
> + NET_FRAGMENT Fragment;
>
> if (Wrap == NULL || Wrap->HttpInstance == NULL) {
> return EFI_INVALID_PARAMETER;
> }
>
> @@ -897,21 +962,15 @@ HttpResponseWorker (
> HttpHeaders = NULL;
> SizeofHeaders = 0;
> BufferSize = 0;
> EndofHeader = NULL;
> ValueInItem = NULL;
> + Fragment.Len = 0;
> + Fragment.Bulk = NULL;
>
> if (HttpMsg->Data.Response != NULL) {
> //
> - // Need receive the HTTP headers, prepare buffer.
> - //
> - Status = HttpCreateTcpRxEventForHeader (HttpInstance);
> - if (EFI_ERROR (Status)) {
> - goto Error;
> - }
> -
> - //
> // Check whether we have cached header from previous call.
> //
> if ((HttpInstance->CacheBody != NULL) && (HttpInstance->NextMsg !=
> NULL)) {
> //
> // The data is stored at [NextMsg, CacheBody + CacheLen].
> @@ -1198,13 +1257,120 @@ HttpResponseWorker (
> ASSERT (HttpInstance->MsgParser != NULL);
>
> //
> // We still need receive more data when there is no cache data and
> MsgParser is not NULL;
> //
> - Status = HttpTcpReceiveBody (Wrap, HttpMsg);
> - if (EFI_ERROR (Status)) {
> - goto Error2;
> + if (!HttpInstance->UseHttps) {
> + Status = HttpTcpReceiveBody (Wrap, HttpMsg);
> +
> + if (EFI_ERROR (Status)) {
> + goto Error2;
> + }
> +
> + } else {
> + if (HttpInstance->TimeoutEvent == NULL) {
> + //
> + // Create TimeoutEvent for response
> + //
> + Status = gBS->CreateEvent (
> + EVT_TIMER,
> + TPL_CALLBACK,
> + NULL,
> + NULL,
> + &HttpInstance->TimeoutEvent
> + );
> + if (EFI_ERROR (Status)) {
> + goto Error2;
> + }
> + }
> +
> + //
> + // Start the timer, and wait Timeout seconds to receive the body packet.
> + //
> + Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative,
> HTTP_RESPONSE_TIMEOUT * TICKS_PER_SECOND);
> + if (EFI_ERROR (Status)) {
> + goto Error2;
> + }
> +
> + Status = HttpsReceive (HttpInstance, &Fragment, HttpInstance-
> >TimeoutEvent);
> +
> + gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);
> +
> + if (EFI_ERROR (Status)) {
> + goto Error2;
> + }
> +
> + //
> + // Check whether we receive a complete HTTP message.
> + //
> + Status = HttpParseMessageBody (
> + HttpInstance->MsgParser,
> + (UINTN) Fragment.Len,
> + (CHAR8 *) Fragment.Bulk
> + );
> + if (EFI_ERROR (Status)) {
> + goto Error2;
> + }
> +
> + if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
> + //
> + // Free the MsgParse since we already have a full HTTP message.
> + //
> + HttpFreeMsgParser (HttpInstance->MsgParser);
> + HttpInstance->MsgParser = NULL;
> + }
> +
> + //
> + // We receive part of header of next HTTP msg.
> + //
> + if (HttpInstance->NextMsg != NULL) {
> + HttpMsg->BodyLength = MIN ((UINTN) (HttpInstance->NextMsg -
> (CHAR8 *) Fragment.Bulk), HttpMsg->BodyLength);
> + CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);
> +
> + HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
> + if (HttpInstance->CacheLen != 0) {
> + if (HttpInstance->CacheBody != NULL) {
> + FreePool (HttpInstance->CacheBody);
> + }
> +
> + HttpInstance->CacheBody = AllocateZeroPool (HttpInstance-
> >CacheLen);
> + if (HttpInstance->CacheBody == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto Error2;
> + }
> +
> + CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg-
> >BodyLength, HttpInstance->CacheLen);
> + HttpInstance->CacheOffset = 0;
> +
> + HttpInstance->NextMsg = HttpInstance->CacheBody + (UINTN)
> (HttpInstance->NextMsg - (CHAR8 *) (Fragment.Bulk + HttpMsg-
> >BodyLength));
> + }
> + } else {
> + HttpMsg->BodyLength = MIN (Fragment.Len, (UINT32) HttpMsg-
> >BodyLength);
> + CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);
> + HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
> + if (HttpInstance->CacheLen != 0) {
> + if (HttpInstance->CacheBody != NULL) {
> + FreePool (HttpInstance->CacheBody);
> + }
> +
> + HttpInstance->CacheBody = AllocateZeroPool (HttpInstance-
> >CacheLen);
> + if (HttpInstance->CacheBody == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto Error2;
> + }
> +
> + CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg-
> >BodyLength, HttpInstance->CacheLen);
> + HttpInstance->CacheOffset = 0;
> + }
> + }
> +
> + if (Fragment.Bulk != NULL) {
> + FreePool (Fragment.Bulk);
> + Fragment.Bulk = NULL;
> + }
> +
> + goto Exit;
> }
>
> return Status;
>
> Exit:
> @@ -1232,19 +1398,30 @@ Error2:
> Error:
> Item = NetMapFindKey (&Wrap->HttpInstance->RxTokens, Wrap-
> >HttpToken);
> if (Item != NULL) {
> NetMapRemoveItem (&Wrap->HttpInstance->RxTokens, Item, NULL);
> }
> -
> - HttpTcpTokenCleanup (Wrap);
> +
> + if (!HttpInstance->UseHttps) {
> + HttpTcpTokenCleanup (Wrap);
> + } else {
> + FreePool (Wrap);
> + }
>
> if (HttpHeaders != NULL) {
> FreePool (HttpHeaders);
> + HttpHeaders = NULL;
> + }
> +
> + if (Fragment.Bulk != NULL) {
> + FreePool (Fragment.Bulk);
> + Fragment.Bulk = NULL;
> }
>
> if (HttpMsg->Headers != NULL) {
> FreePool (HttpMsg->Headers);
> + HttpMsg->Headers = NULL;
> }
>
> if (HttpInstance->CacheBody != NULL) {
> FreePool (HttpInstance->CacheBody);
> HttpInstance->CacheBody = NULL;
> @@ -1351,13 +1528,20 @@ EfiHttpResponse (
> }
>
> Wrap->HttpInstance = HttpInstance;
> Wrap->HttpToken = Token;
>
> - Status = HttpCreateTcpRxEvent (Wrap);
> - if (EFI_ERROR (Status)) {
> - goto Error;
> + //
> + // Notes: For Https, receive token wrapped in HTTP_TOKEN_WRAP is not
> used to
> + // receive the https response. A special TlsRxToken is used for receiving
> TLS
> + // related messages. It should be a blocking response.
> + //
> + if (!HttpInstance->UseHttps) {
> + Status = HttpCreateTcpRxEvent (Wrap);
> + if (EFI_ERROR (Status)) {
> + goto Error;
> + }
> }
>
> Status = NetMapInsertTail (&HttpInstance->RxTokens, Token, Wrap);
> if (EFI_ERROR (Status)) {
> goto Error;
> diff --git a/NetworkPkg/HttpDxe/HttpProto.c
> b/NetworkPkg/HttpDxe/HttpProto.c
> index 6373f07..77a3ee3 100644
> --- a/NetworkPkg/HttpDxe/HttpProto.c
> +++ b/NetworkPkg/HttpDxe/HttpProto.c
> @@ -926,10 +926,26 @@ HttpCleanProtocol (
> HttpInstance->Service->ImageHandle,
> HttpInstance->Handle
> );
> }
>
> + if (HttpInstance->TlsConfigData.CACert != NULL) {
> + FreePool (HttpInstance->TlsConfigData.CACert);
> + HttpInstance->TlsConfigData.CACert = NULL;
> + }
> +
> + if (HttpInstance->TlsConfigData.ClientCert != NULL) {
> + FreePool (HttpInstance->TlsConfigData.ClientCert);
> + HttpInstance->TlsConfigData.ClientCert = NULL;
> + }
> +
> + if (HttpInstance->TlsConfigData.ClientPrivateKey != NULL) {
> + FreePool (HttpInstance->TlsConfigData.ClientPrivateKey);
> + HttpInstance->TlsConfigData.ClientPrivateKey = NULL;
> + }
> +
> + TlsCloseTxRxEvent (HttpInstance);
> }
>
> /**
> Establish TCP connection with HTTP server.
>
> @@ -1183,11 +1199,12 @@ HttpConfigureTcp6 (
> return EFI_SUCCESS;
>
> }
>
> /**
> - Check existing TCP connection, if in error state, recover TCP4 connection.
> + Check existing TCP connection, if in error state, recover TCP4 connection.
> Then,
> + connect one TLS session if required.
>
> @param[in] HttpInstance The HTTP instance private data.
>
> @retval EFI_SUCCESS The TCP connection is established.
> @retval EFI_NOT_READY TCP4 protocol child is not created or
> configured.
> @@ -1224,15 +1241,62 @@ HttpConnectTcp4 (
> return EFI_SUCCESS;
> } else if (Tcp4State > Tcp4StateEstablished ) {
> HttpCloseConnection(HttpInstance);
> }
>
> - return HttpCreateConnection (HttpInstance);
> + Status = HttpCreateConnection (HttpInstance);
> + if (EFI_ERROR(Status)){
> + DEBUG ((EFI_D_ERROR, "Tcp4 Connection fail - %x\n", Status));
> + return Status;
> + }
> +
> + //
> + // Tls session connection.
> + //
> + if (HttpInstance->UseHttps) {
> + if (HttpInstance->TimeoutEvent == NULL) {
> + //
> + // Create TimeoutEvent for TLS connection.
> + //
> + Status = gBS->CreateEvent (
> + EVT_TIMER,
> + TPL_CALLBACK,
> + NULL,
> + NULL,
> + &HttpInstance->TimeoutEvent
> + );
> + if (EFI_ERROR (Status)) {
> + TlsCloseTxRxEvent (HttpInstance);
> + return Status;
> + }
> + }
> +
> + //
> + // Start the timer, and wait Timeout seconds for connection.
> + //
> + Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative,
> HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);
> + if (EFI_ERROR (Status)) {
> + TlsCloseTxRxEvent (HttpInstance);
> + return Status;
> + }
> +
> + Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);
> +
> + gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);
> +
> + if (EFI_ERROR (Status)) {
> + TlsCloseTxRxEvent (HttpInstance);
> + return Status;
> + }
> + }
> +
> + return Status;
> }
>
> /**
> - Check existing TCP connection, if in error state, recover TCP6 connection.
> + Check existing TCP connection, if in error state, recover TCP6 connection.
> Then,
> + connect one TLS session if required.
>
> @param[in] HttpInstance The HTTP instance private data.
>
> @retval EFI_SUCCESS The TCP connection is established.
> @retval EFI_NOT_READY TCP6 protocol child is not created or
> configured.
> @@ -1269,34 +1333,92 @@ HttpConnectTcp6 (
> return EFI_SUCCESS;
> } else if (Tcp6State > Tcp6StateEstablished ) {
> HttpCloseConnection(HttpInstance);
> }
>
> - return HttpCreateConnection (HttpInstance);
> + Status = HttpCreateConnection (HttpInstance);
> + if (EFI_ERROR(Status)){
> + DEBUG ((EFI_D_ERROR, "Tcp6 Connection fail - %x\n", Status));
> + return Status;
> + }
> +
> + //
> + // Tls session connection.
> + //
> + if (HttpInstance->UseHttps) {
> + if (HttpInstance->TimeoutEvent == NULL) {
> + //
> + // Create TimeoutEvent for TLS connection.
> + //
> + Status = gBS->CreateEvent (
> + EVT_TIMER,
> + TPL_CALLBACK,
> + NULL,
> + NULL,
> + &HttpInstance->TimeoutEvent
> + );
> + if (EFI_ERROR (Status)) {
> + TlsCloseTxRxEvent (HttpInstance);
> + return Status;
> + }
> + }
> +
> + //
> + // Start the timer, and wait Timeout seconds for connection.
> + //
> + Status = gBS->SetTimer (HttpInstance->TimeoutEvent, TimerRelative,
> HTTP_CONNECTION_TIMEOUT * TICKS_PER_SECOND);
> + if (EFI_ERROR (Status)) {
> + TlsCloseTxRxEvent (HttpInstance);
> + return Status;
> + }
> +
> + Status = TlsConnectSession (HttpInstance, HttpInstance->TimeoutEvent);
> +
> + gBS->SetTimer (HttpInstance->TimeoutEvent, TimerCancel, 0);
> +
> + if (EFI_ERROR (Status)) {
> + TlsCloseTxRxEvent (HttpInstance);
> + return Status;
> + }
> + }
> +
> + return Status;
> }
>
> /**
> - Initialize TCP related data.
> + Initialize Http session.
>
> @param[in] HttpInstance The HTTP instance private data.
> @param[in] Wrap The HTTP token's wrap data.
> - @param[in] Configure The Flag indicates whether the first time to
> initialize Tcp.
> + @param[in] Configure The Flag indicates whether need to initialize
> session.
> + @param[in] TlsConfigure The Flag indicates whether it's the new Tls
> session.
>
> - @retval EFI_SUCCESS The initialization of TCP instance is done.
> + @retval EFI_SUCCESS The initialization of session is done.
> @retval Others Other error as indicated.
>
> **/
> EFI_STATUS
> -HttpInitTcp (
> +HttpInitSession (
> IN HTTP_PROTOCOL *HttpInstance,
> IN HTTP_TOKEN_WRAP *Wrap,
> - IN BOOLEAN Configure
> + IN BOOLEAN Configure,
> + IN BOOLEAN TlsConfigure
> )
> {
> EFI_STATUS Status;
> ASSERT (HttpInstance != NULL);
>
> + //
> + // Configure Tls session.
> + //
> + if (TlsConfigure) {
> + Status = TlsConfigureSession (HttpInstance);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
> +
> if (!HttpInstance->LocalAddressIsIPv6) {
> //
> // Configure TCP instance.
> //
> if (Configure) {
> @@ -1336,11 +1458,11 @@ HttpInitTcp (
> return EFI_SUCCESS;
>
> }
>
> /**
> - Send the HTTP message through TCP4 or TCP6.
> + Send the HTTP or HTTPS message through TCP4 or TCP6.
>
> @param[in] HttpInstance The HTTP instance private data.
> @param[in] Wrap The HTTP token's wrap data.
> @param[in] TxString Buffer containing the HTTP message string.
> @param[in] TxStringLen Length of the HTTP message string in bytes.
> @@ -1360,18 +1482,68 @@ HttpTransmitTcp (
> EFI_STATUS Status;
> EFI_TCP4_IO_TOKEN *Tx4Token;
> EFI_TCP4_PROTOCOL *Tcp4;
> EFI_TCP6_IO_TOKEN *Tx6Token;
> EFI_TCP6_PROTOCOL *Tcp6;
> + UINT8 *Buffer;
> + UINTN BufferSize;
> + NET_FRAGMENT TempFragment;
> +
> + Status = EFI_SUCCESS;
> + Buffer = NULL;
> +
> + //
> + // Need to encrypt data.
> + //
> + if (HttpInstance->UseHttps) {
> + //
> + // Build BufferOut data
> + //
> + BufferSize = sizeof (TLS_RECORD_HEADER) + TxStringLen;
> + Buffer = AllocateZeroPool (BufferSize);
> + if (Buffer == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> + ((TLS_RECORD_HEADER *) Buffer)->ContentType =
> TLS_CONTENT_TYPE_APPLICATION_DATA;
> + ((TLS_RECORD_HEADER *) Buffer)->Version.Major = HttpInstance-
> >TlsConfigData.Version.Major;
> + ((TLS_RECORD_HEADER *) Buffer)->Version.Minor = HttpInstance-
> >TlsConfigData.Version.Minor;
> + ((TLS_RECORD_HEADER *) Buffer)->Length = (UINT16) (TxStringLen);
> + CopyMem (Buffer + sizeof (TLS_RECORD_HEADER), TxString, TxStringLen);
> +
> + //
> + // Encrypt Packet.
> + //
> + Status = TlsProcessMessage (
> + HttpInstance,
> + Buffer,
> + BufferSize,
> + EfiTlsEncrypt,
> + &TempFragment
> + );
> +
> + FreePool (Buffer);
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> + }
>
> - if (!HttpInstance->LocalAddressIsIPv6) {
> + if (!HttpInstance->LocalAddressIsIPv6) {
> Tcp4 = HttpInstance->Tcp4;
> Tx4Token = &Wrap->TcpWrap.Tx4Token;
> +
> + if (HttpInstance->UseHttps) {
> + Tx4Token->Packet.TxData->DataLength = TempFragment.Len;
> + Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength =
> TempFragment.Len;
> + Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID
> *) TempFragment.Bulk;
> + } else {
> + Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;
> + Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength =
> (UINT32) TxStringLen;
> + Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID
> *) TxString;
> + }
>
> - Tx4Token->Packet.TxData->DataLength = (UINT32) TxStringLen;
> - Tx4Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32)
> TxStringLen;
> - Tx4Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *)
> TxString;
> Tx4Token->CompletionToken.Status = EFI_NOT_READY;
>
> Wrap->TcpWrap.IsTxDone = FALSE;
> Status = Tcp4->Transmit (Tcp4, Tx4Token);
> if (EFI_ERROR (Status)) {
> @@ -1380,25 +1552,31 @@ HttpTransmitTcp (
> }
>
> } else {
> Tcp6 = HttpInstance->Tcp6;
> Tx6Token = &Wrap->TcpWrap.Tx6Token;
> -
> - Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;
> - Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength = (UINT32)
> TxStringLen;
> - Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID *)
> TxString;
> +
> + if (HttpInstance->UseHttps) {
> + Tx6Token->Packet.TxData->DataLength = TempFragment.Len;
> + Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength =
> TempFragment.Len;
> + Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID
> *) TempFragment.Bulk;
> + } else {
> + Tx6Token->Packet.TxData->DataLength = (UINT32) TxStringLen;
> + Tx6Token->Packet.TxData->FragmentTable[0].FragmentLength =
> (UINT32) TxStringLen;
> + Tx6Token->Packet.TxData->FragmentTable[0].FragmentBuffer = (VOID
> *) TxString;
> + }
> +
> Tx6Token->CompletionToken.Status = EFI_NOT_READY;
>
> Wrap->TcpWrap.IsTxDone = FALSE;
> Status = Tcp6->Transmit (Tcp6, Tx6Token);
> if (EFI_ERROR (Status)) {
> DEBUG ((EFI_D_ERROR, "Transmit failed: %r\n", Status));
> return Status;
> }
> }
>
> -
> return Status;
> }
>
> /**
> Check whether the user's token or event has already
> @@ -1464,11 +1642,11 @@ HttpTcpNotReady (
>
> return EFI_SUCCESS;
> }
>
> /**
> - Transmit the HTTP mssage by processing the associated HTTP token.
> + Transmit the HTTP or HTTPS mssage by processing the associated HTTP
> token.
>
> @param[in] Map The container of Tx4Token or Tx6Token.
> @param[in] Item Current item to check against.
> @param[in] Context The Token to check againist.
>
> @@ -1588,167 +1766,235 @@ HttpTcpReceiveHeader (
> EFI_TCP6_IO_TOKEN *Rx6Token;
> EFI_TCP6_PROTOCOL *Tcp6;
> CHAR8 **EndofHeader;
> CHAR8 **HttpHeaders;
> CHAR8 *Buffer;
> + NET_FRAGMENT Fragment;
>
> ASSERT (HttpInstance != NULL);
>
> EndofHeader = HttpInstance->EndofHeader;
> HttpHeaders = HttpInstance->HttpHeaders;
> Tcp4 = HttpInstance->Tcp4;
> Tcp6 = HttpInstance->Tcp6;
> Buffer = NULL;
> Rx4Token = NULL;
> Rx6Token = NULL;
> + Fragment.Len = 0;
> + Fragment.Bulk = NULL;
>
> if (HttpInstance->LocalAddressIsIPv6) {
> ASSERT (Tcp6 != NULL);
> } else {
> ASSERT (Tcp4 != NULL);
> }
>
> - if (!HttpInstance->LocalAddressIsIPv6) {
> - Rx4Token = &HttpInstance->Rx4Token;
> - Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer =
> AllocateZeroPool (DEF_BUF_LEN);
> - if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer ==
> NULL) {
> - Status = EFI_OUT_OF_RESOURCES;
> + if (!HttpInstance->UseHttps) {
> + Status = HttpCreateTcpRxEventForHeader (HttpInstance);
> + if (EFI_ERROR (Status)) {
> return Status;
> }
> + }
> +
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + if (!HttpInstance->UseHttps) {
> + Rx4Token = &HttpInstance->Rx4Token;
> + Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer =
> AllocateZeroPool (DEF_BUF_LEN);
> + if (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer ==
> NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> + }
>
> //
> // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not
> NULL.
> //
> - while (*EndofHeader == NULL) {
> - HttpInstance->IsRxDone = FALSE;
> - Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;
> - Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength =
> DEF_BUF_LEN;
> - Status = Tcp4->Receive (Tcp4, Rx4Token);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
> - return Status;
> - }
> -
> - while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR
> (gBS->CheckEvent (Timeout)))) {
> - Tcp4->Poll (Tcp4);
> + while (*EndofHeader == NULL) {
> + if (!HttpInstance->UseHttps) {
> + HttpInstance->IsRxDone = FALSE;
> + Rx4Token->Packet.RxData->DataLength = DEF_BUF_LEN;
> + Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength =
> DEF_BUF_LEN;
> + Status = Tcp4->Receive (Tcp4, Rx4Token);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
> + return Status;
> + }
> +
> + while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR
> (gBS->CheckEvent (Timeout)))) {
> + Tcp4->Poll (Tcp4);
> + }
> +
> + if (!HttpInstance->IsRxDone) {
> + //
> + // Cancle the Token before close its Event.
> + //
> + Tcp4->Cancel (HttpInstance->Tcp4, &Rx4Token->CompletionToken);
> + gBS->CloseEvent (Rx4Token->CompletionToken.Event);
> + Rx4Token->CompletionToken.Status = EFI_TIMEOUT;
> + }
> +
> + Status = Rx4Token->CompletionToken.Status;
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Fragment.Len = Rx4Token->Packet.RxData-
> >FragmentTable[0].FragmentLength;
> + Fragment.Bulk = (UINT8 *) Rx4Token->Packet.RxData-
> >FragmentTable[0].FragmentBuffer;
> + } else {
> + if (Fragment.Bulk != NULL) {
> + FreePool (Fragment.Bulk);
> + Fragment.Bulk = NULL;
> + }
> +
> + Status = HttpsReceive (HttpInstance, &Fragment, Timeout);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "Tcp4 receive failed: %r\n", Status));
> + return Status;
> + }
> }
>
> - if (!HttpInstance->IsRxDone) {
> - //
> - // Cancle the Token before close its Event.
> - //
> - Tcp4->Cancel (HttpInstance->Tcp4, &Rx4Token->CompletionToken);
> - gBS->CloseEvent (Rx4Token->CompletionToken.Event);
> - Rx4Token->CompletionToken.Status = EFI_TIMEOUT;
> - }
> -
> - Status = Rx4Token->CompletionToken.Status;
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> //
> // Append the response string.
> //
> - *BufferSize = (*SizeofHeaders) + Rx4Token->Packet.RxData-
> >FragmentTable[0].FragmentLength;
> + *BufferSize = *SizeofHeaders + Fragment.Len;
> Buffer = AllocateZeroPool (*BufferSize);
> if (Buffer == NULL) {
> Status = EFI_OUT_OF_RESOURCES;
> return Status;
> }
> -
> +
> if (*HttpHeaders != NULL) {
> - CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));
> + CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);
> FreePool (*HttpHeaders);
> }
> -
> +
> CopyMem (
> - Buffer + (*SizeofHeaders),
> - Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer,
> - Rx4Token->Packet.RxData->FragmentTable[0].FragmentLength
> + Buffer + *SizeofHeaders,
> + Fragment.Bulk,
> + Fragment.Len
> );
> - *HttpHeaders = Buffer;
> - *SizeofHeaders = *BufferSize;
> -
> + *HttpHeaders = Buffer;
> + *SizeofHeaders = *BufferSize;
> +
> //
> // Check whether we received end of HTTP headers.
> //
> *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);
> - }
> - FreePool (Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
> - Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
> + };
>
> + //
> + // Free the buffer.
> + //
> + if (Rx4Token != NULL && Rx4Token->Packet.RxData != NULL &&
> Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
> + FreePool (Rx4Token->Packet.RxData-
> >FragmentTable[0].FragmentBuffer);
> + Rx4Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
> + Fragment.Bulk = NULL;
> + }
> +
> + if (Fragment.Bulk != NULL) {
> + FreePool (Fragment.Bulk);
> + Fragment.Bulk = NULL;
> + }
> } else {
> - Rx6Token = &HttpInstance->Rx6Token;
> - Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer =
> AllocateZeroPool (DEF_BUF_LEN);
> - if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer ==
> NULL) {
> - Status = EFI_OUT_OF_RESOURCES;
> - return Status;
> + if (!HttpInstance->UseHttps) {
> + Rx6Token = &HttpInstance->Rx6Token;
> + Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer =
> AllocateZeroPool (DEF_BUF_LEN);
> + if (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer ==
> NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> }
>
> //
> // Receive the HTTP headers only when EFI_HTTP_RESPONSE_DATA is not
> NULL.
> //
> - while (*EndofHeader == NULL) {
> - HttpInstance->IsRxDone = FALSE;
> - Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;
> - Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength =
> DEF_BUF_LEN;
> - Status = Tcp6->Receive (Tcp6, Rx6Token);
> - if (EFI_ERROR (Status)) {
> - DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));
> - return Status;
> - }
> -
> - while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR
> (gBS->CheckEvent (Timeout)))) {
> - Tcp6->Poll (Tcp6);
> + while (*EndofHeader == NULL) {
> + if (!HttpInstance->UseHttps) {
> + HttpInstance->IsRxDone = FALSE;
> + Rx6Token->Packet.RxData->DataLength = DEF_BUF_LEN;
> + Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength =
> DEF_BUF_LEN;
> + Status = Tcp6->Receive (Tcp6, Rx6Token);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));
> + return Status;
> + }
> +
> + while (!HttpInstance->IsRxDone && ((Timeout == NULL) || EFI_ERROR
> (gBS->CheckEvent (Timeout)))) {
> + Tcp6->Poll (Tcp6);
> + }
> +
> + if (!HttpInstance->IsRxDone) {
> + //
> + // Cancle the Token before close its Event.
> + //
> + Tcp6->Cancel (HttpInstance->Tcp6, &Rx6Token->CompletionToken);
> + gBS->CloseEvent (Rx6Token->CompletionToken.Event);
> + Rx6Token->CompletionToken.Status = EFI_TIMEOUT;
> + }
> +
> + Status = Rx6Token->CompletionToken.Status;
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Fragment.Len = Rx6Token->Packet.RxData-
> >FragmentTable[0].FragmentLength;
> + Fragment.Bulk = (UINT8 *) Rx6Token->Packet.RxData-
> >FragmentTable[0].FragmentBuffer;
> + } else {
> + if (Fragment.Bulk != NULL) {
> + FreePool (Fragment.Bulk);
> + Fragment.Bulk = NULL;
> + }
> +
> + Status = HttpsReceive (HttpInstance, &Fragment, Timeout);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "Tcp6 receive failed: %r\n", Status));
> + return Status;
> + }
> }
>
> - if (!HttpInstance->IsRxDone) {
> - //
> - // Cancle the Token before close its Event.
> - //
> - Tcp6->Cancel (HttpInstance->Tcp6, &Rx6Token->CompletionToken);
> - gBS->CloseEvent (Rx6Token->CompletionToken.Event);
> - Rx6Token->CompletionToken.Status = EFI_TIMEOUT;
> - }
> -
> - Status = Rx6Token->CompletionToken.Status;
> - if (EFI_ERROR (Status)) {
> - return Status;
> - }
> -
> //
> // Append the response string.
> //
> - *BufferSize = (*SizeofHeaders) + Rx6Token->Packet.RxData-
> >FragmentTable[0].FragmentLength;
> + *BufferSize = *SizeofHeaders + Fragment.Len;
> Buffer = AllocateZeroPool (*BufferSize);
> if (Buffer == NULL) {
> Status = EFI_OUT_OF_RESOURCES;
> return Status;
> }
> -
> +
> if (*HttpHeaders != NULL) {
> - CopyMem (Buffer, *HttpHeaders, (*SizeofHeaders));
> + CopyMem (Buffer, *HttpHeaders, *SizeofHeaders);
> FreePool (*HttpHeaders);
> }
> -
> +
> CopyMem (
> - Buffer + (*SizeofHeaders),
> - Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer,
> - Rx6Token->Packet.RxData->FragmentTable[0].FragmentLength
> + Buffer + *SizeofHeaders,
> + Fragment.Bulk,
> + Fragment.Len
> );
> - *HttpHeaders = Buffer;
> - *SizeofHeaders = *BufferSize;
> -
> + *HttpHeaders = Buffer;
> + *SizeofHeaders = *BufferSize;
> +
> //
> // Check whether we received end of HTTP headers.
> //
> - *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);
> -
> + *EndofHeader = AsciiStrStr (*HttpHeaders, HTTP_END_OF_HDR_STR);
> + };
> +
> + //
> + // Free the buffer.
> + //
> + if (Rx6Token != NULL && Rx6Token->Packet.RxData != NULL &&
> Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer != NULL) {
> + FreePool (Rx6Token->Packet.RxData-
> >FragmentTable[0].FragmentBuffer);
> + Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
> + Fragment.Bulk = NULL;
> + }
> +
> + if (Fragment.Bulk != NULL) {
> + FreePool (Fragment.Bulk);
> + Fragment.Bulk = NULL;
> }
> - FreePool (Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer);
> - Rx6Token->Packet.RxData->FragmentTable[0].FragmentBuffer = NULL;
> }
>
> //
> // Skip the CRLF after the HTTP headers.
> //
> diff --git a/NetworkPkg/HttpDxe/HttpProto.h
> b/NetworkPkg/HttpDxe/HttpProto.h
> index e1fd785..e3b3275 100644
> --- a/NetworkPkg/HttpDxe/HttpProto.h
> +++ b/NetworkPkg/HttpDxe/HttpProto.h
> @@ -81,10 +81,24 @@ typedef struct {
> BOOLEAN IsRxDone;
> UINTN BodyLen;
> EFI_HTTP_METHOD Method;
> } HTTP_TCP_TOKEN_WRAP;
>
> +typedef struct {
> + EFI_TLS_VERSION Version;
> + EFI_TLS_CONNECTION_END ConnectionEnd;
> + EFI_TLS_VERIFY VerifyMethod;
> + EFI_TLS_SESSION_STATE SessionState;
> +
> + VOID *CACert;
> + UINTN CACertSize;
> + VOID *ClientCert;
> + UINTN ClientCertSize;
> + VOID *ClientPrivateKey;
> + UINTN ClientPrivateKeySize;
> +} TLS_CONFIG_DATA;
> +
> typedef struct _HTTP_PROTOCOL {
> UINT32 Signature;
> EFI_HTTP_PROTOCOL Http;
> EFI_HANDLE Handle;
> HTTP_SERVICE *Service;
> @@ -151,10 +165,39 @@ typedef struct _HTTP_PROTOCOL {
>
> NET_MAP TxTokens;
> NET_MAP RxTokens;
>
> CHAR8 *Url;
> +
> + //
> + // Https Support
> + //
> + BOOLEAN UseHttps;
> +
> + EFI_HANDLE TlsChildHandle; /// Tls ChildHandle
> + TLS_CONFIG_DATA TlsConfigData;
> + EFI_TLS_PROTOCOL *Tls;
> + EFI_TLS_CONFIGURATION_PROTOCOL *TlsConfiguration;
> + EFI_TLS_SESSION_STATE TlsSessionState;
> +
> + //
> + // TlsTxData used for transmitting TLS related messages.
> + //
> + EFI_TCP4_IO_TOKEN Tcp4TlsTxToken;
> + EFI_TCP4_TRANSMIT_DATA Tcp4TlsTxData;
> + EFI_TCP6_IO_TOKEN Tcp6TlsTxToken;
> + EFI_TCP6_TRANSMIT_DATA Tcp6TlsTxData;
> + BOOLEAN TlsIsTxDone;
> +
> + //
> + // TlsRxData used for receiving TLS related messages.
> + //
> + EFI_TCP4_IO_TOKEN Tcp4TlsRxToken;
> + EFI_TCP4_RECEIVE_DATA Tcp4TlsRxData;
> + EFI_TCP6_IO_TOKEN Tcp6TlsRxToken;
> + EFI_TCP6_RECEIVE_DATA Tcp6TlsRxData;
> + BOOLEAN TlsIsRxDone;
> } HTTP_PROTOCOL;
>
> typedef struct {
> EFI_HTTP_TOKEN *HttpToken;
> HTTP_PROTOCOL *HttpInstance;
> @@ -350,11 +393,12 @@ HttpConfigureTcp6 (
> IN HTTP_PROTOCOL *HttpInstance,
> IN HTTP_TOKEN_WRAP *Wrap
> );
>
> /**
> - Check existing TCP connection, if in error state, receover TCP4 connection.
> + Check existing TCP connection, if in error state, recover TCP4 connection.
> Then,
> + connect one TLS session if required.
>
> @param[in] HttpInstance The HTTP instance private data.
>
> @retval EFI_SUCCESS The TCP connection is established.
> @retval EFI_NOT_READY TCP4 protocol child is not created or
> configured.
> @@ -365,11 +409,12 @@ EFI_STATUS
> HttpConnectTcp4 (
> IN HTTP_PROTOCOL *HttpInstance
> );
>
> /**
> - Check existing TCP connection, if in error state, recover TCP6 connection.
> + Check existing TCP connection, if in error state, recover TCP6 connection.
> Then,
> + connect one TLS session if required.
>
> @param[in] HttpInstance The HTTP instance private data.
>
> @retval EFI_SUCCESS The TCP connection is established.
> @retval EFI_NOT_READY TCP6 protocol child is not created or
> configured.
> @@ -380,11 +425,11 @@ EFI_STATUS
> HttpConnectTcp6 (
> IN HTTP_PROTOCOL *HttpInstance
> );
>
> /**
> - Send the HTTP message through TCP4 or TCP6.
> + Send the HTTP or HTTPS message through TCP4 or TCP6.
>
> @param[in] HttpInstance The HTTP instance private data.
> @param[in] Wrap The HTTP token's wrap data.
> @param[in] TxString Buffer containing the HTTP message string.
> @param[in] TxStringLen Length of the HTTP message string in bytes.
> @@ -441,29 +486,31 @@ HttpTcpNotReady (
> IN NET_MAP_ITEM *Item,
> IN VOID *Context
> );
>
> /**
> - Initialize TCP related data.
> + Initialize Http session.
>
> @param[in] HttpInstance The HTTP instance private data.
> @param[in] Wrap The HTTP token's wrap data.
> - @param[in] Configure The Flag indicates whether the first time to
> initialize Tcp.
> + @param[in] Configure The Flag indicates whether need to initialize
> session.
> + @param[in] TlsConfigure The Flag indicates whether it's the new Tls
> session.
>
> - @retval EFI_SUCCESS The initialization of TCP instance is done.
> + @retval EFI_SUCCESS The initialization of session is done.
> @retval Others Other error as indicated.
>
> **/
> EFI_STATUS
> -HttpInitTcp (
> +HttpInitSession (
> IN HTTP_PROTOCOL *HttpInstance,
> IN HTTP_TOKEN_WRAP *Wrap,
> - IN BOOLEAN Configure
> + IN BOOLEAN Configure,
> + IN BOOLEAN TlsConfigure
> );
>
> /**
> - Transmit the HTTP mssage by processing the associated HTTP token.
> + Transmit the HTTP or HTTPS mssage by processing the associated HTTP
> token.
>
> @param[in] Map The container of TxToken or Tx6Token.
> @param[in] Item Current item to check against.
> @param[in] Context The Token to check againist.
>
> diff --git a/NetworkPkg/HttpDxe/HttpsSupport.c
> b/NetworkPkg/HttpDxe/HttpsSupport.c
> new file mode 100644
> index 0000000..177b9a8
> --- /dev/null
> +++ b/NetworkPkg/HttpDxe/HttpsSupport.c
> @@ -0,0 +1,1692 @@
> +/** @file
> + Miscellaneous routines specific to Https for HttpDxe driver.
> +
> +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution. The full text of the license may be
> found at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#include "HttpDriver.h"
> +
> +/**
> + Returns the first occurrence of a Null-terminated ASCII sub-string in a Null-
> terminated
> + ASCII string and ignore case during the search process.
> +
> + This function scans the contents of the ASCII string specified by String
> + and returns the first occurrence of SearchString and ignore case during the
> search process.
> + If SearchString is not found in String, then NULL is returned. If the length of
> SearchString
> + is zero, then String is returned.
> +
> + If String is NULL, then ASSERT().
> + If SearchString is NULL, then ASSERT().
> +
> + @param[in] String A pointer to a Null-terminated ASCII string.
> + @param[in] SearchString A pointer to a Null-terminated ASCII string to
> search for.
> +
> + @retval NULL If the SearchString does not appear in String.
> + @retval others If there is a match return the first occurrence of
> SearchingString.
> + If the length of SearchString is zero,return String.
> +
> +**/
> +CHAR8 *
> +AsciiStrCaseStr (
> + IN CONST CHAR8 *String,
> + IN CONST CHAR8 *SearchString
> + )
> +{
> + CONST CHAR8 *FirstMatch;
> + CONST CHAR8 *SearchStringTmp;
> +
> + CHAR8 Src;
> + CHAR8 Dst;
> +
> + //
> + // ASSERT both strings are less long than PcdMaximumAsciiStringLength
> + //
> + ASSERT (AsciiStrSize (String) != 0);
> + ASSERT (AsciiStrSize (SearchString) != 0);
> +
> + if (*SearchString == '\0') {
> + return (CHAR8 *) String;
> + }
> +
> + while (*String != '\0') {
> + SearchStringTmp = SearchString;
> + FirstMatch = String;
> +
> + while ((*SearchStringTmp != '\0')
> + && (*String != '\0')) {
> + Src = *String;
> + Dst = *SearchStringTmp;
> +
> + if ((Src >= 'A') && (Src <= 'Z')) {
> + Src -= ('A' - 'a');
> + }
> +
> + if ((Dst >= 'A') && (Dst <= 'Z')) {
> + Dst -= ('A' - 'a');
> + }
> +
> + if (Src != Dst) {
> + break;
> + }
> +
> + String++;
> + SearchStringTmp++;
> + }
> +
> + if (*SearchStringTmp == '\0') {
> + return (CHAR8 *) FirstMatch;
> + }
> +
> + String = FirstMatch + 1;
> + }
> +
> + return NULL;
> +}
> +
> +/**
> + The callback function to free the net buffer list.
> +
> + @param[in] Arg The opaque parameter.
> +
> +**/
> +VOID
> +EFIAPI
> +FreeNbufList (
> + IN VOID *Arg
> + )
> +{
> + ASSERT (Arg != NULL);
> +
> + NetbufFreeList ((LIST_ENTRY *) Arg);
> + FreePool (Arg);
> +}
> +
> +/**
> + Check whether the Url is from Https.
> +
> + @param[in] Url The pointer to a HTTP or HTTPS URL string.
> +
> + @retval TRUE The Url is from HTTPS.
> + @retval FALSE The Url is from HTTP.
> +
> +**/
> +BOOLEAN
> +IsHttpsUrl (
> + IN CHAR8 *Url
> + )
> +{
> + CHAR8 *Tmp;
> +
> + Tmp = NULL;
> +
> + Tmp = AsciiStrCaseStr (Url, HTTPS_FLAG);
> + if (Tmp != NULL && Tmp == Url) {
> + return TRUE;
> + }
> +
> + return FALSE;
> +}
> +
> +/**
> + Creates a Tls child handle, open EFI_TLS_PROTOCOL and
> EFI_TLS_CONFIGURATION_PROTOCOL.
> +
> + @param[in] ImageHandle The firmware allocated handle for the UEFI
> image.
> + @param[out] TlsProto Pointer to the EFI_TLS_PROTOCOL instance.
> + @param[out] TlsConfiguration Pointer to the
> EFI_TLS_CONFIGURATION_PROTOCOL instance.
> +
> + @return The child handle with opened EFI_TLS_PROTOCOL and
> EFI_TLS_CONFIGURATION_PROTOCOL.
> +
> +**/
> +EFI_HANDLE
> +EFIAPI
> +TlsCreateChild (
> + IN EFI_HANDLE ImageHandle,
> + OUT EFI_TLS_PROTOCOL **TlsProto,
> + OUT EFI_TLS_CONFIGURATION_PROTOCOL **TlsConfiguration
> + )
> +{
> + EFI_STATUS Status;
> + EFI_SERVICE_BINDING_PROTOCOL *TlsSb;
> + EFI_HANDLE TlsChildHandle;
> +
> + TlsSb = NULL;
> + TlsChildHandle = 0;
> +
> + //
> + // Locate TlsServiceBinding protocol.
> + //
> + gBS->LocateProtocol (
> + &gEfiTlsServiceBindingProtocolGuid,
> + NULL,
> + (VOID **) &TlsSb
> + );
> + if (TlsSb == NULL) {
> + return NULL;
> + }
> +
> + Status = TlsSb->CreateChild (TlsSb, &TlsChildHandle);
> + if (EFI_ERROR (Status)) {
> + return NULL;
> + }
> +
> + Status = gBS->OpenProtocol (
> + TlsChildHandle,
> + &gEfiTlsProtocolGuid,
> + (VOID **) TlsProto,
> + ImageHandle,
> + TlsChildHandle,
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
> + );
> + if (EFI_ERROR (Status)) {
> + TlsSb->DestroyChild (TlsSb, TlsChildHandle);
> + return NULL;
> + }
> +
> + Status = gBS->OpenProtocol (
> + TlsChildHandle,
> + &gEfiTlsConfigurationProtocolGuid,
> + (VOID **) TlsConfiguration,
> + ImageHandle,
> + TlsChildHandle,
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
> + );
> + if (EFI_ERROR (Status)) {
> + TlsSb->DestroyChild (TlsSb, TlsChildHandle);
> + return NULL;
> + }
> +
> + return TlsChildHandle;
> +}
> +
> +/**
> + Create event for the TLS receive and transmit tokens which are used to
> receive and
> + transmit TLS related messages.
> +
> + @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
> +
> + @retval EFI_SUCCESS The events are created successfully.
> + @retval others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsCreateTxRxEvent (
> + IN OUT HTTP_PROTOCOL *HttpInstance
> + )
> +{
> + EFI_STATUS Status;
> +
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + //
> + // For Tcp4TlsTxToken.
> + //
> + Status = gBS->CreateEvent (
> + EVT_NOTIFY_SIGNAL,
> + TPL_NOTIFY,
> + HttpCommonNotify,
> + &HttpInstance->TlsIsTxDone,
> + &HttpInstance->Tcp4TlsTxToken.CompletionToken.Event
> + );
> + if (EFI_ERROR (Status)) {
> + goto ERROR;
> + }
> +
> + HttpInstance->Tcp4TlsTxData.Push = TRUE;
> + HttpInstance->Tcp4TlsTxData.Urgent = FALSE;
> + HttpInstance->Tcp4TlsTxData.DataLength = 0;
> + HttpInstance->Tcp4TlsTxData.FragmentCount = 1;
> + HttpInstance->Tcp4TlsTxData.FragmentTable[0].FragmentLength =
> HttpInstance->Tcp4TlsTxData.DataLength;
> + HttpInstance->Tcp4TlsTxData.FragmentTable[0].FragmentBuffer = NULL;
> + HttpInstance->Tcp4TlsTxToken.Packet.TxData = &HttpInstance-
> >Tcp4TlsTxData;
> + HttpInstance->Tcp4TlsTxToken.CompletionToken.Status =
> EFI_NOT_READY;
> +
> + //
> + // For Tcp4TlsRxToken.
> + //
> + Status = gBS->CreateEvent (
> + EVT_NOTIFY_SIGNAL,
> + TPL_NOTIFY,
> + HttpCommonNotify,
> + &HttpInstance->TlsIsRxDone,
> + &HttpInstance->Tcp4TlsRxToken.CompletionToken.Event
> + );
> + if (EFI_ERROR (Status)) {
> + goto ERROR;
> + }
> +
> + HttpInstance->Tcp4TlsRxData.DataLength = 0;
> + HttpInstance->Tcp4TlsRxData.FragmentCount = 1;
> + HttpInstance->Tcp4TlsRxData.FragmentTable[0].FragmentLength =
> HttpInstance->Tcp4TlsRxData.DataLength ;
> + HttpInstance->Tcp4TlsRxData.FragmentTable[0].FragmentBuffer = NULL;
> + HttpInstance->Tcp4TlsRxToken.Packet.RxData = &HttpInstance-
> >Tcp4TlsRxData;
> + HttpInstance->Tcp4TlsRxToken.CompletionToken.Status =
> EFI_NOT_READY;
> + } else {
> + //
> + // For Tcp6TlsTxToken.
> + //
> + Status = gBS->CreateEvent (
> + EVT_NOTIFY_SIGNAL,
> + TPL_NOTIFY,
> + HttpCommonNotify,
> + &HttpInstance->TlsIsTxDone,
> + &HttpInstance->Tcp6TlsTxToken.CompletionToken.Event
> + );
> + if (EFI_ERROR (Status)) {
> + goto ERROR;
> + }
> +
> + HttpInstance->Tcp6TlsTxData.Push = TRUE;
> + HttpInstance->Tcp6TlsTxData.Urgent = FALSE;
> + HttpInstance->Tcp6TlsTxData.DataLength = 0;
> + HttpInstance->Tcp6TlsTxData.FragmentCount = 1;
> + HttpInstance->Tcp6TlsTxData.FragmentTable[0].FragmentLength =
> HttpInstance->Tcp6TlsTxData.DataLength;
> + HttpInstance->Tcp6TlsTxData.FragmentTable[0].FragmentBuffer = NULL;
> + HttpInstance->Tcp6TlsTxToken.Packet.TxData = &HttpInstance-
> >Tcp6TlsTxData;
> + HttpInstance->Tcp6TlsTxToken.CompletionToken.Status =
> EFI_NOT_READY;
> +
> + //
> + // For Tcp6TlsRxToken.
> + //
> + Status = gBS->CreateEvent (
> + EVT_NOTIFY_SIGNAL,
> + TPL_NOTIFY,
> + HttpCommonNotify,
> + &HttpInstance->TlsIsRxDone,
> + &HttpInstance->Tcp6TlsRxToken.CompletionToken.Event
> + );
> + if (EFI_ERROR (Status)) {
> + goto ERROR;
> + }
> +
> + HttpInstance->Tcp6TlsRxData.DataLength = 0;
> + HttpInstance->Tcp6TlsRxData.FragmentCount = 1;
> + HttpInstance->Tcp6TlsRxData.FragmentTable[0].FragmentLength =
> HttpInstance->Tcp6TlsRxData.DataLength ;
> + HttpInstance->Tcp6TlsRxData.FragmentTable[0].FragmentBuffer = NULL;
> + HttpInstance->Tcp6TlsRxToken.Packet.RxData = &HttpInstance-
> >Tcp6TlsRxData;
> + HttpInstance->Tcp6TlsRxToken.CompletionToken.Status =
> EFI_NOT_READY;
> + }
> +
> + return Status;
> +
> +ERROR:
> + //
> + // Error handling
> + //
> + TlsCloseTxRxEvent (HttpInstance);
> +
> + return Status;
> +}
> +
> +/**
> + Close events in the TlsTxToken and TlsRxToken.
> +
> + @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
> +
> +**/
> +VOID
> +EFIAPI
> +TlsCloseTxRxEvent (
> + IN HTTP_PROTOCOL *HttpInstance
> + )
> +{
> + ASSERT (HttpInstance != NULL);
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + if (NULL != HttpInstance->Tcp4TlsTxToken.CompletionToken.Event) {
> + gBS->CloseEvent(HttpInstance-
> >Tcp4TlsTxToken.CompletionToken.Event);
> + HttpInstance->Tcp4TlsTxToken.CompletionToken.Event = NULL;
> + }
> +
> + if (NULL != HttpInstance->Tcp4TlsRxToken.CompletionToken.Event) {
> + gBS->CloseEvent (HttpInstance-
> >Tcp4TlsRxToken.CompletionToken.Event);
> + HttpInstance->Tcp4TlsRxToken.CompletionToken.Event = NULL;
> + }
> + } else {
> + if (NULL != HttpInstance->Tcp6TlsTxToken.CompletionToken.Event) {
> + gBS->CloseEvent(HttpInstance-
> >Tcp6TlsTxToken.CompletionToken.Event);
> + HttpInstance->Tcp6TlsTxToken.CompletionToken.Event = NULL;
> + }
> +
> + if (NULL != HttpInstance->Tcp6TlsRxToken.CompletionToken.Event) {
> + gBS->CloseEvent (HttpInstance-
> >Tcp6TlsRxToken.CompletionToken.Event);
> + HttpInstance->Tcp6TlsRxToken.CompletionToken.Event = NULL;
> + }
> + }
> +}
> +
> +/**
> + Read the TlsCaCertificate variable and configure it.
> +
> + @param[in, out] HttpInstance The HTTP instance private data.
> +
> + @retval EFI_SUCCESS TlsCaCertificate is configured.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_NOT_FOUND Fail to get 'TlsCaCertificate' variable.
> + @retval Others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +TlsConfigCertificate (
> + IN OUT HTTP_PROTOCOL *HttpInstance
> + )
> +{
> + EFI_STATUS Status;
> + UINT8 *CACert;
> + UINTN CACertSize;
> + UINT32 Index;
> + EFI_SIGNATURE_LIST *CertList;
> + EFI_SIGNATURE_DATA *Cert;
> + UINTN CertCount;
> + UINT32 ItemDataSize;
> +
> + CACert = (UINT8 *) HttpInstance->TlsConfigData.CACert;
> + CACertSize = HttpInstance->TlsConfigData.CACertSize;
> +
> + //
> + // Try to read the TlsCaCertificate variable.
> + //
> + CACertSize = 0;
> + Status = gRT->GetVariable (
> + EFI_TLS_CA_CERTIFICATE_VARIABLE,
> + &gEfiTlsCaCertificateGuid,
> + NULL,
> + &CACertSize,
> + NULL
> + );
> +
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + //
> + // Allocate buffer and read the config variable.
> + //
> + CACert = AllocatePool (CACertSize);
> + if (CACert == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + Status = gRT->GetVariable (
> + EFI_TLS_CA_CERTIFICATE_VARIABLE,
> + &gEfiTlsCaCertificateGuid,
> + NULL,
> + &CACertSize,
> + CACert
> + );
> + if (EFI_ERROR (Status)) {
> + //
> + // GetVariable still error or the variable is corrupted.
> + // Fall back to the default value.
> + //
> + FreePool (CACert);
> +
> + return EFI_NOT_FOUND;
> + }
> + }
> +
> + //
> + // Enumerate all data and erasing the target item.
> + //
> + ItemDataSize = (UINT32) CACertSize;
> + CertList = (EFI_SIGNATURE_LIST *) CACert;
> + while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize))
> {
> + Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof
> (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
> + CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) -
> CertList->SignatureHeaderSize) / CertList->SignatureSize;
> + for (Index = 0; Index < CertCount; Index++) {
> + //
> + // EfiTlsConfigDataTypeCACertificate
> + //
> + Status = HttpInstance->TlsConfiguration->SetData (
> + HttpInstance->TlsConfiguration,
> + EfiTlsConfigDataTypeCACertificate,
> + Cert->SignatureData,
> + CertList->SignatureSize - sizeof (Cert-
> >SignatureOwner)
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList-
> >SignatureSize);
> + }
> +
> + ItemDataSize -= CertList->SignatureListSize;
> + CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList-
> >SignatureListSize);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Configure TLS session data.
> +
> + @param[in, out] HttpInstance The HTTP instance private data.
> +
> + @retval EFI_SUCCESS TLS session data is configured.
> + @retval Others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsConfigureSession (
> + IN OUT HTTP_PROTOCOL *HttpInstance
> + )
> +{
> + EFI_STATUS Status;
> +
> + //
> + // TlsConfigData initialization
> + //
> + HttpInstance->TlsConfigData.ConnectionEnd = EfiTlsClient;
> + HttpInstance->TlsConfigData.VerifyMethod = EFI_TLS_VERIFY_PEER;
> + HttpInstance->TlsConfigData.SessionState = EfiTlsSessionNotStarted;
> +
> + //
> + // EfiTlsConnectionEnd,
> + // EfiTlsVerifyMethod
> + // EfiTlsSessionState
> + //
> + Status = HttpInstance->Tls->SetSessionData (
> + HttpInstance->Tls,
> + EfiTlsConnectionEnd,
> + &(HttpInstance->TlsConfigData.ConnectionEnd),
> + sizeof (EFI_TLS_CONNECTION_END)
> + );
> + if (EFI_ERROR (Status)) {
> + goto ERROR;
> + }
> +
> + Status = HttpInstance->Tls->SetSessionData (
> + HttpInstance->Tls,
> + EfiTlsVerifyMethod,
> + &HttpInstance->TlsConfigData.VerifyMethod,
> + sizeof (EFI_TLS_VERIFY)
> + );
> + if (EFI_ERROR (Status)) {
> + goto ERROR;
> + }
> +
> + Status = HttpInstance->Tls->SetSessionData (
> + HttpInstance->Tls,
> + EfiTlsSessionState,
> + &(HttpInstance->TlsConfigData.SessionState),
> + sizeof (EFI_TLS_SESSION_STATE)
> + );
> + if (EFI_ERROR (Status)) {
> + goto ERROR;
> + }
> +
> + //
> + // Tls Config Certificate
> + //
> + Status = TlsConfigCertificate (HttpInstance);
> + if (EFI_ERROR (Status)) {
> + DEBUG ((EFI_D_ERROR, "TLS Certificate Config Error!\n"));
> + goto ERROR;
> + }
> +
> + //
> + // TlsCreateTxRxEvent
> + //
> + Status = TlsCreateTxRxEvent (HttpInstance);
> + if (EFI_ERROR (Status)) {
> + goto ERROR;
> + }
> +
> + return Status;
> +
> +ERROR:
> + TlsCloseTxRxEvent (HttpInstance);
> +
> + return Status;
> +}
> +
> +/**
> + Transmit the Packet by processing the associated HTTPS token.
> +
> + @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
> + @param[in] Packet The packet to transmit.
> +
> + @retval EFI_SUCCESS The packet is transmitted.
> + @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsCommonTransmit (
> + IN OUT HTTP_PROTOCOL *HttpInstance,
> + IN NET_BUF *Packet
> + )
> +{
> + EFI_STATUS Status;
> + VOID *Data;
> + UINTN Size;
> +
> + if ((HttpInstance == NULL) || (Packet == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + Size = sizeof (EFI_TCP4_TRANSMIT_DATA) +
> + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP4_FRAGMENT_DATA);
> + } else {
> + Size = sizeof (EFI_TCP6_TRANSMIT_DATA) +
> + (Packet->BlockOpNum - 1) * sizeof (EFI_TCP6_FRAGMENT_DATA);
> + }
> +
> + Data = AllocatePool (Size);
> + if (Data == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + ((EFI_TCP4_TRANSMIT_DATA *) Data)->Push = TRUE;
> + ((EFI_TCP4_TRANSMIT_DATA *) Data)->Urgent = FALSE;
> + ((EFI_TCP4_TRANSMIT_DATA *) Data)->DataLength = Packet->TotalSize;
> +
> + //
> + // Build the fragment table.
> + //
> + ((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount = Packet-
> >BlockOpNum;
> +
> + NetbufBuildExt (
> + Packet,
> + (NET_FRAGMENT *) &((EFI_TCP4_TRANSMIT_DATA *) Data)-
> >FragmentTable[0],
> + &((EFI_TCP4_TRANSMIT_DATA *) Data)->FragmentCount
> + );
> +
> + HttpInstance->Tcp4TlsTxToken.Packet.TxData =
> (EFI_TCP4_TRANSMIT_DATA *) Data;
> +
> + Status = EFI_DEVICE_ERROR;
> +
> + //
> + // Transmit the packet.
> + //
> + Status = HttpInstance->Tcp4->Transmit (HttpInstance->Tcp4,
> &HttpInstance->Tcp4TlsTxToken);
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> +
> + while (!HttpInstance->TlsIsTxDone) {
> + HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
> + }
> +
> + HttpInstance->TlsIsTxDone = FALSE;
> + Status = HttpInstance->Tcp4TlsTxToken.CompletionToken.Status;
> + } else {
> + ((EFI_TCP6_TRANSMIT_DATA *) Data)->Push = TRUE;
> + ((EFI_TCP6_TRANSMIT_DATA *) Data)->Urgent = FALSE;
> + ((EFI_TCP6_TRANSMIT_DATA *) Data)->DataLength = Packet->TotalSize;
> +
> + //
> + // Build the fragment table.
> + //
> + ((EFI_TCP6_TRANSMIT_DATA *) Data)->FragmentCount = Packet-
> >BlockOpNum;
> +
> + NetbufBuildExt (
> + Packet,
> + (NET_FRAGMENT *) &((EFI_TCP6_TRANSMIT_DATA *) Data)-
> >FragmentTable[0],
> + &((EFI_TCP6_TRANSMIT_DATA *) Data)->FragmentCount
> + );
> +
> + HttpInstance->Tcp6TlsTxToken.Packet.TxData =
> (EFI_TCP6_TRANSMIT_DATA *) Data;
> +
> + Status = EFI_DEVICE_ERROR;
> +
> + //
> + // Transmit the packet.
> + //
> + Status = HttpInstance->Tcp6->Transmit (HttpInstance->Tcp6,
> &HttpInstance->Tcp6TlsTxToken);
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> +
> + while (!HttpInstance->TlsIsTxDone) {
> + HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
> + }
> +
> + HttpInstance->TlsIsTxDone = FALSE;
> + Status = HttpInstance->Tcp6TlsTxToken.CompletionToken.Status;
> + }
> +
> +ON_EXIT:
> + FreePool (Data);
> +
> + return Status;
> +}
> +
> +/**
> + Receive the Packet by processing the associated HTTPS token.
> +
> + @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
> + @param[in] Packet The packet to transmit.
> + @param[in] Timeout The time to wait for connection done.
> +
> + @retval EFI_SUCCESS The Packet is received.
> + @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_TIMEOUT The operation is time out.
> + @retval Others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsCommonReceive (
> + IN OUT HTTP_PROTOCOL *HttpInstance,
> + IN NET_BUF *Packet,
> + IN EFI_EVENT Timeout
> + )
> +{
> + EFI_TCP4_RECEIVE_DATA *Tcp4RxData;
> + EFI_TCP6_RECEIVE_DATA *Tcp6RxData;
> + EFI_STATUS Status;
> + NET_FRAGMENT *Fragment;
> + UINT32 FragmentCount;
> + UINT32 CurrentFragment;
> +
> + Tcp4RxData = NULL;
> + Tcp6RxData = NULL;
> +
> + if ((HttpInstance == NULL) || (Packet == NULL)) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + FragmentCount = Packet->BlockOpNum;
> + Fragment = AllocatePool (FragmentCount * sizeof (NET_FRAGMENT));
> + if (Fragment == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> +
> + //
> + // Build the fragment table.
> + //
> + NetbufBuildExt (Packet, Fragment, &FragmentCount);
> +
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + Tcp4RxData = HttpInstance->Tcp4TlsRxToken.Packet.RxData;
> + if (Tcp4RxData == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> + Tcp4RxData->FragmentCount = 1;
> + } else {
> + Tcp6RxData = HttpInstance->Tcp6TlsRxToken.Packet.RxData;
> + if (Tcp6RxData == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> + Tcp6RxData->FragmentCount = 1;
> + }
> +
> + CurrentFragment = 0;
> + Status = EFI_SUCCESS;
> +
> + while (CurrentFragment < FragmentCount) {
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + Tcp4RxData->DataLength = Fragment[CurrentFragment].Len;
> + Tcp4RxData->FragmentTable[0].FragmentLength =
> Fragment[CurrentFragment].Len;
> + Tcp4RxData->FragmentTable[0].FragmentBuffer =
> Fragment[CurrentFragment].Bulk;
> + Status = HttpInstance->Tcp4->Receive (HttpInstance->Tcp4,
> &HttpInstance->Tcp4TlsRxToken);
> + } else {
> + Tcp6RxData->DataLength = Fragment[CurrentFragment].Len;
> + Tcp6RxData->FragmentTable[0].FragmentLength =
> Fragment[CurrentFragment].Len;
> + Tcp6RxData->FragmentTable[0].FragmentBuffer =
> Fragment[CurrentFragment].Bulk;
> + Status = HttpInstance->Tcp6->Receive (HttpInstance->Tcp6,
> &HttpInstance->Tcp6TlsRxToken);
> + }
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> +
> + while (!HttpInstance->TlsIsRxDone && ((Timeout == NULL) || EFI_ERROR
> (gBS->CheckEvent (Timeout)))) {
> + //
> + // Poll until some data is received or an error occurs.
> + //
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + HttpInstance->Tcp4->Poll (HttpInstance->Tcp4);
> + } else {
> + HttpInstance->Tcp6->Poll (HttpInstance->Tcp6);
> + }
> + }
> +
> + if (!HttpInstance->TlsIsRxDone) {
> + //
> + // Timeout occurs, cancel the receive request.
> + //
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + HttpInstance->Tcp4->Cancel (HttpInstance->Tcp4, &HttpInstance-
> >Tcp4TlsRxToken.CompletionToken);
> + } else {
> + HttpInstance->Tcp6->Cancel (HttpInstance->Tcp6, &HttpInstance-
> >Tcp6TlsRxToken.CompletionToken);
> + }
> +
> + Status = EFI_TIMEOUT;
> + goto ON_EXIT;
> + } else {
> + HttpInstance->TlsIsRxDone = FALSE;
> + }
> +
> + if (!HttpInstance->LocalAddressIsIPv6) {
> + Status = HttpInstance->Tcp4TlsRxToken.CompletionToken.Status;
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> +
> + Fragment[CurrentFragment].Len -= Tcp4RxData-
> >FragmentTable[0].FragmentLength;
> + if (Fragment[CurrentFragment].Len == 0) {
> + CurrentFragment++;
> + } else {
> + Fragment[CurrentFragment].Bulk += Tcp4RxData-
> >FragmentTable[0].FragmentLength;
> + }
> + } else {
> + Status = HttpInstance->Tcp6TlsRxToken.CompletionToken.Status;
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> +
> + Fragment[CurrentFragment].Len -= Tcp6RxData-
> >FragmentTable[0].FragmentLength;
> + if (Fragment[CurrentFragment].Len == 0) {
> + CurrentFragment++;
> + } else {
> + Fragment[CurrentFragment].Bulk += Tcp6RxData-
> >FragmentTable[0].FragmentLength;
> + }
> + }
> + }
> +
> +ON_EXIT:
> +
> + if (Fragment != NULL) {
> + FreePool (Fragment);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Receive one TLS PDU. An TLS PDU contains an TLS record header and it's
> + corresponding record data. This two parts will be put into two blocks of
> buffers in the
> + net buffer.
> +
> + @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
> + @param[out] Pdu The received TLS PDU.
> + @param[in] Timeout The time to wait for connection done.
> +
> + @retval EFI_SUCCESS An TLS PDU is received.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_PROTOCOL_ERROR An unexpected TLS packet was received.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsReceiveOnePdu (
> + IN OUT HTTP_PROTOCOL *HttpInstance,
> + OUT NET_BUF **Pdu,
> + IN EFI_EVENT Timeout
> + )
> +{
> + EFI_STATUS Status;
> +
> + LIST_ENTRY *NbufList;
> +
> + UINT32 Len;
> +
> + NET_BUF *PduHdr;
> + UINT8 *Header;
> + TLS_RECORD_HEADER RecordHeader;
> +
> + NET_BUF *DataSeg;
> +
> + NbufList = NULL;
> + PduHdr = NULL;
> + Header = NULL;
> + DataSeg = NULL;
> +
> + NbufList = AllocatePool (sizeof (LIST_ENTRY));
> + if (NbufList == NULL) {
> + return EFI_OUT_OF_RESOURCES;
> + }
> +
> + InitializeListHead (NbufList);
> +
> + //
> + // Allocate buffer to receive one TLS header.
> + //
> + Len = sizeof (TLS_RECORD_HEADER);
> + PduHdr = NetbufAlloc (Len);
> + if (PduHdr == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> +
> + Header = NetbufAllocSpace (PduHdr, Len, NET_BUF_TAIL);
> + if (Header == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> +
> + //
> + // First step, receive one TLS header.
> + //
> + Status = TlsCommonReceive (HttpInstance, PduHdr, Timeout);
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> +
> + RecordHeader = *(TLS_RECORD_HEADER *) Header;
> + if ((RecordHeader.ContentType == TLS_CONTENT_TYPE_HANDSHAKE ||
> + RecordHeader.ContentType == TLS_CONTENT_TYPE_ALERT ||
> + RecordHeader.ContentType ==
> TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC ||
> + RecordHeader.ContentType ==
> TLS_CONTENT_TYPE_APPLICATION_DATA) &&
> + (RecordHeader.Version.Major == 0x03) && /// Major versions are same.
> + (RecordHeader.Version.Minor == TLS10_PROTOCOL_VERSION_MINOR ||
> + RecordHeader.Version.Minor ==TLS11_PROTOCOL_VERSION_MINOR ||
> + RecordHeader.Version.Minor == TLS12_PROTOCOL_VERSION_MINOR)
> + ) {
> + InsertTailList (NbufList, &PduHdr->List);
> + } else {
> + Status = EFI_PROTOCOL_ERROR;
> + goto ON_EXIT;
> + }
> +
> + Len = SwapBytes16(RecordHeader.Length);
> + if (Len == 0) {
> + //
> + // No TLS payload.
> + //
> + goto FORM_PDU;
> + }
> +
> + //
> + // Allocate buffer to receive one TLS payload.
> + //
> + DataSeg = NetbufAlloc (Len);
> + if (DataSeg == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> +
> + NetbufAllocSpace (DataSeg, Len, NET_BUF_TAIL);
> +
> + //
> + // Second step, receive one TLS payload.
> + //
> + Status = TlsCommonReceive (HttpInstance, DataSeg, Timeout);
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> +
> + InsertTailList (NbufList, &DataSeg->List);
> +
> +FORM_PDU:
> + //
> + // Form the PDU from a list of PDU.
> + //
> + *Pdu = NetbufFromBufList (NbufList, 0, 0, FreeNbufList, NbufList);
> + if (*Pdu == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + }
> +
> +ON_EXIT:
> +
> + if (EFI_ERROR (Status)) {
> + //
> + // Free the Nbufs in this NbufList and the NbufList itself.
> + //
> + FreeNbufList (NbufList);
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Connect one TLS session by finishing the TLS handshake process.
> +
> + @param[in] HttpInstance The HTTP instance private data.
> + @param[in] Timeout The time to wait for connection done.
> +
> + @retval EFI_SUCCESS The TLS session is established.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_ABORTED TLS session state is incorrect.
> + @retval Others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsConnectSession (
> + IN HTTP_PROTOCOL *HttpInstance,
> + IN EFI_EVENT Timeout
> + )
> +{
> + EFI_STATUS Status;
> + UINT8 *BufferOut;
> + UINTN BufferOutSize;
> + NET_BUF *PacketOut;
> + UINT8 *DataOut;
> + NET_BUF *Pdu;
> + UINT8 *BufferIn;
> + UINTN BufferInSize;
> + UINT8 *GetSessionDataBuffer;
> + UINTN GetSessionDataBufferSize;
> +
> + BufferOut = NULL;
> + PacketOut = NULL;
> + DataOut = NULL;
> + Pdu = NULL;
> + BufferIn = NULL;
> +
> + //
> + // Initialize TLS state.
> + //
> + HttpInstance->TlsSessionState = EfiTlsSessionNotStarted;
> + Status = HttpInstance->Tls->SetSessionData (
> + HttpInstance->Tls,
> + EfiTlsSessionState,
> + &(HttpInstance->TlsSessionState),
> + sizeof (EFI_TLS_SESSION_STATE)
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + //
> + // Create ClientHello
> + //
> + BufferOutSize = DEF_BUF_LEN;
> + BufferOut = AllocateZeroPool (BufferOutSize);
> + if (BufferOut == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->BuildResponsePacket (
> + HttpInstance->Tls,
> + NULL,
> + 0,
> + BufferOut,
> + &BufferOutSize
> + );
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + FreePool (BufferOut);
> + BufferOut = AllocateZeroPool (BufferOutSize);
> + if (BufferOut == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->BuildResponsePacket (
> + HttpInstance->Tls,
> + NULL,
> + 0,
> + BufferOut,
> + &BufferOutSize
> + );
> + }
> + if (EFI_ERROR (Status)) {
> + FreePool (BufferOut);
> + return Status;
> + }
> +
> + //
> + // Transmit ClientHello
> + //
> + PacketOut = NetbufAlloc ((UINT32) BufferOutSize);
> + DataOut = NetbufAllocSpace (PacketOut, (UINT32) BufferOutSize,
> NET_BUF_TAIL);
> + CopyMem (DataOut, BufferOut, BufferOutSize);
> + Status = TlsCommonTransmit (HttpInstance, PacketOut);
> +
> + FreePool (BufferOut);
> + NetbufFree (PacketOut);
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + while(HttpInstance->TlsSessionState != EfiTlsSessionDataTransferring && \
> + ((Timeout == NULL) || EFI_ERROR (gBS->CheckEvent (Timeout)))) {
> + //
> + // Receive one TLS record.
> + //
> + Status = TlsReceiveOnePdu (HttpInstance, &Pdu, Timeout);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + BufferInSize = Pdu->TotalSize;
> + BufferIn = AllocateZeroPool (BufferInSize);
> + if (BufferIn == NULL) {
> + NetbufFree (Pdu);
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + NetbufCopy (Pdu, 0, (UINT32)BufferInSize, BufferIn);
> +
> + NetbufFree (Pdu);
> +
> + //
> + // Handle Receive data.
> + //
> + BufferOutSize = DEF_BUF_LEN;
> + BufferOut = AllocateZeroPool (BufferOutSize);
> + if (BufferOut == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->BuildResponsePacket (
> + HttpInstance->Tls,
> + BufferIn,
> + BufferInSize,
> + BufferOut,
> + &BufferOutSize
> + );
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + FreePool (BufferOut);
> + BufferOut = AllocateZeroPool (BufferOutSize);
> + if (BufferOut == NULL) {
> + FreePool (BufferIn);
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->BuildResponsePacket (
> + HttpInstance->Tls,
> + BufferIn,
> + BufferInSize,
> + BufferOut,
> + &BufferOutSize
> + );
> + }
> +
> + FreePool (BufferIn);
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + if (BufferOutSize != 0) {
> + //
> + // Transmit the response packet.
> + //
> + PacketOut = NetbufAlloc ((UINT32) BufferOutSize);
> + DataOut = NetbufAllocSpace (PacketOut, (UINT32) BufferOutSize,
> NET_BUF_TAIL);
> + CopyMem (DataOut, BufferOut, BufferOutSize);
> +
> + Status = TlsCommonTransmit (HttpInstance, PacketOut);
> +
> + NetbufFree (PacketOut);
> +
> + if (EFI_ERROR (Status)) {
> + FreePool (BufferOut);
> + return Status;
> + }
> + }
> +
> + FreePool (BufferOut);
> +
> + //
> + // Get the session state, then decide whether need to continue handle
> received packet.
> + //
> + GetSessionDataBufferSize = DEF_BUF_LEN;
> + GetSessionDataBuffer = AllocateZeroPool (GetSessionDataBufferSize);
> + if (GetSessionDataBuffer == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->GetSessionData (
> + HttpInstance->Tls,
> + EfiTlsSessionState,
> + GetSessionDataBuffer,
> + &GetSessionDataBufferSize
> + );
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + FreePool (GetSessionDataBuffer);
> + GetSessionDataBuffer = AllocateZeroPool (GetSessionDataBufferSize);
> + if (GetSessionDataBuffer == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->GetSessionData (
> + HttpInstance->Tls,
> + EfiTlsSessionState,
> + GetSessionDataBuffer,
> + &GetSessionDataBufferSize
> + );
> + }
> + if (EFI_ERROR (Status)) {
> + FreePool(GetSessionDataBuffer);
> + return Status;
> + }
> +
> + ASSERT(GetSessionDataBufferSize == sizeof (EFI_TLS_SESSION_STATE));
> + HttpInstance->TlsSessionState = *(EFI_TLS_SESSION_STATE *)
> GetSessionDataBuffer;
> +
> + FreePool (GetSessionDataBuffer);
> +
> + if(HttpInstance->TlsSessionState == EfiTlsSessionError) {
> + return EFI_ABORTED;
> + }
> + }
> +
> + if (HttpInstance->TlsSessionState != EfiTlsSessionDataTransferring) {
> + Status = EFI_ABORTED;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Close the TLS session and send out the close notification message.
> +
> + @param[in] HttpInstance The HTTP instance private data.
> +
> + @retval EFI_SUCCESS The TLS session is closed.
> + @retval EFI_INVALID_PARAMETER HttpInstance is NULL.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval Others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsCloseSession (
> + IN HTTP_PROTOCOL *HttpInstance
> + )
> +{
> + EFI_STATUS Status;
> +
> + UINT8 *BufferOut;
> + UINTN BufferOutSize;
> +
> + NET_BUF *PacketOut;
> + UINT8 *DataOut;
> +
> + Status = EFI_SUCCESS;
> + BufferOut = NULL;
> + PacketOut = NULL;
> + DataOut = NULL;
> +
> + if (HttpInstance == NULL) {
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + HttpInstance->TlsSessionState = EfiTlsSessionClosing;
> +
> + Status = HttpInstance->Tls->SetSessionData (
> + HttpInstance->Tls,
> + EfiTlsSessionState,
> + &(HttpInstance->TlsSessionState),
> + sizeof (EFI_TLS_SESSION_STATE)
> + );
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + BufferOutSize = DEF_BUF_LEN;
> + BufferOut = AllocateZeroPool (BufferOutSize);
> + if (BufferOut == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->BuildResponsePacket (
> + HttpInstance->Tls,
> + NULL,
> + 0,
> + BufferOut,
> + &BufferOutSize
> + );
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + FreePool (BufferOut);
> + BufferOut = AllocateZeroPool (BufferOutSize);
> + if (BufferOut == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->BuildResponsePacket (
> + HttpInstance->Tls,
> + NULL,
> + 0,
> + BufferOut,
> + &BufferOutSize
> + );
> + }
> +
> + if (EFI_ERROR (Status)) {
> + FreePool (BufferOut);
> + return Status;
> + }
> +
> + PacketOut = NetbufAlloc ((UINT32) BufferOutSize);
> + DataOut = NetbufAllocSpace (PacketOut, (UINT32) BufferOutSize,
> NET_BUF_TAIL);
> + CopyMem (DataOut, BufferOut, BufferOutSize);
> +
> + Status = TlsCommonTransmit (HttpInstance, PacketOut);
> +
> + FreePool (BufferOut);
> + NetbufFree (PacketOut);
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Process one message according to the CryptMode.
> +
> + @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
> + @param[in] Message Pointer to the message buffer needed to
> processed.
> + @param[in] MessageSize Pointer to the message buffer size.
> + @param[in] ProcessMode Process mode.
> + @param[in, out] Fragment Only one Fragment returned after the
> Message is
> + processed successfully.
> +
> + @retval EFI_SUCCESS Message is processed successfully.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsProcessMessage (
> + IN HTTP_PROTOCOL *HttpInstance,
> + IN UINT8 *Message,
> + IN UINTN MessageSize,
> + IN EFI_TLS_CRYPT_MODE ProcessMode,
> + IN OUT NET_FRAGMENT *Fragment
> + )
> +{
> + EFI_STATUS Status;
> + UINT8 *Buffer;
> + UINT32 BufferSize;
> + UINT32 BytesCopied;
> + EFI_TLS_FRAGMENT_DATA *FragmentTable;
> + UINT32 FragmentCount;
> + EFI_TLS_FRAGMENT_DATA *OriginalFragmentTable;
> + UINTN Index;
> +
> + Status = EFI_SUCCESS;
> + Buffer = NULL;
> + BufferSize = 0;
> + BytesCopied = 0;
> + FragmentTable = NULL;
> + OriginalFragmentTable = NULL;
> +
> + //
> + // Rebuild fragment table from BufferIn.
> + //
> + FragmentCount = 1;
> + FragmentTable = AllocateZeroPool (FragmentCount * sizeof
> (EFI_TLS_FRAGMENT_DATA));
> + if (FragmentTable == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> +
> + FragmentTable->FragmentLength = (UINT32) MessageSize;
> + FragmentTable->FragmentBuffer = Message;
> +
> + //
> + // Record the original FragmentTable.
> + //
> + OriginalFragmentTable = FragmentTable;
> +
> + //
> + // Process the Message.
> + //
> + Status = HttpInstance->Tls->ProcessPacket (
> + HttpInstance->Tls,
> + &FragmentTable,
> + &FragmentCount,
> + ProcessMode
> + );
> + if (EFI_ERROR (Status)) {
> + goto ON_EXIT;
> + }
> +
> + //
> + // Calculate the size according to FragmentTable.
> + //
> + for (Index = 0; Index < FragmentCount; Index++) {
> + BufferSize += FragmentTable[Index].FragmentLength;
> + }
> +
> + //
> + // Allocate buffer for processed data.
> + //
> + Buffer = AllocateZeroPool (BufferSize);
> + if (Buffer == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + goto ON_EXIT;
> + }
> +
> + //
> + // Copy the new FragmentTable buffer into Buffer.
> + //
> + for (Index = 0; Index < FragmentCount; Index++) {
> + CopyMem (
> + (Buffer + BytesCopied),
> + FragmentTable[Index].FragmentBuffer,
> + FragmentTable[Index].FragmentLength
> + );
> + BytesCopied += FragmentTable[Index].FragmentLength;
> +
> + //
> + // Free the FragmentBuffer since it has been copied.
> + //
> + FreePool (FragmentTable[Index].FragmentBuffer);
> + }
> +
> + Fragment->Len = BufferSize;
> + Fragment->Bulk = Buffer;
> +
> +ON_EXIT:
> +
> + if (OriginalFragmentTable != NULL) {
> + FreePool (OriginalFragmentTable);
> + OriginalFragmentTable = NULL;
> + }
> +
> + //
> + // Caller has the responsibility to free the FragmentTable.
> + //
> + if (FragmentTable != NULL) {
> + FreePool (FragmentTable);
> + FragmentTable = NULL;
> + }
> +
> + return Status;
> +}
> +
> +/**
> + Receive one fragment decrypted from one TLS record.
> +
> + @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
> + @param[in, out] Fragment The received Fragment.
> + @param[in] Timeout The time to wait for connection done.
> +
> + @retval EFI_SUCCESS One fragment is received.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_ABORTED Something wrong decryption the message.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +HttpsReceive (
> + IN HTTP_PROTOCOL *HttpInstance,
> + IN OUT NET_FRAGMENT *Fragment,
> + IN EFI_EVENT Timeout
> + )
> +{
> + EFI_STATUS Status;
> + NET_BUF *Pdu;
> + TLS_RECORD_HEADER RecordHeader;
> + UINT8 *BufferIn;
> + UINTN BufferInSize;
> + NET_FRAGMENT TempFragment;
> + UINT8 *BufferOut;
> + UINTN BufferOutSize;
> + NET_BUF *PacketOut;
> + UINT8 *DataOut;
> + UINT8 *GetSessionDataBuffer;
> + UINTN GetSessionDataBufferSize;
> +
> + Status = EFI_SUCCESS;
> + Pdu = NULL;
> + BufferIn = NULL;
> + BufferInSize = 0;
> + BufferOut = NULL;
> + BufferOutSize = 0;
> + PacketOut = NULL;
> + DataOut = NULL;
> + GetSessionDataBuffer = NULL;
> + GetSessionDataBufferSize = 0;
> +
> + //
> + // Receive only one TLS record
> + //
> + Status = TlsReceiveOnePdu (HttpInstance, &Pdu, Timeout);
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + BufferInSize = Pdu->TotalSize;
> + BufferIn = AllocateZeroPool (BufferInSize);
> + if (BufferIn == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + NetbufFree (Pdu);
> + return Status;
> + }
> +
> + NetbufCopy (Pdu, 0, (UINT32) BufferInSize, BufferIn);
> +
> + NetbufFree (Pdu);
> +
> + //
> + // Handle Receive data.
> + //
> + RecordHeader = *(TLS_RECORD_HEADER *) BufferIn;
> +
> + if ((RecordHeader.ContentType ==
> TLS_CONTENT_TYPE_APPLICATION_DATA) &&
> + (RecordHeader.Version.Major == 0x03) &&
> + (RecordHeader.Version.Minor == TLS10_PROTOCOL_VERSION_MINOR ||
> + RecordHeader.Version.Minor == TLS11_PROTOCOL_VERSION_MINOR ||
> + RecordHeader.Version.Minor == TLS12_PROTOCOL_VERSION_MINOR)
> + ) {
> + //
> + // Decrypt Packet.
> + //
> + Status = TlsProcessMessage (
> + HttpInstance,
> + BufferIn,
> + BufferInSize,
> + EfiTlsDecrypt,
> + &TempFragment
> + );
> +
> + FreePool (BufferIn);
> +
> + if (EFI_ERROR (Status)) {
> + if (Status == EFI_ABORTED) {
> + //
> + // Something wrong decryption the message.
> + // BuildResponsePacket() will be called to generate Error Alert message
> and send it out.
> + //
> + BufferOutSize = DEF_BUF_LEN;
> + BufferOut = AllocateZeroPool (BufferOutSize);
> + if (BufferOut == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->BuildResponsePacket (
> + HttpInstance->Tls,
> + NULL,
> + 0,
> + BufferOut,
> + &BufferOutSize
> + );
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + FreePool (BufferOut);
> + BufferOut = AllocateZeroPool (BufferOutSize);
> + if (BufferOut == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->BuildResponsePacket (
> + HttpInstance->Tls,
> + NULL,
> + 0,
> + BufferOut,
> + &BufferOutSize
> + );
> + }
> + if (EFI_ERROR (Status)) {
> + FreePool(BufferOut);
> + return Status;
> + }
> +
> + if (BufferOutSize != 0) {
> + PacketOut = NetbufAlloc ((UINT32)BufferOutSize);
> + DataOut = NetbufAllocSpace (PacketOut, (UINT32) BufferOutSize,
> NET_BUF_TAIL);
> + CopyMem (DataOut, BufferOut, BufferOutSize);
> +
> + Status = TlsCommonTransmit (HttpInstance, PacketOut);
> +
> + NetbufFree (PacketOut);
> + }
> +
> + FreePool(BufferOut);
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + return EFI_ABORTED;
> + }
> +
> + return Status;
> + }
> +
> + //
> + // Parsing buffer.
> + //
> + ASSERT (((TLS_RECORD_HEADER *) (TempFragment.Bulk))->ContentType
> == TLS_CONTENT_TYPE_APPLICATION_DATA);
> +
> + BufferInSize = ((TLS_RECORD_HEADER *) (TempFragment.Bulk))->Length;
> + BufferIn = AllocateZeroPool (BufferInSize);
> + if (BufferIn == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + CopyMem (BufferIn, TempFragment.Bulk + sizeof
> (TLS_RECORD_HEADER), BufferInSize);
> +
> + //
> + // Free the buffer in TempFragment.
> + //
> + FreePool (TempFragment.Bulk);
> +
> + } else if ((RecordHeader.ContentType == TLS_CONTENT_TYPE_ALERT) &&
> + (RecordHeader.Version.Major == 0x03) &&
> + (RecordHeader.Version.Minor == TLS10_PROTOCOL_VERSION_MINOR ||
> + RecordHeader.Version.Minor == TLS11_PROTOCOL_VERSION_MINOR ||
> + RecordHeader.Version.Minor == TLS12_PROTOCOL_VERSION_MINOR)
> + ) {
> + BufferOutSize = DEF_BUF_LEN;
> + BufferOut = AllocateZeroPool (BufferOutSize);
> + if (BufferOut == NULL) {
> + FreePool (BufferIn);
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->BuildResponsePacket (
> + HttpInstance->Tls,
> + BufferIn,
> + BufferInSize,
> + BufferOut,
> + &BufferOutSize
> + );
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + FreePool (BufferOut);
> + BufferOut = AllocateZeroPool (BufferOutSize);
> + if (BufferOut == NULL) {
> + FreePool (BufferIn);
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->BuildResponsePacket (
> + HttpInstance->Tls,
> + BufferIn,
> + BufferInSize,
> + BufferOut,
> + &BufferOutSize
> + );
> + }
> +
> + FreePool (BufferIn);
> +
> + if (EFI_ERROR (Status)) {
> + FreePool (BufferOut);
> + return Status;
> + }
> +
> + if (BufferOutSize != 0) {
> + PacketOut = NetbufAlloc ((UINT32) BufferOutSize);
> + DataOut = NetbufAllocSpace (PacketOut, (UINT32) BufferOutSize,
> NET_BUF_TAIL);
> + CopyMem (DataOut, BufferOut, BufferOutSize);
> +
> + Status = TlsCommonTransmit (HttpInstance, PacketOut);
> +
> + NetbufFree (PacketOut);
> + }
> +
> + FreePool (BufferOut);
> +
> + //
> + // Get the session state.
> + //
> + GetSessionDataBufferSize = DEF_BUF_LEN;
> + GetSessionDataBuffer = AllocateZeroPool (GetSessionDataBufferSize);
> + if (GetSessionDataBuffer == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->GetSessionData (
> + HttpInstance->Tls,
> + EfiTlsSessionState,
> + GetSessionDataBuffer,
> + &GetSessionDataBufferSize
> + );
> + if (Status == EFI_BUFFER_TOO_SMALL) {
> + FreePool (GetSessionDataBuffer);
> + GetSessionDataBuffer = AllocateZeroPool (GetSessionDataBufferSize);
> + if (GetSessionDataBuffer == NULL) {
> + Status = EFI_OUT_OF_RESOURCES;
> + return Status;
> + }
> +
> + Status = HttpInstance->Tls->GetSessionData (
> + HttpInstance->Tls,
> + EfiTlsSessionState,
> + GetSessionDataBuffer,
> + &GetSessionDataBufferSize
> + );
> + }
> + if (EFI_ERROR (Status)) {
> + FreePool (GetSessionDataBuffer);
> + return Status;
> + }
> +
> + ASSERT(GetSessionDataBufferSize == sizeof (EFI_TLS_SESSION_STATE));
> + HttpInstance->TlsSessionState = *(EFI_TLS_SESSION_STATE *)
> GetSessionDataBuffer;
> +
> + FreePool (GetSessionDataBuffer);
> +
> + if(HttpInstance->TlsSessionState == EfiTlsSessionError) {
> + DEBUG ((EFI_D_ERROR, "TLS Session State Error!\n"));
> + return EFI_ABORTED;
> + }
> +
> + BufferIn = NULL;
> + BufferInSize = 0;
> + }
> +
> + Fragment->Bulk = BufferIn;
> + Fragment->Len = (UINT32) BufferInSize;
> +
> + return Status;
> +}
> diff --git a/NetworkPkg/HttpDxe/HttpsSupport.h
> b/NetworkPkg/HttpDxe/HttpsSupport.h
> new file mode 100644
> index 0000000..d846b76
> --- /dev/null
> +++ b/NetworkPkg/HttpDxe/HttpsSupport.h
> @@ -0,0 +1,260 @@
> +/** @file
> + The header files of miscellaneous routines specific to Https for HttpDxe
> driver.
> +
> +Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
> +This program and the accompanying materials
> +are licensed and made available under the terms and conditions of the BSD
> License
> +which accompanies this distribution. The full text of the license may be
> found at
> +http://opensource.org/licenses/bsd-license.php
> +
> +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS"
> BASIS,
> +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER
> EXPRESS OR IMPLIED.
> +
> +**/
> +
> +#ifndef __EFI_HTTPS_SUPPORT_H__
> +#define __EFI_HTTPS_SUPPORT_H__
> +
> +#define HTTPS_DEFAULT_PORT 443
> +
> +#define HTTPS_FLAG "https"
> +
> +/**
> + Check whether the Url is from Https.
> +
> + @param[in] Url The pointer to a HTTP or HTTPS URL string.
> +
> + @retval TRUE The Url is from HTTPS.
> + @retval FALSE The Url is from HTTP.
> +
> +**/
> +BOOLEAN
> +IsHttpsUrl (
> + IN CHAR8 *Url
> + );
> +
> +/**
> + Creates a Tls child handle, open EFI_TLS_PROTOCOL and
> EFI_TLS_CONFIGURATION_PROTOCOL.
> +
> + @param[in] ImageHandle The firmware allocated handle for the UEFI
> image.
> + @param[out] TlsProto Pointer to the EFI_TLS_PROTOCOL instance.
> + @param[out] TlsConfiguration Pointer to the
> EFI_TLS_CONFIGURATION_PROTOCOL instance.
> +
> + @return The child handle with opened EFI_TLS_PROTOCOL and
> EFI_TLS_CONFIGURATION_PROTOCOL.
> +
> +**/
> +EFI_HANDLE
> +EFIAPI
> +TlsCreateChild (
> + IN EFI_HANDLE ImageHandle,
> + OUT EFI_TLS_PROTOCOL **TlsProto,
> + OUT EFI_TLS_CONFIGURATION_PROTOCOL **TlsConfiguration
> + );
> +
> +/**
> + Create event for the TLS receive and transmit tokens which are used to
> receive and
> + transmit TLS related messages.
> +
> + @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
> +
> + @retval EFI_SUCCESS The events are created successfully.
> + @retval others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsCreateTxRxEvent (
> + IN OUT HTTP_PROTOCOL *HttpInstance
> + );
> +
> +/**
> + Close events in the TlsTxToken and TlsRxToken.
> +
> + @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
> +
> +**/
> +VOID
> +EFIAPI
> +TlsCloseTxRxEvent (
> + IN HTTP_PROTOCOL *HttpInstance
> + );
> +
> +/**
> + Read the TlsCaCertificate variable and configure it.
> +
> + @param[in, out] HttpInstance The HTTP instance private data.
> +
> + @retval EFI_SUCCESS TlsCaCertificate is configured.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_NOT_FOUND Fail to get "TlsCaCertificate" variable.
> + @retval Others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +TlsConfigCertificate (
> + IN OUT HTTP_PROTOCOL *HttpInstance
> + );
> +
> +/**
> + Configure TLS session data.
> +
> + @param[in, out] HttpInstance The HTTP instance private data.
> +
> + @retval EFI_SUCCESS TLS session data is configured.
> + @retval Others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsConfigureSession (
> + IN OUT HTTP_PROTOCOL *HttpInstance
> + );
> +
> +/**
> + Transmit the Packet by processing the associated HTTPS token.
> +
> + @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
> + @param[in] Packet The packet to transmit.
> +
> + @retval EFI_SUCCESS The packet is transmitted.
> + @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_DEVICE_ERROR An unexpected system or network error
> occurred.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsCommonTransmit (
> + IN OUT HTTP_PROTOCOL *HttpInstance,
> + IN NET_BUF *Packet
> + );
> +
> +/**
> + Receive the Packet by processing the associated HTTPS token.
> +
> + @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
> + @param[in] Packet The packet to transmit.
> + @param[in] Timeout The time to wait for connection done.
> +
> + @retval EFI_SUCCESS The Packet is received.
> + @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_TIMEOUT The operation is time out.
> + @retval Others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsCommonReceive (
> + IN OUT HTTP_PROTOCOL *HttpInstance,
> + IN NET_BUF *Packet,
> + IN EFI_EVENT Timeout
> + );
> +
> +/**
> + Receive one TLS PDU. An TLS PDU contains an TLS record header and it's
> + corresponding record data. The two parts will be put into two blocks of
> buffers in the
> + net buffer.
> +
> + @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure.
> + @param[out] Pdu The received TLS PDU.
> + @param[in] Timeout The time to wait for connection done.
> +
> + @retval EFI_SUCCESS An TLS PDU is received.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_PROTOCOL_ERROR An unexpected TLS packet was received.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsReceiveOnePdu (
> + IN OUT HTTP_PROTOCOL *HttpInstance,
> + OUT NET_BUF **Pdu,
> + IN EFI_EVENT Timeout
> + );
> +
> +/**
> + Connect one TLS session by finishing the TLS handshake process.
> +
> + @param[in] HttpInstance The HTTP instance private data.
> + @param[in] Timeout The time to wait for connection done.
> +
> + @retval EFI_SUCCESS The TLS session is established.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_ABORTED TLS session state is incorrect.
> + @retval Others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsConnectSession (
> + IN HTTP_PROTOCOL *HttpInstance,
> + IN EFI_EVENT Timeout
> + );
> +
> +/**
> + Close the TLS session and send out the close notification message.
> +
> + @param[in] HttpInstance The HTTP instance private data.
> +
> + @retval EFI_SUCCESS The TLS session is closed.
> + @retval EFI_INVALID_PARAMETER HttpInstance is NULL or Packet is NULL.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval Others Other error as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsCloseSession (
> + IN HTTP_PROTOCOL *HttpInstance
> + );
> +
> +/**
> + Process one message according to the CryptMode.
> +
> + @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
> + @param[in] Message Pointer to the message buffer needed to
> processed.
> + @param[in] MessageSize Pointer to the message buffer size.
> + @param[in] ProcessMode Process mode.
> + @param[in, out] Fragment Only one Fragment returned after the
> Message is
> + processed successfully.
> +
> + @retval EFI_SUCCESS Message is processed successfully.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsProcessMessage (
> + IN HTTP_PROTOCOL *HttpInstance,
> + IN UINT8 *Message,
> + IN UINTN MessageSize,
> + IN EFI_TLS_CRYPT_MODE ProcessMode,
> + IN OUT NET_FRAGMENT *Fragment
> + );
> +
> +/**
> + Receive one fragment decrypted from one TLS record.
> +
> + @param[in] HttpInstance Pointer to HTTP_PROTOCOL structure.
> + @param[in, out] Fragment The received Fragment.
> + @param[in] Timeout The time to wait for connection done.
> +
> + @retval EFI_SUCCESS One fragment is received.
> + @retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
> + @retval EFI_ABORTED Something wrong decryption the message.
> + @retval Others Other errors as indicated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +HttpsReceive (
> + IN HTTP_PROTOCOL *HttpInstance,
> + IN OUT NET_FRAGMENT *Fragment,
> + IN EFI_EVENT Timeout
> + );
> +
> +#endif
> --
> 1.9.5.msysgit.1
next prev parent reply other threads:[~2016-12-15 7:15 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-12-14 7:34 [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master Jiaxin Wu
2016-12-14 7:34 ` [Patch 01/10] MdePkg: Add TLS related protocol definition Jiaxin Wu
2016-12-14 8:36 ` Long, Qin
2016-12-14 8:39 ` Wu, Jiaxin
2016-12-15 8:34 ` Ye, Ting
2016-12-14 8:43 ` Fu, Siyuan
2016-12-14 7:34 ` [Patch 02/10] MdePkg: Add a header to standardize TLS definitions Jiaxin Wu
2016-12-14 8:42 ` Long, Qin
2016-12-14 8:43 ` Fu, Siyuan
2016-12-15 8:35 ` Ye, Ting
2016-12-14 7:34 ` [Patch 03/10] CryptoPkg: Enable ssl build in OpensslLib directly Jiaxin Wu
2016-12-15 8:37 ` Ye, Ting
2016-12-14 7:34 ` [Patch 04/10] CryptoPkg: Add new TlsLib library Jiaxin Wu
2016-12-16 2:10 ` Ye, Ting
2016-12-16 2:51 ` Wu, Jiaxin
2016-12-14 7:34 ` [Patch 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL Jiaxin Wu
2016-12-14 8:41 ` Fu, Siyuan
2016-12-15 7:24 ` Wu, Jiaxin
2016-12-14 7:34 ` [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration Jiaxin Wu
2016-12-15 2:22 ` Fu, Siyuan
2016-12-22 2:52 ` Ye, Ting
2016-12-22 3:13 ` Wu, Jiaxin
2016-12-14 7:34 ` [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6 Jiaxin Wu
2016-12-15 2:39 ` Fu, Siyuan
2016-12-15 7:14 ` Wu, Jiaxin [this message]
2016-12-22 7:33 ` Ye, Ting
2016-12-22 8:30 ` Wu, Jiaxin
2016-12-14 7:34 ` [Patch 08/10] NetworkPkg/NetworkPkg.dsc: Enable TlsDxe and TlsAuthConfigDxe module Jiaxin Wu
2016-12-15 2:39 ` Fu, Siyuan
2016-12-22 7:37 ` Ye, Ting
2016-12-14 7:34 ` [Patch 09/10] Nt32Pkg/Nt32Pkg.dsc: Remove the flag for OpensslLib and BaseCryptLib Jiaxin Wu
2016-12-14 7:56 ` Ni, Ruiyu
2016-12-15 8:25 ` Long, Qin
2016-12-22 7:39 ` Ye, Ting
2016-12-14 7:34 ` [Patch 10/10] Nt32Pkg: Enable HTTPS boot feature for Nt32 platform Jiaxin Wu
2016-12-14 7:44 ` Yao, Jiewen
2016-12-14 7:46 ` Wu, Jiaxin
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=895558F6EA4E3B41AC93A00D163B72741627F514@SHSMSX103.ccr.corp.intel.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