public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Fu, Siyuan" <siyuan.fu@intel.com>
To: "Wu, Jiaxin" <jiaxin.wu@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 02:39:29 +0000	[thread overview]
Message-ID: <B1FF2E9001CE9041BD10B825821D5BC58A88641B@SHSMSX151.ccr.corp.intel.com> (raw)
In-Reply-To: <1481700859-76060-8-git-send-email-jiaxin.wu@intel.com>

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


  reply	other threads:[~2016-12-15  2:39 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 [this message]
2016-12-15  7:14     ` Wu, Jiaxin
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=B1FF2E9001CE9041BD10B825821D5BC58A88641B@SHSMSX151.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