public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master
@ 2016-12-14  7:34 Jiaxin Wu
  2016-12-14  7:34 ` [Patch 01/10] MdePkg: Add TLS related protocol definition Jiaxin Wu
                   ` (9 more replies)
  0 siblings, 10 replies; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Long Qin, Ye Ting, Fu Siyuan, Zhang Lubo, Liming Gao, Ni Ruiyu,
	Michael D Kinney, Zimmer Vincent, Li Ruth, Thomas Palmer,
	Wu Jiaxin

The series patches are used to sync the edk2-staging/HTTPS-TLS 
feature into edk2 master. Detailed feature description can be 
found @ https://github.com/tianocore/edk2-staging/tree/HTTPS-TLS, 
including feature timeline, support scope and verifications.

Cc: Long Qin <qin.long@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Ni Ruiyu <ruiyu.ni@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Cc: Zimmer Vincent <vincent.zimmer@intel.com>
Cc: Li Ruth <ruth.li@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>

Jiaxin Wu (10):
  MdePkg: Add TLS related protocol definition
  MdePkg: Add a header to standardize TLS definitions
  CryptoPkg: Enable ssl build in OpensslLib directly
  CryptoPkg: Add new TlsLib library
  NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL
  NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration
  NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6
  NetworkPkg/NetworkPkg.dsc: Enable TlsDxe and TlsAuthConfigDxe module
  Nt32Pkg/Nt32Pkg.dsc: Remove the flag for OpensslLib and BaseCryptLib
  Nt32Pkg: Enable HTTPS boot feature for Nt32 platform

 CryptoPkg/CryptoPkg.dec                            |    4 +
 CryptoPkg/CryptoPkg.dsc                            |    1 +
 CryptoPkg/Include/Library/TlsLib.h                 |  785 +++++++++
 CryptoPkg/Include/OpenSslSupport.h                 |   11 +-
 .../Library/BaseCryptLib/SysCall/CrtWrapper.c      |   10 +
 CryptoPkg/Library/OpensslLib/Install.cmd           |    1 +
 CryptoPkg/Library/OpensslLib/Install.sh            |    1 +
 CryptoPkg/Library/OpensslLib/OpensslLib.inf        |   52 +-
 CryptoPkg/Library/OpensslLib/process_files.sh      |    7 +-
 CryptoPkg/Library/TlsLib/InternalTlsLib.h          |   35 +
 CryptoPkg/Library/TlsLib/TlsConfig.c               | 1055 +++++++++++
 CryptoPkg/Library/TlsLib/TlsInit.c                 |  291 ++++
 CryptoPkg/Library/TlsLib/TlsLib.inf                |   49 +
 CryptoPkg/Library/TlsLib/TlsLib.uni                |   19 +
 CryptoPkg/Library/TlsLib/TlsProcess.c              |  461 +++++
 MdePkg/Include/IndustryStandard/Tls1.h             |   93 +
 MdePkg/Include/Protocol/Tls.h                      |  460 +++++
 MdePkg/Include/Protocol/TlsConfig.h                |  132 ++
 MdePkg/MdePkg.dec                                  |    9 +
 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 +++
 NetworkPkg/Include/Guid/TlsAuthConfigHii.h         |   25 +
 NetworkPkg/Include/Guid/TlsAuthentication.h        |   29 +
 NetworkPkg/NetworkPkg.dec                          |    7 +
 NetworkPkg/NetworkPkg.dsc                          |    4 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c     |  135 ++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf   |   73 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni   |   21 +
 .../TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni     |   19 +
 .../TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni   |   39 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c    | 1841 ++++++++++++++++++++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h    |  282 +++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h  |   49 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr   |  152 ++
 NetworkPkg/TlsDxe/TlsConfigProtocol.c              |  152 ++
 NetworkPkg/TlsDxe/TlsDriver.c                      |  498 ++++++
 NetworkPkg/TlsDxe/TlsDriver.h                      |  237 +++
 NetworkPkg/TlsDxe/TlsDxe.inf                       |   65 +
 NetworkPkg/TlsDxe/TlsDxe.uni                       |   25 +
 NetworkPkg/TlsDxe/TlsDxeExtra.uni                  |   18 +
 NetworkPkg/TlsDxe/TlsImpl.c                        |  270 +++
 NetworkPkg/TlsDxe/TlsImpl.h                        |  315 ++++
 NetworkPkg/TlsDxe/TlsProtocol.c                    |  632 +++++++
 Nt32Pkg/Nt32Pkg.dsc                                |   25 +-
 Nt32Pkg/Nt32Pkg.fdf                                |    4 +
 50 files changed, 10978 insertions(+), 170 deletions(-)
 create mode 100644 CryptoPkg/Include/Library/TlsLib.h
 create mode 100644 CryptoPkg/Library/TlsLib/InternalTlsLib.h
 create mode 100644 CryptoPkg/Library/TlsLib/TlsConfig.c
 create mode 100644 CryptoPkg/Library/TlsLib/TlsInit.c
 create mode 100644 CryptoPkg/Library/TlsLib/TlsLib.inf
 create mode 100644 CryptoPkg/Library/TlsLib/TlsLib.uni
 create mode 100644 CryptoPkg/Library/TlsLib/TlsProcess.c
 create mode 100644 MdePkg/Include/IndustryStandard/Tls1.h
 create mode 100644 MdePkg/Include/Protocol/Tls.h
 create mode 100644 MdePkg/Include/Protocol/TlsConfig.h
 create mode 100644 NetworkPkg/HttpDxe/HttpsSupport.c
 create mode 100644 NetworkPkg/HttpDxe/HttpsSupport.h
 create mode 100644 NetworkPkg/Include/Guid/TlsAuthConfigHii.h
 create mode 100644 NetworkPkg/Include/Guid/TlsAuthentication.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
 create mode 100644 NetworkPkg/TlsDxe/TlsConfigProtocol.c
 create mode 100644 NetworkPkg/TlsDxe/TlsDriver.c
 create mode 100644 NetworkPkg/TlsDxe/TlsDriver.h
 create mode 100644 NetworkPkg/TlsDxe/TlsDxe.inf
 create mode 100644 NetworkPkg/TlsDxe/TlsDxe.uni
 create mode 100644 NetworkPkg/TlsDxe/TlsDxeExtra.uni
 create mode 100644 NetworkPkg/TlsDxe/TlsImpl.c
 create mode 100644 NetworkPkg/TlsDxe/TlsImpl.h
 create mode 100644 NetworkPkg/TlsDxe/TlsProtocol.c

-- 
1.9.5.msysgit.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* [Patch 01/10] MdePkg: Add TLS related protocol definition
  2016-12-14  7:34 [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master Jiaxin Wu
@ 2016-12-14  7:34 ` Jiaxin Wu
  2016-12-14  8:36   ` Long, Qin
  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
                   ` (8 subsequent siblings)
  9 siblings, 2 replies; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Long Qin, Ye Ting, Fu Siyuan, Zhang Lubo, Liming Gao,
	Michael D Kinney, Thomas Palmer, Wu Jiaxin

This patch is used to add Tls.h and TlsConfig.h header
files to define EFI TLS Configuration Protocol,
EFI TLS Service Binding Protocol and
EFI TLS Configuration Protocol.

Cc: Long Qin <qin.long@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@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>
---
 MdePkg/Include/Protocol/Tls.h       | 460 ++++++++++++++++++++++++++++++++++++
 MdePkg/Include/Protocol/TlsConfig.h | 132 +++++++++++
 MdePkg/MdePkg.dec                   |   9 +
 3 files changed, 601 insertions(+)
 create mode 100644 MdePkg/Include/Protocol/Tls.h
 create mode 100644 MdePkg/Include/Protocol/TlsConfig.h

diff --git a/MdePkg/Include/Protocol/Tls.h b/MdePkg/Include/Protocol/Tls.h
new file mode 100644
index 0000000..51a3cda
--- /dev/null
+++ b/MdePkg/Include/Protocol/Tls.h
@@ -0,0 +1,460 @@
+/** @file
+  EFI TLS Protocols as defined in UEFI 2.5.
+
+  The EFI TLS Service Binding Protocol is used to locate EFI TLS Protocol drivers
+  to create and destroy child of the driver to communicate with other host using
+  TLS protocol.
+  The EFI TLS Protocol provides the ability to manage TLS session.
+
+  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.
+
+  @par Revision Reference:
+  This Protocol is introduced in UEFI Specification 2.5
+
+**/
+
+#ifndef __EFI_TLS_PROTOCOL_H__
+#define __EFI_TLS_PROTOCOL_H__
+
+///
+/// The EFI TLS Service Binding Protocol is used to locate EFI TLS Protocol drivers to
+/// create and destroy child of the driver to communicate with other host using TLS
+/// protocol.
+///
+#define EFI_TLS_SERVICE_BINDING_PROTOCOL_GUID \
+  { \
+    0x952cb795, 0xff36, 0x48cf, {0xa2, 0x49, 0x4d, 0xf4, 0x86, 0xd6, 0xab, 0x8d } \
+  }
+
+///
+/// The EFI TLS protocol provides the ability to manage TLS session.
+///
+#define EFI_TLS_PROTOCOL_GUID \
+  { \
+    0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc, 0xe4, 0x6c, 0x47, 0x51, 0x43, 0x90 } \
+  }
+
+typedef struct _EFI_TLS_PROTOCOL EFI_TLS_PROTOCOL;
+
+///
+/// EFI_TLS_SESSION_DATA_TYPE
+///
+typedef enum {
+  ///
+  /// Session Configuration
+  ///
+
+  ///
+  /// TLS session Version. The corresponding Data is of type EFI_TLS_VERSION.
+  ///
+  EfiTlsVersion,
+  ///
+  /// TLS session as client or as server. The corresponding Data is of
+  /// EFI_TLS_CONNECTION_END.
+  ///
+  EfiTlsConnectionEnd,
+  ///
+  /// A priority list of preferred algorithms for the TLS session.
+  /// The corresponding Data is a list of EFI_TLS_CIPHER.
+  ///
+  EfiTlsCipherList,
+  ///
+  /// TLS session compression method.
+  /// The corresponding Data is of type EFI_TLS_COMPRESSION.
+  ///
+  EfiTlsCompressionMethod,
+  ///
+  /// TLS session extension data.
+  /// The corresponding Data is a list of type EFI_TLS_EXTENDION.
+  ///
+  EfiTlsExtensionData,
+  ///
+  /// TLS session verify method.
+  /// The corresponding Data is of type EFI_TLS_VERIFY.
+  ///
+  EfiTlsVerifyMethod,
+  ///
+  /// TLS session data session ID.
+  /// For SetSessionData(), it is TLS session ID used for session resumption.
+  /// For GetSessionData(), it is the TLS session ID used for current session.
+  /// The corresponding Data is of type EFI_TLS_SESSION_ID.
+  ///
+  EfiTlsSessionID,
+  ///
+  /// TLS session data session state.
+  /// The corresponding Data is of type EFI_TLS_SESSION_STATE.
+  ///
+  EfiTlsSessionState,
+
+  ///
+  /// Session information
+  ///
+
+  ///
+  /// TLS session data client random.
+  /// The corresponding Data is of type EFI_TLS_RANDOM.
+  ///
+  EfiTlsClientRandom,
+  ///
+  /// TLS session data server random.
+  /// The corresponding Data is of type EFI_TLS_RANDOM.
+  ///
+  EfiTlsServerRandom,
+  ///
+  /// TLS session data key material.
+  /// The corresponding Data is of type EFI_TLS_MASTER_SECRET.
+  ///
+  EfiTlsKeyMaterial,
+
+  EfiTlsSessionDataTypeMaximum
+
+} EFI_TLS_SESSION_DATA_TYPE;
+
+///
+/// EFI_TLS_VERSION
+/// Note: The TLS version definition is from SSL3.0 to the latest TLS (e.g. 1.2).
+///       SSL2.0 is obsolete and should not be used.
+///
+typedef struct {
+  UINT8                         Major;
+  UINT8                         Minor;
+} EFI_TLS_VERSION;
+
+///
+/// EFI_TLS_CONNECTION_END to define TLS session as client or server.
+///
+typedef enum {
+  EfiTlsClient,
+  EfiTlsServer,
+} EFI_TLS_CONNECTION_END;
+
+///
+/// EFI_TLS_CIPHER
+/// Note: The definition of EFI_TLS_CIPHER definition is from "RFC 5246, A.4.1.
+///       Hello Messages". The value of EFI_TLS_CIPHER is from TLS Cipher
+///       Suite Registry of IANA.
+///
+typedef struct {
+  UINT8                         Data1;
+  UINT8                         Data2;
+} EFI_TLS_CIPHER;
+
+///
+/// EFI_TLS_COMPRESSION
+/// Note: The value of EFI_TLS_COMPRESSION definition is from "RFC 3749".
+///
+typedef UINT8 EFI_TLS_COMPRESSION;
+
+///
+/// EFI_TLS_EXTENSION
+/// Note: The definition of EFI_TLS_EXTENSION if from "RFC 5246 A.4.1.
+///       Hello Messages".
+///
+typedef struct {
+  UINT16                        ExtensionType;
+  UINT16                        Length;
+  UINT8                         Data[1];
+} EFI_TLS_EXTENSION;
+
+///
+/// EFI_TLS_VERIFY
+/// Use either EFI_TLS_VERIFY_NONE or EFI_TLS_VERIFY_PEER, the last two options
+/// are 'ORed' with EFI_TLS_VERIFY_PEER if they are desired.
+///
+typedef UINT32  EFI_TLS_VERIFY;
+///
+/// No certificates will be sent or the TLS/SSLhandshake will be continued regardless
+/// of the certificate verification result.
+///
+#define EFI_TLS_VERIFY_NONE                  0x0
+///
+/// The TLS/SSL handshake is immediately terminated with an alert message containing
+/// the reason for the certificate verification failure.
+///
+#define EFI_TLS_VERIFY_PEER                  0x1
+///
+/// TLS session will fail peer certificate is absent.
+///
+#define EFI_TLS_VERIFY_FAIL_IF_NO_PEER_CERT  0x2
+///
+/// TLS session only verify client once, and doesn't request cerfificate during
+/// re-negotiation.
+///
+#define EFI_TLS_VERIFY_CLIENT_ONCE           0x4
+
+///
+/// EFI_TLS_RANDOM
+/// Note: The definition of EFI_TLS_RANDOM is from "RFC 5246 A.4.1.
+///       Hello Messages".
+///
+typedef struct {
+  UINT32                        GmtUnixTime;
+  UINT8                         RandomBytes[28];
+} EFI_TLS_RANDOM;
+
+///
+/// EFI_TLS_MASTER_SECRET
+/// Note: The definition of EFI_TLS_MASTER_SECRET is from "RFC 5246 8.1.
+///       Computing the Master Secret".
+///
+typedef struct {
+  UINT8                         Data[48];
+} EFI_TLS_MASTER_SECRET;
+
+///
+/// EFI_TLS_SESSION_ID
+/// Note: The definition of EFI_TLS_SESSION_ID is from "RFC 5246 A.4.1. Hello Messages".
+///
+#define MAX_TLS_SESSION_ID_LENGTH  32
+typedef struct {
+  UINT16                        Length;
+  UINT8                         Data[MAX_TLS_SESSION_ID_LENGTH];
+} EFI_TLS_SESSION_ID;
+
+///
+/// EFI_TLS_SESSION_STATE
+///
+typedef enum {
+  ///
+  /// When a new child of TLS protocol is created, the initial state of TLS session
+  /// is EfiTlsSessionNotStarted.
+  ///
+  EfiTlsSessionNotStarted,
+  ///
+  /// The consumer can call BuildResponsePacket() with NULL to get ClientHello to
+  /// start the TLS session. Then the status is EfiTlsSessionHandShaking.
+  ///
+  EfiTlsSessionHandShaking,
+  ///
+  /// During handshake, the consumer need call BuildResponsePacket() with input
+  /// data from peer, then get response packet and send to peer. After handshake
+  /// finish, the TLS session status becomes EfiTlsSessionDataTransferring, and
+  /// consumer can use ProcessPacket() for data transferring.
+  ///
+  EfiTlsSessionDataTransferring,
+  ///
+  /// Finally, if consumer wants to active close TLS session, consumer need
+  /// call SetSessionData to set TLS session state to EfiTlsSessionClosing, and
+  /// call BuildResponsePacket() with NULL to get CloseNotify alert message,
+  /// and sent it out.
+  ///
+  EfiTlsSessionClosing,
+  ///
+  /// If any error happen during parsing ApplicationData content type, EFI_ABORT
+  /// will be returned by ProcessPacket(), and TLS session state will become
+  /// EfiTlsSessionError. Then consumer need call BuildResponsePacket() with
+  /// NULL to get alert message and sent it out.
+  ///
+  EfiTlsSessionError,
+
+  EfiTlsSessionStateMaximum
+
+} EFI_TLS_SESSION_STATE;
+
+///
+/// EFI_TLS_FRAGMENT_DATA
+///
+typedef struct {
+  ///
+  /// Length of data buffer in the fragment.
+  ///
+  UINT32                        FragmentLength;
+  ///
+  /// Pointer to the data buffer in the fragment.
+  ///
+  VOID                          *FragmentBuffer;
+} EFI_TLS_FRAGMENT_DATA;
+
+///
+/// EFI_TLS_CRYPT_MODE
+///
+typedef enum {
+  ///
+  /// Encrypt data provided in the fragment buffers.
+  ///
+  EfiTlsEncrypt,
+  ///
+  /// Decrypt data provided in the fragment buffers.
+  ///
+  EfiTlsDecrypt,
+} EFI_TLS_CRYPT_MODE;
+
+/**
+  Set TLS session data.
+
+  The SetSessionData() function set data for a new TLS session. All session data should
+  be set before BuildResponsePacket() invoked.
+
+  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]  DataType            TLS session data type.
+  @param[in]  Data                Pointer to session data.
+  @param[in]  DataSize            Total size of session data.
+
+  @retval EFI_SUCCESS             The TLS session data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
+                                  EfiTlsClientRandom
+                                  EfiTlsServerRandom
+                                  EfiTlsKeyMaterial
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionStateNotStarted.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_SET_SESSION_DATA) (
+  IN EFI_TLS_PROTOCOL                *This,
+  IN EFI_TLS_SESSION_DATA_TYPE       DataType,
+  IN VOID                            *Data,
+  IN UINTN                           DataSize
+  );
+
+/**
+  Get TLS session data.
+
+  The GetSessionData() function return the TLS session information.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       DataType       TLS session data type.
+  @param[in, out]  Data           Pointer to session data.
+  @param[in, out]  DataSize       Total size of session data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS session data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS session data is not found.
+  @retval EFI_NOT_READY           The DataType is not ready in current session state.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_GET_SESSION_DATA) (
+  IN EFI_TLS_PROTOCOL                *This,
+  IN EFI_TLS_SESSION_DATA_TYPE       DataType,
+  IN OUT VOID                        *Data,  OPTIONAL
+  IN OUT UINTN                       *DataSize
+  );
+
+/**
+  Build response packet according to TLS state machine. This function is only valid for
+  alert, handshake and change_cipher_spec content type.
+
+  The BuildResponsePacket() function builds TLS response packet in response to the TLS
+  request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and
+  RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session
+  will be initiated and the response packet needs to be ClientHello. If RequestBuffer is
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS
+  session will be closed and response packet needs to be CloseNotify. If RequestBuffer is
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS
+  session has errors and the response packet needs to be Alert message based on error
+  type.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       RequestBuffer  Pointer to the most recently received TLS packet. NULL
+                                  means TLS need initiate the TLS session and response
+                                  packet need to be ClientHello.
+  @param[in]       RequestSize    Packet size in bytes for the most recently received TLS
+                                  packet. 0 is only valid when RequestBuffer is NULL.
+  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  RequestBuffer is NULL but RequestSize is NOT 0.
+                                  RequestSize is 0 but RequestBuffer is NOT NULL.
+                                  BufferSize is NULL.
+                                  Buffer is NULL if *BufferSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.
+  @retval EFI_NOT_READY           Current TLS session state is NOT ready to build
+                                  ResponsePacket.
+  @retval EFI_ABORTED             Something wrong build response packet.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_BUILD_RESPONSE_PACKET) (
+  IN EFI_TLS_PROTOCOL                *This,
+  IN UINT8                           *RequestBuffer, OPTIONAL
+  IN UINTN                           RequestSize, OPTIONAL
+  OUT UINT8                          *Buffer, OPTIONAL
+  IN OUT UINTN                       *BufferSize
+  );
+
+/**
+  Decrypt or encrypt TLS packet during session. This function is only valid after
+  session connected and for application_data content type.
+
+  The ProcessPacket () function process each inbound or outbound TLS APP packet.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment. The caller will take
+                                  responsible to handle the original FragmentTable while
+                                  it may be reallocated in TLS driver. If CryptMode is
+                                  EfiTlsEncrypt, on input these fragments contain the TLS
+                                  header and plain text TLS APP payload; on output these
+                                  fragments contain the TLS header and cypher text TLS
+                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
+                                  these fragments contain the TLS header and cypher text
+                                  TLS APP payload; on output these fragments contain the
+                                  TLS header and plain text TLS APP payload.
+  @param[in]       FragmentCount  Number of fragment.
+  @param[in]       CryptMode      Crypt mode.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  FragmentTable is NULL.
+                                  FragmentCount is NULL.
+                                  CryptoMode is invalid.
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionDataTransferring.
+  @retval EFI_ABORTED             Something wrong decryption the message. TLS session
+                                  status will become EfiTlsSessionError. The caller need
+                                  call BuildResponsePacket() to generate Error Alert
+                                  message and send it out.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the operation.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_PROCESS_PACKET) (
+  IN EFI_TLS_PROTOCOL                *This,
+  IN OUT EFI_TLS_FRAGMENT_DATA       **FragmentTable,
+  IN UINT32                          *FragmentCount,
+  IN EFI_TLS_CRYPT_MODE              CryptMode
+  );
+
+///
+/// The EFI_TLS_PROTOCOL is used to create, destroy and manage TLS session.
+/// For detail of TLS, please refer to TLS related RFC.
+///
+struct _EFI_TLS_PROTOCOL {
+  EFI_TLS_SET_SESSION_DATA           SetSessionData;
+  EFI_TLS_GET_SESSION_DATA           GetSessionData;
+  EFI_TLS_BUILD_RESPONSE_PACKET      BuildResponsePacket;
+  EFI_TLS_PROCESS_PACKET             ProcessPacket;
+};
+
+extern EFI_GUID gEfiTlsServiceBindingProtocolGuid;
+extern EFI_GUID gEfiTlsProtocolGuid;
+
+#endif  // __EFI_TLS_PROTOCOL_H__
diff --git a/MdePkg/Include/Protocol/TlsConfig.h b/MdePkg/Include/Protocol/TlsConfig.h
new file mode 100644
index 0000000..4b62bf5
--- /dev/null
+++ b/MdePkg/Include/Protocol/TlsConfig.h
@@ -0,0 +1,132 @@
+/** @file
+  EFI TLS Configuration Protocol as defined in UEFI 2.5.
+  The EFI TLS Configuration Protocol provides a way to set and get TLS configuration.
+
+  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.
+
+  @par Revision Reference:
+  This Protocol is introduced in UEFI Specification 2.5
+
+**/
+#ifndef __EFI_TLS_CONFIGURATION_PROTOCOL_H__
+#define __EFI_TLS_CONFIGURATION_PROTOCOL_H__
+
+///
+/// The EFI Configuration protocol provides a way to set and get TLS configuration.
+///
+#define EFI_TLS_CONFIGURATION_PROTOCOL_GUID  \
+  { \
+    0x1682fe44, 0xbd7a, 0x4407, { 0xb7, 0xc7, 0xdc, 0xa3, 0x7c, 0xa3, 0x92, 0x2d }  \
+  }
+
+typedef struct _EFI_TLS_CONFIGURATION_PROTOCOL EFI_TLS_CONFIGURATION_PROTOCOL;
+
+///
+/// EFI_TLS_CONFIG_DATA_TYPE
+///
+typedef enum {
+  ///
+  /// Local host configuration data: public certificate data.
+  /// This data should be DER-encoded binaryX.509 certificate 
+  /// or PEMencoded X.509 certificate.
+  ///
+  EfiTlsConfigDataTypeHostPublicCert,
+  ///
+  /// Local host configuration data: private key data.
+  ///
+  EfiTlsConfigDataTypeHostPrivateKey,
+  ///
+  /// CA certificate to verify peer. This data should be PEM-encoded 
+  /// RSA or PKCS#8 private key.
+  ///
+  EfiTlsConfigDataTypeCACertificate,
+  ///
+  /// CA-supplied Certificate Revocation List data. This data should
+  /// be DER-encoded CRL data.
+  ///
+  EfiTlsConfigDataTypeCertRevocationList,
+
+  EfiTlsConfigDataTypeMaximum
+
+} EFI_TLS_CONFIG_DATA_TYPE;
+
+/**
+  Set TLS configuration data.
+
+  The SetData() function sets TLS configuration to non-volatile storage or volatile
+  storage.
+
+  @param[in]  This                Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]  DataType            Configuration data type.
+  @param[in]  Data                Pointer to configuration data.
+  @param[in]  DataSize            Total size of configuration data.
+
+  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_CONFIGURATION_SET_DATA)(
+  IN EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN VOID                            *Data,
+  IN UINTN                           DataSize
+  );
+
+/**
+  Get TLS configuration data.
+
+  The GetData() function gets TLS configuration.
+
+  @param[in]       This           Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]       DataType       Configuration data type.
+  @param[in, out]  Data           Pointer to configuration data.
+  @param[in, out]  DataSize       Total size of configuration data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_CONFIGURATION_GET_DATA)(
+  IN EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN OUT VOID                        *Data,  OPTIONAL
+  IN OUT UINTN                       *DataSize
+  );
+
+///
+/// The EFI_TLS_CONFIGURATION_PROTOCOL is designed to provide a way to set and get
+/// TLS configuration, such as Certificate, private key data.
+///
+struct _EFI_TLS_CONFIGURATION_PROTOCOL {
+  EFI_TLS_CONFIGURATION_SET_DATA     SetData;
+  EFI_TLS_CONFIGURATION_GET_DATA     GetData;
+};
+
+extern EFI_GUID gEfiTlsConfigurationProtocolGuid;
+
+#endif  //__EFI_TLS_CONFIGURATION_PROTOCOL_H__
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec
index 3e08bed..f2bdb30 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -1607,10 +1607,19 @@
   gEfiHttpProtocolGuid                 = { 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b }}
 
   ## Include/Protocol/HttpUtilities.h
   gEfiHttpUtilitiesProtocolGuid        = { 0x3e35c163, 0x4074, 0x45dd, {0x43, 0x1e, 0x23, 0x98, 0x9d, 0xd8, 0x6b, 0x32 }}
 
+  ## Include/Protocol/Tls.h
+  gEfiTlsServiceBindingProtocolGuid   = { 0x952cb795, 0xff36, 0x48cf, {0xa2, 0x49, 0x4d, 0xf4, 0x86, 0xd6, 0xab, 0x8d }}
+
+  ## Include/Protocol/Tls.h
+  gEfiTlsProtocolGuid                 = { 0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc, 0xe4, 0x6c, 0x47, 0x51, 0x43, 0x90 }}
+  
+  ## Include/Protocol/TlsConfig.h
+  gEfiTlsConfigurationProtocolGuid    = { 0x1682fe44, 0xbd7a, 0x4407, { 0xb7, 0xc7, 0xdc, 0xa3, 0x7c, 0xa3, 0x92, 0x2d }}
+
   ## Include/Protocol/Rest.h
   gEfiRestProtocolGuid                 =  { 0x0db48a36, 0x4e54, 0xea9c, {0x9b, 0x09, 0x1e, 0xa5, 0xbe, 0x3a, 0x66, 0x0b }}
 
   ## Include/Protocol/Supplicant.h
   gEfiSupplicantServiceBindingProtocolGuid  = { 0x45bcd98e, 0x59ad, 0x4174, { 0x95, 0x46, 0x34, 0x4a, 0x7, 0x48, 0x58, 0x98 }}
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Patch 02/10] MdePkg: Add a header to standardize TLS definitions
  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  7:34 ` Jiaxin Wu
  2016-12-14  8:42   ` Long, Qin
                     ` (2 more replies)
  2016-12-14  7:34 ` [Patch 03/10] CryptoPkg: Enable ssl build in OpensslLib directly Jiaxin Wu
                   ` (7 subsequent siblings)
  9 siblings, 3 replies; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Long Qin, Ye Ting, Fu Siyuan, Zhang Lubo, Liming Gao,
	Michael D Kinney, Thomas Palmer, Wu Jiaxin

This path is used to standardize TLS definitions from related
RFCs. Including TLS Cipher Suites, TLS Version, TLS Content Type
and TLS Record Header, etc.

Cc: Long Qin <qin.long@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@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>
---
 MdePkg/Include/IndustryStandard/Tls1.h | 93 ++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 MdePkg/Include/IndustryStandard/Tls1.h

diff --git a/MdePkg/Include/IndustryStandard/Tls1.h b/MdePkg/Include/IndustryStandard/Tls1.h
new file mode 100644
index 0000000..14eb265
--- /dev/null
+++ b/MdePkg/Include/IndustryStandard/Tls1.h
@@ -0,0 +1,93 @@
+/** @file
+  Transport Layer Security  -- TLS 1.0/1.1/1.2 Standard definitions, from RFC 2246/4346/5246    
+
+  This file contains common TLS 1.0/1.1/1.2 definitions from RFC 2246/4346/5246 
+
+  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 __TLS_1_H__
+#define __TLS_1_H__
+
+#pragma pack(1)
+
+///
+/// TLS Cipher Suite, refers to A.5 of rfc-2246, rfc-4346 and rfc-5246.
+///
+#define TLS_RSA_WITH_NULL_MD5                    {0x00, 0x01}
+#define TLS_RSA_WITH_NULL_SHA                    {0x00, 0x02}
+#define TLS_RSA_WITH_RC4_128_MD5                 {0x00, 0x04}
+#define TLS_RSA_WITH_RC4_128_SHA                 {0x00, 0x05}
+#define TLS_RSA_WITH_IDEA_CBC_SHA                {0x00, 0x07}
+#define TLS_RSA_WITH_DES_CBC_SHA                 {0x00, 0x09}
+#define TLS_RSA_WITH_3DES_EDE_CBC_SHA            {0x00, 0x0A}
+#define TLS_DH_DSS_WITH_DES_CBC_SHA              {0x00, 0x0C}
+#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA         {0x00, 0x0D}
+#define TLS_DH_RSA_WITH_DES_CBC_SHA              {0x00, 0x0F}
+#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA         {0x00, 0x10}
+#define TLS_DHE_DSS_WITH_DES_CBC_SHA             {0x00, 0x12}
+#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA        {0x00, 0x13}
+#define TLS_DHE_RSA_WITH_DES_CBC_SHA             {0x00, 0x15}
+#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA        {0x00, 0x16}
+#define TLS_RSA_WITH_AES_128_CBC_SHA             {0x00, 0x2F}
+#define TLS_DH_DSS_WITH_AES_128_CBC_SHA          {0x00, 0x30}
+#define TLS_DH_RSA_WITH_AES_128_CBC_SHA          {0x00, 0x31}
+#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA         {0x00, 0x32}
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA         {0x00, 0x33}
+#define TLS_RSA_WITH_AES_256_CBC_SHA             {0x00, 0x35}
+#define TLS_DH_DSS_WITH_AES_256_CBC_SHA          {0x00, 0x36}
+#define TLS_DH_RSA_WITH_AES_256_CBC_SHA          {0x00, 0x37}
+#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA         {0x00, 0x38}
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA         {0x00, 0x39}
+#define TLS_RSA_WITH_NULL_SHA256                 {0x00, 0x3B}
+#define TLS_RSA_WITH_AES_128_CBC_SHA256          {0x00, 0x3C}
+#define TLS_RSA_WITH_AES_256_CBC_SHA256          {0x00, 0x3D}
+#define TLS_DH_DSS_WITH_AES_128_CBC_SHA256       {0x00, 0x3E}
+#define TLS_DH_RSA_WITH_AES_128_CBC_SHA256       {0x00, 0x3F}
+#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA256      {0x00, 0x40}
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256      {0x00, 0x67}
+#define TLS_DH_DSS_WITH_AES_256_CBC_SHA256       {0x00, 0x68}
+#define TLS_DH_RSA_WITH_AES_256_CBC_SHA256       {0x00, 0x69}
+#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA256      {0x00, 0x6A}
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256      {0x00, 0x6B}
+
+///
+/// TLS Version, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
+///
+#define TLS10_PROTOCOL_VERSION_MAJOR  0x03
+#define TLS10_PROTOCOL_VERSION_MINOR  0x01
+#define TLS11_PROTOCOL_VERSION_MAJOR  0x03
+#define TLS11_PROTOCOL_VERSION_MINOR  0x02
+#define TLS12_PROTOCOL_VERSION_MAJOR  0x03
+#define TLS12_PROTOCOL_VERSION_MINOR  0x03
+
+///
+/// TLS Content Type, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
+///
+typedef enum {
+  TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20,
+  TLS_CONTENT_TYPE_ALERT              = 21,
+  TLS_CONTENT_TYPE_HANDSHAKE          = 22,
+  TLS_CONTENT_TYPE_APPLICATION_DATA   = 23,
+} TLS_CONTENT_TYPE;
+
+///
+/// TLS Record Header, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
+///
+typedef struct {   
+  UINT8                   ContentType;
+  EFI_TLS_VERSION         Version;
+  UINT16                  Length;
+} TLS_RECORD_HEADER;
+
+#pragma pack()
+
+#endif
+
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Patch 03/10] CryptoPkg: Enable ssl build in OpensslLib directly
  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  7:34 ` [Patch 02/10] MdePkg: Add a header to standardize TLS definitions Jiaxin Wu
@ 2016-12-14  7:34 ` Jiaxin Wu
  2016-12-15  8:37   ` Ye, Ting
  2016-12-14  7:34 ` [Patch 04/10] CryptoPkg: Add new TlsLib library Jiaxin Wu
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Wu Jiaxin, Ye Ting, Long Qin, Fu Siyuan, Zhang Lubo,
	Thomas Palmer

This patch is used to enable ssl build in OpensslLib module
directly.

Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Long Qin <qin.long@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Cc: Thomas Palmer <thomas.palmer@hpe.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Long Qin <qin.long@intel.com>
Reviewed-by: Wu Jiaxin <jiaxin.wu@intel.com>
Tested-by: Wu Jiaxin <jiaxin.wu@intel.com>
---
 CryptoPkg/Include/OpenSslSupport.h                 | 11 ++++-
 .../Library/BaseCryptLib/SysCall/CrtWrapper.c      | 10 +++++
 CryptoPkg/Library/OpensslLib/Install.cmd           |  1 +
 CryptoPkg/Library/OpensslLib/Install.sh            |  1 +
 CryptoPkg/Library/OpensslLib/OpensslLib.inf        | 52 +++++++++++++++++++++-
 CryptoPkg/Library/OpensslLib/process_files.sh      |  7 +--
 6 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/CryptoPkg/Include/OpenSslSupport.h b/CryptoPkg/Include/OpenSslSupport.h
index dad40e4..600578e 100644
--- a/CryptoPkg/Include/OpenSslSupport.h
+++ b/CryptoPkg/Include/OpenSslSupport.h
@@ -1,9 +1,9 @@
 /** @file
   Root include file to support building OpenSSL Crypto Library.
 
-Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 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
 
@@ -116,10 +116,12 @@ typedef UINT32         ino_t;
 typedef UINT32         dev_t;
 typedef UINT16         nlink_t;
 typedef int            pid_t;
 typedef void           *DIR;
 typedef void           __sighandler_t (int);
+typedef UINT8          __uint8_t;
+typedef UINT8          sa_family_t;
 
 //
 // Structures from EFI Application Toolkit required to build Open SSL
 //
 struct tm {
@@ -170,10 +172,16 @@ struct stat {
   UINT32   st_gen;          /* file generation number */
   INT32    st_lspare;
   INT64    st_qspare[2];
 };
 
+struct sockaddr {
+  __uint8_t sa_len;         /* total length */
+  sa_family_t sa_family;    /* address family */
+  char    sa_data[14];      /* actually longer; address value */
+};
+
 //
 // Externs from EFI Application Toolkit required to build Open SSL
 //
 extern int errno;
 
@@ -271,7 +279,8 @@ extern FILE  *stdout;
 #define abort()                           ASSERT (FALSE)
 #define assert(expression)
 #define localtime(timer)                  NULL
 #define gmtime_r(timer,result)            (result = NULL)
 #define atoi(nptr)                        AsciiStrDecimalToUintn(nptr)
+#define gettimeofday(tvp,tz)              do { (tvp)->tv_sec = time(NULL); (tvp)->tv_usec = 0; } while (0)
 
 #endif
diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
index c0ccc0e..a2386bc 100644
--- a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
+++ b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
@@ -382,10 +382,15 @@ FILE *fopen (const char *c, const char *m)
 size_t fread (void *b, size_t c, size_t i, FILE *f)
 {
   return 0;
 }
 
+int fputs (const char *s, FILE *f)
+{
+  return 0;
+}
+
 int fprintf (FILE *f, const char *s, ...)
 {
   return 0;
 }
 
@@ -446,5 +451,10 @@ void syslog (int a, const char *c, ...)
 
 ssize_t write (int f, const void *b, size_t l)
 {
   return 0;
 }
+
+int printf (char const *fmt, ...)
+{
+  return 0;
+}
diff --git a/CryptoPkg/Library/OpensslLib/Install.cmd b/CryptoPkg/Library/OpensslLib/Install.cmd
index 3d86bc7..093414d 100755
--- a/CryptoPkg/Library/OpensslLib/Install.cmd
+++ b/CryptoPkg/Library/OpensslLib/Install.cmd
@@ -6,10 +6,11 @@ copy crypto\crypto.h            include\openssl
 copy crypto\opensslv.h          include\openssl
 copy crypto\opensslconf.h       include\openssl
 copy crypto\ebcdic.h            include\openssl
 copy crypto\symhacks.h          include\openssl
 copy crypto\ossl_typ.h          include\openssl
+copy crypto\o_dir.h             include
 copy crypto\objects\objects.h   include\openssl
 copy crypto\objects\obj_mac.h   include\openssl
 copy crypto\md4\md4.h           include\openssl
 copy crypto\md5\md5.h           include\openssl
 copy crypto\sha\sha.h           include\openssl
diff --git a/CryptoPkg/Library/OpensslLib/Install.sh b/CryptoPkg/Library/OpensslLib/Install.sh
index e6703d1..7bd55f6 100755
--- a/CryptoPkg/Library/OpensslLib/Install.sh
+++ b/CryptoPkg/Library/OpensslLib/Install.sh
@@ -8,10 +8,11 @@ cp crypto/crypto.h            include/openssl
 cp crypto/opensslv.h          include/openssl
 cp crypto/opensslconf.h       include/openssl
 cp crypto/ebcdic.h            include/openssl
 cp crypto/symhacks.h          include/openssl
 cp crypto/ossl_typ.h          include/openssl
+cp crypto/o_dir.h             include
 cp crypto/objects/objects.h   include/openssl
 cp crypto/objects/obj_mac.h   include/openssl
 cp crypto/md4/md4.h           include/openssl
 cp crypto/md5/md5.h           include/openssl
 cp crypto/sha/sha.h           include/openssl
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLib.inf b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
index 8121e83..c14e36d 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLib.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
@@ -468,13 +468,63 @@
   $(OPENSSL_PATH)/crypto/ocsp/ocsp_srv.c
   $(OPENSSL_PATH)/crypto/ocsp/ocsp_prn.c
   $(OPENSSL_PATH)/crypto/ocsp/ocsp_vfy.c
   $(OPENSSL_PATH)/crypto/ocsp/ocsp_err.c
   $(OPENSSL_PATH)/crypto/krb5/krb5_asn.c
+  $(OPENSSL_PATH)/crypto/pqueue/pqueue.c
   $(OPENSSL_PATH)/crypto/cmac/cmac.c
   $(OPENSSL_PATH)/crypto/cmac/cm_ameth.c
   $(OPENSSL_PATH)/crypto/cmac/cm_pmeth.c
+  $(OPENSSL_PATH)/ssl/s2_meth.c
+  $(OPENSSL_PATH)/ssl/s2_srvr.c
+  $(OPENSSL_PATH)/ssl/s2_clnt.c
+  $(OPENSSL_PATH)/ssl/s2_lib.c
+  $(OPENSSL_PATH)/ssl/s2_enc.c
+  $(OPENSSL_PATH)/ssl/s2_pkt.c
+  $(OPENSSL_PATH)/ssl/s3_meth.c
+  $(OPENSSL_PATH)/ssl/s3_srvr.c
+  $(OPENSSL_PATH)/ssl/s3_clnt.c
+  $(OPENSSL_PATH)/ssl/s3_lib.c
+  $(OPENSSL_PATH)/ssl/s3_enc.c
+  $(OPENSSL_PATH)/ssl/s3_pkt.c
+  $(OPENSSL_PATH)/ssl/s3_both.c
+  $(OPENSSL_PATH)/ssl/s3_cbc.c
+  $(OPENSSL_PATH)/ssl/s23_meth.c
+  $(OPENSSL_PATH)/ssl/s23_srvr.c
+  $(OPENSSL_PATH)/ssl/s23_clnt.c
+  $(OPENSSL_PATH)/ssl/s23_lib.c
+  $(OPENSSL_PATH)/ssl/s23_pkt.c
+  $(OPENSSL_PATH)/ssl/t1_meth.c
+  $(OPENSSL_PATH)/ssl/t1_srvr.c
+  $(OPENSSL_PATH)/ssl/t1_clnt.c
+  $(OPENSSL_PATH)/ssl/t1_lib.c
+  $(OPENSSL_PATH)/ssl/t1_enc.c
+  $(OPENSSL_PATH)/ssl/t1_ext.c
+  $(OPENSSL_PATH)/ssl/d1_meth.c
+  $(OPENSSL_PATH)/ssl/d1_srvr.c
+  $(OPENSSL_PATH)/ssl/d1_clnt.c
+  $(OPENSSL_PATH)/ssl/d1_lib.c
+  $(OPENSSL_PATH)/ssl/d1_pkt.c
+  $(OPENSSL_PATH)/ssl/d1_both.c
+  $(OPENSSL_PATH)/ssl/d1_srtp.c
+  $(OPENSSL_PATH)/ssl/ssl_lib.c
+  $(OPENSSL_PATH)/ssl/ssl_err2.c
+  $(OPENSSL_PATH)/ssl/ssl_cert.c
+  $(OPENSSL_PATH)/ssl/ssl_sess.c
+  $(OPENSSL_PATH)/ssl/ssl_ciph.c
+  $(OPENSSL_PATH)/ssl/ssl_stat.c
+  $(OPENSSL_PATH)/ssl/ssl_rsa.c
+  $(OPENSSL_PATH)/ssl/ssl_asn1.c
+  $(OPENSSL_PATH)/ssl/ssl_txt.c
+  $(OPENSSL_PATH)/ssl/ssl_algs.c
+  $(OPENSSL_PATH)/ssl/bio_ssl.c
+  $(OPENSSL_PATH)/ssl/ssl_err.c
+  $(OPENSSL_PATH)/ssl/kssl.c
+  $(OPENSSL_PATH)/ssl/t1_reneg.c
+  $(OPENSSL_PATH)/ssl/tls_srp.c
+  $(OPENSSL_PATH)/ssl/t1_trce.c
+  $(OPENSSL_PATH)/ssl/ssl_utst.c
 
 # Autogenerated files list ends here
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -498,11 +548,11 @@
   # C4305: truncation from type1 to type2 of smaller size
   # C4306: conversion from type1 to type2 of greater size
   # C4702: Potentially uninitialized local variable name used
   # C4311: pointer truncation from 'type' to 'type'
   #
-  MSFT:*_*_IA32_CC_FLAGS    = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4244 /wd4701 /wd4702 /wd4706
+  MSFT:*_*_IA32_CC_FLAGS    = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4244 /wd4245 /wd4701 /wd4702 /wd4706
   MSFT:*_*_X64_CC_FLAGS     = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4133 /wd4244 /wd4245 /wd4267 /wd4701 /wd4305 /wd4306 /wd4702 /wd4706 /wd4311
   MSFT:*_*_IPF_CC_FLAGS     = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4133 /wd4244 /wd4245 /wd4267 /wd4701 /wd4305 /wd4306 /wd4702 /wd4706
 
   INTEL:*_*_IA32_CC_FLAGS   = -U_WIN32 -U_WIN64 -U_MSC_VER -U__ICC $(OPENSSL_FLAGS) /w
   INTEL:*_*_X64_CC_FLAGS    = -U_WIN32 -U_WIN64 -U_MSC_VER -U__ICC $(OPENSSL_FLAGS) /w
diff --git a/CryptoPkg/Library/OpensslLib/process_files.sh b/CryptoPkg/Library/OpensslLib/process_files.sh
index 885adf3..6f069ce 100755
--- a/CryptoPkg/Library/OpensslLib/process_files.sh
+++ b/CryptoPkg/Library/OpensslLib/process_files.sh
@@ -40,11 +40,10 @@ fi
 	no-jpake \
 	no-krb5 \
 	no-locking \
 	no-mdc2 \
 	no-posix-io \
-	no-pqueue \
 	no-rc2 \
 	no-rcs \
 	no-rfc3779 \
 	no-ripemd \
 	no-scrypt \
@@ -75,17 +74,15 @@ function filelist ()
 	    RELATIVE_DIRECTORY=*)
 		eval "$LINE"
 		;;
 	    LIBSRC=*)
 		LIBSRC=$(echo "$LINE" | sed s/^LIBSRC=//)
-		if [ "$RELATIVE_DIRECTORY" != "ssl" ]; then
-		    for FILE in $LIBSRC; do
+		for FILE in $LIBSRC; do
 			if [ "$FILE" != "b_print.c" ]; then
 			    echo -e '  $(OPENSSL_PATH)/'$RELATIVE_DIRECTORY/$FILE\\r\\
 			fi
-		    done
-		fi
+		done
 		;;
 	esac
     done
     echo -e \\r
 }
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Patch 04/10] CryptoPkg: Add new TlsLib library
  2016-12-14  7:34 [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master Jiaxin Wu
                   ` (2 preceding siblings ...)
  2016-12-14  7:34 ` [Patch 03/10] CryptoPkg: Enable ssl build in OpensslLib directly Jiaxin Wu
@ 2016-12-14  7:34 ` Jiaxin Wu
  2016-12-16  2:10   ` Ye, Ting
  2016-12-14  7:34 ` [Patch 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL Jiaxin Wu
                   ` (5 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ye Ting, Long Qin, Fu Siyuan, Zhang Lubo, Thomas Palmer,
	Wu Jiaxin

This patch is used to add new TlsLib library, which is wrapped
over OpenSSL. The implementation provides TLS library functions
for EFI TLS protocol and EFI TLS Configuration Protocol.

Cc: Ye Ting <ting.ye@intel.com>
Cc: Long Qin <qin.long@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@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>
---
 CryptoPkg/CryptoPkg.dec                   |    4 +
 CryptoPkg/CryptoPkg.dsc                   |    1 +
 CryptoPkg/Include/Library/TlsLib.h        |  785 +++++++++++++++++++++
 CryptoPkg/Library/TlsLib/InternalTlsLib.h |   35 +
 CryptoPkg/Library/TlsLib/TlsConfig.c      | 1055 +++++++++++++++++++++++++++++
 CryptoPkg/Library/TlsLib/TlsInit.c        |  291 ++++++++
 CryptoPkg/Library/TlsLib/TlsLib.inf       |   49 ++
 CryptoPkg/Library/TlsLib/TlsLib.uni       |   19 +
 CryptoPkg/Library/TlsLib/TlsProcess.c     |  461 +++++++++++++
 9 files changed, 2700 insertions(+)
 create mode 100644 CryptoPkg/Include/Library/TlsLib.h
 create mode 100644 CryptoPkg/Library/TlsLib/InternalTlsLib.h
 create mode 100644 CryptoPkg/Library/TlsLib/TlsConfig.c
 create mode 100644 CryptoPkg/Library/TlsLib/TlsInit.c
 create mode 100644 CryptoPkg/Library/TlsLib/TlsLib.inf
 create mode 100644 CryptoPkg/Library/TlsLib/TlsLib.uni
 create mode 100644 CryptoPkg/Library/TlsLib/TlsProcess.c

diff --git a/CryptoPkg/CryptoPkg.dec b/CryptoPkg/CryptoPkg.dec
index 80579b7..eee26cb 100644
--- a/CryptoPkg/CryptoPkg.dec
+++ b/CryptoPkg/CryptoPkg.dec
@@ -29,10 +29,14 @@
 [LibraryClasses]
   ##  @libraryclass  Provides basic library functions for cryptographic primitives.
   ##
   BaseCryptLib|Include/Library/BaseCryptLib.h
 
+  ##  @libraryclass  Provides TLS library functions for EFI TLS protocol.
+  ##
+  TlsLib|Include/Library/TlsLib.h
+
 [Protocols]
   ## Include/Protocol/RuntimeCrypt.h
   gEfiRuntimeCryptProtocolGuid = { 0xe1475e0c, 0x1746, 0x4802, {0x86, 0x2e, 0x1, 0x1c, 0x2c, 0x2d, 0x9d, 0x86 }}
 
 [UserExtensions.TianoCore."ExtraFiles"]
diff --git a/CryptoPkg/CryptoPkg.dsc b/CryptoPkg/CryptoPkg.dsc
index 3c3e444..468e60b 100644
--- a/CryptoPkg/CryptoPkg.dsc
+++ b/CryptoPkg/CryptoPkg.dsc
@@ -121,10 +121,11 @@
 ###################################################################################################
 [Components]
   CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
   CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+  CryptoPkg/Library/TlsLib/TlsLib.inf
 
   CryptoPkg/Application/Cryptest/Cryptest.inf
 
   CryptoPkg/CryptRuntimeDxe/CryptRuntimeDxe.inf
 
diff --git a/CryptoPkg/Include/Library/TlsLib.h b/CryptoPkg/Include/Library/TlsLib.h
new file mode 100644
index 0000000..38b861e
--- /dev/null
+++ b/CryptoPkg/Include/Library/TlsLib.h
@@ -0,0 +1,785 @@
+/** @file
+  Defines TLS Library APIs.
+
+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 __TLS_LIB_H__
+#define __TLS_LIB_H__
+
+/**
+  Initializes the OpenSSL library.
+
+  This function registers ciphers and digests used directly and indirectly
+  by SSL/TLS, and initializes the readable error messages.
+  This function must be called before any other action takes places.
+
+**/
+VOID
+EFIAPI
+TlsInitialize (
+  VOID
+  );
+
+/**
+  Free an allocated SSL_CTX object.
+
+  @param[in]  TlsCtx    Pointer to the SSL_CTX object to be released.
+
+**/
+VOID
+EFIAPI
+TlsCtxFree (
+  IN   VOID                  *TlsCtx
+  );
+
+/**
+  Creates a new SSL_CTX object as framework to establish TLS/SSL enabled
+  connections.
+
+  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
+  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
+
+  @return  Pointer to an allocated SSL_CTX object.
+           If the creation failed, TlsCtxNew() returns NULL.
+
+**/
+VOID *
+EFIAPI
+TlsCtxNew (
+  IN     UINT8                    MajorVer,
+  IN     UINT8                    MinorVer
+  );
+
+/**
+  Free an allocated TLS object.
+
+  This function removes the TLS object pointed to by Tls and frees up the
+  allocated memory. If Tls is NULL, nothing is done.
+
+  @param[in]  Tls    Pointer to the TLS object to be freed.
+
+**/
+VOID
+EFIAPI
+TlsFree (
+  IN     VOID                     *Tls
+  );
+
+/**
+  Create a new TLS object for a connection.
+
+  This function creates a new TLS object for a connection. The new object
+  inherits the setting of the underlying context TlsCtx: connection method,
+  options, verification setting.
+
+  @param[in]  TlsCtx    Pointer to the SSL_CTX object.
+
+  @return  Pointer to an allocated SSL object.
+           If the creation failed, TlsNew() returns NULL.
+
+**/
+VOID *
+EFIAPI
+TlsNew (
+  IN     VOID                     *TlsCtx
+  );
+
+/**
+  Checks if the TLS handshake was done.
+
+  This function will check if the specified TLS handshake was done.
+
+  @param[in]  Tls    Pointer to the TLS object for handshake state checking.
+
+  @retval  TRUE     The TLS handshake was done.
+  @retval  FALSE    The TLS handshake was not done.
+
+**/
+BOOLEAN
+EFIAPI
+TlsInHandshake (
+  IN     VOID                     *Tls
+  );
+
+/**
+  Perform a TLS/SSL handshake.
+
+  This function will perform a TLS/SSL handshake.
+
+  @param[in]       Tls            Pointer to the TLS object for handshake operation.
+  @param[in]       BufferIn       Pointer to the most recently received TLS Handshake packet.
+  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS
+                                  Handshake packet.
+  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferIn is NULL but BufferInSize is NOT 0.
+                                  BufferInSize is 0 but BufferIn is NOT NULL.
+                                  BufferOutSize is NULL.
+                                  BufferOut is NULL if *BufferOutSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsDoHandshake (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *BufferIn, OPTIONAL
+  IN     UINTN                    BufferInSize, OPTIONAL
+     OUT UINT8                    *BufferOut, OPTIONAL
+  IN OUT UINTN                    *BufferOutSize
+  );
+
+/**
+  Hande Alert message recorded in BufferIn. If BufferIn is NULL and BufferInSize is zero,
+  TLS session has errors and the response packet needs to be Alert message based on error type.
+
+  @param[in]       Tls            Pointer to the TLS object for state checking.
+  @param[in]       BufferIn       Pointer to the most recently received TLS Alert packet.
+  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS
+                                  Alert packet.
+  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferIn is NULL but BufferInSize is NOT 0.
+                                  BufferInSize is 0 but BufferIn is NOT NULL.
+                                  BufferOutSize is NULL.
+                                  BufferOut is NULL if *BufferOutSize is not zero.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsHandeAlert (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *BufferIn, OPTIONAL
+  IN     UINTN                    BufferInSize, OPTIONAL
+     OUT UINT8                    *BufferOut, OPTIONAL
+  IN OUT UINTN                    *BufferOutSize
+  );
+
+/**
+  Build the CloseNotify packet.
+
+  @param[in]       Tls            Pointer to the TLS object for state checking.
+  @param[in, out]  Buffer         Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferSize is NULL.
+                                  Buffer is NULL if *BufferSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsCloseNotify (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *Buffer,
+  IN OUT UINTN                    *BufferSize
+  );
+
+/**
+  Attempts to read bytes from one TLS object and places the data in Buffer.
+
+  This function will attempt to read BufferSize bytes from the TLS object
+  and places the data in Buffer.
+
+  @param[in]      Tls           Pointer to the TLS object.
+  @param[in,out]  Buffer        Pointer to the buffer to store the data.
+  @param[in]      BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The amount of data successfully read from the TLS object.
+  @retval  <=0   No data was successfully read.
+
+**/
+INTN
+EFIAPI
+TlsCtrlTrafficOut (
+  IN     VOID                     *Tls,
+  IN OUT VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  );
+
+/**
+  Attempts to write data from the buffer to TLS object.
+
+  This function will attempt to write BufferSize bytes data from the Buffer
+  to the TLS object.
+
+  @param[in]  Tls           Pointer to the TLS object.
+  @param[in]  Buffer        Pointer to the data buffer.
+  @param[in]  BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The amount of data successfully written to the TLS object.
+  @retval <=0    No data was successfully written.
+
+**/
+INTN
+EFIAPI
+TlsCtrlTrafficIn (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  );
+
+/**
+  Attempts to read bytes from the specified TLS connection into the buffer.
+
+  This function tries to read BufferSize bytes data from the specified TLS
+  connection into the Buffer.
+
+  @param[in]      Tls           Pointer to the TLS connection for data reading.
+  @param[in,out]  Buffer        Pointer to the data buffer.
+  @param[in]      BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The read operation was successful, and return value is the
+                 number of bytes actually read from the TLS connection.
+  @retval  <=0   The read operation was not successful.
+
+**/
+INTN
+EFIAPI
+TlsRead (
+  IN     VOID                     *Tls,
+  IN OUT VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  );
+
+/**
+  Attempts to write data to a TLS connection.
+
+  This function tries to write BufferSize bytes data from the Buffer into the
+  specified TLS connection.
+
+  @param[in]  Tls           Pointer to the TLS connection for data writing.
+  @param[in]  Buffer        Pointer to the data buffer.
+  @param[in]  BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The write operation was successful, and return value is the
+                 number of bytes actually written to the TLS connection.
+  @retval <=0    The write operation was not successful.
+
+**/
+INTN
+EFIAPI
+TlsWrite (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  );
+
+/**
+  Set a new TLS/SSL method for a particular TLS object.
+
+  This function sets a new TLS/SSL method for a particular TLS object.
+
+  @param[in]  Tls         Pointer to a TLS object.
+  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
+  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
+
+  @retval  EFI_SUCCESS           The TLS/SSL method was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetVersion (
+  IN     VOID                     *Tls,
+  IN     UINT8                    MajorVer,
+  IN     UINT8                    MinorVer
+  );
+
+/**
+  Set TLS object to work in client or server mode.
+
+  This function prepares a TLS object to work in client or server mode.
+
+  @param[in]  Tls         Pointer to a TLS object.
+  @param[in]  IsServer    Work in server mode.
+
+  @retval  EFI_SUCCESS           The TLS/SSL work mode was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL work mode.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetConnectionEnd (
+  IN     VOID                     *Tls,
+  IN     BOOLEAN                  IsServer
+  );
+
+/**
+  Set the ciphers list to be used by the TLS object.
+
+  This function sets the ciphers for use by a specified TLS object.
+
+  @param[in]  Tls          Pointer to a TLS object.
+  @param[in]  CipherId     Pointer to a string that contains one or more
+                           ciphers separated by a colon.
+  @param[in]  CipherNum    The number of cipher in the list.
+
+  @retval  EFI_SUCCESS           The ciphers list was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS cipher in the list.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCipherList (
+  IN     VOID                     *Tls,
+  IN     UINT16                   *CipherId,
+  IN     UINTN                    CipherNum
+  );
+
+/**
+  Set the compression method for TLS/SSL operations.
+
+  This function handles TLS/SSL integrated compression methods.
+
+  @param[in]  CompMethod    The compression method ID.
+
+  @retval  EFI_SUCCESS        The compression method for the communication was
+                              set successfully.
+  @retval  EFI_UNSUPPORTED    Unsupported compression method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCompressionMethod (
+  IN     UINT8                    CompMethod
+  );
+
+/**
+  Set peer certificate verification mode for the TLS connection.
+
+  This function sets the verification mode flags for the TLS connection.
+
+  @param[in]  Tls           Pointer to the TLS object.
+  @param[in]  VerifyMode    A set of logically or'ed verification mode flags.
+
+**/
+VOID
+EFIAPI
+TlsSetVerify (
+  IN     VOID                     *Tls,
+  IN     UINT32                   VerifyMode
+  );
+
+/**
+  Sets a TLS/SSL session ID to be used during TLS/SSL connect.
+
+  This function sets a session ID to be used when the TLS/SSL connection is
+  to be established.
+
+  @param[in]  Tls             Pointer to the TLS object.
+  @param[in]  SessionId       Session ID data used for session resumption.
+  @param[in]  SessionIdLen    Length of Session ID in bytes.
+
+  @retval  EFI_SUCCESS           Session ID was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       No available session for ID setting.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetSessionId (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *SessionId,
+  IN     UINT16                   SessionIdLen
+  );
+
+/**
+  Adds the CA to the cert store when requesting Server or Client authentication.
+
+  This function adds the CA certificate to the list of CAs when requesting
+  Server or Client authentication for the chosen TLS connection.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
+                          X.509 certificate or PEM-encoded X.509 certificate.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be allocated.
+  @retval  EFI_ABORTED             Invalid X.509 certificate.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCaCertificate (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  );
+
+/**
+  Loads the local public certificate into the specified TLS object.
+
+  This function loads the X.509 certificate into the specified TLS object
+  for TLS negotiation.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
+                          X.509 certificate or PEM-encoded X.509 certificate.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be allocated.
+  @retval  EFI_ABORTED             Invalid X.509 certificate.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetHostPublicCert (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  );
+
+/**
+  Adds the local private key to the specified TLS object.
+
+  This function adds the local private key (PEM-encoded RSA or PKCS#8 private
+  key) into the specified TLS object for TLS negotiation.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a PEM-encoded RSA
+                          or PKCS#8 private key.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS     The operation succeeded.
+  @retval  EFI_UNSUPPORTED This function is not supported.
+  @retval  EFI_ABORTED     Invalid private key data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetHostPrivateKey (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  );
+
+/**
+  Adds the CA-supplied certificate revocation list for certificate validation.
+
+  This function adds the CA-supplied certificate revocation list data for
+  certificate validity checking.
+
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded CRL data.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS     The operation succeeded.
+  @retval  EFI_UNSUPPORTED This function is not supported.
+  @retval  EFI_ABORTED     Invalid CRL data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCertRevocationList (
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  );
+
+/**
+  Gets the protocol version used by the specified TLS connection.
+
+  This function returns the protocol version used by the specified TLS
+  connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The protocol version of the specified TLS connection.
+
+**/
+UINT16
+EFIAPI
+TlsGetVersion (
+  IN     VOID                     *Tls
+  );
+
+/**
+  Gets the connection end of the specified TLS connection.
+
+  This function returns the connection end (as client or as server) used by
+  the specified TLS connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The connection end used by the specified TLS connection.
+
+**/
+UINT8
+EFIAPI
+TlsGetConnectionEnd (
+  IN     VOID                     *Tls
+  );
+
+/**
+  Gets the cipher suite used by the specified TLS connection.
+
+  This function returns current cipher suite used by the specified
+  TLS connection.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[in,out]  CipherId    The cipher suite used by the TLS object.
+
+  @retval  EFI_SUCCESS           The cipher suite was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported cipher suite.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCurrentCipher (
+  IN     VOID                     *Tls,
+  IN OUT UINT16                   *CipherId
+  );
+
+/**
+  Gets the compression methods used by the specified TLS connection.
+
+  This function returns current integrated compression methods used by
+  the specified TLS connection.
+
+  @param[in]      Tls              Pointer to the TLS object.
+  @param[in,out]  CompressionId    The current compression method used by
+                                   the TLS object.
+
+  @retval  EFI_SUCCESS           The compression method was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_ABORTED           Invalid Compression method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCurrentCompressionId (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *CompressionId
+  );
+
+/**
+  Gets the verification mode currently set in the TLS connection.
+
+  This function returns the peer verification mode currently set in the
+  specified TLS connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The verification mode set in the specified TLS connection.
+
+**/
+UINT32
+EFIAPI
+TlsGetVerify (
+  IN     VOID                     *Tls
+  );
+
+/**
+  Gets the session ID used by the specified TLS connection.
+
+  This function returns the TLS/SSL session ID currently used by the
+  specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  SessionId       Buffer to contain the returned session ID.
+  @param[in,out]  SessionIdLen    The length of Session ID in bytes.
+
+  @retval  EFI_SUCCESS           The Session ID was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetSessionId (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *SessionId,
+  IN OUT UINT16                   *SessionIdLen
+  );
+
+/**
+  Gets the client random data used in the specified TLS connection.
+
+  This function returns the TLS/SSL client random data currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  ClientRandom    Buffer to contain the returned client
+                                  random data (32 bytes).
+
+**/
+VOID
+EFIAPI
+TlsGetClientRandom (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *ClientRandom
+  );
+
+/**
+  Gets the server random data used in the specified TLS connection.
+
+  This function returns the TLS/SSL server random data currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  ServerRandom    Buffer to contain the returned server
+                                  random data (32 bytes).
+
+**/
+VOID
+EFIAPI
+TlsGetServerRandom (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *ServerRandom
+  );
+
+/**
+  Gets the master key data used in the specified TLS connection.
+
+  This function returns the TLS/SSL master key material currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls            Pointer to the TLS object.
+  @param[in,out]  KeyMaterial    Buffer to contain the returned key material.
+
+  @retval  EFI_SUCCESS           Key material was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetKeyMaterial (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *KeyMaterial
+  );
+
+/**
+  Gets the CA Certificate from the cert store.
+
+  This function returns the CA certificate for the chosen
+  TLS connection.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the CA
+                              certificate data sent to the client.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCaCertificate (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  );
+
+/**
+  Gets the local public Certificate set in the specified TLS object.
+
+  This function returns the local public certificate which was currently set
+  in the specified TLS object.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the local
+                              public certificate.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_NOT_FOUND           The certificate is not found.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetHostPublicCert (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  );
+
+/**
+  Gets the local private key set in the specified TLS object.
+
+  This function returns the local private key data which was currently set
+  in the specified TLS object.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the local
+                              private key data.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetHostPrivateKey (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  );
+
+/**
+  Gets the CA-supplied certificate revocation list data set in the specified
+  TLS object.
+
+  This function returns the CA-supplied certificate revocation list data which
+  was currently set in the specified TLS object.
+
+  @param[out]     Data        Pointer to the data buffer to receive the CRL data.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCertRevocationList (
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  );
+
+#endif // __TLS_LIB_H__
diff --git a/CryptoPkg/Library/TlsLib/InternalTlsLib.h b/CryptoPkg/Library/TlsLib/InternalTlsLib.h
new file mode 100644
index 0000000..2438de9
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/InternalTlsLib.h
@@ -0,0 +1,35 @@
+/** @file
+  Internal include file for TlsLib.
+
+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.
+
+**/
+
+#include <Library/BaseCryptLib.h>
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+
+typedef struct {
+  //
+  // Main SSL Connection which is created by a server or a client
+  // per established connection.
+  //
+  SSL                             *Ssl;
+  //
+  // Memory BIO for the TLS/SSL Reading operations.
+  //
+  BIO                             *InBio;
+  //
+  // Memory BIO for the TLS/SSL Writing operations.
+  //
+  BIO                             *OutBio;
+} TLS_CONNECTION;
+
diff --git a/CryptoPkg/Library/TlsLib/TlsConfig.c b/CryptoPkg/Library/TlsLib/TlsConfig.c
new file mode 100644
index 0000000..31220b3
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/TlsConfig.c
@@ -0,0 +1,1055 @@
+/** @file
+  SSL/TLS Configuration Library Wrapper Implementation over OpenSSL.
+
+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 "InternalTlsLib.h"
+
+typedef struct {
+  //
+  // IANA/IETF defined Cipher Suite ID
+  //
+  UINT16                          IanaCipher;
+  //
+  // OpenSSL-used Cipher Suite String
+  //
+  CONST CHAR8                     *OpensslCipher;
+} TLS_CIPHER_PAIR;
+
+//
+// The mapping table between IANA/IETF Cipher Suite definitions and
+// OpenSSL-used Cipher Suite name.
+//
+STATIC CONST TLS_CIPHER_PAIR TlsCipherMappingTable[] = {
+  { 0x0001, "NULL-MD5" },                 /// TLS_RSA_WITH_NULL_MD5
+  { 0x0002, "NULL-SHA" },                 /// TLS_RSA_WITH_NULL_SHA
+  { 0x0004, "RC4-MD5" },                  /// TLS_RSA_WITH_RC4_128_MD5
+  { 0x0005, "RC4-SHA" },                  /// TLS_RSA_WITH_RC4_128_SHA
+  { 0x000A, "DES-CBC3-SHA" },             /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1
+  { 0x0016, "DHE-RSA-DES-CBC3-SHA" },     /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+  { 0x002F, "AES128-SHA" },               /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2
+  { 0x0030, "DH-DSS-AES128-SHA" },        /// TLS_DH_DSS_WITH_AES_128_CBC_SHA
+  { 0x0031, "DH-RSA-AES128-SHA" },        /// TLS_DH_RSA_WITH_AES_128_CBC_SHA
+  { 0x0033, "DHE-RSA-AES128-SHA" },       /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+  { 0x0035, "AES256-SHA" },               /// TLS_RSA_WITH_AES_256_CBC_SHA
+  { 0x0036, "DH-DSS-AES256-SHA" },        /// TLS_DH_DSS_WITH_AES_256_CBC_SHA
+  { 0x0037, "DH-RSA-AES256-SHA" },        /// TLS_DH_RSA_WITH_AES_256_CBC_SHA
+  { 0x0039, "DHE-RSA-AES256-SHA" },       /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+  { 0x003B, "NULL-SHA256" },              /// TLS_RSA_WITH_NULL_SHA256
+  { 0x003C, "AES128-SHA256" },            /// TLS_RSA_WITH_AES_128_CBC_SHA256
+  { 0x003D, "AES256-SHA256" },            /// TLS_RSA_WITH_AES_256_CBC_SHA256
+  { 0x003E, "DH-DSS-AES128-SHA256" },     /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256
+  { 0x003F, "DH-RSA-AES128-SHA256" },     /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256
+  { 0x0067, "DHE-RSA-AES128-SHA256" },    /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+  { 0x0068, "DH-DSS-AES256-SHA256" },     /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256
+  { 0x0069, "DH-RSA-AES256-SHA256" },     /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256
+  { 0x006B, "DHE-RSA-AES256-SHA256" }     /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+};
+
+/**
+  Gets the OpenSSL cipher suite string for the supplied IANA TLS cipher suite.
+
+  @param[in]  CipherId    The supplied IANA TLS cipher suite ID.
+
+  @return  The corresponding OpenSSL cipher suite string if found,
+           NULL otherwise.
+
+**/
+STATIC
+CONST CHAR8 *
+TlsGetCipherString (
+  IN     UINT16                   CipherId
+  )
+{
+  CONST TLS_CIPHER_PAIR  *CipherEntry;
+  UINTN                  TableSize;
+  UINTN                  Index;
+
+  CipherEntry = TlsCipherMappingTable;
+  TableSize = sizeof (TlsCipherMappingTable) / sizeof (TLS_CIPHER_PAIR);
+
+  //
+  // Search Cipher Mapping Table for IANA-OpenSSL Cipher Translation
+  //
+  for (Index = 0; Index < TableSize; Index++, CipherEntry++) {
+    //
+    // Translate IANA cipher suite name to OpenSSL name.
+    //
+    if (CipherEntry->IanaCipher == CipherId) {
+      return CipherEntry->OpensslCipher;
+    }
+  }
+
+  //
+  // No Cipher Mapping found, return NULL.
+  //
+  return NULL;
+}
+
+/**
+  Set a new TLS/SSL method for a particular TLS object.
+
+  This function sets a new TLS/SSL method for a particular TLS object.
+
+  @param[in]  Tls         Pointer to a TLS object.
+  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
+  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
+
+  @retval  EFI_SUCCESS           The TLS/SSL method was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetVersion (
+  IN     VOID                     *Tls,
+  IN     UINT8                    MajorVer,
+  IN     UINT8                    MinorVer
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  UINT16          ProtoVersion;
+
+  TlsConn = (TLS_CONNECTION *)Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ProtoVersion = (MajorVer << 8) | MinorVer;
+
+  switch (ProtoVersion) {
+  case TLS1_VERSION:
+    //
+    // TLS 1.0
+    //
+    SSL_set_ssl_method (TlsConn->Ssl, TLSv1_method ());
+    break;
+  case TLS1_1_VERSION:
+    //
+    // TLS 1.1
+    //
+    SSL_set_ssl_method (TlsConn->Ssl, TLSv1_1_method ());
+    break;
+  case TLS1_2_VERSION:
+    //
+    // TLS 1.2
+    //
+    SSL_set_ssl_method (TlsConn->Ssl, TLSv1_2_method ());
+    break;
+  default:
+    //
+    // Unsupported Protocol Version
+    //
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;;
+}
+
+/**
+  Set TLS object to work in client or server mode.
+
+  This function prepares a TLS object to work in client or server mode.
+
+  @param[in]  Tls         Pointer to a TLS object.
+  @param[in]  IsServer    Work in server mode.
+
+  @retval  EFI_SUCCESS           The TLS/SSL work mode was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL work mode.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetConnectionEnd (
+  IN     VOID                     *Tls,
+  IN     BOOLEAN                  IsServer
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IsServer) {
+    //
+    // Set TLS to work in Client mode.
+    //
+    SSL_set_connect_state (TlsConn->Ssl);
+  } else {
+    //
+    // Set TLS to work in Server mode.
+    // It is unsupported for UEFI version currently.
+    //
+    //SSL_set_accept_state (TlsConn->Ssl);
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set the ciphers list to be used by the TLS object.
+
+  This function sets the ciphers for use by a specified TLS object.
+
+  @param[in]  Tls          Pointer to a TLS object.
+  @param[in]  CipherId     Pointer to a UINT16 cipher Id.
+  @param[in]  CipherNum    The number of cipher in the list.
+
+  @retval  EFI_SUCCESS           The ciphers list was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS cipher in the list.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCipherList (
+  IN     VOID                     *Tls,
+  IN     UINT16                   *CipherId,
+  IN     UINTN                    CipherNum
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  UINTN           Index;
+  CONST CHAR8     *MappingName;
+  CHAR8           CipherString[500];
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MappingName = NULL;
+
+  memset (CipherString, 0, sizeof (CipherString));
+
+  for (Index = 0; Index < CipherNum; Index++) {
+    //
+    // Handling OpenSSL / RFC Cipher name mapping.
+    //
+    MappingName = TlsGetCipherString (*(CipherId + Index));
+    if (MappingName == NULL) {
+      return EFI_UNSUPPORTED;
+    }
+
+    if (Index != 0) {
+      //
+      // The ciphers were separated by a colon.
+      //
+      AsciiStrCatS (CipherString, sizeof (CipherString), ":");
+    }
+
+    AsciiStrCatS (CipherString, sizeof (CipherString), MappingName);
+  }
+
+  AsciiStrCatS (CipherString, sizeof (CipherString), ":@STRENGTH");
+
+  //
+  // Sets the ciphers for use by the Tls object.
+  //
+  if (SSL_set_cipher_list (TlsConn->Ssl, CipherString) <= 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set the compression method for TLS/SSL operations.
+
+  This function handles TLS/SSL integrated compression methods.
+
+  @param[in]  CompMethod    The compression method ID.
+
+  @retval  EFI_SUCCESS        The compression method for the communication was
+                              set successfully.
+  @retval  EFI_UNSUPPORTED    Unsupported compression method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCompressionMethod (
+  IN     UINT8                    CompMethod
+  )
+{
+  COMP_METHOD  *Cm;
+  INTN         Ret;
+
+  Cm  = NULL;
+  Ret = 0;
+
+  if (CompMethod == 0) {
+    //
+    // TLS defines one standard compression method, CompressionMethod.null (0),
+    // which specifies that data exchanged via the record protocol will not be compressed.
+    // So, return EFI_SUCCESS directly (RFC 3749).
+    //
+    return EFI_SUCCESS;
+  } else if (CompMethod == 1) {
+    Cm = COMP_zlib();
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Adds the compression method to the list of available
+  // compression methods.
+  //
+  Ret = SSL_COMP_add_compression_method (CompMethod, Cm);
+  if (Ret != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set peer certificate verification mode for the TLS connection.
+
+  This function sets the verification mode flags for the TLS connection.
+
+  @param[in]  Tls           Pointer to the TLS object.
+  @param[in]  VerifyMode    A set of logically or'ed verification mode flags.
+
+**/
+VOID
+EFIAPI
+TlsSetVerify (
+  IN     VOID                     *Tls,
+  IN     UINT32                   VerifyMode
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return;
+  }
+
+  //
+  // Set peer certificate verification parameters with NULL callback.
+  //
+  SSL_set_verify (TlsConn->Ssl, VerifyMode, NULL);
+}
+
+/**
+  Sets a TLS/SSL session ID to be used during TLS/SSL connect.
+
+  This function sets a session ID to be used when the TLS/SSL connection is
+  to be established.
+
+  @param[in]  Tls             Pointer to the TLS object.
+  @param[in]  SessionId       Session ID data used for session resumption.
+  @param[in]  SessionIdLen    Length of Session ID in bytes.
+
+  @retval  EFI_SUCCESS           Session ID was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       No available session for ID setting.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetSessionId (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *SessionId,
+  IN     UINT16                   SessionIdLen
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  SSL_SESSION     *Session;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  Session = NULL;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Session = SSL_get_session (TlsConn->Ssl);
+  if (Session == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Session->session_id_length = SessionIdLen;
+  CopyMem (Session->session_id, SessionId, Session->session_id_length);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Adds the CA to the cert store when requesting Server or Client authentication.
+
+  This function adds the CA certificate to the list of CAs when requesting
+  Server or Client authentication for the chosen TLS connection.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
+                          X.509 certificate or PEM-encoded X.509 certificate.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be allocated.
+  @retval  EFI_ABORTED             Invalid X.509 certificate.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCaCertificate (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  )
+{
+  BIO             *BioCert;
+  X509            *Cert;
+  X509_STORE      *X509Store;
+  EFI_STATUS      Status;
+  TLS_CONNECTION  *TlsConn;
+  SSL_CTX         *SslCtx;
+  INTN            Ret;
+  unsigned long   ErrorCode;
+
+  BioCert   = NULL;
+  Cert      = NULL;
+  X509Store = NULL;
+  Status    = EFI_SUCCESS;
+  TlsConn   = (TLS_CONNECTION *) Tls;
+  Ret       = 0;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
+  // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
+  //
+  Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize);
+  if (Cert == NULL) {
+    //
+    // Certificate is from PEM encoding.
+    //
+    BioCert = BIO_new (BIO_s_mem ());
+    if (BioCert == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ON_EXIT;
+    }
+
+    if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+    }
+
+    Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
+    if (Cert == NULL) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+    }
+  }
+
+  SslCtx    = SSL_get_SSL_CTX (TlsConn->Ssl);
+  X509Store = SSL_CTX_get_cert_store (SslCtx);
+  if (X509Store == NULL) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+  }
+
+  //
+  // Add certificate to X509 store
+  //
+  Ret = X509_STORE_add_cert (X509Store, Cert);
+  if (Ret != 1) {
+    ErrorCode = ERR_peek_last_error ();
+    //
+    // Ignore "already in table" errors
+    //
+    if (!(ERR_GET_FUNC (ErrorCode) == X509_F_X509_STORE_ADD_CERT &&
+        ERR_GET_REASON (ErrorCode) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+    }
+  }
+
+ON_EXIT:
+  if (BioCert != NULL) {
+    BIO_free (BioCert);
+  }
+
+  if (Cert != NULL) {
+    X509_free (Cert);
+  }
+
+  return Status;
+}
+
+/**
+  Loads the local public certificate into the specified TLS object.
+
+  This function loads the X.509 certificate into the specified TLS object
+  for TLS negotiation.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
+                          X.509 certificate or PEM-encoded X.509 certificate.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be allocated.
+  @retval  EFI_ABORTED             Invalid X.509 certificate.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetHostPublicCert (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  )
+{
+  BIO             *BioCert;
+  X509            *Cert;
+  EFI_STATUS      Status;
+  TLS_CONNECTION  *TlsConn;
+
+  BioCert = NULL;
+  Cert    = NULL;
+  Status  = EFI_SUCCESS;
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
+  // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
+  //
+  Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize);
+  if (Cert == NULL) {
+    //
+    // Certificate is from PEM encoding.
+    //
+    BioCert = BIO_new (BIO_s_mem ());
+    if (BioCert == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ON_EXIT;
+    }
+
+    if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+    }
+
+    Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
+    if (Cert == NULL) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+    }
+  }
+
+  if (SSL_use_certificate (TlsConn->Ssl, Cert) != 1) {
+    Status = EFI_ABORTED;
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+  if (BioCert != NULL) {
+    BIO_free (BioCert);
+  }
+
+  if (Cert != NULL) {
+    X509_free (Cert);
+  }
+
+  return Status;
+}
+
+/**
+  Adds the local private key to the specified TLS object.
+
+  This function adds the local private key (PEM-encoded RSA or PKCS#8 private
+  key) into the specified TLS object for TLS negotiation.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a PEM-encoded RSA
+                          or PKCS#8 private key.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS     The operation succeeded.
+  @retval  EFI_UNSUPPORTED This function is not supported.
+  @retval  EFI_ABORTED     Invalid private key data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetHostPrivateKey (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Adds the CA-supplied certificate revocation list for certificate validation.
+
+  This function adds the CA-supplied certificate revocation list data for
+  certificate validity checking.
+
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded CRL data.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS     The operation succeeded.
+  @retval  EFI_UNSUPPORTED This function is not supported.
+  @retval  EFI_ABORTED     Invalid CRL data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCertRevocationList (
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Gets the protocol version used by the specified TLS connection.
+
+  This function returns the protocol version used by the specified TLS
+  connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The protocol version of the specified TLS connection.
+
+**/
+UINT16
+EFIAPI
+TlsGetVersion (
+  IN     VOID                     *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  ASSERT (TlsConn != NULL);
+
+  return (UINT16)(SSL_version (TlsConn->Ssl));
+}
+
+/**
+  Gets the connection end of the specified TLS connection.
+
+  This function returns the connection end (as client or as server) used by
+  the specified TLS connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The connection end used by the specified TLS connection.
+
+**/
+UINT8
+EFIAPI
+TlsGetConnectionEnd (
+  IN     VOID                     *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  ASSERT (TlsConn != NULL);
+
+  return (UINT8)SSL_is_server (TlsConn->Ssl);
+}
+
+/**
+  Gets the cipher suite used by the specified TLS connection.
+
+  This function returns current cipher suite used by the specified
+  TLS connection.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[in,out]  CipherId    The cipher suite used by the TLS object.
+
+  @retval  EFI_SUCCESS           The cipher suite was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported cipher suite.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCurrentCipher (
+  IN     VOID                     *Tls,
+  IN OUT UINT16                   *CipherId
+  )
+{
+  TLS_CONNECTION    *TlsConn;
+  CONST SSL_CIPHER  *Cipher;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  Cipher  = NULL;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Cipher = SSL_get_current_cipher (TlsConn->Ssl);
+  if (Cipher == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  *CipherId = (SSL_CIPHER_get_id (Cipher)) & 0xFFFF;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets the compression methods used by the specified TLS connection.
+
+  This function returns current integrated compression methods used by
+  the specified TLS connection.
+
+  @param[in]      Tls              Pointer to the TLS object.
+  @param[in,out]  CompressionId    The current compression method used by
+                                   the TLS object.
+
+  @retval  EFI_SUCCESS           The compression method was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_ABORTED           Invalid Compression method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCurrentCompressionId (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *CompressionId
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Gets the verification mode currently set in the TLS connection.
+
+  This function returns the peer verification mode currently set in the
+  specified TLS connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The verification mode set in the specified TLS connection.
+
+**/
+UINT32
+EFIAPI
+TlsGetVerify (
+  IN     VOID                     *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  ASSERT (TlsConn != NULL);
+
+  return SSL_get_verify_mode (TlsConn->Ssl);
+}
+
+/**
+  Gets the session ID used by the specified TLS connection.
+
+  This function returns the TLS/SSL session ID currently used by the
+  specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  SessionId       Buffer to contain the returned session ID.
+  @param[in,out]  SessionIdLen    The length of Session ID in bytes.
+
+  @retval  EFI_SUCCESS           The Session ID was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetSessionId (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *SessionId,
+  IN OUT UINT16                   *SessionIdLen
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  SSL_SESSION     *Session;
+  CONST UINT8     *SslSessionId;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  Session = NULL;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL || SessionIdLen == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Session = SSL_get_session (TlsConn->Ssl);
+  if (Session == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  SslSessionId = SSL_SESSION_get_id (Session, (unsigned int *)SessionIdLen);
+  CopyMem (SessionId, SslSessionId, *SessionIdLen);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets the client random data used in the specified TLS connection.
+
+  This function returns the TLS/SSL client random data currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  ClientRandom    Buffer to contain the returned client
+                                  random data (32 bytes).
+
+**/
+VOID
+EFIAPI
+TlsGetClientRandom (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *ClientRandom
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || ClientRandom == NULL) {
+    return;
+  }
+
+  CopyMem (ClientRandom, TlsConn->Ssl->s3->client_random, SSL3_RANDOM_SIZE);
+}
+
+/**
+  Gets the server random data used in the specified TLS connection.
+
+  This function returns the TLS/SSL server random data currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  ServerRandom    Buffer to contain the returned server
+                                  random data (32 bytes).
+
+**/
+VOID
+EFIAPI
+TlsGetServerRandom (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *ServerRandom
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || ServerRandom == NULL) {
+    return;
+  }
+
+  CopyMem (ServerRandom, TlsConn->Ssl->s3->server_random, SSL3_RANDOM_SIZE);
+}
+
+/**
+  Gets the master key data used in the specified TLS connection.
+
+  This function returns the TLS/SSL master key material currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls            Pointer to the TLS object.
+  @param[in,out]  KeyMaterial    Buffer to contain the returned key material.
+
+  @retval  EFI_SUCCESS           Key material was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetKeyMaterial (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *KeyMaterial
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  SSL_SESSION     *Session;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  Session = NULL;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || KeyMaterial == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Session = SSL_get_session (TlsConn->Ssl);
+
+  if (Session == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  CopyMem (KeyMaterial, Session->master_key, Session->master_key_length);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets the CA Certificate from the cert store.
+
+  This function returns the CA certificate for the chosen
+  TLS connection.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the CA
+                              certificate data sent to the client.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCaCertificate (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Gets the local public Certificate set in the specified TLS object.
+
+  This function returns the local public certificate which was currently set
+  in the specified TLS object.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the local
+                              public certificate.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_NOT_FOUND           The certificate is not found.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetHostPublicCert (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  )
+{
+  X509            *Cert;
+  EFI_STATUS      Status;
+  TLS_CONNECTION  *TlsConn;
+
+  Cert    = NULL;
+  Status  = EFI_SUCCESS;
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || DataSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Cert = SSL_get_certificate(TlsConn->Ssl);
+  if (Cert == NULL) {
+    Status = EFI_NOT_FOUND;
+  }
+
+  //
+  // Only DER encoding is supported currently.
+  //
+  if (*DataSize < (UINTN) i2d_X509 (Cert, NULL)) {
+    *DataSize = (UINTN) i2d_X509 (Cert, NULL);
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *DataSize = (UINTN) i2d_X509 (Cert, (unsigned char **) &Data);
+
+  return Status;
+}
+
+/**
+  Gets the local private key set in the specified TLS object.
+
+  This function returns the local private key data which was currently set
+  in the specified TLS object.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the local
+                              private key data.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetHostPrivateKey (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Gets the CA-supplied certificate revocation list data set in the specified
+  TLS object.
+
+  This function returns the CA-supplied certificate revocation list data which
+  was currently set in the specified TLS object.
+
+  @param[out]     Data        Pointer to the data buffer to receive the CRL data.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCertRevocationList (
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/CryptoPkg/Library/TlsLib/TlsInit.c b/CryptoPkg/Library/TlsLib/TlsInit.c
new file mode 100644
index 0000000..6b1fd93
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/TlsInit.c
@@ -0,0 +1,291 @@
+/** @file
+  SSL/TLS Initialization Library Wrapper Implementation over OpenSSL.
+
+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 "InternalTlsLib.h"
+
+/**
+  Initializes the OpenSSL library.
+
+  This function registers ciphers and digests used directly and indirectly
+  by SSL/TLS, and initializes the readable error messages.
+  This function must be called before any other action takes places.
+
+**/
+VOID
+EFIAPI
+TlsInitialize (
+  VOID
+  )
+{
+  //
+  // Performs initialization of crypto and ssl library, and loads required
+  // algorithms.
+  //
+  SSL_library_init ();
+
+  //
+  // Loads error strings from both crypto and ssl library.
+  //
+  SSL_load_error_strings ();
+
+  /// OpenSSL_add_all_algorithms();
+
+  //
+  // Initialize the pseudorandom number generator.
+  //
+  RandomSeed (NULL, 0);
+}
+
+/**
+  Free an allocated SSL_CTX object.
+
+  @param[in]  TlsCtx    Pointer to the SSL_CTX object to be released.
+
+**/
+VOID
+EFIAPI
+TlsCtxFree (
+  IN   VOID                  *TlsCtx
+  )
+{
+  if (TlsCtx == NULL) {
+    return;
+  }
+
+  if (TlsCtx != NULL) {
+    SSL_CTX_free ((SSL_CTX *) (TlsCtx));
+  }
+}
+
+/**
+  Creates a new SSL_CTX object as framework to establish TLS/SSL enabled
+  connections.
+
+  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
+  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
+
+  @return  Pointer to an allocated SSL_CTX object.
+           If the creation failed, TlsCtxNew() returns NULL.
+
+**/
+VOID *
+EFIAPI
+TlsCtxNew (
+  IN     UINT8                    MajorVer,
+  IN     UINT8                    MinorVer
+  )
+{
+  SSL_CTX  *TlsCtx;
+  UINT16   ProtoVersion;
+
+  ProtoVersion = (MajorVer << 8) | MinorVer;
+
+  TlsCtx = SSL_CTX_new (SSLv23_client_method ());
+  if (TlsCtx == NULL) {
+    return NULL;
+  }
+
+  //
+  // Ensure SSLv3 is disabled
+  //
+  SSL_CTX_set_options (TlsCtx, SSL_OP_NO_SSLv3);
+
+  //
+  // Treat as minimum accepted versions.  Client can use higher
+  // TLS version if server supports it
+  //
+  switch (ProtoVersion) {
+  case TLS1_VERSION:
+    //
+    // TLS 1.0
+    //
+    break;
+  case TLS1_1_VERSION:
+    //
+    // TLS 1.1
+    //
+    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1);
+    break;
+  case TLS1_2_VERSION:
+    //
+    // TLS 1.2
+    //
+    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1);
+    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1_1);
+    break;
+  default:
+    //
+    // Unsupported TLS/SSL Protocol Version.
+    //
+    break;
+  }
+
+  return (VOID *) TlsCtx;
+}
+
+/**
+  Free an allocated TLS object.
+
+  This function removes the TLS object pointed to by Tls and frees up the
+  allocated memory. If Tls is NULL, nothing is done.
+
+  @param[in]  Tls    Pointer to the TLS object to be freed.
+
+**/
+VOID
+EFIAPI
+TlsFree (
+  IN     VOID                     *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL) {
+    return;
+  }
+
+  //
+  // Free the internal TLS and BIO objects.
+  //
+  if (TlsConn->Ssl != NULL) {
+    SSL_free (TlsConn->Ssl);
+  }
+
+  if (TlsConn->InBio != NULL) {
+    BIO_free (TlsConn->InBio);
+  }
+
+  if (TlsConn->OutBio != NULL) {
+    BIO_free (TlsConn->OutBio);
+  }
+
+  OPENSSL_free (Tls);
+}
+
+/**
+  Create a new TLS object for a connection.
+
+  This function creates a new TLS object for a connection. The new object
+  inherits the setting of the underlying context TlsCtx: connection method,
+  options, verification setting.
+
+  @param[in]  TlsCtx    Pointer to the SSL_CTX object.
+
+  @return  Pointer to an allocated SSL object.
+           If the creation failed, TlsNew() returns NULL.
+
+**/
+VOID *
+EFIAPI
+TlsNew (
+  IN     VOID                     *TlsCtx
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  SSL_CTX         *SslCtx;
+  X509_STORE      *X509Store;
+
+  TlsConn = NULL;
+
+  //
+  // Allocate one new TLS_CONNECTION object
+  //
+  TlsConn = (TLS_CONNECTION *) OPENSSL_malloc (sizeof (TLS_CONNECTION));
+  if (TlsConn == NULL) {
+    return NULL;
+  }
+
+  TlsConn->Ssl = NULL;
+
+  //
+  // Create a new SSL Object
+  //
+  TlsConn->Ssl = SSL_new ((SSL_CTX *) TlsCtx);
+  if (TlsConn->Ssl == NULL) {
+    TlsFree ((VOID *) TlsConn);
+    return NULL;
+  }
+
+  //
+  // Initialize the created SSL Object
+  //
+  SSL_set_info_callback (TlsConn->Ssl, NULL);
+
+  TlsConn->InBio = NULL;
+
+  //
+  // Set up Reading BIO for TLS connection
+  //
+  TlsConn->InBio = BIO_new (BIO_s_mem ());
+  if (TlsConn->InBio == NULL) {
+    TlsFree ((VOID *) TlsConn);
+    return NULL;
+  }
+
+  //
+  // Sets the behaviour of memory BIO when it is empty. It will set the
+  // read retry flag.
+  //
+  BIO_set_mem_eof_return (TlsConn->InBio, -1);
+
+  TlsConn->OutBio = NULL;
+
+  //
+  // Set up Writing BIO for TLS connection
+  //
+  TlsConn->OutBio = BIO_new (BIO_s_mem ());
+  if (TlsConn->OutBio == NULL) {
+    TlsFree ((VOID *) TlsConn);
+    return NULL;
+  }
+
+  //
+  // Sets the behaviour of memory BIO when it is empty. It will set the
+  // write retry flag.
+  //
+  BIO_set_mem_eof_return (TlsConn->OutBio, -1);
+
+  ASSERT (TlsConn->Ssl != NULL && TlsConn->InBio != NULL && TlsConn->OutBio != NULL);
+
+  //
+  // Connects the InBio and OutBio for the read and write operations.
+  //
+  SSL_set_bio (TlsConn->Ssl, TlsConn->InBio, TlsConn->OutBio);
+
+  //
+  // Create new X509 store if needed
+  //
+  SslCtx    = SSL_get_SSL_CTX (TlsConn->Ssl);
+  X509Store = SSL_CTX_get_cert_store (SslCtx);
+  if (X509Store == NULL) {
+    X509Store = X509_STORE_new ();
+    if (X509Store == NULL) {
+      TlsFree ((VOID *) TlsConn);
+      return NULL;
+    }
+    SSL_CTX_set1_verify_cert_store (SslCtx, X509Store);
+    X509_STORE_free (X509Store);
+  }
+
+  //
+  // Set X509_STORE flags used in certificate validation
+  //
+  X509_STORE_set_flags (
+    X509Store,
+    X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME
+    );
+  return (VOID *) TlsConn;
+}
diff --git a/CryptoPkg/Library/TlsLib/TlsLib.inf b/CryptoPkg/Library/TlsLib/TlsLib.inf
new file mode 100644
index 0000000..2122b3b
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/TlsLib.inf
@@ -0,0 +1,49 @@
+## @file
+#  SSL/TLS Wrapper Library Instance based on OpenSSL.
+#
+#  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.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = TlsLib
+  MODULE_UNI_FILE                = TlsLib.uni
+  FILE_GUID                      = CC729DC5-4E21-0B36-1A00-3A8E1B86A155
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TlsLib|DXE_DRIVER DXE_CORE UEFI_APPLICATION UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF ARM AARCH64
+#
+
+[Sources]
+  InternalTlsLib.h
+  TlsInit.c
+  TlsConfig.c
+  TlsProcess.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  UefiRuntimeServicesTableLib
+  DebugLib
+  OpensslLib
+  IntrinsicLib
+  PrintLib
diff --git a/CryptoPkg/Library/TlsLib/TlsLib.uni b/CryptoPkg/Library/TlsLib/TlsLib.uni
new file mode 100644
index 0000000..9b79287
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/TlsLib.uni
@@ -0,0 +1,19 @@
+// /** @file
+// SSL/TLS Wrapper Library Instance based on OpenSSL.
+//
+// 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.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "SSL/TLS Wrapper Library Instance"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This module provides SSL/TLS Wrapper Library Instance."
\ No newline at end of file
diff --git a/CryptoPkg/Library/TlsLib/TlsProcess.c b/CryptoPkg/Library/TlsLib/TlsProcess.c
new file mode 100644
index 0000000..52b55d7
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/TlsProcess.c
@@ -0,0 +1,461 @@
+/** @file
+  SSL/TLS Process Library Wrapper Implementation over OpenSSL.
+  The process includes the TLS handshake and packet I/O.
+
+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 "InternalTlsLib.h"
+
+#define MAX_BUFFER_SIZE   32768
+
+/**
+  Checks if the TLS handshake was done.
+
+  This function will check if the specified TLS handshake was done.
+
+  @param[in]  Tls    Pointer to the TLS object for handshake state checking.
+
+  @retval  TRUE     The TLS handshake was done.
+  @retval  FALSE    The TLS handshake was not done.
+
+**/
+BOOLEAN
+EFIAPI
+TlsInHandshake (
+  IN     VOID                     *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return FALSE;
+  }
+
+  //
+  // Return the status which indicates if the TLS handshake was done.
+  //
+  return !SSL_is_init_finished (TlsConn->Ssl);
+}
+
+/**
+  Perform a TLS/SSL handshake.
+
+  This function will perform a TLS/SSL handshake.
+
+  @param[in]       Tls            Pointer to the TLS object for handshake operation.
+  @param[in]       BufferIn       Pointer to the most recently received TLS Handshake packet.
+  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS
+                                  Handshake packet.
+  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferIn is NULL but BufferInSize is NOT 0.
+                                  BufferInSize is 0 but BufferIn is NOT NULL.
+                                  BufferOutSize is NULL.
+                                  BufferOut is NULL if *BufferOutSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsDoHandshake (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *BufferIn, OPTIONAL
+  IN     UINTN                    BufferInSize, OPTIONAL
+     OUT UINT8                    *BufferOut, OPTIONAL
+  IN OUT UINTN                    *BufferOutSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  UINTN           PendingBufferSize;
+  INTN            Ret;
+  unsigned long   ErrorCode;
+
+  TlsConn           = (TLS_CONNECTION *) Tls;
+  PendingBufferSize = 0;
+  Ret               = 1;
+
+  if (TlsConn == NULL || \
+    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \
+    BufferOutSize == NULL || \
+    (BufferIn == NULL && BufferInSize != 0) || \
+    (BufferIn != NULL && BufferInSize == 0) || \
+    (BufferOut == NULL && *BufferOutSize != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if(BufferIn == NULL && BufferInSize == 0) {
+    //
+    // If RequestBuffer is NULL and RequestSize is 0, and TLS session
+    // status is EfiTlsSessionNotStarted, the TLS session will be initiated
+    // and the response packet needs to be ClientHello.
+    //
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+    if (PendingBufferSize == 0) {
+      SSL_set_connect_state (TlsConn->Ssl);
+      Ret = SSL_do_handshake (TlsConn->Ssl);
+      PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+    }
+  } else {
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+    if (PendingBufferSize == 0) {
+      BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);
+      Ret = SSL_do_handshake (TlsConn->Ssl);
+      PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+    }
+  }
+
+  if (Ret < 1) {
+    Ret = SSL_get_error (TlsConn->Ssl, (int) Ret);
+    if (Ret == SSL_ERROR_SSL ||
+        Ret == SSL_ERROR_SYSCALL ||
+        Ret == SSL_ERROR_ZERO_RETURN) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a SSL_HANDSHAKE_ERROR State=0x%x SSL_ERROR_%a\n",
+        __FUNCTION__,
+        SSL_get_state (TlsConn->Ssl),
+        Ret == SSL_ERROR_SSL ? "SSL" : Ret == SSL_ERROR_SYSCALL ? "SYSCALL" : "ZERO_RETURN"
+        ));
+      DEBUG_CODE_BEGIN ();
+        while (TRUE) {
+          ErrorCode = ERR_get_error ();
+          if (ErrorCode == 0) {
+            break;
+          }
+          DEBUG ((
+            DEBUG_ERROR,
+            "%a ERROR 0x%x=L%x:F%x:R%x\n",
+            __FUNCTION__,
+            ErrorCode,
+            ERR_GET_LIB (ErrorCode),
+            ERR_GET_FUNC (ErrorCode),
+            ERR_GET_REASON (ErrorCode)
+            ));
+        }
+      DEBUG_CODE_END ();
+      return EFI_PROTOCOL_ERROR;
+    }
+  }
+
+  if (PendingBufferSize > *BufferOutSize) {
+    *BufferOutSize = PendingBufferSize;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (PendingBufferSize > 0) {
+    *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize);
+  } else {
+    *BufferOutSize = 0;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Hande Alert message recorded in BufferIn. If BufferIn is NULL and BufferInSize is zero,
+  TLS session has errors and the response packet needs to be Alert message based on error type.
+
+  @param[in]       Tls            Pointer to the TLS object for state checking.
+  @param[in]       BufferIn       Pointer to the most recently received TLS Alert packet.
+  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS
+                                  Alert packet.
+  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferIn is NULL but BufferInSize is NOT 0.
+                                  BufferInSize is 0 but BufferIn is NOT NULL.
+                                  BufferOutSize is NULL.
+                                  BufferOut is NULL if *BufferOutSize is not zero.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsHandeAlert (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *BufferIn, OPTIONAL
+  IN     UINTN                    BufferInSize, OPTIONAL
+     OUT UINT8                    *BufferOut, OPTIONAL
+  IN OUT UINTN                    *BufferOutSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  UINTN           PendingBufferSize;
+  UINT8           *TempBuffer;
+  INTN            Ret;
+
+  TlsConn           = (TLS_CONNECTION *) Tls;
+  PendingBufferSize = 0;
+  TempBuffer        = NULL;
+  Ret               = 0;
+
+  if (TlsConn == NULL || \
+    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \
+    BufferOutSize == NULL || \
+    (BufferIn == NULL && BufferInSize != 0) || \
+    (BufferIn != NULL && BufferInSize == 0) || \
+    (BufferOut == NULL && *BufferOutSize != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+  if (PendingBufferSize == 0 && BufferIn != NULL && BufferInSize != 0) {
+    Ret = BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);
+    if (Ret != (INTN) BufferInSize) {
+      return EFI_ABORTED;
+    }
+
+    TempBuffer = (UINT8 *) OPENSSL_malloc (MAX_BUFFER_SIZE);
+
+    //
+    // ssl3_send_alert() will be called in ssl3_read_bytes() function.
+    // TempBuffer is invalid since it's a Alert message, so just ignore it.
+    //
+    SSL_read (TlsConn->Ssl, TempBuffer, MAX_BUFFER_SIZE);
+
+    OPENSSL_free (TempBuffer);
+
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+  }
+
+  if (PendingBufferSize > *BufferOutSize) {
+    *BufferOutSize = PendingBufferSize;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (PendingBufferSize > 0) {
+    *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize);
+  } else {
+    *BufferOutSize = 0;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Build the CloseNotify packet.
+
+  @param[in]       Tls            Pointer to the TLS object for state checking.
+  @param[in, out]  Buffer         Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferSize is NULL.
+                                  Buffer is NULL if *BufferSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsCloseNotify (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *Buffer,
+  IN OUT UINTN                    *BufferSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  UINTN           PendingBufferSize;
+
+  TlsConn           = (TLS_CONNECTION *) Tls;
+  PendingBufferSize = 0;
+
+  if (TlsConn == NULL || \
+    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \
+    BufferSize == NULL || \
+    (Buffer == NULL && *BufferSize != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+  if (PendingBufferSize == 0) {
+    //
+    // ssl3_send_alert() and ssl3_dispatch_alert() function will be called.
+    //
+    SSL_shutdown (TlsConn->Ssl);
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+  }
+
+  if (PendingBufferSize > *BufferSize) {
+    *BufferSize = PendingBufferSize;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (PendingBufferSize > 0) {
+    *BufferSize = BIO_read (TlsConn->OutBio, Buffer, (UINT32) PendingBufferSize);
+  } else {
+    *BufferSize = 0;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Attempts to read bytes from one TLS object and places the data in Buffer.
+
+  This function will attempt to read BufferSize bytes from the TLS object
+  and places the data in Buffer.
+
+  @param[in]      Tls           Pointer to the TLS object.
+  @param[in,out]  Buffer        Pointer to the buffer to store the data.
+  @param[in]      BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The amount of data successfully read from the TLS object.
+  @retval  <=0   No data was successfully read.
+
+**/
+INTN
+EFIAPI
+TlsCtrlTrafficOut (
+  IN     VOID                     *Tls,
+  IN OUT VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->OutBio == 0) {
+    return -1;
+  }
+
+  //
+  // Read and return the amount of data from the BIO.
+  //
+  return BIO_read (TlsConn->OutBio, Buffer, (UINT32) BufferSize);
+}
+
+/**
+  Attempts to write data from the buffer to TLS object.
+
+  This function will attempt to write BufferSize bytes data from the Buffer
+  to the TLS object.
+
+  @param[in]  Tls           Pointer to the TLS object.
+  @param[in]  Buffer        Pointer to the data buffer.
+  @param[in]  BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The amount of data successfully written to the TLS object.
+  @retval <=0    No data was successfully written.
+
+**/
+INTN
+EFIAPI
+TlsCtrlTrafficIn (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->InBio == 0) {
+    return -1;
+  }
+
+  //
+  // Write and return the amount of data to the BIO.
+  //
+  return BIO_write (TlsConn->InBio, Buffer, (UINT32) BufferSize);
+}
+/**
+  Attempts to read bytes from the specified TLS connection into the buffer.
+
+  This function tries to read BufferSize bytes data from the specified TLS
+  connection into the Buffer.
+
+  @param[in]      Tls           Pointer to the TLS connection for data reading.
+  @param[in,out]  Buffer        Pointer to the data buffer.
+  @param[in]      BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The read operation was successful, and return value is the
+                 number of bytes actually read from the TLS connection.
+  @retval  <=0   The read operation was not successful.
+
+**/
+INTN
+EFIAPI
+TlsRead (
+  IN     VOID                     *Tls,
+  IN OUT VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return -1;
+  }
+
+  //
+  // Read bytes from the specified TLS connection.
+  //
+  return SSL_read (TlsConn->Ssl, Buffer, (UINT32) BufferSize);
+}
+
+/**
+  Attempts to write data to a TLS connection.
+
+  This function tries to write BufferSize bytes data from the Buffer into the
+  specified TLS connection.
+
+  @param[in]  Tls           Pointer to the TLS connection for data writing.
+  @param[in]  Buffer        Pointer to the data buffer.
+  @param[in]  BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The write operation was successful, and return value is the
+                 number of bytes actually written to the TLS connection.
+  @retval <=0    The write operation was not successful.
+
+**/
+INTN
+EFIAPI
+TlsWrite (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return -1;
+  }
+
+  //
+  // Write bytes to the specified TLS connection.
+  //
+  return SSL_write (TlsConn->Ssl, Buffer, (UINT32) BufferSize);
+}
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Patch 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL
  2016-12-14  7:34 [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master Jiaxin Wu
                   ` (3 preceding siblings ...)
  2016-12-14  7:34 ` [Patch 04/10] CryptoPkg: Add new TlsLib library Jiaxin Wu
@ 2016-12-14  7:34 ` Jiaxin Wu
  2016-12-14  8:41   ` Fu, Siyuan
  2016-12-14  7:34 ` [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration Jiaxin Wu
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ye Ting, Fu Siyuan, Zhang Lubo, Long Qin, Thomas Palmer,
	Wu Jiaxin

This patch is the implementation of EFI TLS Service Binding
Protocol, EFI TLS Protocol and EFI TLS Configuration Protocol
Interfaces.

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/TlsDxe/TlsConfigProtocol.c | 152 ++++++++
 NetworkPkg/TlsDxe/TlsDriver.c         | 498 +++++++++++++++++++++++++++
 NetworkPkg/TlsDxe/TlsDriver.h         | 237 +++++++++++++
 NetworkPkg/TlsDxe/TlsDxe.inf          |  65 ++++
 NetworkPkg/TlsDxe/TlsDxe.uni          |  25 ++
 NetworkPkg/TlsDxe/TlsDxeExtra.uni     |  18 +
 NetworkPkg/TlsDxe/TlsImpl.c           | 270 +++++++++++++++
 NetworkPkg/TlsDxe/TlsImpl.h           | 315 +++++++++++++++++
 NetworkPkg/TlsDxe/TlsProtocol.c       | 632 ++++++++++++++++++++++++++++++++++
 9 files changed, 2212 insertions(+)
 create mode 100644 NetworkPkg/TlsDxe/TlsConfigProtocol.c
 create mode 100644 NetworkPkg/TlsDxe/TlsDriver.c
 create mode 100644 NetworkPkg/TlsDxe/TlsDriver.h
 create mode 100644 NetworkPkg/TlsDxe/TlsDxe.inf
 create mode 100644 NetworkPkg/TlsDxe/TlsDxe.uni
 create mode 100644 NetworkPkg/TlsDxe/TlsDxeExtra.uni
 create mode 100644 NetworkPkg/TlsDxe/TlsImpl.c
 create mode 100644 NetworkPkg/TlsDxe/TlsImpl.h
 create mode 100644 NetworkPkg/TlsDxe/TlsProtocol.c

diff --git a/NetworkPkg/TlsDxe/TlsConfigProtocol.c b/NetworkPkg/TlsDxe/TlsConfigProtocol.c
new file mode 100644
index 0000000..2ec79c9
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsConfigProtocol.c
@@ -0,0 +1,152 @@
+/** @file
+  Implementation of EFI TLS Configuration Protocol Interfaces.
+
+  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.
+
+**/
+
+#include "TlsImpl.h"
+
+EFI_TLS_CONFIGURATION_PROTOCOL  mTlsConfigurationProtocol = {
+  TlsConfigurationSetData,
+  TlsConfigurationGetData
+};
+
+/**
+  Set TLS configuration data.
+
+  The SetData() function sets TLS configuration to non-volatile storage or volatile
+  storage.
+
+  @param[in]  This                Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]  DataType            Configuration data type.
+  @param[in]  Data                Pointer to configuration data.
+  @param[in]  DataSize            Total size of configuration data.
+
+  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationSetData (
+  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN     VOID                            *Data,
+  IN     UINTN                           DataSize
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+
+  if (This == NULL ||  Data == NULL || DataSize == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This);
+
+  switch (DataType) {
+  case EfiTlsConfigDataTypeCACertificate:
+    Status = TlsSetCaCertificate (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeHostPublicCert:
+    Status = TlsSetHostPublicCert (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeHostPrivateKey:
+    Status = TlsSetHostPrivateKey (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeCertRevocationList:
+    Status = TlsSetCertRevocationList (Data, DataSize);
+    break;
+  default:
+     Status = EFI_UNSUPPORTED;
+  }
+
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  Get TLS configuration data.
+
+  The GetData() function gets TLS configuration.
+
+  @param[in]       This           Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]       DataType       Configuration data type.
+  @param[in, out]  Data           Pointer to configuration data.
+  @param[in, out]  DataSize       Total size of configuration data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationGetData (
+  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN OUT VOID                            *Data, OPTIONAL
+  IN OUT UINTN                           *DataSize
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+
+  if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This);
+
+  switch (DataType) {
+  case EfiTlsConfigDataTypeCACertificate:
+    Status = TlsGetCaCertificate (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeHostPublicCert:
+    Status = TlsGetHostPublicCert (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeHostPrivateKey:
+    Status = TlsGetHostPrivateKey (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeCertRevocationList:
+    Status = TlsGetCertRevocationList (Data, DataSize);
+    break;
+  default:
+    Status = EFI_UNSUPPORTED;
+  }
+
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
diff --git a/NetworkPkg/TlsDxe/TlsDriver.c b/NetworkPkg/TlsDxe/TlsDriver.c
new file mode 100644
index 0000000..0a75c39
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDriver.c
@@ -0,0 +1,498 @@
+/** @file
+  The Driver Binding and Service Binding Protocol for TlsDxe 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.
+
+**/
+
+#include "TlsImpl.h"
+
+EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding = {
+  TlsServiceBindingCreateChild,
+  TlsServiceBindingDestroyChild
+};
+
+/**
+  Release all the resources used by the TLS instance.
+
+  @param[in]  Instance        The TLS instance data.
+
+**/
+VOID
+TlsCleanInstance (
+  IN TLS_INSTANCE           *Instance
+  )
+{
+  if (Instance != NULL) {
+    if (Instance->TlsConn != NULL) {
+      TlsFree (Instance->TlsConn);
+    }
+
+    FreePool (Instance);
+  }
+}
+
+/**
+  Create the TLS instance and initialize it.
+
+  @param[in]  Service              The pointer to the TLS service.
+  @param[out] Instance             The pointer to the TLS instance.
+
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
+  @retval EFI_SUCCESS            The TLS instance is created.
+
+**/
+EFI_STATUS
+TlsCreateInstance (
+  IN  TLS_SERVICE         *Service,
+  OUT TLS_INSTANCE        **Instance
+  )
+{
+  TLS_INSTANCE            *TlsInstance;
+
+  *Instance = NULL;
+
+  TlsInstance = AllocateZeroPool (sizeof (TLS_INSTANCE));
+  if (TlsInstance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  TlsInstance->Signature = TLS_INSTANCE_SIGNATURE;
+  InitializeListHead (&TlsInstance->Link);
+  TlsInstance->InDestroy = FALSE;
+  TlsInstance->Service   = Service;
+
+  CopyMem (&TlsInstance->Tls, &mTlsProtocol, sizeof (TlsInstance->Tls));
+  CopyMem (&TlsInstance->TlsConfig, &mTlsConfigurationProtocol, sizeof (TlsInstance->TlsConfig));
+
+  TlsInstance->TlsSessionState = EfiTlsSessionNotStarted;
+
+  *Instance = TlsInstance;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Release all the resources used by the TLS service binding instance.
+
+  @param[in]  Service        The TLS service data.
+
+**/
+VOID
+TlsCleanService (
+  IN TLS_SERVICE     *Service
+  )
+{
+  if (Service != NULL) {
+    if (Service->TlsCtx != NULL) {
+      TlsCtxFree (Service->TlsCtx);
+    }
+
+    FreePool (Service);
+  }
+}
+
+/**
+  Create then initialize a TLS service.
+
+  @param[in]  Image                  ImageHandle of the TLS driver
+  @param[out] Service                The service for TLS driver
+
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create the service.
+  @retval EFI_SUCCESS            The service is created for the driver.
+
+**/
+EFI_STATUS
+TlsCreateService (
+  IN  EFI_HANDLE            Image,
+  OUT TLS_SERVICE           **Service
+  )
+{
+  EFI_STATUS             Status;
+  TLS_SERVICE            *TlsService;
+
+  Status = EFI_SUCCESS;
+  *Service = NULL;
+
+  ASSERT (Service != NULL);
+
+  //
+  // Allocate a TLS Service Data
+  //
+  TlsService = AllocateZeroPool (sizeof (TLS_SERVICE));
+  if (TlsService == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize TLS Service Data
+  //
+  TlsService->Signature        = TLS_SERVICE_SIGNATURE;
+  CopyMem (&TlsService->ServiceBinding, &mTlsServiceBinding, sizeof (TlsService->ServiceBinding));
+  TlsService->TlsChildrenNum   = 0;
+  InitializeListHead (&TlsService->TlsChildrenList);
+  TlsService->ImageHandle      = Image;
+
+  *Service = TlsService;
+
+  return Status;
+}
+
+/**
+  Unloads an image.
+
+  @param[in]  ImageHandle           Handle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           HandleNum;
+  EFI_HANDLE                      *HandleBuffer;
+  UINT32                          Index;
+  EFI_SERVICE_BINDING_PROTOCOL    *ServiceBinding;
+  TLS_SERVICE                     *TlsService;
+
+  HandleBuffer   = NULL;
+  ServiceBinding = NULL;
+  TlsService     = NULL;
+
+  //
+  // Locate all the handles with Tls service binding protocol.
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiTlsServiceBindingProtocolGuid,
+                  NULL,
+                  &HandleNum,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Index = 0; Index < HandleNum; Index++) {
+    //
+    // Firstly, find ServiceBinding interface
+    //
+    Status = gBS->OpenProtocol (
+                    HandleBuffer[Index],
+                    &gEfiTlsServiceBindingProtocolGuid,
+                    (VOID **) &ServiceBinding,
+                    ImageHandle,
+                    NULL,
+                    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+                    );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    TlsService = TLS_SERVICE_FROM_THIS (ServiceBinding);
+
+    //
+    // Then, uninstall ServiceBinding interface
+    //
+    Status = gBS->UninstallMultipleProtocolInterfaces (
+                    HandleBuffer[Index],
+                    &gEfiTlsServiceBindingProtocolGuid, ServiceBinding,
+                    NULL
+                    );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    TlsCleanService (TlsService);
+  }
+
+  if (HandleBuffer != NULL) {
+    FreePool (HandleBuffer);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS             Status;
+
+  TLS_SERVICE            *TlsService;
+
+  //
+  // Create TLS Service
+  //
+  Status = TlsCreateService (ImageHandle, &TlsService);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ASSERT (TlsService != NULL);
+
+  //
+  // Initializes the OpenSSL library.
+  //
+  TlsInitialize ();
+
+  //
+  // Create a new SSL_CTX object as framework to establish TLS/SSL enabled
+  // connections. TLS 1.0 is used as the default version.
+  //
+  TlsService->TlsCtx = TlsCtxNew (TLS10_PROTOCOL_VERSION_MAJOR, TLS10_PROTOCOL_VERSION_MINOR);
+  if (TlsService->TlsCtx == NULL) {
+    FreePool (TlsService);
+    return EFI_ABORTED;
+  }
+
+  //
+  // Install the TlsServiceBinding Protocol onto Handle
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &TlsService->Handle,
+                  &gEfiTlsServiceBindingProtocolGuid,
+                  &TlsService->ServiceBinding,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_CLEAN_SERVICE;
+  }
+
+  return Status;
+
+ON_CLEAN_SERVICE:
+  TlsCleanService (TlsService);
+
+  return Status;
+}
+
+/**
+  Creates a child handle and installs a protocol.
+
+  The CreateChild() function installs a protocol on ChildHandle.
+  If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+  If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+  @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+  @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+                         then a new handle is created. If it is a pointer to an existing UEFI handle,
+                         then the protocol is added to the existing UEFI handle.
+
+  @retval EFI_SUCCES            The protocol was added to ChildHandle.
+  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create
+                                the child.
+  @retval other                 The child handle was not created.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingCreateChild (
+  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                    *ChildHandle
+  )
+{
+  TLS_SERVICE         *TlsService;
+  TLS_INSTANCE        *TlsInstance;
+  EFI_STATUS           Status;
+  EFI_TPL              OldTpl;
+
+  if ((This == NULL) || (ChildHandle == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TlsService = TLS_SERVICE_FROM_THIS (This);
+
+  Status = TlsCreateInstance (TlsService, &TlsInstance);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ASSERT (TlsInstance != NULL);
+
+  //
+  // Create a new TLS connection object.
+  //
+  TlsInstance->TlsConn = TlsNew (TlsService->TlsCtx);
+  if (TlsInstance->TlsConn == NULL) {
+    Status = EFI_ABORTED;
+    goto ON_ERROR;
+  }
+
+  //
+  // Set default ConnectionEnd to EfiTlsClient
+  //
+  Status = TlsSetConnectionEnd (TlsInstance->TlsConn, EfiTlsClient);
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  //
+  // Install TLS protocol and configuration protocol onto ChildHandle
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  ChildHandle,
+                  &gEfiTlsProtocolGuid,
+                  &TlsInstance->Tls,
+                  &gEfiTlsConfigurationProtocolGuid,
+                  &TlsInstance->TlsConfig,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  TlsInstance->ChildHandle = *ChildHandle;
+
+  //
+  // Add it to the TLS service's child list.
+  //
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  InsertTailList (&TlsService->TlsChildrenList, &TlsInstance->Link);
+  TlsService->TlsChildrenNum++;
+
+  gBS->RestoreTPL (OldTpl);
+
+  return EFI_SUCCESS;
+
+ON_ERROR:
+  TlsCleanInstance (TlsInstance);
+  return Status;
+}
+
+/**
+  Destroys a child handle with a protocol installed on it.
+
+  The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+  that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+  last protocol on ChildHandle, then ChildHandle is destroyed.
+
+  @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+  @param  ChildHandle Handle of the child to destroy.
+
+  @retval EFI_SUCCES            The protocol was removed from ChildHandle.
+  @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.
+  @retval EFI_INVALID_PARAMETER Child handle is NULL.
+  @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle
+                                because its services are being used.
+  @retval other                 The child handle was not destroyed.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingDestroyChild (
+  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                    ChildHandle
+  )
+{
+  TLS_SERVICE                    *TlsService;
+  TLS_INSTANCE                   *TlsInstance;
+
+  EFI_TLS_PROTOCOL               *Tls;
+  EFI_TLS_CONFIGURATION_PROTOCOL *TlsConfig;
+  EFI_STATUS                     Status;
+  EFI_TPL                        OldTpl;
+
+  if ((This == NULL) || (ChildHandle == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TlsService = TLS_SERVICE_FROM_THIS (This);
+
+  //
+  // Find TLS protocol interface installed in ChildHandle
+  //
+  Status = gBS->OpenProtocol (
+                  ChildHandle,
+                  &gEfiTlsProtocolGuid,
+                  (VOID **) &Tls,
+                  TlsService->ImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Find TLS configuration protocol interface installed in ChildHandle
+  //
+  Status = gBS->OpenProtocol (
+                  ChildHandle,
+                  &gEfiTlsConfigurationProtocolGuid,
+                  (VOID **) &TlsConfig,
+                  TlsService->ImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  TlsInstance  = TLS_INSTANCE_FROM_PROTOCOL_THIS (Tls);
+
+  if (TlsInstance->Service != TlsService) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (TlsInstance->InDestroy) {
+    return EFI_SUCCESS;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  TlsInstance->InDestroy = TRUE;
+
+  //
+  // Uninstall the TLS protocol and TLS Configuration Protocol interface installed in ChildHandle.
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  ChildHandle,
+                  &gEfiTlsProtocolGuid,
+                  Tls,
+                  &gEfiTlsConfigurationProtocolGuid,
+                  TlsConfig,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  RemoveEntryList (&TlsInstance->Link);
+  TlsService->TlsChildrenNum--;
+
+  gBS->RestoreTPL (OldTpl);
+
+  TlsCleanInstance (TlsInstance);
+
+  return EFI_SUCCESS;
+}
diff --git a/NetworkPkg/TlsDxe/TlsDriver.h b/NetworkPkg/TlsDxe/TlsDriver.h
new file mode 100644
index 0000000..c3c30a8
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDriver.h
@@ -0,0 +1,237 @@
+/** @file
+  Header file of the Driver Binding and Service Binding Protocol for TlsDxe 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_TLS_DRIVER_H__
+#define __EFI_TLS_DRIVER_H__
+
+#include <Uefi.h>
+
+//
+// Driver Protocols
+//
+#include <Protocol/ServiceBinding.h>
+
+//
+// Driver Version
+//
+#define TLS_VERSION  0x00000000
+
+#define TLS_SERVICE_SIGNATURE    SIGNATURE_32 ('T', 'L', 'S', 'S')
+
+#define TLS_INSTANCE_SIGNATURE   SIGNATURE_32 ('T', 'L', 'S', 'I')
+
+///
+/// TLS Service Data
+///
+typedef struct _TLS_SERVICE  TLS_SERVICE;
+
+///
+/// TLS Instance Data
+///
+typedef struct _TLS_INSTANCE TLS_INSTANCE;
+
+
+struct _TLS_SERVICE {
+  UINT32                          Signature;
+  EFI_SERVICE_BINDING_PROTOCOL    ServiceBinding;
+
+  UINT16                          TlsChildrenNum;
+  LIST_ENTRY                      TlsChildrenList;
+
+  //
+  // Handle to install TlsServiceBinding protocol.
+  //
+  EFI_HANDLE                      Handle;
+  EFI_HANDLE                      ImageHandle;
+
+  //
+  // Main SSL Context object which is created by a server or client once per program
+  // life-time and which holds mainly default values for the SSL object which are later
+  // created for the connections.
+  //
+  VOID                            *TlsCtx;
+};
+
+struct _TLS_INSTANCE {
+  UINT32                          Signature;
+  LIST_ENTRY                      Link;
+
+  BOOLEAN                         InDestroy;
+
+  TLS_SERVICE                     *Service;
+  EFI_HANDLE                      ChildHandle;
+
+  EFI_TLS_PROTOCOL                Tls;
+  EFI_TLS_CONFIGURATION_PROTOCOL  TlsConfig;
+
+  EFI_TLS_SESSION_STATE           TlsSessionState;
+
+  //
+  // Main SSL Connection which is created by a server or a client
+  // per established connection.
+  //
+  VOID                            *TlsConn;
+};
+
+
+#define TLS_SERVICE_FROM_THIS(a)   \
+  CR (a, TLS_SERVICE, ServiceBinding, TLS_SERVICE_SIGNATURE)
+
+#define TLS_INSTANCE_FROM_PROTOCOL_THIS(a)  \
+  CR (a, TLS_INSTANCE, Tls, TLS_INSTANCE_SIGNATURE)
+
+#define TLS_INSTANCE_FROM_CONFIGURATION_THIS(a)  \
+  CR (a, TLS_INSTANCE, TlsConfig, TLS_INSTANCE_SIGNATURE)
+
+
+/**
+  Release all the resources used by the TLS instance.
+
+  @param[in]  Instance        The TLS instance data.
+
+**/
+VOID
+TlsCleanInstance (
+  IN TLS_INSTANCE           *Instance
+  );
+
+/**
+  Create the TLS instance and initialize it.
+
+  @param[in]  Service              The pointer to the TLS service.
+  @param[out] Instance             The pointer to the TLS instance.
+
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
+  @retval EFI_SUCCESS            The TLS instance is created.
+
+**/
+EFI_STATUS
+TlsCreateInstance (
+  IN  TLS_SERVICE         *Service,
+  OUT TLS_INSTANCE        **Instance
+  );
+
+/**
+  Release all the resources used by the TLS service binding instance.
+
+  @param[in]  Service        The TLS service data.
+
+**/
+VOID
+TlsCleanService (
+  IN TLS_SERVICE     *Service
+  );
+
+/**
+  Create then initialize a TLS service.
+
+  @param[in]  Image                  ImageHandle of the TLS driver
+  @param[out] Service                The service for TLS driver
+
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create the service.
+  @retval EFI_SUCCESS            The service is created for the driver.
+
+**/
+EFI_STATUS
+TlsCreateService (
+  IN  EFI_HANDLE            Image,
+  OUT TLS_SERVICE           **Service
+  );
+
+/**
+  Unloads an image.
+
+  @param[in]  ImageHandle       Handle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsUnload (
+  IN EFI_HANDLE  ImageHandle
+  );
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+/**
+  Creates a child handle and installs a protocol.
+
+  The CreateChild() function installs a protocol on ChildHandle.
+  If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+  If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+  @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+  @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+                         then a new handle is created. If it is a pointer to an existing UEFI handle,
+                         then the protocol is added to the existing UEFI handle.
+
+  @retval EFI_SUCCES            The protocol was added to ChildHandle.
+  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create
+                                the child.
+  @retval other                 The child handle was not created.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingCreateChild (
+  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                    *ChildHandle
+  );
+
+/**
+  Destroys a child handle with a protocol installed on it.
+
+  The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+  that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+  last protocol on ChildHandle, then ChildHandle is destroyed.
+
+  @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+  @param  ChildHandle Handle of the child to destroy.
+
+  @retval EFI_SUCCES            The protocol was removed from ChildHandle.
+  @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.
+  @retval EFI_INVALID_PARAMETER Child handle is NULL.
+  @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle
+                                because its services are being used.
+  @retval other                 The child handle was not destroyed.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingDestroyChild (
+  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                    ChildHandle
+  );
+
+#endif
diff --git a/NetworkPkg/TlsDxe/TlsDxe.inf b/NetworkPkg/TlsDxe/TlsDxe.inf
new file mode 100644
index 0000000..dba3257
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDxe.inf
@@ -0,0 +1,65 @@
+## @file
+#  This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and
+#  EFI TLS Configuration Protocol.
+#
+#  This module produces EFI TLS (Transport Layer Security) Protocol and EFI TLS
+#  Service Binding Protocol, to provide TLS services.
+#
+#  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.
+#
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = TlsDxe
+  FILE_GUID                 = 3aceb0c0-3c72-11e4-9a56-74d435052646
+  MODULE_TYPE               = UEFI_DRIVER
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = TlsDriverEntryPoint
+  UNLOAD_IMAGE              = TlsUnload
+  MODULE_UNI_FILE           = TlsDxe.uni
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  CryptoPkg/CryptoPkg.dec
+
+[Sources]
+  TlsDriver.h
+  TlsDriver.c
+  TlsProtocol.c
+  TlsConfigProtocol.c
+  TlsImpl.h
+  TlsImpl.c
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  BaseLib
+  UefiLib
+  DebugLib
+  NetLib
+  BaseCryptLib
+  TlsLib
+
+[Protocols]
+  gEfiTlsServiceBindingProtocolGuid          ## PRODUCES
+  gEfiTlsProtocolGuid                        ## PRODUCES
+  gEfiTlsConfigurationProtocolGuid           ## PRODUCES
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  TlsDxeExtra.uni
diff --git a/NetworkPkg/TlsDxe/TlsDxe.uni b/NetworkPkg/TlsDxe/TlsDxe.uni
new file mode 100644
index 0000000..98c41ca
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDxe.uni
@@ -0,0 +1,25 @@
+// /** @file
+// This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and
+// EFI TLS Configuration Protocol.
+//
+// This module produces EFI TLS (Transport Layer Security) Protocol, EFI TLS
+// Service Binding Protocol, and EFI TLS Configuration Protocol to provide TLS
+// services.
+//
+// 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.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "UEFI TLS service"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and EFI TLS Configuration Protocol to provide EFI TLS services."
+
diff --git a/NetworkPkg/TlsDxe/TlsDxeExtra.uni b/NetworkPkg/TlsDxe/TlsDxeExtra.uni
new file mode 100644
index 0000000..a38582a
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDxeExtra.uni
@@ -0,0 +1,18 @@
+// /** @file
+// TlsDxe Localized Strings and Content
+//
+// 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.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"EFI TLS DXE Driver"
diff --git a/NetworkPkg/TlsDxe/TlsImpl.c b/NetworkPkg/TlsDxe/TlsImpl.c
new file mode 100644
index 0000000..5fb1e78
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsImpl.c
@@ -0,0 +1,270 @@
+/** @file
+  The Miscellaneous Routines for TlsDxe 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.
+
+**/
+
+#include "TlsImpl.h"
+
+/**
+  Encrypt the message listed in fragment.
+
+  @param[in]       TlsInstance    The pointer to the TLS instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment.
+                                  On input these fragments contain the TLS header and
+                                  plain text TLS payload;
+                                  On output these fragments contain the TLS header and
+                                  cipher text TLS payload.
+  @param[in]       FragmentCount  Number of fragment.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
+  @retval EFI_ABORTED             TLS session state is incorrect.
+  @retval Others                  Other errors as indicated.
+**/
+EFI_STATUS
+TlsEcryptPacket (
+  IN     TLS_INSTANCE                  *TlsInstance,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount
+  )
+{
+  UINTN               Index;
+  UINT32              BytesCopied;
+  UINT32              BufferInSize;
+  UINT8               *BufferIn;
+  UINT8               *BufferInPtr;
+  TLS_RECORD_HEADER   *RecordHeaderIn;
+  UINT16              ThisPlainMessageSize;
+  TLS_RECORD_HEADER   *TempRecordHeader;
+  UINT16              ThisMessageSize;
+  UINT32              BufferOutSize;
+  UINT8               *BufferOut;
+  INTN                Ret;
+
+  BytesCopied      = 0;
+  BufferInSize     = 0;
+  BufferIn         = NULL;
+  BufferInPtr      = NULL;
+  RecordHeaderIn   = NULL;
+  TempRecordHeader = NULL;
+  BufferOutSize    = 0;
+  BufferOut        = NULL;
+  Ret              = 0;
+
+  //
+  // Calculate the size according to the fragment table.
+  //
+  for (Index = 0; Index < *FragmentCount; Index++) {
+    BufferInSize += (*FragmentTable)[Index].FragmentLength;
+  }
+
+  //
+  // Allocate buffer for processing data.
+  //
+  BufferIn = AllocateZeroPool (BufferInSize);
+  if (BufferIn == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Copy all TLS plain record header and payload into ProcessBuffer.
+  //
+  for (Index = 0; Index < *FragmentCount; Index++) {
+    CopyMem (
+      (BufferIn + BytesCopied),
+      (*FragmentTable)[Index].FragmentBuffer,
+      (*FragmentTable)[Index].FragmentLength
+      );
+    BytesCopied += (*FragmentTable)[Index].FragmentLength;
+  }
+
+  BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE);
+  if (BufferOut == NULL) {
+    FreePool (BufferIn);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Parsing buffer.
+  //
+  BufferInPtr = BufferIn;
+  TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
+  while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
+    RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
+    ASSERT (RecordHeaderIn->ContentType == TLS_CONTENT_TYPE_APPLICATION_DATA);
+    ThisPlainMessageSize = RecordHeaderIn->Length;
+
+    TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), ThisPlainMessageSize);
+    
+    Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader), MAX_BUFFER_SIZE);
+
+    if (Ret > 0) {
+      ThisMessageSize = (UINT16) Ret;
+    } else {
+      ThisMessageSize = 0;
+    }
+
+    BufferOutSize += ThisMessageSize;
+
+    BufferInPtr += RECORD_HEADER_LEN + ThisPlainMessageSize;
+    TempRecordHeader += ThisMessageSize;
+  }
+
+  FreePool (BufferIn);
+
+  //
+  // The caller will take responsible to handle the original fragment table.
+  //
+  *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
+  if (*FragmentTable == NULL) {
+    FreePool (BufferOut);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  (*FragmentTable)[0].FragmentBuffer  = BufferOut;
+  (*FragmentTable)[0].FragmentLength  = BufferOutSize;
+  *FragmentCount                      = 1;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Decrypt the message listed in fragment.
+
+  @param[in]       TlsInstance    The pointer to the TLS instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment.
+                                  On input these fragments contain the TLS header and
+                                  cipher text TLS payload;
+                                  On output these fragments contain the TLS header and
+                                  plain text TLS payload.
+  @param[in]       FragmentCount  Number of fragment.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
+  @retval EFI_ABORTED             TLS session state is incorrect.
+  @retval Others                  Other errors as indicated.
+**/
+EFI_STATUS
+TlsDecryptPacket (
+  IN     TLS_INSTANCE                  *TlsInstance,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount
+  )
+{
+  UINTN               Index;
+  UINT32              BytesCopied;
+  UINT8               *BufferIn;
+  UINT32              BufferInSize;
+  UINT8               *BufferInPtr;
+  TLS_RECORD_HEADER   *RecordHeaderIn;
+  UINT16              ThisCipherMessageSize;
+  TLS_RECORD_HEADER   *TempRecordHeader;
+  UINT16              ThisPlainMessageSize;
+  UINT8               *BufferOut;
+  UINT32              BufferOutSize;
+  INTN                Ret;
+
+  BytesCopied      = 0;
+  BufferIn         = NULL;
+  BufferInSize     = 0;
+  BufferInPtr      = NULL;
+  RecordHeaderIn   = NULL;
+  TempRecordHeader = NULL;
+  BufferOut        = NULL;
+  BufferOutSize    = 0;
+  Ret              = 0;
+
+  //
+  // Calculate the size according to the fragment table.
+  //
+  for (Index = 0; Index < *FragmentCount; Index++) {
+    BufferInSize += (*FragmentTable)[Index].FragmentLength;
+  }
+
+  //
+  // Allocate buffer for processing data
+  //
+  BufferIn = AllocateZeroPool (BufferInSize);
+  if (BufferIn == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Copy all TLS plain record header and payload to ProcessBuffer
+  //
+  for (Index = 0; Index < *FragmentCount; Index++) {
+    CopyMem (
+      (BufferIn + BytesCopied),
+      (*FragmentTable)[Index].FragmentBuffer,
+      (*FragmentTable)[Index].FragmentLength
+      );
+    BytesCopied += (*FragmentTable)[Index].FragmentLength;
+  }
+
+  BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE);
+  if (BufferOut == NULL) {
+    FreePool (BufferIn);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Parsing buffer. Received packet may have multiply TLS record message.
+  //
+  BufferInPtr = BufferIn;
+  TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
+  while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
+    RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
+    ASSERT (RecordHeaderIn->ContentType == TLS_CONTENT_TYPE_APPLICATION_DATA);
+    ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length);
+
+    Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn), RECORD_HEADER_LEN + ThisCipherMessageSize);
+    if (Ret != RECORD_HEADER_LEN + ThisCipherMessageSize) {
+      FreePool (BufferIn);
+      TlsInstance->TlsSessionState = EfiTlsSessionError;
+      return EFI_ABORTED;
+    }
+
+    Ret = 0;
+    Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1), MAX_BUFFER_SIZE);
+
+    if (Ret > 0) {
+      ThisPlainMessageSize = (UINT16) Ret;
+    } else {
+      ThisPlainMessageSize = 0;
+    }
+
+    CopyMem (TempRecordHeader, RecordHeaderIn, RECORD_HEADER_LEN);
+    TempRecordHeader->Length = ThisPlainMessageSize;
+    BufferOutSize += RECORD_HEADER_LEN + ThisPlainMessageSize;
+
+    BufferInPtr += RECORD_HEADER_LEN + ThisCipherMessageSize;
+    TempRecordHeader += RECORD_HEADER_LEN + ThisPlainMessageSize;
+  }
+
+  FreePool (BufferIn);
+
+  //
+  // The caller will take responsible to handle the original fragment table
+  //
+  *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
+  if (*FragmentTable == NULL) {
+    FreePool (BufferOut);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  (*FragmentTable)[0].FragmentBuffer  = BufferOut;
+  (*FragmentTable)[0].FragmentLength  = BufferOutSize;
+  *FragmentCount                      = 1;
+
+  return EFI_SUCCESS;
+}
diff --git a/NetworkPkg/TlsDxe/TlsImpl.h b/NetworkPkg/TlsDxe/TlsImpl.h
new file mode 100644
index 0000000..b0615cb
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsImpl.h
@@ -0,0 +1,315 @@
+/** @file
+  Header file of Miscellaneous Routines for TlsDxe 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_TLS_IMPL_H__
+#define __EFI_TLS_IMPL_H__
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/NetLib.h>
+#include <Library/BaseCryptLib.h>
+#include <Library/TlsLib.h>
+
+//
+// Consumed Protocols
+//
+#include <Protocol/Tls.h>
+#include <Protocol/TlsConfig.h>
+
+#include <IndustryStandard/Tls1.h>
+
+#include "TlsDriver.h"
+
+//
+// Protocol instances
+//
+extern EFI_SERVICE_BINDING_PROTOCOL    mTlsServiceBinding;
+extern EFI_TLS_PROTOCOL                mTlsProtocol;
+extern EFI_TLS_CONFIGURATION_PROTOCOL  mTlsConfigurationProtocol;
+
+#define RECORD_HEADER_LEN 5 /// ContentType(1) + Version(2) + Length(2)
+
+#define MAX_BUFFER_SIZE   32768
+
+/**
+  Encrypt the message listed in fragment.
+
+  @param[in]       TlsInstance    The pointer to the TLS instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment.
+                                  On input these fragments contain the TLS header and
+                                  plain text TLS payload;
+                                  On output these fragments contain the TLS header and
+                                  cipher text TLS payload.
+  @param[in]       FragmentCount  Number of fragment.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
+  @retval EFI_ABORTED             TLS session state is incorrect.
+  @retval Others                  Other errors as indicated.
+**/
+EFI_STATUS
+TlsEcryptPacket (
+  IN     TLS_INSTANCE                  *TlsInstance,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount
+  );
+
+/**
+  Decrypt the message listed in fragment.
+
+  @param[in]       TlsInstance    The pointer to the TLS instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment.
+                                  On input these fragments contain the TLS header and
+                                  cipher text TLS payload;
+                                  On output these fragments contain the TLS header and
+                                  plain text TLS payload.
+  @param[in]       FragmentCount  Number of fragment.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
+  @retval EFI_ABORTED             TLS session state is incorrect.
+  @retval Others                  Other errors as indicated.
+**/
+EFI_STATUS
+TlsDecryptPacket (
+  IN     TLS_INSTANCE                  *TlsInstance,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount
+  );
+
+/**
+  Set TLS session data.
+
+  The SetSessionData() function set data for a new TLS session. All session data should
+  be set before BuildResponsePacket() invoked.
+
+  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]  DataType            TLS session data type.
+  @param[in]  Data                Pointer to session data.
+  @param[in]  DataSize            Total size of session data.
+
+  @retval EFI_SUCCESS             The TLS session data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
+                                  EfiTlsClientRandom
+                                  EfiTlsServerRandom
+                                  EfiTlsKeyMaterial
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionStateNotStarted.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+TlsSetSessionData (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
+  IN     VOID                          *Data,
+  IN     UINTN                         DataSize
+  );
+
+/**
+  Get TLS session data.
+
+  The GetSessionData() function return the TLS session information.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       DataType       TLS session data type.
+  @param[in, out]  Data           Pointer to session data.
+  @param[in, out]  DataSize       Total size of session data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS session data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS session data is not found.
+  @retval EFI_NOT_READY           The DataType is not ready in current session state.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsGetSessionData (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
+  IN OUT VOID                          *Data,  OPTIONAL
+  IN OUT UINTN                         *DataSize
+  );
+
+/**
+  Build response packet according to TLS state machine. This function is only valid for
+  alert, handshake and change_cipher_spec content type.
+
+  The BuildResponsePacket() function builds TLS response packet in response to the TLS
+  request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and
+  RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session
+  will be initiated and the response packet needs to be ClientHello. If RequestBuffer is
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS
+  session will be closed and response packet needs to be CloseNotify. If RequestBuffer is
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS
+  session has errors and the response packet needs to be Alert message based on error
+  type.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       RequestBuffer  Pointer to the most recently received TLS packet. NULL
+                                  means TLS need initiate the TLS session and response
+                                  packet need to be ClientHello.
+  @param[in]       RequestSize    Packet size in bytes for the most recently received TLS
+                                  packet. 0 is only valid when RequestBuffer is NULL.
+  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  RequestBuffer is NULL but RequestSize is NOT 0.
+                                  RequestSize is 0 but RequestBuffer is NOT NULL.
+                                  BufferSize is NULL.
+                                  Buffer is NULL if *BufferSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.
+  @retval EFI_NOT_READY           Current TLS session state is NOT ready to build
+                                  ResponsePacket.
+  @retval EFI_ABORTED             Something wrong build response packet.
+**/
+EFI_STATUS
+EFIAPI
+TlsBuildResponsePacket (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     UINT8                         *RequestBuffer, OPTIONAL
+  IN     UINTN                         RequestSize, OPTIONAL
+     OUT UINT8                         *Buffer, OPTIONAL
+  IN OUT UINTN                         *BufferSize
+  );
+
+/**
+  Decrypt or encrypt TLS packet during session. This function is only valid after
+  session connected and for application_data content type.
+
+  The ProcessPacket () function process each inbound or outbound TLS APP packet.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment. The caller will take
+                                  responsible to handle the original FragmentTable while
+                                  it may be reallocated in TLS driver. If CryptMode is
+                                  EfiTlsEncrypt, on input these fragments contain the TLS
+                                  header and plain text TLS APP payload; on output these
+                                  fragments contain the TLS header and cipher text TLS
+                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
+                                  these fragments contain the TLS header and cipher text
+                                  TLS APP payload; on output these fragments contain the
+                                  TLS header and plain text TLS APP payload.
+  @param[in]       FragmentCount  Number of fragment.
+  @param[in]       CryptMode      Crypt mode.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  FragmentTable is NULL.
+                                  FragmentCount is NULL.
+                                  CryptoMode is invalid.
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionDataTransferring.
+  @retval EFI_ABORTED             Something wrong decryption the message. TLS session
+                                  status will become EfiTlsSessionError. The caller need
+                                  call BuildResponsePacket() to generate Error Alert
+                                  message and send it out.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the operation.
+**/
+EFI_STATUS
+EFIAPI
+TlsProcessPacket (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount,
+  IN     EFI_TLS_CRYPT_MODE            CryptMode
+  );
+
+/**
+  Set TLS configuration data.
+
+  The SetData() function sets TLS configuration to non-volatile storage or volatile
+  storage.
+
+  @param[in]  This                Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]  DataType            Configuration data type.
+  @param[in]  Data                Pointer to configuration data.
+  @param[in]  DataSize            Total size of configuration data.
+
+  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationSetData (
+  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN     VOID                            *Data,
+  IN     UINTN                           DataSize
+  );
+
+/**
+  Get TLS configuration data.
+
+  The GetData() function gets TLS configuration.
+
+  @param[in]       This           Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]       DataType       Configuration data type.
+  @param[in, out]  Data           Pointer to configuration data.
+  @param[in, out]  DataSize       Total size of configuration data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationGetData (
+  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN OUT VOID                            *Data, OPTIONAL
+  IN OUT UINTN                           *DataSize
+  );
+
+#endif
diff --git a/NetworkPkg/TlsDxe/TlsProtocol.c b/NetworkPkg/TlsDxe/TlsProtocol.c
new file mode 100644
index 0000000..bc617e1
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsProtocol.c
@@ -0,0 +1,632 @@
+/** @file
+  Implementation of EFI TLS Protocol Interfaces.
+
+  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.
+
+**/
+
+#include "TlsImpl.h"
+
+EFI_TLS_PROTOCOL  mTlsProtocol = {
+  TlsSetSessionData,
+  TlsGetSessionData,
+  TlsBuildResponsePacket,
+  TlsProcessPacket
+};
+
+/**
+  Set TLS session data.
+
+  The SetSessionData() function set data for a new TLS session. All session data should
+  be set before BuildResponsePacket() invoked.
+
+  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]  DataType            TLS session data type.
+  @param[in]  Data                Pointer to session data.
+  @param[in]  DataSize            Total size of session data.
+
+  @retval EFI_SUCCESS             The TLS session data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
+                                  EfiTlsClientRandom
+                                  EfiTlsServerRandom
+                                  EfiTlsKeyMaterial
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionStateNotStarted.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+TlsSetSessionData (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
+  IN     VOID                          *Data,
+  IN     UINTN                         DataSize
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+  UINT16                    *CipherId;
+  UINTN                     Index;
+
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+  CipherId = NULL;
+
+  if (This == NULL || Data == NULL || DataSize == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
+
+  if (DataType != EfiTlsSessionState  && Instance->TlsSessionState != EfiTlsSessionNotStarted){
+    Status = EFI_NOT_READY;
+    goto ON_EXIT;
+  }
+
+  switch (DataType) {
+  //
+  // Session Configuration
+  //
+  case EfiTlsVersion:
+    if (DataSize != sizeof (EFI_TLS_VERSION)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    Status = TlsSetVersion (Instance->TlsConn, ((EFI_TLS_VERSION *) Data)->Major, ((EFI_TLS_VERSION *) Data)->Minor);
+    break;
+  case EfiTlsConnectionEnd:
+    if (DataSize != sizeof (EFI_TLS_CONNECTION_END)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    Status = TlsSetConnectionEnd (Instance->TlsConn, *((EFI_TLS_CONNECTION_END *) Data));
+    break;
+  case EfiTlsCipherList:
+    CipherId = AllocatePool (DataSize);
+    if (CipherId == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ON_EXIT;
+    }
+
+    for (Index = 0; Index < DataSize / sizeof (EFI_TLS_CIPHER); Index++) {
+      *(CipherId +Index) = HTONS (*(((UINT16 *) Data) + Index));
+    }
+
+    Status = TlsSetCipherList (Instance->TlsConn, CipherId, DataSize / sizeof (EFI_TLS_CIPHER));
+
+    FreePool (CipherId);
+    break;
+  case EfiTlsCompressionMethod:
+    //
+    // TLS seems only define one CompressionMethod.null, which specifies that data exchanged via the
+    // record protocol will not be compressed.
+    // More information from OpenSSL: http://www.openssl.org/docs/manmaster/ssl/SSL_COMP_add_compression_method.html
+    // The TLS RFC does however not specify compression methods or their corresponding identifiers,
+    // so there is currently no compatible way to integrate compression with unknown peers.
+    // It is therefore currently not recommended to integrate compression into applications.
+    // Applications for non-public use may agree on certain compression methods.
+    // Using different compression methods with the same identifier will lead to connection failure.
+    //
+    for (Index = 0; Index < DataSize / sizeof (EFI_TLS_COMPRESSION); Index++) {
+      Status = TlsSetCompressionMethod (*((UINT8 *) Data + Index));
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+    }
+
+    break;
+  case EfiTlsExtensionData:
+    Status = EFI_UNSUPPORTED;
+    goto ON_EXIT;
+  case EfiTlsVerifyMethod:
+    if (DataSize != sizeof (EFI_TLS_VERIFY)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    TlsSetVerify (Instance->TlsConn, *((UINT32 *) Data));
+    break;
+  case EfiTlsSessionID:
+    if (DataSize != sizeof (EFI_TLS_SESSION_ID)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    Status = TlsSetSessionId (
+               Instance->TlsConn,
+               ((EFI_TLS_SESSION_ID *) Data)->Data,
+               ((EFI_TLS_SESSION_ID *) Data)->Length
+               );
+    break;
+  case EfiTlsSessionState:
+    if (DataSize != sizeof (EFI_TLS_SESSION_STATE)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    Instance->TlsSessionState = *(EFI_TLS_SESSION_STATE *) Data;
+    break;
+  //
+  // Session information
+  //
+  case EfiTlsClientRandom:
+    Status = EFI_ACCESS_DENIED;
+    break;
+  case EfiTlsServerRandom:
+    Status = EFI_ACCESS_DENIED;
+    break;
+  case EfiTlsKeyMaterial:
+    Status = EFI_ACCESS_DENIED;
+    break;
+  //
+  // Unsupported type.
+  //
+  default:
+    Status = EFI_UNSUPPORTED;
+  }
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  Get TLS session data.
+
+  The GetSessionData() function return the TLS session information.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       DataType       TLS session data type.
+  @param[in, out]  Data           Pointer to session data.
+  @param[in, out]  DataSize       Total size of session data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS session data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS session data is not found.
+  @retval EFI_NOT_READY           The DataType is not ready in current session state.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsGetSessionData (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
+  IN OUT VOID                          *Data,  OPTIONAL
+  IN OUT UINTN                         *DataSize
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+
+  if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
+
+  if (Instance->TlsSessionState == EfiTlsSessionNotStarted &&
+    (DataType == EfiTlsSessionID || DataType == EfiTlsClientRandom ||
+    DataType == EfiTlsServerRandom || DataType == EfiTlsKeyMaterial)) {
+    Status = EFI_NOT_READY;
+    goto ON_EXIT;
+  }
+
+  switch (DataType) {
+  case EfiTlsVersion:
+    if (*DataSize < sizeof (EFI_TLS_VERSION)) {
+      *DataSize = sizeof (EFI_TLS_VERSION);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_VERSION);
+    *((UINT16 *) Data) = HTONS (TlsGetVersion (Instance->TlsConn));
+    break;
+  case EfiTlsConnectionEnd:
+    if (*DataSize < sizeof (EFI_TLS_CONNECTION_END)) {
+      *DataSize = sizeof (EFI_TLS_CONNECTION_END);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_CONNECTION_END);
+    *((UINT8 *) Data) = TlsGetConnectionEnd (Instance->TlsConn);
+    break;
+  case EfiTlsCipherList:
+    //
+    // Get the current session cipher suite.
+    //
+    if (*DataSize < sizeof (EFI_TLS_CIPHER)) {
+      *DataSize = sizeof (EFI_TLS_CIPHER);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof(EFI_TLS_CIPHER);
+    Status = TlsGetCurrentCipher (Instance->TlsConn, (UINT16 *) Data);
+    *((UINT16 *) Data) = HTONS (*((UINT16 *) Data));
+    break;
+  case EfiTlsCompressionMethod:
+    //
+    // Get the current session compression method.
+    //
+    if (*DataSize < sizeof (EFI_TLS_COMPRESSION)) {
+      *DataSize = sizeof (EFI_TLS_COMPRESSION);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_COMPRESSION);
+    Status = TlsGetCurrentCompressionId (Instance->TlsConn, (UINT8 *) Data);
+    break;
+  case EfiTlsExtensionData:
+    Status = EFI_UNSUPPORTED;
+    goto ON_EXIT;
+  case EfiTlsVerifyMethod:
+    if (*DataSize < sizeof (EFI_TLS_VERIFY)) {
+      *DataSize = sizeof (EFI_TLS_VERIFY);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_VERIFY);
+    *((UINT32 *) Data) = TlsGetVerify (Instance->TlsConn);
+    break;
+  case EfiTlsSessionID:
+    if (*DataSize < sizeof (EFI_TLS_SESSION_ID)) {
+      *DataSize = sizeof (EFI_TLS_SESSION_ID);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_SESSION_ID);
+    Status = TlsGetSessionId (
+               Instance->TlsConn,
+               ((EFI_TLS_SESSION_ID *) Data)->Data,
+               &(((EFI_TLS_SESSION_ID *) Data)->Length)
+               );
+    break;
+  case EfiTlsSessionState:
+    if (*DataSize < sizeof (EFI_TLS_SESSION_STATE)) {
+      *DataSize = sizeof (EFI_TLS_SESSION_STATE);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_SESSION_STATE);
+    CopyMem (Data, &Instance->TlsSessionState, *DataSize);
+    break;
+  case EfiTlsClientRandom:
+    if (*DataSize < sizeof (EFI_TLS_RANDOM)) {
+      *DataSize = sizeof (EFI_TLS_RANDOM);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_RANDOM);
+    TlsGetClientRandom (Instance->TlsConn, (UINT8 *) Data);
+    break;
+  case EfiTlsServerRandom:
+    if (*DataSize < sizeof (EFI_TLS_RANDOM)) {
+      *DataSize = sizeof (EFI_TLS_RANDOM);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_RANDOM);
+    TlsGetServerRandom (Instance->TlsConn, (UINT8 *) Data);
+    break;
+  case EfiTlsKeyMaterial:
+    if (*DataSize < sizeof (EFI_TLS_MASTER_SECRET)) {
+      *DataSize = sizeof (EFI_TLS_MASTER_SECRET);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_MASTER_SECRET);
+    Status = TlsGetKeyMaterial (Instance->TlsConn, (UINT8 *) Data);
+    break;
+  //
+  // Unsupported type.
+  //
+  default:
+    Status = EFI_UNSUPPORTED;
+  }
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  Build response packet according to TLS state machine. This function is only valid for
+  alert, handshake and change_cipher_spec content type.
+
+  The BuildResponsePacket() function builds TLS response packet in response to the TLS
+  request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and
+  RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session
+  will be initiated and the response packet needs to be ClientHello. If RequestBuffer is
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS
+  session will be closed and response packet needs to be CloseNotify. If RequestBuffer is
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS
+  session has errors and the response packet needs to be Alert message based on error
+  type.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       RequestBuffer  Pointer to the most recently received TLS packet. NULL
+                                  means TLS need initiate the TLS session and response
+                                  packet need to be ClientHello.
+  @param[in]       RequestSize    Packet size in bytes for the most recently received TLS
+                                  packet. 0 is only valid when RequestBuffer is NULL.
+  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  RequestBuffer is NULL but RequestSize is NOT 0.
+                                  RequestSize is 0 but RequestBuffer is NOT NULL.
+                                  BufferSize is NULL.
+                                  Buffer is NULL if *BufferSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.
+  @retval EFI_NOT_READY           Current TLS session state is NOT ready to build
+                                  ResponsePacket.
+  @retval EFI_ABORTED             Something wrong build response packet.
+**/
+EFI_STATUS
+EFIAPI
+TlsBuildResponsePacket (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     UINT8                         *RequestBuffer, OPTIONAL
+  IN     UINTN                         RequestSize, OPTIONAL
+     OUT UINT8                         *Buffer, OPTIONAL
+  IN OUT UINTN                         *BufferSize
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+
+  if ((This == NULL) || (BufferSize == NULL) ||
+      (RequestBuffer == NULL && RequestSize != 0) ||
+      (RequestBuffer != NULL && RequestSize == 0) ||
+      (Buffer == NULL && *BufferSize !=0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
+
+  if(RequestBuffer == NULL && RequestSize == 0) {
+    switch (Instance->TlsSessionState) {
+    case EfiTlsSessionNotStarted:
+      //
+      // ClientHello.
+      //
+      Status = TlsDoHandshake (
+                 Instance->TlsConn,
+                 NULL,
+                 0,
+                 Buffer,
+                 BufferSize
+                 );
+      if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+      }
+
+      //
+      // *BufferSize should not be zero when ClientHello.
+      //
+      if (*BufferSize == 0) {
+        Status = EFI_ABORTED;
+        goto ON_EXIT;
+      }
+
+      Instance->TlsSessionState = EfiTlsSessionHandShaking;
+
+      break;
+    case EfiTlsSessionClosing:
+      //
+      // TLS session will be closed and response packet needs to be CloseNotify.
+      //
+      Status = TlsCloseNotify (
+                 Instance->TlsConn,
+                 Buffer,
+                 BufferSize
+                 );
+      if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+      }
+
+      //
+      // *BufferSize should not be zero when build CloseNotify message.
+      //
+      if (*BufferSize == 0) {
+        Status = EFI_ABORTED;
+        goto ON_EXIT;
+      }
+
+      break;
+    case EfiTlsSessionError:
+      //
+      // TLS session has errors and the response packet needs to be Alert
+      // message based on error type.
+      //
+      Status = TlsHandeAlert (
+                 Instance->TlsConn,
+                 NULL,
+                 0,
+                 Buffer,
+                 BufferSize
+                 );
+      if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+      }
+
+      break;
+    default:
+      //
+      // Current TLS session state is NOT ready to build ResponsePacket.
+      //
+      Status = EFI_NOT_READY;
+    }
+  } else {
+    //
+    // 1. Received packet may have multiply TLS record messages.
+    // 2. One TLS record message may have multiply handshake protocol.
+    // 3. Some errors may be happened in handshake.
+    // TlsDoHandshake() can handle all of those cases.
+    //
+    if (TlsInHandshake (Instance->TlsConn)) {
+      Status = TlsDoHandshake (
+                 Instance->TlsConn,
+                 RequestBuffer,
+                 RequestSize,
+                 Buffer,
+                 BufferSize
+                 );
+      if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+      }
+
+      if (!TlsInHandshake (Instance->TlsConn)) {
+        Instance->TlsSessionState = EfiTlsSessionDataTransferring;
+      }
+    } else {
+      //
+      // Must be alert message, Decrypt it and build the ResponsePacket.
+      //
+      ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType == TLS_CONTENT_TYPE_ALERT);
+
+      Status = TlsHandeAlert (
+                 Instance->TlsConn,
+                 RequestBuffer,
+                 RequestSize,
+                 Buffer,
+                 BufferSize
+                 );
+      if (EFI_ERROR (Status)) {
+        if (Status != EFI_BUFFER_TOO_SMALL) {
+          Instance->TlsSessionState = EfiTlsSessionError;
+        }
+
+        goto ON_EXIT;
+      }
+    }
+  }
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  Decrypt or encrypt TLS packet during session. This function is only valid after
+  session connected and for application_data content type.
+
+  The ProcessPacket () function process each inbound or outbound TLS APP packet.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment. The caller will take
+                                  responsible to handle the original FragmentTable while
+                                  it may be reallocated in TLS driver. If CryptMode is
+                                  EfiTlsEncrypt, on input these fragments contain the TLS
+                                  header and plain text TLS APP payload; on output these
+                                  fragments contain the TLS header and cipher text TLS
+                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
+                                  these fragments contain the TLS header and cipher text
+                                  TLS APP payload; on output these fragments contain the
+                                  TLS header and plain text TLS APP payload.
+  @param[in]       FragmentCount  Number of fragment.
+  @param[in]       CryptMode      Crypt mode.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  FragmentTable is NULL.
+                                  FragmentCount is NULL.
+                                  CryptoMode is invalid.
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionDataTransferring.
+  @retval EFI_ABORTED             Something wrong decryption the message. TLS session
+                                  status will become EfiTlsSessionError. The caller need
+                                  call BuildResponsePacket() to generate Error Alert
+                                  message and send it out.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the operation.
+**/
+EFI_STATUS
+EFIAPI
+TlsProcessPacket (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount,
+  IN     EFI_TLS_CRYPT_MODE            CryptMode
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+
+  if (This == NULL || FragmentTable == NULL || FragmentCount == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
+
+  if (Instance->TlsSessionState != EfiTlsSessionDataTransferring) {
+    Status = EFI_NOT_READY;
+    goto ON_EXIT;
+  }
+
+  //
+  // Packet sent or received may have multiply TLS record message(Application data type).
+  // So,on input these fragments contain the TLS header and TLS APP payload;
+  // on output these fragments also contain the TLS header and TLS APP payload.
+  //
+  switch (CryptMode) {
+  case EfiTlsEncrypt:
+    Status = TlsEcryptPacket (Instance, FragmentTable, FragmentCount);
+    break;
+  case EfiTlsDecrypt:
+    Status = TlsDecryptPacket (Instance, FragmentTable, FragmentCount);
+    break;
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration
  2016-12-14  7:34 [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master Jiaxin Wu
                   ` (4 preceding siblings ...)
  2016-12-14  7:34 ` [Patch 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL Jiaxin Wu
@ 2016-12-14  7:34 ` Jiaxin Wu
  2016-12-15  2:22   ` Fu, Siyuan
  2016-12-14  7:34 ` [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6 Jiaxin Wu
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ye Ting, Fu Siyuan, Zhang Lubo, Long Qin, Thomas Palmer,
	Wu Jiaxin

This patch provides the UI to support TLS auth configuration.
* EFI_SIGNATURE_LIST format is used for 'TlsCaCertificate'
variable. So, TLS supports multiple certificate configuration.
* The variable attribute is BS with NV, which only target at
preventing runtime phase attack.

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/Include/Guid/TlsAuthConfigHii.h         |   25 +
 NetworkPkg/Include/Guid/TlsAuthentication.h        |   29 +
 NetworkPkg/NetworkPkg.dec                          |    7 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c     |  135 ++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf   |   73 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni   |   21 +
 .../TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni     |   19 +
 .../TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni   |   39 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c    | 1841 ++++++++++++++++++++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h    |  282 +++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h  |   49 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr   |  152 ++
 12 files changed, 2672 insertions(+)
 create mode 100644 NetworkPkg/Include/Guid/TlsAuthConfigHii.h
 create mode 100644 NetworkPkg/Include/Guid/TlsAuthentication.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr

diff --git a/NetworkPkg/Include/Guid/TlsAuthConfigHii.h b/NetworkPkg/Include/Guid/TlsAuthConfigHii.h
new file mode 100644
index 0000000..9d21426
--- /dev/null
+++ b/NetworkPkg/Include/Guid/TlsAuthConfigHii.h
@@ -0,0 +1,25 @@
+/** @file
+  GUIDs used as HII FormSet and HII Package list GUID in TlsAuthConfigDxe 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 that 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 __TLS_AUTH_CONFIG_HII_GUID_H__
+#define __TLS_AUTH_CONFIG_HII_GUID_H__
+
+#define TLS_AUTH_CONFIG_GUID \
+  { \
+    0xb0eae4f8, 0x9a04, 0x4c6d, { 0xa7, 0x48, 0x79, 0x3d, 0xaa, 0xf, 0x65, 0xdf } \
+  }
+
+extern EFI_GUID gTlsAuthConfigGuid;
+
+#endif
diff --git a/NetworkPkg/Include/Guid/TlsAuthentication.h b/NetworkPkg/Include/Guid/TlsAuthentication.h
new file mode 100644
index 0000000..2e800dc
--- /dev/null
+++ b/NetworkPkg/Include/Guid/TlsAuthentication.h
@@ -0,0 +1,29 @@
+/** @file
+  This file defines TlsCaCertificate variable.
+  
+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 that 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 __TLS_AUTHENTICATION_H__
+#define __TLS_AUTHENTICATION_H__
+
+// Private variable for CA Certificate configuration
+//
+#define EFI_TLS_CA_CERTIFICATE_GUID \
+  { \
+    0xfd2340D0, 0x3dab, 0x4349, { 0xa6, 0xc7, 0x3b, 0x4f, 0x12, 0xb4, 0x8e, 0xae } \
+  }
+
+#define EFI_TLS_CA_CERTIFICATE_VARIABLE       L"TlsCaCertificate"
+
+extern EFI_GUID gEfiTlsCaCertificateGuid;
+
+#endif
diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec
index 268188a..24d45f4 100644
--- a/NetworkPkg/NetworkPkg.dec
+++ b/NetworkPkg/NetworkPkg.dec
@@ -38,10 +38,17 @@
   gIScsiConfigGuid              = { 0x4b47d616, 0xa8d6, 0x4552, { 0x9d, 0x44, 0xcc, 0xad, 0x2e, 0xf, 0x4c, 0xf9}}
 
   # Include/Guid/HttpBootConfigHii.h
   gHttpBootConfigGuid           = { 0x4d20583a, 0x7765, 0x4e7a, { 0x8a, 0x67, 0xdc, 0xde, 0x74, 0xee, 0x3e, 0xc5 }}
 
+  # Include/Guid/TlsAuthConfigHii.h
+  gTlsAuthConfigGuid            = { 0xb0eae4f8, 0x9a04, 0x4c6d, { 0xa7, 0x48, 0x79, 0x3d, 0xaa, 0xf, 0x65, 0xdf }}
+  
+  # Include/Guid/TlsAuthentication.h
+  gEfiTlsCaCertificateGuid      = { 0xfd2340D0, 0x3dab, 0x4349, { 0xa6, 0xc7, 0x3b, 0x4f, 0x12, 0xb4, 0x8e, 0xae }}
+  
+
 [PcdsFeatureFlag]
   ## Indicates if the IPsec IKEv2 Certificate Authentication feature is enabled or not.<BR><BR>
   #   TRUE  - Certificate Authentication feature is enabled.<BR>
   #   FALSE - Does not support Certificate Authentication.<BR>
   # @Prompt Enable IPsec IKEv2 Certificate Authentication.
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
new file mode 100644
index 0000000..647bc2f
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
@@ -0,0 +1,135 @@
+/** @file
+  The DriverEntryPoint for TlsAuthConfigDxe 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.
+
+**/
+
+#include "TlsAuthConfigImpl.h"
+
+/**
+  Unloads an image.
+
+  @param  ImageHandle           Handle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS 
+EFIAPI
+TlsAuthConfigDxeUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS                     Status;
+  TLS_AUTH_CONFIG_PRIVATE_DATA   *PrivateData;
+
+  Status = gBS->HandleProtocol (
+                  ImageHandle,
+                  &gEfiCallerIdGuid,
+                  (VOID **) &PrivateData
+                  );  
+  if (EFI_ERROR (Status)) {
+    return Status;  
+  }
+  
+  ASSERT (PrivateData->Signature == TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE);
+
+  gBS->UninstallMultipleProtocolInterfaces (
+         &ImageHandle,
+         &gEfiCallerIdGuid,
+         PrivateData,
+         NULL
+         );
+  
+  TlsAuthConfigFormUnload (PrivateData);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigDxeDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  TLS_AUTH_CONFIG_PRIVATE_DATA   *PrivateData;
+
+  PrivateData = NULL;
+  
+  //
+  // If already started, return.
+  //
+  Status = gBS->OpenProtocol (
+                  ImageHandle,
+                  &gEfiCallerIdGuid,
+                  NULL,
+                  ImageHandle,
+                  ImageHandle,
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                  );
+  if (!EFI_ERROR (Status)) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  //
+  // Initialize the private data structure.
+  //
+  PrivateData = AllocateZeroPool (sizeof (TLS_AUTH_CONFIG_PRIVATE_DATA));
+  if (PrivateData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize the HII configuration form.
+  //
+  Status = TlsAuthConfigFormInit (PrivateData);
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  //
+  // Install private GUID.
+  //    
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &ImageHandle,
+                  &gEfiCallerIdGuid,
+                  PrivateData,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+  
+  return EFI_SUCCESS;
+
+ON_ERROR:
+  TlsAuthConfigFormUnload (PrivateData);
+  FreePool (PrivateData);
+
+  return Status;
+}
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
new file mode 100644
index 0000000..19f095e
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
@@ -0,0 +1,73 @@
+## @file
+#  Provides the capability to configure Tls Authentication in a setup browser
+#  By this module, user may change the content of TlsCaCertificate.
+#
+# 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.
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = TlsAuthConfigDxe
+  MODULE_UNI_FILE           = TlsAuthConfigDxe.uni
+  FILE_GUID                 = 7ca1024f-eb17-11e5-9dba-28d2447c4829
+  MODULE_TYPE               = DXE_DRIVER
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = TlsAuthConfigDxeDriverEntryPoint
+  UNLOAD_IMAGE              = TlsAuthConfigDxeUnload
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+  
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  NetworkPkg/NetworkPkg.dec
+
+[Sources]
+  TlsAuthConfigImpl.c
+  TlsAuthConfigImpl.h
+  TlsAuthConfigNvData.h
+  TlsAuthConfigDxe.c
+  TlsAuthConfigDxeStrings.uni
+  TlsAuthConfigVfr.vfr
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  UefiLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+  DebugLib
+  HiiLib
+  DevicePathLib
+  UefiHiiServicesLib
+  FileExplorerLib
+  PrintLib
+  
+[Protocols]
+  gEfiDevicePathProtocolGuid                    ## PRODUCES
+  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
+  gEfiSimpleFileSystemProtocolGuid              ## SOMETIMES_CONSUMES
+
+[Guids]
+  gTlsAuthConfigGuid                            ## PRODUCES  ## GUID
+  gEfiCertX509Guid                              ## CONSUMES  ## GUID  # Indicate the cert type
+  gEfiIfrTianoGuid                              ## CONSUMES  ## HII
+  gEfiTlsCaCertificateGuid                      ## PRODUCES  ## GUID
+
+[Depex]
+  gEfiHiiConfigRoutingProtocolGuid  AND
+  gEfiHiiDatabaseProtocolGuid
+  
+[UserExtensions.TianoCore."ExtraFiles"]
+  TlsAuthConfigDxeExtra.uni
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
new file mode 100644
index 0000000..f99a14f
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
@@ -0,0 +1,21 @@
+// /** @file
+// Provides the capability to configure Tls Authentication in a setup browser
+//
+// By this module, user may change the content of TlsCaCertificate.
+//
+// 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.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Provides the capability to configure Tls Authentication in a setup browser"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "By this module, user may change the content of TlsCaCertificate."
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
new file mode 100644
index 0000000..ee4c49f
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
@@ -0,0 +1,19 @@
+// /** @file
+// TlsAuthConfigDxe Localized Strings and Content
+//
+// 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.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME 
+#language en-US 
+"TLS Auth Config DXE"
+
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
new file mode 100644
index 0000000..a8f7e43
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
@@ -0,0 +1,39 @@
+/** @file
+  String definitions for Tls Authentication Configuration form.
+
+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.
+
+**/
+
+#langdef en-US "English"
+
+#string STR_TLS_AUTH_CONFIG_TITLE                    #language en-US "Tls Auth Configuration"
+#string STR_TLS_AUTH_CONFIG_HELP                     #language en-US "Press <Enter> to select Tls Auth Configuration."
+
+#string STR_TLS_AUTH_CONFIG_SERVER_CA         		 #language en-US "Server CA Configuration"
+#string STR_TLS_AUTH_CONFIG_SERVER_CA_HELP    		 #language en-US "Press <Enter> to configure Server CA."
+#string STR_TLS_AUTH_CONFIG_CLIENT_CERT         	 #language en-US "Client Cert Configuration"
+#string STR_TLS_AUTH_CONFIG_CLIENT_CERT_HELP    	 #language en-US "Client cert configuration is unsupported currently."
+
+#string STR_TLS_AUTH_CONFIG_ENROLL_CERT              #language en-US "Enroll Cert"    
+#string STR_TLS_AUTH_CONFIG_ENROLL_CERT_HELP         #language en-US "Press <Enter> to enroll cert."
+#string STR_TLS_AUTH_CONFIG_DELETE_CERT              #language en-US "Delete Cert"    
+#string STR_TLS_AUTH_CONFIG_DELETE_CERT_HELP         #language en-US "Press <Enter> to delete cert."
+
+#string STR_TLS_AUTH_CONFIG_ADD_CERT_FILE            #language en-US "Enroll Cert Using File"
+
+#string STR_TLS_AUTH_CONFIG_CERT_GUID                #language en-US "Cert GUID"
+#string STR_TLS_AUTH_CONFIG_CERT_GUID_HELP           #language en-US "Input digit character in 11111111-2222-3333-4444-1234567890ab format."
+#string STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT            #language en-US "Commit Changes and Exit"
+#string STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT         #language en-US "Discard Changes and Exit"
+
+#string STR_CERT_TYPE_PCKS_GUID                      #language en-US "GUID for CERT"
+
+#string STR_NULL                                     #language en-US ""
\ No newline at end of file
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
new file mode 100644
index 0000000..1132cac
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
@@ -0,0 +1,1841 @@
+/** @file
+  The Miscellaneous Routines for TlsAuthConfigDxe 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.
+
+**/
+
+#include "TlsAuthConfigImpl.h"
+
+VOID                    *mStartOpCodeHandle = NULL;
+VOID                    *mEndOpCodeHandle   = NULL;
+EFI_IFR_GUID_LABEL      *mStartLabel        = NULL;
+EFI_IFR_GUID_LABEL      *mEndLabel          = NULL;
+
+
+CHAR16                  mTlsAuthConfigStorageName[] = L"TLS_AUTH_CONFIG_IFR_NVDATA";
+
+TLS_AUTH_CONFIG_PRIVATE_DATA      *mTlsAuthPrivateData = NULL;
+
+HII_VENDOR_DEVICE_PATH  mTlsAuthConfigHiiVendorDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    TLS_AUTH_CONFIG_GUID
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      (UINT8) (END_DEVICE_PATH_LENGTH),
+      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+    }
+  }
+};
+
+//
+// Possible DER-encoded certificate file suffixes, end with NULL pointer.
+//
+CHAR16* mDerPemEncodedSuffix[] = {
+  L".cer",
+  L".der",
+  L".crt",
+  L".pem",
+  NULL
+};
+
+/**
+  This code checks if the FileSuffix is one of the possible DER/PEM-encoded certificate suffix.
+
+  @param[in] FileSuffix            The suffix of the input certificate file
+
+  @retval    TRUE           It's a DER/PEM-encoded certificate.
+  @retval    FALSE          It's NOT a DER/PEM-encoded certificate.
+
+**/
+BOOLEAN
+IsDerPemEncodeCertificate (
+  IN CONST CHAR16         *FileSuffix
+)
+{
+  UINTN     Index;
+  for (Index = 0; mDerPemEncodedSuffix[Index] != NULL; Index++) {
+    if (StrCmp (FileSuffix, mDerPemEncodedSuffix[Index]) == 0) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+  Worker function that prints an EFI_GUID into specified Buffer.
+
+  @param[in]     Guid          Pointer to GUID to print.
+  @param[in]     Buffer        Buffer to print Guid into.
+  @param[in]     BufferSize    Size of Buffer.
+  
+  @retval    Number of characters printed.
+
+**/
+UINTN
+GuidToString (
+  IN  EFI_GUID  *Guid,
+  IN  CHAR16    *Buffer,
+  IN  UINTN     BufferSize
+  )
+{
+  UINTN Size;
+
+  Size = UnicodeSPrint (
+            Buffer,
+            BufferSize, 
+            L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+            (UINTN)Guid->Data1,                    
+            (UINTN)Guid->Data2,
+            (UINTN)Guid->Data3,
+            (UINTN)Guid->Data4[0],
+            (UINTN)Guid->Data4[1],
+            (UINTN)Guid->Data4[2],
+            (UINTN)Guid->Data4[3],
+            (UINTN)Guid->Data4[4],
+            (UINTN)Guid->Data4[5],
+            (UINTN)Guid->Data4[6],
+            (UINTN)Guid->Data4[7]
+            );
+
+  //
+  // SPrint will null terminate the string. The -1 skips the null
+  //
+  return Size - 1;
+}
+
+/**
+  Convert a String to Guid Value.
+
+  @param[in]   Str        Specifies the String to be converted.
+  @param[in]   StrLen     Number of Unicode Characters of String (exclusive \0)
+  @param[out]  Guid       Return the result Guid value.
+
+  @retval    EFI_SUCCESS           The operation is finished successfully.
+  @retval    EFI_NOT_FOUND         Invalid string.
+
+**/
+EFI_STATUS
+StringToGuid (
+  IN   CHAR16           *Str, 
+  IN   UINTN            StrLen, 
+  OUT  EFI_GUID         *Guid
+  )
+{
+  CHAR16             *PtrBuffer;
+  CHAR16             *PtrPosition;
+  UINT16             *Buffer;
+  UINTN              Data;
+  UINTN              Index;
+  UINT16             Digits[3];
+
+  Buffer = (CHAR16 *) AllocateZeroPool (sizeof (CHAR16) * (StrLen + 1));
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  StrCpyS (Buffer, (StrLen + 1), Str);
+
+  //
+  // Data1
+  //
+  PtrBuffer       = Buffer;
+  PtrPosition     = PtrBuffer; 
+  while (*PtrBuffer != L'\0') {
+    if (*PtrBuffer == L'-') {
+      break;
+    }
+    PtrBuffer++;
+  }
+  if (*PtrBuffer == L'\0') {
+    FreePool (Buffer);
+    return EFI_NOT_FOUND;
+  }
+
+  *PtrBuffer      = L'\0';
+  Data            = StrHexToUintn (PtrPosition);
+  Guid->Data1     = (UINT32)Data;
+
+  //
+  // Data2
+  //
+  PtrBuffer++;
+  PtrPosition     = PtrBuffer;
+  while (*PtrBuffer != L'\0') {
+    if (*PtrBuffer == L'-') {
+      break;
+    }
+    PtrBuffer++;
+  }
+  if (*PtrBuffer == L'\0') {
+    FreePool (Buffer);
+    return EFI_NOT_FOUND;
+  }
+  *PtrBuffer      = L'\0';
+  Data            = StrHexToUintn (PtrPosition);
+  Guid->Data2     = (UINT16)Data;
+
+  //
+  // Data3
+  //
+  PtrBuffer++;
+  PtrPosition     = PtrBuffer;
+  while (*PtrBuffer != L'\0') {
+    if (*PtrBuffer == L'-') {
+      break;
+    }
+    PtrBuffer++;
+  }
+  if (*PtrBuffer == L'\0') {
+    FreePool (Buffer);
+    return EFI_NOT_FOUND;
+  }
+  *PtrBuffer      = L'\0';
+  Data            = StrHexToUintn (PtrPosition);
+  Guid->Data3     = (UINT16)Data;
+
+  //
+  // Data4[0..1]
+  //
+  for ( Index = 0 ; Index < 2 ; Index++) {
+    PtrBuffer++;
+    if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {
+      FreePool (Buffer);
+      return EFI_NOT_FOUND;
+    }
+    Digits[0]     = *PtrBuffer;
+    PtrBuffer++;
+    Digits[1]     = *PtrBuffer;
+    Digits[2]     = L'\0';
+    Data          = StrHexToUintn (Digits);
+    Guid->Data4[Index] = (UINT8)Data;
+  }
+
+  //
+  // skip the '-'
+  //
+  PtrBuffer++;
+  if ((*PtrBuffer != L'-' ) || ( *PtrBuffer == L'\0')) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Data4[2..7]
+  //
+  for ( ; Index < 8; Index++) {
+    PtrBuffer++;
+    if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {
+      FreePool (Buffer);
+      return EFI_NOT_FOUND;
+    }
+    Digits[0]     = *PtrBuffer;
+    PtrBuffer++;
+    Digits[1]     = *PtrBuffer;
+    Digits[2]     = L'\0';
+    Data          = StrHexToUintn (Digits);
+    Guid->Data4[Index] = (UINT8)Data;
+  }
+
+  FreePool (Buffer);
+  
+  return EFI_SUCCESS;
+}
+
+
+/**
+  List all cert in specified database by GUID in the page 
+  for user to select and delete as needed.
+
+  @param[in]    PrivateData         Module's private data.
+  @param[in]    VariableName        The variable name of the vendor's signature database.
+  @param[in]    VendorGuid          A unique identifier for the vendor.
+  @param[in]    LabelNumber         Label number to insert opcodes.
+  @param[in]    FormId              Form ID of current page.
+  @param[in]    QuestionIdBase      Base question id of the signature list.
+
+  @retval   EFI_SUCCESS             Success to update the signature list page
+  @retval   EFI_OUT_OF_RESOURCES    Unable to allocate required resources.
+
+**/
+EFI_STATUS
+UpdateDeletePage (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private,
+  IN CHAR16                           *VariableName,
+  IN EFI_GUID                         *VendorGuid,
+  IN UINT16                           LabelNumber,
+  IN EFI_FORM_ID                      FormId,
+  IN EFI_QUESTION_ID                  QuestionIdBase
+  )
+{
+  EFI_STATUS                  Status;
+  UINT32                      Index;
+  UINTN                       CertCount;
+  UINTN                       GuidIndex;
+  VOID                        *StartOpCodeHandle;
+  VOID                        *EndOpCodeHandle;
+  EFI_IFR_GUID_LABEL          *StartLabel;
+  EFI_IFR_GUID_LABEL          *EndLabel;
+  UINTN                       DataSize;
+  UINT8                       *Data;
+  EFI_SIGNATURE_LIST          *CertList;
+  EFI_SIGNATURE_DATA          *Cert;
+  UINT32                      ItemDataSize;
+  CHAR16                      *GuidStr;
+  EFI_STRING_ID               GuidID;
+  EFI_STRING_ID               Help;
+
+  Data     = NULL;
+  CertList = NULL;
+  Cert     = NULL;
+  GuidStr  = NULL;
+  StartOpCodeHandle = NULL;
+  EndOpCodeHandle   = NULL;
+
+  //
+  // Initialize the container for dynamic opcodes.
+  //
+  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (StartOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (EndOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Create Hii Extend Label OpCode.
+  //
+  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                        StartOpCodeHandle,
+                                        &gEfiIfrTianoGuid,
+                                        NULL,
+                                        sizeof (EFI_IFR_GUID_LABEL)
+                                        );
+  StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
+  StartLabel->Number        = LabelNumber;
+
+  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                      EndOpCodeHandle,
+                                      &gEfiIfrTianoGuid,
+                                      NULL,
+                                      sizeof (EFI_IFR_GUID_LABEL)
+                                      );
+  EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
+  EndLabel->Number        = LABEL_END;
+
+  //
+  // Read Variable.
+  //
+  DataSize = 0;
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+    goto ON_EXIT;
+  }
+
+  Data = (UINT8 *) AllocateZeroPool (DataSize);
+  if (Data == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  GuidStr = AllocateZeroPool (100);
+  if (GuidStr == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Enumerate all data.
+  //
+  ItemDataSize = (UINT32) DataSize;
+  CertList = (EFI_SIGNATURE_LIST *) Data;
+  GuidIndex = 0;
+
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
+      Help = STRING_TOKEN (STR_CERT_TYPE_PCKS_GUID);
+    } else {
+      //
+      // The signature type is not supported in current implementation.
+      //
+      ItemDataSize -= CertList->SignatureListSize;
+      CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+      continue;
+    }
+
+    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+    for (Index = 0; Index < CertCount; Index++) {
+      Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList
+                                              + sizeof (EFI_SIGNATURE_LIST)
+                                              + CertList->SignatureHeaderSize
+                                              + Index * CertList->SignatureSize);
+      //
+      // Display GUID and help
+      //
+      GuidToString (&Cert->SignatureOwner, GuidStr, 100);
+      GuidID  = HiiSetString (Private->RegisteredHandle, 0, GuidStr, NULL);
+      HiiCreateCheckBoxOpCode (
+        StartOpCodeHandle,
+        (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),
+        0,
+        0,
+        GuidID,
+        Help,
+        EFI_IFR_FLAG_CALLBACK,
+        0,
+        NULL
+        );
+    }
+
+    ItemDataSize -= CertList->SignatureListSize;
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+  }
+
+ON_EXIT:
+  HiiUpdateForm (
+    Private->RegisteredHandle,
+    &gTlsAuthConfigGuid,
+    FormId,
+    StartOpCodeHandle,
+    EndOpCodeHandle
+    );
+
+  if (StartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (StartOpCodeHandle);
+  }
+
+  if (EndOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (EndOpCodeHandle);
+  }
+
+  if (Data != NULL) {
+    FreePool (Data);
+  }
+
+  if (GuidStr != NULL) {
+    FreePool (GuidStr);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Delete one entry from cert database.
+
+  @param[in]    PrivateData         Module's private data.
+  @param[in]    VariableName        The variable name of the database.
+  @param[in]    VendorGuid          A unique identifier for the vendor.
+  @param[in]    LabelNumber         Label number to insert opcodes.
+  @param[in]    FormId              Form ID of current page.
+  @param[in]    QuestionIdBase      Base question id of the cert list.
+  @param[in]    DeleteIndex         Cert index to delete.
+
+  @retval   EFI_SUCCESS             Delete siganture successfully.
+  @retval   EFI_NOT_FOUND           Can't find the signature item,
+  @retval   EFI_OUT_OF_RESOURCES    Could not allocate needed resources.
+**/
+EFI_STATUS
+DeleteCert (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private,
+  IN CHAR16                           *VariableName,
+  IN EFI_GUID                         *VendorGuid,
+  IN UINT16                           LabelNumber,
+  IN EFI_FORM_ID                      FormId,
+  IN EFI_QUESTION_ID                  QuestionIdBase,
+  IN UINTN                            DeleteIndex
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       DataSize;
+  UINT8                       *Data;
+  UINT8                       *OldData;
+  UINT32                      Attr;
+  UINT32                      Index;
+  EFI_SIGNATURE_LIST          *CertList;
+  EFI_SIGNATURE_LIST          *NewCertList;
+  EFI_SIGNATURE_DATA          *Cert;
+  UINTN                       CertCount;
+  UINT32                      Offset;
+  BOOLEAN                     IsItemFound;
+  UINT32                      ItemDataSize;
+  UINTN                       GuidIndex;
+
+  Data            = NULL;
+  OldData         = NULL;
+  CertList        = NULL;
+  Cert            = NULL;
+  Attr            = 0;
+
+  //
+  // Get original signature list data.
+  //
+  DataSize = 0;
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+    goto ON_EXIT;
+  }
+
+  OldData = (UINT8 *) AllocateZeroPool (DataSize);
+  if (OldData == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);
+  if (EFI_ERROR(Status)) {
+    goto ON_EXIT;
+  }
+
+  //
+  // Allocate space for new variable.
+  //
+  Data = (UINT8*) AllocateZeroPool (DataSize);
+  if (Data == NULL) {
+    Status  =  EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Enumerate all data and erasing the target item.
+  //
+  IsItemFound = FALSE;
+  ItemDataSize = (UINT32) DataSize;
+  CertList = (EFI_SIGNATURE_LIST *) OldData;
+  Offset = 0;
+  GuidIndex = 0;
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
+      //
+      // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
+      //
+      CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
+      NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);
+      Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+      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++) {
+        if (GuidIndex == DeleteIndex) {
+          //
+          // Find it! Skip it!
+          //
+          NewCertList->SignatureListSize -= CertList->SignatureSize;
+          IsItemFound = TRUE;
+        } else {
+          //
+          // This item doesn't match. Copy it to the Data buffer.
+          //
+          CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);
+          Offset += CertList->SignatureSize;
+        }
+        GuidIndex++;
+        Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
+      }
+    } else {
+      //
+      // This List doesn't match. Just copy it to the Data buffer.
+      //
+      CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
+      Offset += CertList->SignatureListSize;
+    }
+
+    ItemDataSize -= CertList->SignatureListSize;
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+  }
+
+  if (!IsItemFound) {
+    //
+    // Doesn't find the signature Item!
+    //
+    Status = EFI_NOT_FOUND;
+    goto ON_EXIT;
+  }
+
+  //
+  // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
+  //
+  ItemDataSize = Offset;
+  CertList = (EFI_SIGNATURE_LIST *) Data;
+  Offset = 0;
+  ZeroMem (OldData, ItemDataSize);
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+    DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));
+    if (CertCount != 0) {
+      CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
+      Offset += CertList->SignatureListSize;
+    }
+    ItemDataSize -= CertList->SignatureListSize;
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+  }
+
+  DataSize = Offset;
+
+  Status = gRT->SetVariable(
+                  VariableName,
+                  VendorGuid,
+                  Attr,
+                  DataSize,
+                  OldData
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+  if (Data != NULL) {
+    FreePool(Data);
+  }
+
+  if (OldData != NULL) {
+    FreePool(OldData);
+  }
+
+  return UpdateDeletePage (
+           Private,
+           VariableName,
+           VendorGuid,
+           LabelNumber,
+           FormId,
+           QuestionIdBase
+           );
+}
+
+
+/**
+  Close an open file handle.
+
+  @param[in] FileHandle           The file handle to close.
+  
+**/
+VOID
+CloseFile (
+  IN EFI_FILE_HANDLE   FileHandle
+  )
+{
+  if (FileHandle != NULL) {
+    FileHandle->Close (FileHandle);  
+  }
+}
+
+/**
+  Read file content into BufferPtr, the size of the allocate buffer 
+  is *FileSize plus AddtionAllocateSize.
+
+  @param[in]       FileHandle            The file to be read.
+  @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.
+  @param[out]      FileSize              Size of input file
+  @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated. 
+                                         In case the buffer need to contain others besides the file content.
+  
+  @retval   EFI_SUCCESS                  The file was read into the buffer.
+  @retval   EFI_INVALID_PARAMETER        A parameter was invalid.
+  @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.
+  @retval   others                       Unexpected error.
+
+**/
+EFI_STATUS
+ReadFileContent (
+  IN      EFI_FILE_HANDLE           FileHandle,
+  IN OUT  VOID                      **BufferPtr,
+     OUT  UINTN                     *FileSize,
+  IN      UINTN                     AddtionAllocateSize
+  )
+
+{
+  UINTN      BufferSize;
+  UINT64     SourceFileSize;
+  VOID       *Buffer;
+  EFI_STATUS Status;
+
+  if ((FileHandle == NULL) || (FileSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Buffer = NULL;
+
+  //
+  // Get the file size
+  //
+  Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+  
+  Status = FileHandle->SetPosition (FileHandle, 0);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  BufferSize = (UINTN) SourceFileSize + AddtionAllocateSize;
+  Buffer =  AllocateZeroPool(BufferSize);
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  BufferSize = (UINTN) SourceFileSize;
+  *FileSize  = BufferSize;
+
+  Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
+  if (EFI_ERROR (Status) || BufferSize != *FileSize) {
+    FreePool (Buffer);
+    Buffer = NULL;
+    Status  = EFI_BAD_BUFFER_SIZE;
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+  
+  *BufferPtr = Buffer;
+  return Status;
+}
+
+/**
+  This function will open a file or directory referenced by DevicePath.
+
+  This function opens a file with the open mode according to the file path. The
+  Attributes is valid only for EFI_FILE_MODE_CREATE.
+
+  @param[in, out]  FilePath        On input, the device path to the file.
+                                   On output, the remaining device path.
+  @param[out]      FileHandle      Pointer to the file handle.
+  @param[in]       OpenMode        The mode to open the file with.
+  @param[in]       Attributes      The file's file attributes.
+
+  @retval EFI_SUCCESS              The information was set.
+  @retval EFI_INVALID_PARAMETER    One of the parameters has an invalid value.
+  @retval EFI_UNSUPPORTED          Could not open the file path.
+  @retval EFI_NOT_FOUND            The specified file could not be found on the
+                                   device or the file system could not be found on
+                                   the device.
+  @retval EFI_NO_MEDIA             The device has no medium.
+  @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the
+                                   medium is no longer supported.
+  @retval EFI_DEVICE_ERROR         The device reported an error.
+  @retval EFI_VOLUME_CORRUPTED     The file system structures are corrupted.
+  @retval EFI_WRITE_PROTECTED      The file or medium is write protected.
+  @retval EFI_ACCESS_DENIED        The file was opened read only.
+  @retval EFI_OUT_OF_RESOURCES     Not enough resources were available to open the
+                                   file.
+  @retval EFI_VOLUME_FULL          The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+OpenFileByDevicePath (
+  IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,
+  OUT EFI_FILE_HANDLE                 *FileHandle,
+  IN UINT64                           OpenMode,
+  IN UINT64                           Attributes
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
+  EFI_FILE_PROTOCOL               *Handle1;
+  EFI_FILE_PROTOCOL               *Handle2;
+  EFI_HANDLE                      DeviceHandle;
+
+  if ((FilePath == NULL || FileHandle == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = gBS->LocateDevicePath (
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  FilePath,
+                  &DeviceHandle
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->OpenProtocol(
+                  DeviceHandle,
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  (VOID**)&EfiSimpleFileSystemProtocol,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
+  if (EFI_ERROR (Status)) {
+    FileHandle = NULL;
+    return Status;
+  }
+
+  //
+  // go down directories one node at a time.
+  //
+  while (!IsDevicePathEnd (*FilePath)) {
+    //
+    // For file system access each node should be a file path component
+    //
+    if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
+        DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
+       ) {
+      FileHandle = NULL;
+      return (EFI_INVALID_PARAMETER);
+    }
+    //
+    // Open this file path node
+    //
+    Handle2  = Handle1;
+    Handle1 = NULL;
+
+    //
+    // Try to test opening an existing file
+    //
+    Status = Handle2->Open (
+                        Handle2,
+                        &Handle1,
+                        ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
+                        OpenMode &~EFI_FILE_MODE_CREATE,
+                        0
+                        );
+
+    //
+    // see if the error was that it needs to be created
+    //
+    if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
+      Status = Handle2->Open (
+                          Handle2,
+                          &Handle1,
+                          ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
+                          OpenMode,
+                          Attributes
+                          );
+    }
+    //
+    // Close the last node
+    //
+    Handle2->Close (Handle2);
+
+    if (EFI_ERROR(Status)) {
+      return (Status);
+    }
+
+    //
+    // Get the next node
+    //
+    *FilePath = NextDevicePathNode (*FilePath);
+  }
+
+  //
+  // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
+  //
+  *FileHandle = (VOID*)Handle1;
+  return EFI_SUCCESS;
+}
+
+/**
+  This function converts an input device structure to a Unicode string.
+
+  @param[in] DevPath                  A pointer to the device path structure.
+
+  @return A new allocated Unicode string that represents the device path.
+
+**/
+CHAR16 *
+EFIAPI
+DevicePathToStr (
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
+  )
+{
+  return ConvertDevicePathToText (
+           DevPath,
+           FALSE,
+           TRUE
+           );
+}
+
+
+/**
+  Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
+  The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL
+  means not enough memory resource.
+
+  @param DevicePath       Device path.
+
+  @retval NULL            Not enough memory resourece for AllocateCopyPool.
+  @retval Other           A new allocated string that represents the file name.
+
+**/
+CHAR16 *
+ExtractFileNameFromDevicePath (
+  IN   EFI_DEVICE_PATH_PROTOCOL *DevicePath
+  )
+{
+  CHAR16          *String;
+  CHAR16          *MatchString;
+  CHAR16          *LastMatch;
+  CHAR16          *FileName;
+  UINTN           Length;
+
+  ASSERT(DevicePath != NULL);
+
+  String = DevicePathToStr(DevicePath);
+  MatchString = String;
+  LastMatch   = String;
+  FileName    = NULL;
+
+  while(MatchString != NULL){
+    LastMatch   = MatchString + 1;
+    MatchString = StrStr(LastMatch,L"\\");
+  }
+
+  Length = StrLen(LastMatch);
+  FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
+  if (FileName != NULL) {
+    *(FileName + Length) = 0;
+  }
+
+  FreePool(String);
+
+  return FileName;
+}
+
+/**
+  Enroll a new X509 certificate into Variable.
+
+  @param[in] PrivateData     The module's private data.
+  @param[in] VariableName    Variable name of CA database.
+
+  @retval   EFI_SUCCESS            New X509 is enrolled successfully.
+  @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
+
+**/
+EFI_STATUS
+EnrollX509toVariable (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA   *Private,
+  IN CHAR16                         *VariableName
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             X509DataSize;
+  VOID                              *X509Data;
+  EFI_SIGNATURE_LIST                *CACert;
+  EFI_SIGNATURE_DATA                *CACertData;
+  VOID                              *Data;
+  UINTN                             DataSize;
+  UINTN                             SigDataSize;
+  UINT32                            Attr;
+
+  X509DataSize  = 0;
+  SigDataSize   = 0;
+  DataSize      = 0;
+  X509Data      = NULL;
+  CACert        = NULL;
+  CACertData    = NULL;
+  Data          = NULL;
+
+  Status = ReadFileContent (
+             Private->FileContext->FHandle,
+             &X509Data,
+             &X509DataSize,
+             0
+             );
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+  ASSERT (X509Data != NULL);
+
+  SigDataSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
+
+  Data = AllocateZeroPool (SigDataSize);
+  if (Data == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Fill Certificate Database parameters.
+  //
+  CACert = (EFI_SIGNATURE_LIST*) Data;
+  CACert->SignatureListSize   = (UINT32) SigDataSize;
+  CACert->SignatureHeaderSize = 0;
+  CACert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
+  CopyGuid (&CACert->SignatureType, &gEfiCertX509Guid);
+
+  CACertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) CACert + sizeof (EFI_SIGNATURE_LIST));
+  CopyGuid (&CACertData->SignatureOwner, Private->CertGuid);
+  CopyMem ((UINT8* ) (CACertData->SignatureData), X509Data, X509DataSize);
+
+  //
+  // Check if signature database entry has been already existed.
+  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
+  // new signature data to original variable
+  //
+  Attr = TLS_AUTH_CONFIG_VAR_BASE_ATTR;
+
+  Status = gRT->GetVariable(
+                  VariableName,
+                  &gEfiTlsCaCertificateGuid,
+                  NULL,
+                  &DataSize,
+                  NULL
+                  );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    Attr |= EFI_VARIABLE_APPEND_WRITE;
+  } else if (Status != EFI_NOT_FOUND) {
+    goto ON_EXIT;
+  }
+
+  Status = gRT->SetVariable(
+                  VariableName,
+                  &gEfiTlsCaCertificateGuid,
+                  Attr,
+                  SigDataSize,
+                  Data
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+
+  CloseFile (Private->FileContext->FHandle);
+  if (Private->FileContext->FileName != NULL) {
+    FreePool(Private->FileContext->FileName);
+    Private->FileContext->FileName = NULL;
+  }
+
+  Private->FileContext->FHandle = NULL;
+
+  if (Private->CertGuid != NULL) {
+    FreePool (Private->CertGuid);
+    Private->CertGuid = NULL;
+  }
+
+  if (Data != NULL) {
+    FreePool (Data);
+  }
+
+  if (X509Data != NULL) {
+    FreePool (X509Data);
+  }
+
+  return Status;
+}
+
+/**
+  Enroll Cert into TlsCaCertificate. The GUID will be Private->CertGuid.
+
+  @param[in] PrivateData     The module's private data.
+  @param[in] VariableName    Variable name of signature database.
+
+  @retval   EFI_SUCCESS            New Cert enrolled successfully.
+  @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
+  @retval   EFI_UNSUPPORTED        The Cert file is unsupported type.
+  @retval   others                 Fail to enroll Cert data.
+
+**/
+EFI_STATUS
+EnrollCertDatabase (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA  *Private,
+  IN CHAR16                        *VariableName
+  )
+{
+  UINT16*      FilePostFix;
+  UINTN        NameLength;
+
+  if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->CertGuid == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Parse the file's postfix.
+  //
+  NameLength = StrLen (Private->FileContext->FileName);
+  if (NameLength <= 4) {
+    return EFI_INVALID_PARAMETER;
+  }
+  FilePostFix = Private->FileContext->FileName + NameLength - 4;
+
+  if (IsDerPemEncodeCertificate (FilePostFix)) {
+    //
+    // Supports DER-encoded X509 certificate.
+    //
+    return EnrollX509toVariable (Private, VariableName);
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Refresh the global UpdateData structure.
+
+**/
+VOID
+RefreshUpdateData (
+  VOID
+  )
+{
+  //
+  // Free current updated date
+  //
+  if (mStartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mStartOpCodeHandle);
+  }
+
+  //
+  // Create new OpCode Handle
+  //
+  mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                         mStartOpCodeHandle,
+                                         &gEfiIfrTianoGuid,
+                                         NULL,
+                                         sizeof (EFI_IFR_GUID_LABEL)
+                                         );
+  mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+}
+
+/**
+  Clean up the dynamic opcode at label and form specified by both LabelId.
+
+  @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.
+  @param[in] PrivateData     Module private data.
+
+**/
+VOID
+CleanUpPage (
+  IN UINT16                           LabelId,
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *PrivateData
+  )
+{
+  RefreshUpdateData ();
+
+  //
+  // Remove all op-codes from dynamic page
+  //
+  mStartLabel->Number = LabelId;
+  HiiUpdateForm (
+    PrivateData->RegisteredHandle,
+    &gTlsAuthConfigGuid,
+    LabelId,
+    mStartOpCodeHandle, // Label LabelId
+    mEndOpCodeHandle    // LABEL_END
+    );
+}
+
+/**
+  Update the form base on the selected file.
+
+  @param FilePath   Point to the file path.
+  @param FormId     The form need to display.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+
+**/
+BOOLEAN
+UpdatePage(
+  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
+  IN  EFI_FORM_ID               FormId
+  )
+{
+  CHAR16                *FileName;
+  EFI_STRING_ID         StringToken;
+
+  FileName = NULL;
+
+  if (FilePath != NULL) {
+    FileName = ExtractFileNameFromDevicePath(FilePath);
+  }
+  if (FileName == NULL) {
+    //
+    // FileName = NULL has two case:
+    // 1. FilePath == NULL, not select file.
+    // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.
+    // In these two case, no need to update the form, and exit the caller function.
+    //
+    return TRUE;
+  }
+  StringToken =  HiiSetString (mTlsAuthPrivateData->RegisteredHandle, 0, FileName, NULL);
+
+  mTlsAuthPrivateData->FileContext->FileName = FileName;
+
+  OpenFileByDevicePath (
+    &FilePath,
+    &mTlsAuthPrivateData->FileContext->FHandle,
+    EFI_FILE_MODE_READ,
+    0
+    );
+  //
+  // Create Subtitle op-code for the display string of the option.
+  //
+  RefreshUpdateData ();
+  mStartLabel->Number = FormId;
+
+  HiiCreateSubTitleOpCode (
+    mStartOpCodeHandle,
+    StringToken,
+    0,
+    0,
+    0
+   );
+
+  HiiUpdateForm (
+    mTlsAuthPrivateData->RegisteredHandle,
+    &gTlsAuthConfigGuid,
+    FormId,
+    mStartOpCodeHandle, /// Label FormId
+    mEndOpCodeHandle    /// LABEL_END
+    );
+
+  return TRUE;
+}
+
+/**
+  Update the form base on the input file path info.
+
+  @param FilePath    Point to the file path.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+**/
+BOOLEAN
+UpdateCAFromFile (
+  IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
+  )
+{
+  return UpdatePage(FilePath, TLS_AUTH_CONFIG_FORMID4_FORM);
+}
+
+/**
+  Unload the configuration form, this includes: delete all the configuration
+  entries, uninstall the form callback protocol, and free the resources used.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is unloaded.
+  @retval Others                  Failed to unload the form.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormUnload (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  )
+{
+  if (Private->DriverHandle != NULL) {
+    //
+    // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
+    //
+    gBS->UninstallMultipleProtocolInterfaces (
+           Private->DriverHandle,
+           &gEfiDevicePathProtocolGuid,
+           &mTlsAuthConfigHiiVendorDevicePath,
+           &gEfiHiiConfigAccessProtocolGuid,
+           &Private->ConfigAccess,
+           NULL
+           );
+    Private->DriverHandle = NULL;
+  }
+
+  if (Private->RegisteredHandle != NULL) {
+    //
+    // Remove HII package list
+    //
+    HiiRemovePackages (Private->RegisteredHandle);
+    Private->RegisteredHandle = NULL;
+  }
+
+  if (Private->CertGuid != NULL) {
+    FreePool (Private->CertGuid);
+  }
+
+  if (Private->FileContext != NULL) {
+    FreePool (Private->FileContext);
+  }
+
+  FreePool (Private);
+
+  if (mStartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mStartOpCodeHandle);
+  }
+
+  if (mEndOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mEndOpCodeHandle);
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Initialize the configuration form.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is initialized.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormInit (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  )
+{
+  EFI_STATUS                        Status;
+
+  Private->Signature = TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE;
+  
+  Private->ConfigAccess.ExtractConfig = TlsAuthConfigAccessExtractConfig;
+  Private->ConfigAccess.RouteConfig   = TlsAuthConfigAccessRouteConfig;
+  Private->ConfigAccess.Callback      = TlsAuthConfigAccessCallback;
+
+  //
+  // Install Device Path Protocol and Config Access protocol to driver handle.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Private->DriverHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  &mTlsAuthConfigHiiVendorDevicePath,
+                  &gEfiHiiConfigAccessProtocolGuid,
+                  &Private->ConfigAccess,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  
+  //
+  // Publish our HII data.
+  //
+  Private->RegisteredHandle = HiiAddPackages (
+                                &gTlsAuthConfigGuid,
+                                Private->DriverHandle,
+                                TlsAuthConfigDxeStrings,
+                                TlsAuthConfigVfrBin,
+                                NULL
+                                );
+  if (Private->RegisteredHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  Private->FileContext = AllocateZeroPool (sizeof (TLS_AUTH_CONFIG_FILE_CONTEXT));
+  if (Private->FileContext == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  //
+  // Init OpCode Handle and Allocate space for creation of Buffer
+  //
+  mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (mStartOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (mEndOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                         mStartOpCodeHandle,
+                                         &gEfiIfrTianoGuid,
+                                         NULL,
+                                         sizeof (EFI_IFR_GUID_LABEL)
+                                         );
+  mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+
+  //
+  // Create Hii Extend Label OpCode as the end opcode
+  //
+  mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                       mEndOpCodeHandle,
+                                       &gEfiIfrTianoGuid,
+                                       NULL,
+                                       sizeof (EFI_IFR_GUID_LABEL)
+                                       );
+  mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  mEndLabel->Number       = LABEL_END;
+
+  return EFI_SUCCESS;
+  
+Error:
+  TlsAuthConfigFormUnload (Private);
+  return Status;
+}
+
+/**
+   
+  This function allows the caller to request the current
+  configuration for one or more named elements. The resulting
+  string is in <ConfigAltResp> format. Any and all alternative
+  configuration strings shall also be appended to the end of the
+  current configuration string. If they are, they must appear
+  after the current configuration. They must contain the same
+  routing (GUID, NAME, PATH) as the current configuration string.
+  They must have an additional description indicating the type of
+  alternative configuration the string represents,
+  "ALTCFG=<StringToken>". That <StringToken> (when
+  converted from Hex UNICODE to binary) is a reference to a
+  string in the associated string pack.
+
+  @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Request    A null-terminated Unicode string in
+                    <ConfigRequest> format. Note that this
+                    includes the routing information as well as
+                    the configurable name / value pairs. It is
+                    invalid for this string to be in
+                    <MultiConfigRequest> format. 
+                    If a NULL is passed in for the Request field, 
+                    all of the settings being abstracted by this function 
+                    will be returned in the Results field.  In addition, 
+                    if a ConfigHdr is passed in with no request elements, 
+                    all of the settings being abstracted for that particular 
+                    ConfigHdr reference will be returned in the Results Field.
+
+  @param Progress   On return, points to a character in the
+                    Request string. Points to the string's null
+                    terminator if request was successful. Points
+                    to the most recent "&" before the first
+                    failing name / value pair (or the beginning
+                    of the string if the failure is in the first
+                    name / value pair) if the request was not
+                    successful.
+
+  @param Results    A null-terminated Unicode string in
+                    <MultiConfigAltResp> format which has all values
+                    filled in for the names in the Request string.
+                    String to be allocated by the called function.
+
+  @retval EFI_SUCCESS             The Results string is filled with the
+                                  values corresponding to all requested
+                                  names.
+
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+
+  @retval EFI_NOT_FOUND           Routing data doesn't match any
+                                  known driver. Progress set to the
+                                  first character in the routing header.
+                                  Note: There is no requirement that the
+                                  driver validate the routing data. It
+                                  must skip the <ConfigHdr> in order to
+                                  process the names.
+
+  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
+                                  to most recent "&" before the
+                                  error or the beginning of the
+                                  string.
+
+  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
+                                  to the & before the name in
+                                  question.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessExtractConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Request,
+  OUT       EFI_STRING                      *Progress,
+  OUT       EFI_STRING                      *Results
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             BufferSize;
+  UINTN                             Size;
+  EFI_STRING                        ConfigRequest;
+  EFI_STRING                        ConfigRequestHdr;
+  TLS_AUTH_CONFIG_PRIVATE_DATA      *Private;
+  BOOLEAN                           AllocatedRequest;
+
+  if (Progress == NULL || Results == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AllocatedRequest = FALSE;
+  ConfigRequestHdr = NULL;
+  ConfigRequest    = NULL;
+  Size             = 0;
+
+  Private          = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
+
+  BufferSize       = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+  ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
+  
+  *Progress        = Request;
+
+  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+  
+  ConfigRequest = Request;
+  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+    //
+    // Request is set to NULL or OFFSET is NULL, construct full request string.
+    //
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+    //
+    ConfigRequestHdr = HiiConstructConfigHdr (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, Private->DriverHandle);
+    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+    ConfigRequest = AllocateZeroPool (Size);
+    ASSERT (ConfigRequest != NULL);
+    AllocatedRequest = TRUE;
+    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+    FreePool (ConfigRequestHdr);
+    ConfigRequestHdr = NULL;
+  }
+
+  Status = gHiiConfigRouting->BlockToConfig (
+                                gHiiConfigRouting,
+                                ConfigRequest,
+                                (UINT8 *) &Private->TlsAuthConfigNvData,
+                                BufferSize,
+                                Results,
+                                Progress
+                                );
+
+  //
+  // Free the allocated config request string.
+  //
+  if (AllocatedRequest) {
+    FreePool (ConfigRequest);
+  }
+
+  //
+  // Set Progress string to the original request string.
+  //
+  if (Request == NULL) {
+    *Progress = NULL;
+  } else if (StrStr (Request, L"OFFSET") == NULL) {
+    *Progress = Request + StrLen (Request);
+  }
+
+  return Status;
+}
+
+/**
+   
+  This function applies changes in a driver's configuration.
+  Input is a Configuration, which has the routing data for this
+  driver followed by name / value configuration pairs. The driver
+  must apply those pairs to its configurable storage. If the
+  driver's configuration is stored in a linear block of data
+  and the driver's name / value pairs are in <BlockConfig>
+  format, it may use the ConfigToBlock helper function (above) to
+  simplify the job.
+
+  @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Configuration  A null-terminated Unicode string in
+                        <ConfigString> format. 
+  
+  @param Progress       A pointer to a string filled in with the
+                        offset of the most recent '&' before the
+                        first failing name / value pair (or the
+                        beginn ing of the string if the failure
+                        is in the first name / value pair) or
+                        the terminating NULL if all was
+                        successful.
+
+  @retval EFI_SUCCESS             The results have been distributed or are
+                                  awaiting distribution.
+  
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+  
+  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
+                                  Results parameter would result
+                                  in this type of error.
+  
+  @retval EFI_NOT_FOUND           Target for the specified routing data
+                                  was not found
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessRouteConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Configuration,
+  OUT       EFI_STRING                      *Progress
+  )
+{
+  EFI_STATUS                       Status;
+  UINTN                            BufferSize;
+  TLS_AUTH_CONFIG_PRIVATE_DATA     *Private;
+
+  if (Progress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  *Progress = Configuration;
+
+  if (Configuration == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check routing data in <ConfigHdr>.
+  // Note: there is no name for Name/Value storage, only GUID will be checked
+  //
+  if (!HiiIsConfigHdrMatch (Configuration, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+
+  Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
+  
+  BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+  ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
+
+  Status = gHiiConfigRouting->ConfigToBlock (
+                                gHiiConfigRouting,
+                                Configuration,
+                                (UINT8 *) &Private->TlsAuthConfigNvData,
+                                &BufferSize,
+                                Progress
+                                );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return Status;
+}  
+
+/**
+   
+  This function is called to provide results data to the driver.
+  This data consists of a unique key that is used to identify
+  which data is either being passed back or being asked for.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  QuestionId             A unique value which is sent to the original
+                                 exporting driver so that it can identify the type
+                                 of data to expect. The format of the data tends to 
+                                 vary based on the opcode that generated the callback.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  ActionRequest          On return, points to the action requested by the
+                                 callback function.
+
+  @retval EFI_SUCCESS            The callback successfully handled the action.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
+                                 variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
+                                 callback.
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessCallback (
+  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN     EFI_BROWSER_ACTION                     Action,
+  IN     EFI_QUESTION_ID                        QuestionId,
+  IN     UINT8                                  Type,
+  IN OUT EFI_IFR_TYPE_VALUE                     *Value,
+  OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
+  )
+{
+  EFI_INPUT_KEY                   Key;
+  EFI_STATUS                      Status;
+  TLS_AUTH_CONFIG_PRIVATE_DATA    *Private;
+  UINTN                           BufferSize;
+  TLS_AUTH_CONFIG_IFR_NVDATA      *IfrNvData;
+  UINT16                          LabelId;
+  EFI_DEVICE_PATH_PROTOCOL        *File;
+
+  Status           = EFI_SUCCESS;
+  File             = NULL;
+
+  if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
+
+  mTlsAuthPrivateData = Private;
+
+  //
+  // Retrieve uncommitted data from Browser
+  //
+  BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+  IfrNvData = AllocateZeroPool (BufferSize);
+  if (IfrNvData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  HiiGetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8 *) IfrNvData);
+
+  if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
+      (Action != EFI_BROWSER_ACTION_CHANGING)) {
+    Status = EFI_UNSUPPORTED;
+    goto EXIT;
+  }
+
+  if (Action == EFI_BROWSER_ACTION_CHANGING) {
+    switch (QuestionId) {
+    case KEY_TLS_AUTH_CONFIG_CLIENT_CERT:
+    case KEY_TLS_AUTH_CONFIG_SERVER_CA:
+      //
+      // Clear Cert GUID.
+      //
+      ZeroMem (IfrNvData->CertGuid, sizeof (IfrNvData->CertGuid));
+      if (Private->CertGuid == NULL) {
+        Private->CertGuid = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));
+        if (Private->CertGuid == NULL) {
+          return EFI_OUT_OF_RESOURCES;
+        }
+      }
+      if (QuestionId == KEY_TLS_AUTH_CONFIG_CLIENT_CERT) {
+        LabelId = TLS_AUTH_CONFIG_FORMID3_FORM;
+      } else if (QuestionId == KEY_TLS_AUTH_CONFIG_SERVER_CA) {
+        LabelId = TLS_AUTH_CONFIG_FORMID4_FORM;
+      }
+
+      //
+      // Refresh selected file.
+      //
+      CleanUpPage (LabelId, Private);
+      break;
+    case KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE:
+      ChooseFile( NULL, NULL, (CHOOSE_HANDLER) UpdateCAFromFile, &File);
+      break;
+
+    case KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT:
+      Status = EnrollCertDatabase (Private, EFI_TLS_CA_CERTIFICATE_VARIABLE);
+      if (EFI_ERROR (Status)) {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"ERROR: Enroll Cert Failure!",
+          NULL
+          );
+      }
+      break;
+
+    case KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT:
+      if (Private->FileContext->FHandle != NULL) {
+        CloseFile (Private->FileContext->FHandle);
+        Private->FileContext->FHandle = NULL;
+        if (Private->FileContext->FileName!= NULL){
+          FreePool(Private->FileContext->FileName);
+          Private->FileContext->FileName = NULL;
+        }
+      }
+
+      if (Private->CertGuid!= NULL) {
+        FreePool (Private->CertGuid);
+        Private->CertGuid = NULL;
+      }
+      break;
+
+    case KEY_TLS_AUTH_CONFIG_DELETE_CERT:
+      UpdateDeletePage (
+        Private,
+        EFI_TLS_CA_CERTIFICATE_VARIABLE,
+        &gEfiTlsCaCertificateGuid,
+        LABEL_CA_DELETE,
+        TLS_AUTH_CONFIG_FORMID5_FORM,
+        OPTION_DEL_CA_ESTION_ID
+        );
+       break;
+      
+    default:
+      if ((QuestionId >= OPTION_DEL_CA_ESTION_ID) &&
+                 (QuestionId < (OPTION_DEL_CA_ESTION_ID + OPTION_CONFIG_RANGE)))  {
+        DeleteCert (
+          Private,
+          EFI_TLS_CA_CERTIFICATE_VARIABLE,
+          &gEfiTlsCaCertificateGuid,
+          LABEL_CA_DELETE,
+          TLS_AUTH_CONFIG_FORMID5_FORM,
+          OPTION_DEL_CA_ESTION_ID,
+          QuestionId - OPTION_DEL_CA_ESTION_ID
+          );
+      }
+      break;
+    }
+  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
+    switch (QuestionId) {
+    case KEY_TLS_AUTH_CONFIG_CERT_GUID:
+      ASSERT (Private->CertGuid != NULL);
+      Status = StringToGuid (
+                 IfrNvData->CertGuid,
+                 StrLen (IfrNvData->CertGuid),
+                 Private->CertGuid
+                 );
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+      break;
+    default:
+      break;
+    }
+  }
+  
+EXIT:
+
+  if (!EFI_ERROR (Status)) {
+    BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+    HiiSetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8*) IfrNvData, NULL);
+  }
+
+  FreePool (IfrNvData);
+
+  if (File != NULL){
+    FreePool(File);
+    File = NULL;
+  }
+
+  return EFI_SUCCESS;
+
+}
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
new file mode 100644
index 0000000..398f7b6
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
@@ -0,0 +1,282 @@
+/** @file
+  Header file of Miscellaneous Routines for TlsAuthConfigDxe 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 __TLS_AUTH_CONFIG_IMPL_H__
+#define __TLS_AUTH_CONFIG_IMPL_H__
+
+#include <Uefi.h>
+
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/SimpleFileSystem.h>
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/FileExplorerLib.h>
+#include <Library/PrintLib.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/ImageAuthentication.h>
+#include <Guid/TlsAuthentication.h>
+
+
+//
+// Include files with function prototypes
+//
+#include "TlsAuthConfigNvData.h"
+
+extern   UINT8       TlsAuthConfigDxeStrings[];
+extern   UINT8       TlsAuthConfigVfrBin[];
+
+#define TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE    SIGNATURE_32 ('T', 'A', 'C', 'D')
+#define TLS_AUTH_CONFIG_PRIVATE_FROM_THIS(a)      CR (a, TLS_AUTH_CONFIG_PRIVATE_DATA, ConfigAccess, TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE)
+
+#define TLS_AUTH_CONFIG_VAR_BASE_ATTR  (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)
+
+typedef struct _TLS_AUTH_CONFIG_PRIVATE_DATA      TLS_AUTH_CONFIG_PRIVATE_DATA;
+typedef struct _TLS_AUTH_CONFIG_FILE_CONTEXT      TLS_AUTH_CONFIG_FILE_CONTEXT;
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+  VENDOR_DEVICE_PATH                VendorDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL          End;
+} HII_VENDOR_DEVICE_PATH;
+
+struct _TLS_AUTH_CONFIG_FILE_CONTEXT {
+  EFI_FILE_HANDLE                   FHandle;
+  UINT16                            *FileName;
+};
+
+struct _TLS_AUTH_CONFIG_PRIVATE_DATA {
+  UINTN                             Signature;
+
+  EFI_HANDLE                        DriverHandle;
+  EFI_HII_HANDLE                    RegisteredHandle;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL    ConfigAccess;
+  TLS_AUTH_CONFIG_IFR_NVDATA        TlsAuthConfigNvData;
+
+  TLS_AUTH_CONFIG_FILE_CONTEXT      *FileContext;
+
+  EFI_GUID                          *CertGuid;
+};
+
+/**
+  Unload the configuration form, this includes: delete all the configuration
+  entries, uninstall the form callback protocol, and free the resources used.
+  The form will only be unload completely when both IP4 and IP6 stack are stopped.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is unloaded.
+  @retval Others                  Failed to unload the form.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormUnload (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  );
+
+/**
+  Initialize the configuration form.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is initialized.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormInit (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  );
+
+/**
+   
+  This function allows the caller to request the current
+  configuration for one or more named elements. The resulting
+  string is in <ConfigAltResp> format. Any and all alternative
+  configuration strings shall also be appended to the end of the
+  current configuration string. If they are, they must appear
+  after the current configuration. They must contain the same
+  routing (GUID, NAME, PATH) as the current configuration string.
+  They must have an additional description indicating the type of
+  alternative configuration the string represents,
+  "ALTCFG=<StringToken>". That <StringToken> (when
+  converted from Hex UNICODE to binary) is a reference to a
+  string in the associated string pack.
+
+  @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Request    A null-terminated Unicode string in
+                    <ConfigRequest> format. Note that this
+                    includes the routing information as well as
+                    the configurable name / value pairs. It is
+                    invalid for this string to be in
+                    <MultiConfigRequest> format. 
+                    If a NULL is passed in for the Request field, 
+                    all of the settings being abstracted by this function 
+                    will be returned in the Results field.  In addition, 
+                    if a ConfigHdr is passed in with no request elements, 
+                    all of the settings being abstracted for that particular 
+                    ConfigHdr reference will be returned in the Results Field.
+
+  @param Progress   On return, points to a character in the
+                    Request string. Points to the string's null
+                    terminator if request was successful. Points
+                    to the most recent "&" before the first
+                    failing name / value pair (or the beginning
+                    of the string if the failure is in the first
+                    name / value pair) if the request was not
+                    successful.
+
+  @param Results    A null-terminated Unicode string in
+                    <MultiConfigAltResp> format which has all values
+                    filled in for the names in the Request string.
+                    String to be allocated by the called function.
+
+  @retval EFI_SUCCESS             The Results string is filled with the
+                                  values corresponding to all requested
+                                  names.
+
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+
+  @retval EFI_NOT_FOUND           Routing data doesn't match any
+                                  known driver. Progress set to the
+                                  first character in the routing header.
+                                  Note: There is no requirement that the
+                                  driver validate the routing data. It
+                                  must skip the <ConfigHdr> in order to
+                                  process the names.
+
+  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
+                                  to most recent "&" before the
+                                  error or the beginning of the
+                                  string.
+
+  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
+                                  to the & before the name in
+                                  question.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessExtractConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Request,
+  OUT       EFI_STRING                      *Progress,
+  OUT       EFI_STRING                      *Results
+  );
+
+/**
+   
+  This function applies changes in a driver's configuration.
+  Input is a Configuration, which has the routing data for this
+  driver followed by name / value configuration pairs. The driver
+  must apply those pairs to its configurable storage. If the
+  driver's configuration is stored in a linear block of data
+  and the driver's name / value pairs are in <BlockConfig>
+  format, it may use the ConfigToBlock helper function (above) to
+  simplify the job.
+
+  @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Configuration  A null-terminated Unicode string in
+                        <ConfigString> format. 
+  
+  @param Progress       A pointer to a string filled in with the
+                        offset of the most recent '&' before the
+                        first failing name / value pair (or the
+                        beginn ing of the string if the failure
+                        is in the first name / value pair) or
+                        the terminating NULL if all was
+                        successful.
+
+  @retval EFI_SUCCESS             The results have been distributed or are
+                                  awaiting distribution.
+  
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+  
+  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
+                                  Results parameter would result
+                                  in this type of error.
+  
+  @retval EFI_NOT_FOUND           Target for the specified routing data
+                                  was not found
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessRouteConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Configuration,
+  OUT       EFI_STRING                      *Progress
+  );  
+
+/**
+   
+  This function is called to provide results data to the driver.
+  This data consists of a unique key that is used to identify
+  which data is either being passed back or being asked for.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  QuestionId             A unique value which is sent to the original
+                                 exporting driver so that it can identify the type
+                                 of data to expect. The format of the data tends to 
+                                 vary based on the opcode that generated the callback.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  ActionRequest          On return, points to the action requested by the
+                                 callback function.
+
+  @retval EFI_SUCCESS            The callback successfully handled the action.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
+                                 variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
+                                 callback.
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessCallback (
+  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN     EFI_BROWSER_ACTION                     Action,
+  IN     EFI_QUESTION_ID                        QuestionId,
+  IN     UINT8                                  Type,
+  IN OUT EFI_IFR_TYPE_VALUE                     *Value,
+  OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
+  );
+
+#endif
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
new file mode 100644
index 0000000..f453201
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
@@ -0,0 +1,49 @@
+/** @file
+  Header file for NV data structure definition.
+
+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 __TLS_AUTH_CONFIG_NV_DATA_H__
+#define __TLS_AUTH_CONFIG_NV_DATA_H__
+
+#include <Guid/TlsAuthConfigHii.h>
+
+#define TLS_AUTH_CONFIG_GUID_SIZE                 36
+#define TLS_AUTH_CONFIG_GUID_STORAGE_SIZE         37
+
+#define TLS_AUTH_CONFIG_FORMID1_FORM              1
+#define TLS_AUTH_CONFIG_FORMID2_FORM              2
+#define TLS_AUTH_CONFIG_FORMID3_FORM              3
+#define TLS_AUTH_CONFIG_FORMID4_FORM              4
+#define TLS_AUTH_CONFIG_FORMID5_FORM              5
+
+
+#define KEY_TLS_AUTH_CONFIG_SERVER_CA                  0x1000
+#define KEY_TLS_AUTH_CONFIG_CLIENT_CERT                0x1001
+#define KEY_TLS_AUTH_CONFIG_ENROLL_CERT                0x1002
+#define KEY_TLS_AUTH_CONFIG_DELETE_CERT                0x1003
+#define KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE      0x1004
+#define KEY_TLS_AUTH_CONFIG_CERT_GUID                  0x1005
+#define KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT        0x1006
+#define KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT     0x1007
+
+#define OPTION_DEL_CA_ESTION_ID                        0x2000
+#define OPTION_CONFIG_RANGE                            0x1000
+
+#define LABEL_CA_DELETE                                0x1101
+#define LABEL_END                                      0xffff
+
+typedef struct {
+  CHAR16    CertGuid[TLS_AUTH_CONFIG_GUID_STORAGE_SIZE];
+} TLS_AUTH_CONFIG_IFR_NVDATA;
+
+#endif
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
new file mode 100644
index 0000000..fb130d9
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
@@ -0,0 +1,152 @@
+/** @file
+  VFR file used by TlsAuthConfigDxe 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.
+
+**/
+
+#include "TlsAuthConfigNvData.h"
+
+formset
+  guid   = TLS_AUTH_CONFIG_GUID,
+  title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_TITLE),
+  help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_HELP),
+
+  varstore TLS_AUTH_CONFIG_IFR_NVDATA,
+    name = TLS_AUTH_CONFIG_IFR_NVDATA,
+    guid = TLS_AUTH_CONFIG_GUID;
+
+  //
+  // ##1 Form1: Main form for Tls Auth configration
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID1_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_TITLE);
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+    
+    //
+    // Display Server CA configration
+    //
+    goto TLS_AUTH_CONFIG_FORMID2_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_SERVER_CA;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    //
+    // Display Client cert configration
+    //
+    grayoutif TRUE; /// Current unsupported.
+    goto TLS_AUTH_CONFIG_FORMID3_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_CLIENT_CERT;
+    endif;
+  endform; 
+
+  //
+  // ##2 Form2: CA configuration
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID2_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA);
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID4_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_ENROLL_CERT;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID5_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_DELETE_CERT;
+  endform;
+
+  //
+  // ##3 Form3 : Client cert configuration
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID3_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT);
+    
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+  //
+  // TODO...
+  //
+  endform;
+
+  //
+  // ##4 Form4: Enroll cert for CA
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID4_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT);
+    
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID4_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ADD_CERT_FILE),
+         help = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ADD_CERT_FILE),
+         flags = INTERACTIVE,
+         key = KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+    label TLS_AUTH_CONFIG_FORMID4_FORM;
+    label LABEL_END;
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    string  varid   = TLS_AUTH_CONFIG_IFR_NVDATA.CertGuid,
+            prompt  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CERT_GUID),
+            help    = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CERT_GUID_HELP),
+            flags   = INTERACTIVE,
+            key     = KEY_TLS_AUTH_CONFIG_CERT_GUID,
+            minsize = TLS_AUTH_CONFIG_GUID_SIZE,
+            maxsize = TLS_AUTH_CONFIG_GUID_SIZE,
+    endstring;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID1_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT;
+
+    goto TLS_AUTH_CONFIG_FORMID1_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT;
+         
+  endform;
+
+  //
+  // ##5 Form5: Delete cert for CA
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID5_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT);
+
+    label LABEL_CA_DELETE;
+    label LABEL_END;
+    
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+  endform;
+  
+endformset;
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6
  2016-12-14  7:34 [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master Jiaxin Wu
                   ` (5 preceding siblings ...)
  2016-12-14  7:34 ` [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration Jiaxin Wu
@ 2016-12-14  7:34 ` Jiaxin Wu
  2016-12-15  2:39   ` Fu, Siyuan
  2016-12-22  7:33   ` Ye, Ting
  2016-12-14  7:34 ` [Patch 08/10] NetworkPkg/NetworkPkg.dsc: Enable TlsDxe and TlsAuthConfigDxe module Jiaxin Wu
                   ` (2 subsequent siblings)
  9 siblings, 2 replies; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ye Ting, Fu Siyuan, Zhang Lubo, Long Qin, Thomas Palmer,
	Wu Jiaxin

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



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Patch 08/10] NetworkPkg/NetworkPkg.dsc: Enable TlsDxe and TlsAuthConfigDxe module
  2016-12-14  7:34 [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master Jiaxin Wu
                   ` (6 preceding siblings ...)
  2016-12-14  7:34 ` [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6 Jiaxin Wu
@ 2016-12-14  7:34 ` 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:34 ` [Patch 10/10] Nt32Pkg: Enable HTTPS boot feature for Nt32 platform Jiaxin Wu
  9 siblings, 2 replies; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Ye Ting, Fu Siyuan, Zhang Lubo, Long Qin, Thomas Palmer,
	Wu Jiaxin

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/NetworkPkg.dsc | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/NetworkPkg/NetworkPkg.dsc b/NetworkPkg/NetworkPkg.dsc
index 1ef353e..3d881e9 100644
--- a/NetworkPkg/NetworkPkg.dsc
+++ b/NetworkPkg/NetworkPkg.dsc
@@ -53,12 +53,14 @@
   TcpIoLib|MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf
   HttpLib|MdeModulePkg/Library/DxeHttpLib/DxeHttpLib.inf
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
   IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+  TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
   DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf  
   FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+  FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf
   SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
 
 [LibraryClasses.common.UEFI_DRIVER]
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
@@ -111,10 +113,12 @@
   NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf
   NetworkPkg/DnsDxe/DnsDxe.inf
   NetworkPkg/HttpDxe/HttpDxe.inf
   NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
   NetworkPkg/HttpBootDxe/HttpBootDxe.inf
+  NetworkPkg/TlsDxe/TlsDxe.inf
+  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
 
   NetworkPkg/Application/IfConfig6/IfConfig6.inf
   NetworkPkg/Application/IpsecConfig/IpSecConfig.inf
   NetworkPkg/Application/VConfig/VConfig.inf
 
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Patch 09/10] Nt32Pkg/Nt32Pkg.dsc: Remove the flag for OpensslLib and BaseCryptLib
  2016-12-14  7:34 [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master Jiaxin Wu
                   ` (7 preceding siblings ...)
  2016-12-14  7:34 ` [Patch 08/10] NetworkPkg/NetworkPkg.dsc: Enable TlsDxe and TlsAuthConfigDxe module Jiaxin Wu
@ 2016-12-14  7:34 ` Jiaxin Wu
  2016-12-14  7:56   ` Ni, Ruiyu
                     ` (2 more replies)
  2016-12-14  7:34 ` [Patch 10/10] Nt32Pkg: Enable HTTPS boot feature for Nt32 platform Jiaxin Wu
  9 siblings, 3 replies; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Long Qin, Ni Ruiyu, Ye Ting, Fu Siyuan, Zhang Lubo, Thomas Palmer,
	Wu Jiaxin

This patch is used to remove the 'SECURE_BOOT_ENABLE' flag for OpensslLib
and BaseCryptLib modules.

Cc: Long Qin <qin.long@intel.com>
Cc: Ni Ruiyu <ruiyu.ni@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@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>
---
 Nt32Pkg/Nt32Pkg.dsc | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc
index 4458c02..79ab2f7 100644
--- a/Nt32Pkg/Nt32Pkg.dsc
+++ b/Nt32Pkg/Nt32Pkg.dsc
@@ -131,15 +131,15 @@
   DebugPrintErrorLevelLib|MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
   CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
   LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
+  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
   
 !if $(SECURE_BOOT_ENABLE) == TRUE
   PlatformSecureLib|Nt32Pkg/Library/PlatformSecureLib/PlatformSecureLib.inf
-  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
-  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
   TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
   AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
 !else
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
@@ -173,13 +173,11 @@
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 
 [LibraryClasses.common.PEIM]
   PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
   OemHookStatusCodeLib|Nt32Pkg/Library/PeiNt32OemHookStatusCodeLib/PeiNt32OemHookStatusCodeLib.inf
-!if $(SECURE_BOOT_ENABLE) == TRUE  
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
-!endif
 
 [LibraryClasses.common]
   #
   # DXE phase common
   #
@@ -190,13 +188,11 @@
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
   OemHookStatusCodeLib|Nt32Pkg/Library/DxeNt32OemHookStatusCodeLib/DxeNt32OemHookStatusCodeLib.inf
   PeCoffExtraActionLib|Nt32Pkg/Library/DxeNt32PeCoffExtraActionLib/DxeNt32PeCoffExtraActionLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
   WinNtLib|Nt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.inf
-!if $(SECURE_BOOT_ENABLE) == TRUE
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
-!endif
 
 [LibraryClasses.common.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
@@ -213,13 +209,11 @@
   
 [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   #
   # Runtime
   #
-!if $(SECURE_BOOT_ENABLE) == TRUE
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
-!endif
 
 ################################################################################
 #
 # Pcd Section - list of all EDK II PCD Entries defined by this Platform
 #
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* [Patch 10/10] Nt32Pkg: Enable HTTPS boot feature for Nt32 platform
  2016-12-14  7:34 [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master Jiaxin Wu
                   ` (8 preceding siblings ...)
  2016-12-14  7:34 ` [Patch 09/10] Nt32Pkg/Nt32Pkg.dsc: Remove the flag for OpensslLib and BaseCryptLib Jiaxin Wu
@ 2016-12-14  7:34 ` Jiaxin Wu
  2016-12-14  7:44   ` Yao, Jiewen
  9 siblings, 1 reply; 37+ messages in thread
From: Jiaxin Wu @ 2016-12-14  7:34 UTC (permalink / raw)
  To: edk2-devel
  Cc: Long Qin, Ni Ruiyu, Ye Ting, Fu Siyuan, Zhang Lubo, Thomas Palmer,
	Wu Jiaxin

This path is used to enable HTTPS boot feature for Nt32 platform.

Cc: Long Qin <qin.long@intel.com>
Cc: Ni Ruiyu <ruiyu.ni@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@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>
---
 Nt32Pkg/Nt32Pkg.dsc | 15 ++++++++++++++-
 Nt32Pkg/Nt32Pkg.fdf |  4 ++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc
index 79ab2f7..07703a3 100644
--- a/Nt32Pkg/Nt32Pkg.dsc
+++ b/Nt32Pkg/Nt32Pkg.dsc
@@ -43,10 +43,17 @@
   #
   # Defines for default states.  These can be changed on the command line.
   # -D FLAG=VALUE
   #
   DEFINE SECURE_BOOT_ENABLE      = FALSE
+  
+  #
+  # This flag is to enable or disable HTTPS boot feature.  
+  # These can be changed on the command line.
+  # -D FLAG=VALUE
+  #
+  DEFINE HTTPS_BOOT_ENABLE      = TRUE
 
 ################################################################################
 #
 # SKU Identification section - list of all SKU IDs supported by this
 #                              Platform.
@@ -189,10 +196,11 @@
   OemHookStatusCodeLib|Nt32Pkg/Library/DxeNt32OemHookStatusCodeLib/DxeNt32OemHookStatusCodeLib.inf
   PeCoffExtraActionLib|Nt32Pkg/Library/DxeNt32PeCoffExtraActionLib/DxeNt32PeCoffExtraActionLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
   WinNtLib|Nt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.inf
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+  TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
 
 [LibraryClasses.common.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
@@ -232,11 +240,11 @@
   gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f
   gEfiNt32PkgTokenSpaceGuid.PcdWinNtFirmwareVolume|L"..\\Fv\\Nt32.fd"
   gEfiNt32PkgTokenSpaceGuid.PcdWinNtFirmwareBlockSize|0x10000
   gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x0f
   gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChange|FALSE
-!if $(SECURE_BOOT_ENABLE) == TRUE
+!if $(SECURE_BOOT_ENABLE) == TRUE || $(HTTPS_BOOT_ENABLE) == TRUE
   gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
 !endif
 
 !ifndef $(USE_OLD_SHELL)
   gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }
@@ -437,10 +445,15 @@
 
   NetworkPkg/HttpBootDxe/HttpBootDxe.inf
   NetworkPkg/DnsDxe/DnsDxe.inf
   NetworkPkg/HttpDxe/HttpDxe.inf
   NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
+   
+!if $(HTTPS_BOOT_ENABLE) == TRUE
+  NetworkPkg/TlsDxe/TlsDxe.inf
+  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
+!endif
 
   MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
   MdeModulePkg/Application/UiApp/UiApp.inf{
     <LibraryClasses>
       NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
diff --git a/Nt32Pkg/Nt32Pkg.fdf b/Nt32Pkg/Nt32Pkg.fdf
index cf00a13..094ed91 100644
--- a/Nt32Pkg/Nt32Pkg.fdf
+++ b/Nt32Pkg/Nt32Pkg.fdf
@@ -260,10 +260,14 @@ INF  MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
 INF  MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf
 INF  NetworkPkg/HttpBootDxe/HttpBootDxe.inf
 INF  NetworkPkg/DnsDxe/DnsDxe.inf
 INF  NetworkPkg/HttpDxe/HttpDxe.inf
 INF  NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
+!if $(HTTPS_BOOT_ENABLE) == TRUE
+INF  NetworkPkg/TlsDxe/TlsDxe.inf
+INF  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
+!endif
 INF  MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.inf
 ################################################################################
 #
 # FILE statements are provided so that a platform integrator can include
 # complete EFI FFS files, as well as a method for constructing FFS files
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 10/10] Nt32Pkg: Enable HTTPS boot feature for Nt32 platform
  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
  0 siblings, 1 reply; 37+ messages in thread
From: Yao, Jiewen @ 2016-12-14  7:44 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Ni, Ruiyu, Ye, Ting, Zhang,  Lubo, Wu, Jiaxin, Long, Qin,
	Fu, Siyuan

Hi Jiaxin
Thanks to contribute this.

I found below update is NOT related to HTTPS.

Can we use a better name, such as TLS_ENABLE ?

+!if $(HTTPS_BOOT_ENABLE) == TRUE
+  NetworkPkg/TlsDxe/TlsDxe.inf
+  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
+!endif

Thank you
Yao Jiewen

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiaxin
> Wu
> Sent: Wednesday, December 14, 2016 3:34 PM
> To: edk2-devel@lists.01.org
> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; Ye, Ting <ting.ye@intel.com>; Zhang, Lubo
> <lubo.zhang@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Long, Qin
> <qin.long@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>
> Subject: [edk2] [Patch 10/10] Nt32Pkg: Enable HTTPS boot feature for Nt32
> platform
> 
> This path is used to enable HTTPS boot feature for Nt32 platform.
> 
> Cc: Long Qin <qin.long@intel.com>
> Cc: Ni Ruiyu <ruiyu.ni@intel.com>
> Cc: Ye Ting <ting.ye@intel.com>
> Cc: Fu Siyuan <siyuan.fu@intel.com>
> Cc: Zhang Lubo <lubo.zhang@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>
> ---
>  Nt32Pkg/Nt32Pkg.dsc | 15 ++++++++++++++-
>  Nt32Pkg/Nt32Pkg.fdf |  4 ++++
>  2 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc
> index 79ab2f7..07703a3 100644
> --- a/Nt32Pkg/Nt32Pkg.dsc
> +++ b/Nt32Pkg/Nt32Pkg.dsc
> @@ -43,10 +43,17 @@
>    #
>    # Defines for default states.  These can be changed on the command line.
>    # -D FLAG=VALUE
>    #
>    DEFINE SECURE_BOOT_ENABLE      = FALSE
> +
> +  #
> +  # This flag is to enable or disable HTTPS boot feature.
> +  # These can be changed on the command line.
> +  # -D FLAG=VALUE
> +  #
> +  DEFINE HTTPS_BOOT_ENABLE      = TRUE
> 
> 
> #############################################################
> ###################
>  #
>  # SKU Identification section - list of all SKU IDs supported by this
>  #                              Platform.
> @@ -189,10 +196,11 @@
> 
> OemHookStatusCodeLib|Nt32Pkg/Library/DxeNt32OemHookStatusCodeLib/Dxe
> Nt32OemHookStatusCodeLib.inf
> 
> PeCoffExtraActionLib|Nt32Pkg/Library/DxeNt32PeCoffExtraActionLib/DxeNt32P
> eCoffExtraActionLib.inf
> 
> ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtra
> ctGuidedSectionLib.inf
>    WinNtLib|Nt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.inf
>    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> +  TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
> 
>  [LibraryClasses.common.DXE_CORE]
>    HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
> 
> MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/Dx
> eCoreMemoryAllocationLib.inf
>    PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
> @@ -232,11 +240,11 @@
>    gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f
>    gEfiNt32PkgTokenSpaceGuid.PcdWinNtFirmwareVolume|L"..\\Fv\\Nt32.fd"
>    gEfiNt32PkgTokenSpaceGuid.PcdWinNtFirmwareBlockSize|0x10000
>    gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x0f
> 
> gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationChang
> e|FALSE
> -!if $(SECURE_BOOT_ENABLE) == TRUE
> +!if $(SECURE_BOOT_ENABLE) == TRUE || $(HTTPS_BOOT_ENABLE) == TRUE
>    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
>  !endif
> 
>  !ifndef $(USE_OLD_SHELL)
>    gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5,
> 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4,
> 0xD1 }
> @@ -437,10 +445,15 @@
> 
>    NetworkPkg/HttpBootDxe/HttpBootDxe.inf
>    NetworkPkg/DnsDxe/DnsDxe.inf
>    NetworkPkg/HttpDxe/HttpDxe.inf
>    NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
> +
> +!if $(HTTPS_BOOT_ENABLE) == TRUE
> +  NetworkPkg/TlsDxe/TlsDxe.inf
> +  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
> +!endif
> 
>    MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
>    MdeModulePkg/Application/UiApp/UiApp.inf{
>      <LibraryClasses>
> 
> NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
> diff --git a/Nt32Pkg/Nt32Pkg.fdf b/Nt32Pkg/Nt32Pkg.fdf
> index cf00a13..094ed91 100644
> --- a/Nt32Pkg/Nt32Pkg.fdf
> +++ b/Nt32Pkg/Nt32Pkg.fdf
> @@ -260,10 +260,14 @@ INF
> MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
>  INF  MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf
>  INF  NetworkPkg/HttpBootDxe/HttpBootDxe.inf
>  INF  NetworkPkg/DnsDxe/DnsDxe.inf
>  INF  NetworkPkg/HttpDxe/HttpDxe.inf
>  INF  NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
> +!if $(HTTPS_BOOT_ENABLE) == TRUE
> +INF  NetworkPkg/TlsDxe/TlsDxe.inf
> +INF  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
> +!endif
>  INF
> MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuApp.in
> f
> 
> #############################################################
> ###################
>  #
>  # FILE statements are provided so that a platform integrator can include
>  # complete EFI FFS files, as well as a method for constructing FFS files
> --
> 1.9.5.msysgit.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 10/10] Nt32Pkg: Enable HTTPS boot feature for Nt32 platform
  2016-12-14  7:44   ` Yao, Jiewen
@ 2016-12-14  7:46     ` Wu, Jiaxin
  0 siblings, 0 replies; 37+ messages in thread
From: Wu, Jiaxin @ 2016-12-14  7:46 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org
  Cc: Ni, Ruiyu, Ye, Ting, Zhang,  Lubo, Long, Qin, Fu, Siyuan

Thanks Jiewen, I'm fine with the flag rename:). 

Best Regards!
Jiaxin

> -----Original Message-----
> From: Yao, Jiewen
> Sent: Wednesday, December 14, 2016 3:45 PM
> To: Wu, Jiaxin <jiaxin.wu@intel.com>; edk2-devel@lists.01.org
> Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; Ye, Ting <ting.ye@intel.com>; Zhang,
> Lubo <lubo.zhang@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>; Long, Qin
> <qin.long@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>
> Subject: RE: [edk2] [Patch 10/10] Nt32Pkg: Enable HTTPS boot feature for
> Nt32 platform
> 
> Hi Jiaxin
> Thanks to contribute this.
> 
> I found below update is NOT related to HTTPS.
> 
> Can we use a better name, such as TLS_ENABLE ?
> 
> +!if $(HTTPS_BOOT_ENABLE) == TRUE
> +  NetworkPkg/TlsDxe/TlsDxe.inf
> +  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
> +!endif
> 
> Thank you
> Yao Jiewen
> 
> > -----Original Message-----
> > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> > Jiaxin Wu
> > Sent: Wednesday, December 14, 2016 3:34 PM
> > To: edk2-devel@lists.01.org
> > Cc: Ni, Ruiyu <ruiyu.ni@intel.com>; Ye, Ting <ting.ye@intel.com>;
> > Zhang, Lubo <lubo.zhang@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>;
> > Long, Qin <qin.long@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>
> > Subject: [edk2] [Patch 10/10] Nt32Pkg: Enable HTTPS boot feature for
> > Nt32 platform
> >
> > This path is used to enable HTTPS boot feature for Nt32 platform.
> >
> > Cc: Long Qin <qin.long@intel.com>
> > Cc: Ni Ruiyu <ruiyu.ni@intel.com>
> > Cc: Ye Ting <ting.ye@intel.com>
> > Cc: Fu Siyuan <siyuan.fu@intel.com>
> > Cc: Zhang Lubo <lubo.zhang@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>
> > ---
> >  Nt32Pkg/Nt32Pkg.dsc | 15 ++++++++++++++-  Nt32Pkg/Nt32Pkg.fdf |  4
> > ++++
> >  2 files changed, 18 insertions(+), 1 deletion(-)
> >
> > diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc index
> > 79ab2f7..07703a3 100644
> > --- a/Nt32Pkg/Nt32Pkg.dsc
> > +++ b/Nt32Pkg/Nt32Pkg.dsc
> > @@ -43,10 +43,17 @@
> >    #
> >    # Defines for default states.  These can be changed on the command line.
> >    # -D FLAG=VALUE
> >    #
> >    DEFINE SECURE_BOOT_ENABLE      = FALSE
> > +
> > +  #
> > +  # This flag is to enable or disable HTTPS boot feature.
> > +  # These can be changed on the command line.
> > +  # -D FLAG=VALUE
> > +  #
> > +  DEFINE HTTPS_BOOT_ENABLE      = TRUE
> >
> >
> >
> ##########################################################
> ###
> > ###################
> >  #
> >  # SKU Identification section - list of all SKU IDs supported by this
> >  #                              Platform.
> > @@ -189,10 +196,11 @@
> >
> >
> OemHookStatusCodeLib|Nt32Pkg/Library/DxeNt32OemHookStatusCodeLib/
> Dxe
> > Nt32OemHookStatusCodeLib.inf
> >
> >
> PeCoffExtraActionLib|Nt32Pkg/Library/DxeNt32PeCoffExtraActionLib/DxeNt
> > PeCoffExtraActionLib|32P
> > eCoffExtraActionLib.inf
> >
> >
> ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeE
> > ExtractGuidedSectionLib|xtra
> > ctGuidedSectionLib.inf
> >    WinNtLib|Nt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.inf
> >    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > +  TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
> >
> >  [LibraryClasses.common.DXE_CORE]
> >    HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
> >
> >
> MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLi
> b/Dx
> > eCoreMemoryAllocationLib.inf
> >    PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
> > @@ -232,11 +240,11 @@
> >    gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0x1f
> >
> gEfiNt32PkgTokenSpaceGuid.PcdWinNtFirmwareVolume|L"..\\Fv\\Nt32.fd"
> >    gEfiNt32PkgTokenSpaceGuid.PcdWinNtFirmwareBlockSize|0x10000
> >    gEfiMdePkgTokenSpaceGuid.PcdReportStatusCodePropertyMask|0x0f
> >
> >
> gEfiMdeModulePkgTokenSpaceGuid.PcdResetOnMemoryTypeInformationC
> hang
> > e|FALSE
> > -!if $(SECURE_BOOT_ENABLE) == TRUE
> > +!if $(SECURE_BOOT_ENABLE) == TRUE || $(HTTPS_BOOT_ENABLE) ==
> TRUE
> >    gEfiMdeModulePkgTokenSpaceGuid.PcdMaxVariableSize|0x2000
> >  !endif
> >
> >  !ifndef $(USE_OLD_SHELL)
> >    gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83,
> > 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52,
> > 0x68, 0xD0, 0xB4,
> > 0xD1 }
> > @@ -437,10 +445,15 @@
> >
> >    NetworkPkg/HttpBootDxe/HttpBootDxe.inf
> >    NetworkPkg/DnsDxe/DnsDxe.inf
> >    NetworkPkg/HttpDxe/HttpDxe.inf
> >    NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
> > +
> > +!if $(HTTPS_BOOT_ENABLE) == TRUE
> > +  NetworkPkg/TlsDxe/TlsDxe.inf
> > +  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
> > +!endif
> >
> >    MdeModulePkg/Universal/BdsDxe/BdsDxe.inf
> >    MdeModulePkg/Application/UiApp/UiApp.inf{
> >      <LibraryClasses>
> >
> >
> NULL|MdeModulePkg/Library/DeviceManagerUiLib/DeviceManagerUiLib.inf
> > diff --git a/Nt32Pkg/Nt32Pkg.fdf b/Nt32Pkg/Nt32Pkg.fdf index
> > cf00a13..094ed91 100644
> > --- a/Nt32Pkg/Nt32Pkg.fdf
> > +++ b/Nt32Pkg/Nt32Pkg.fdf
> > @@ -260,10 +260,14 @@ INF
> > MdeModulePkg/Universal/Network/UefiPxeBcDxe/UefiPxeBcDxe.inf
> >  INF  MdeModulePkg/Universal/Network/IScsiDxe/IScsiDxe.inf
> >  INF  NetworkPkg/HttpBootDxe/HttpBootDxe.inf
> >  INF  NetworkPkg/DnsDxe/DnsDxe.inf
> >  INF  NetworkPkg/HttpDxe/HttpDxe.inf
> >  INF  NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
> > +!if $(HTTPS_BOOT_ENABLE) == TRUE
> > +INF  NetworkPkg/TlsDxe/TlsDxe.inf
> > +INF  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
> > +!endif
> >  INF
> >
> MdeModulePkg/Application/BootManagerMenuApp/BootManagerMenuAp
> p.in
> > f
> >
> >
> ##########################################################
> ###
> > ###################
> >  #
> >  # FILE statements are provided so that a platform integrator can
> > include  # complete EFI FFS files, as well as a method for
> > constructing FFS files
> > --
> > 1.9.5.msysgit.1
> >
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 09/10] Nt32Pkg/Nt32Pkg.dsc: Remove the flag for OpensslLib and BaseCryptLib
  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
  2 siblings, 0 replies; 37+ messages in thread
From: Ni, Ruiyu @ 2016-12-14  7:56 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Long, Qin, Ye, Ting, Fu, Siyuan, Zhang, Lubo, Thomas Palmer

Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>

Thanks/Ray

> -----Original Message-----
> From: Wu, Jiaxin
> Sent: Wednesday, December 14, 2016 3:34 PM
> To: edk2-devel@lists.01.org
> Cc: Long, Qin <qin.long@intel.com>; Ni, Ruiyu <ruiyu.ni@intel.com>; Ye, Ting
> <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo
> <lubo.zhang@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>; Wu,
> Jiaxin <jiaxin.wu@intel.com>
> Subject: [Patch 09/10] Nt32Pkg/Nt32Pkg.dsc: Remove the flag for OpensslLib
> and BaseCryptLib
> 
> This patch is used to remove the 'SECURE_BOOT_ENABLE' flag for OpensslLib
> and BaseCryptLib modules.
> 
> Cc: Long Qin <qin.long@intel.com>
> Cc: Ni Ruiyu <ruiyu.ni@intel.com>
> Cc: Ye Ting <ting.ye@intel.com>
> Cc: Fu Siyuan <siyuan.fu@intel.com>
> Cc: Zhang Lubo <lubo.zhang@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>
> ---
>  Nt32Pkg/Nt32Pkg.dsc | 10 ++--------
>  1 file changed, 2 insertions(+), 8 deletions(-)
> 
> diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc index
> 4458c02..79ab2f7 100644
> --- a/Nt32Pkg/Nt32Pkg.dsc
> +++ b/Nt32Pkg/Nt32Pkg.dsc
> @@ -131,15 +131,15 @@
> 
> DebugPrintErrorLevelLib|MdeModulePkg/Library/DxeDebugPrintErrorLevelL
> ib/DxeDebugPrintErrorLevelLib.inf
> 
> PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanc
> eLibNull.inf
> 
> DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLi
> bNull.inf
> 
> CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibN
> ull/CpuExceptionHandlerLibNull.inf
>    LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
> +  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
> +  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
> 
>  !if $(SECURE_BOOT_ENABLE) == TRUE
> 
> PlatformSecureLib|Nt32Pkg/Library/PlatformSecureLib/PlatformSecureLib.in
> f
> -  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
> -  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
> 
> TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTp
> mMeasurementLib.inf
>    AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
>  !else
> 
> TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/Tp
> mMeasurementLibNull.inf
> 
> AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableL
> ibNull.inf
> @@ -173,13 +173,11 @@
> 
> OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibN
> ull/OemHookStatusCodeLibNull.inf
> 
>  [LibraryClasses.common.PEIM]
>    PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
> 
> OemHookStatusCodeLib|Nt32Pkg/Library/PeiNt32OemHookStatusCodeLib/
> PeiNt32OemHookStatusCodeLib.inf
> -!if $(SECURE_BOOT_ENABLE) == TRUE
>    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> -!endif
> 
>  [LibraryClasses.common]
>    #
>    # DXE phase common
>    #
> @@ -190,13 +188,11 @@
> 
> ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/Dx
> eReportStatusCodeLib.inf
> 
> OemHookStatusCodeLib|Nt32Pkg/Library/DxeNt32OemHookStatusCodeLib/
> DxeNt32OemHookStatusCodeLib.inf
> 
> PeCoffExtraActionLib|Nt32Pkg/Library/DxeNt32PeCoffExtraActionLib/DxeNt
> 32PeCoffExtraActionLib.inf
> 
> ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeE
> xtractGuidedSectionLib.inf
>    WinNtLib|Nt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.inf
> -!if $(SECURE_BOOT_ENABLE) == TRUE
>    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> -!endif
> 
>  [LibraryClasses.common.DXE_CORE]
>    HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
> 
> MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLi
> b/DxeCoreMemoryAllocationLib.inf
>    PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
> @@ -213,13 +209,11 @@
> 
>  [LibraryClasses.common.DXE_RUNTIME_DRIVER]
>    #
>    # Runtime
>    #
> -!if $(SECURE_BOOT_ENABLE) == TRUE
>    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> -!endif
> 
> 
> ##########################################################
> ######################
>  #
>  # Pcd Section - list of all EDK II PCD Entries defined by this Platform  #
> --
> 1.9.5.msysgit.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 01/10] MdePkg: Add TLS related protocol definition
  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-14  8:43   ` Fu, Siyuan
  1 sibling, 1 reply; 37+ messages in thread
From: Long, Qin @ 2016-12-14  8:36 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Ye, Ting, Fu, Siyuan, Zhang, Lubo, Gao, Liming, Kinney, Michael D,
	Thomas Palmer

Reviewed-by: Qin Long <qin.long@intel.com>

Please correct some typos later:
EFI_TLS_EXTENDION  --> EFI_TLS_EXTENSION
TLS/SSLhandshake --> TLS/SSL handshake
cerfificate --> certificate
cypher --> cipher
binaryX.509 --> binary X.509
PEMencoded --> PEM-encoded

Best Regards & Thanks,
LONG, Qin

> -----Original Message-----
> From: Wu, Jiaxin
> Sent: Wednesday, December 14, 2016 3:34 PM
> To: edk2-devel@lists.01.org
> Cc: Long, Qin; Ye, Ting; Fu, Siyuan; Zhang, Lubo; Gao, Liming; Kinney, Michael
> D; Thomas Palmer; Wu, Jiaxin
> Subject: [Patch 01/10] MdePkg: Add TLS related protocol definition
> 
> This patch is used to add Tls.h and TlsConfig.h header files to define EFI TLS
> Configuration Protocol, EFI TLS Service Binding Protocol and EFI TLS
> Configuration Protocol.
> 
> Cc: Long Qin <qin.long@intel.com>
> Cc: Ye Ting <ting.ye@intel.com>
> Cc: Fu Siyuan <siyuan.fu@intel.com>
> Cc: Zhang Lubo <lubo.zhang@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@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>
> ---
>  MdePkg/Include/Protocol/Tls.h       | 460
> ++++++++++++++++++++++++++++++++++++
>  MdePkg/Include/Protocol/TlsConfig.h | 132 +++++++++++
>  MdePkg/MdePkg.dec                   |   9 +
>  3 files changed, 601 insertions(+)
>  create mode 100644 MdePkg/Include/Protocol/Tls.h  create mode 100644
> MdePkg/Include/Protocol/TlsConfig.h
> 
> diff --git a/MdePkg/Include/Protocol/Tls.h b/MdePkg/Include/Protocol/Tls.h
> new file mode 100644 index 0000000..51a3cda
> --- /dev/null
> +++ b/MdePkg/Include/Protocol/Tls.h
> @@ -0,0 +1,460 @@
> +/** @file
> +  EFI TLS Protocols as defined in UEFI 2.5.
> +
> +  The EFI TLS Service Binding Protocol is used to locate EFI TLS
> + Protocol drivers  to create and destroy child of the driver to
> + communicate with other host using  TLS protocol.
> +  The EFI TLS Protocol provides the ability to manage TLS session.
> +
> +  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.
> +
> +  @par Revision Reference:
> +  This Protocol is introduced in UEFI Specification 2.5
> +
> +**/
> +
> +#ifndef __EFI_TLS_PROTOCOL_H__
> +#define __EFI_TLS_PROTOCOL_H__
> +
> +///
> +/// The EFI TLS Service Binding Protocol is used to locate EFI TLS
> +Protocol drivers to /// create and destroy child of the driver to
> +communicate with other host using TLS /// protocol.
> +///
> +#define EFI_TLS_SERVICE_BINDING_PROTOCOL_GUID \
> +  { \
> +    0x952cb795, 0xff36, 0x48cf, {0xa2, 0x49, 0x4d, 0xf4, 0x86, 0xd6,
> +0xab, 0x8d } \
> +  }
> +
> +///
> +/// The EFI TLS protocol provides the ability to manage TLS session.
> +///
> +#define EFI_TLS_PROTOCOL_GUID \
> +  { \
> +    0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc, 0xe4, 0x6c, 0x47, 0x51,
> +0x43, 0x90 } \
> +  }
> +
> +typedef struct _EFI_TLS_PROTOCOL EFI_TLS_PROTOCOL;
> +
> +///
> +/// EFI_TLS_SESSION_DATA_TYPE
> +///
> +typedef enum {
> +  ///
> +  /// Session Configuration
> +  ///
> +
> +  ///
> +  /// TLS session Version. The corresponding Data is of type
> EFI_TLS_VERSION.
> +  ///
> +  EfiTlsVersion,
> +  ///
> +  /// TLS session as client or as server. The corresponding Data is of
> + /// EFI_TLS_CONNECTION_END.
> +  ///
> +  EfiTlsConnectionEnd,
> +  ///
> +  /// A priority list of preferred algorithms for the TLS session.
> +  /// The corresponding Data is a list of EFI_TLS_CIPHER.
> +  ///
> +  EfiTlsCipherList,
> +  ///
> +  /// TLS session compression method.
> +  /// The corresponding Data is of type EFI_TLS_COMPRESSION.
> +  ///
> +  EfiTlsCompressionMethod,
> +  ///
> +  /// TLS session extension data.
> +  /// The corresponding Data is a list of type EFI_TLS_EXTENDION.
> +  ///
> +  EfiTlsExtensionData,
> +  ///
> +  /// TLS session verify method.
> +  /// The corresponding Data is of type EFI_TLS_VERIFY.
> +  ///
> +  EfiTlsVerifyMethod,
> +  ///
> +  /// TLS session data session ID.
> +  /// For SetSessionData(), it is TLS session ID used for session resumption.
> +  /// For GetSessionData(), it is the TLS session ID used for current session.
> +  /// The corresponding Data is of type EFI_TLS_SESSION_ID.
> +  ///
> +  EfiTlsSessionID,
> +  ///
> +  /// TLS session data session state.
> +  /// The corresponding Data is of type EFI_TLS_SESSION_STATE.
> +  ///
> +  EfiTlsSessionState,
> +
> +  ///
> +  /// Session information
> +  ///
> +
> +  ///
> +  /// TLS session data client random.
> +  /// The corresponding Data is of type EFI_TLS_RANDOM.
> +  ///
> +  EfiTlsClientRandom,
> +  ///
> +  /// TLS session data server random.
> +  /// The corresponding Data is of type EFI_TLS_RANDOM.
> +  ///
> +  EfiTlsServerRandom,
> +  ///
> +  /// TLS session data key material.
> +  /// The corresponding Data is of type EFI_TLS_MASTER_SECRET.
> +  ///
> +  EfiTlsKeyMaterial,
> +
> +  EfiTlsSessionDataTypeMaximum
> +
> +} EFI_TLS_SESSION_DATA_TYPE;
> +
> +///
> +/// EFI_TLS_VERSION
> +/// Note: The TLS version definition is from SSL3.0 to the latest TLS (e.g. 1.2).
> +///       SSL2.0 is obsolete and should not be used.
> +///
> +typedef struct {
> +  UINT8                         Major;
> +  UINT8                         Minor;
> +} EFI_TLS_VERSION;
> +
> +///
> +/// EFI_TLS_CONNECTION_END to define TLS session as client or server.
> +///
> +typedef enum {
> +  EfiTlsClient,
> +  EfiTlsServer,
> +} EFI_TLS_CONNECTION_END;
> +
> +///
> +/// EFI_TLS_CIPHER
> +/// Note: The definition of EFI_TLS_CIPHER definition is from "RFC 5246,
> A.4.1.
> +///       Hello Messages". The value of EFI_TLS_CIPHER is from TLS Cipher
> +///       Suite Registry of IANA.
> +///
> +typedef struct {
> +  UINT8                         Data1;
> +  UINT8                         Data2;
> +} EFI_TLS_CIPHER;
> +
> +///
> +/// EFI_TLS_COMPRESSION
> +/// Note: The value of EFI_TLS_COMPRESSION definition is from "RFC 3749".
> +///
> +typedef UINT8 EFI_TLS_COMPRESSION;
> +
> +///
> +/// EFI_TLS_EXTENSION
> +/// Note: The definition of EFI_TLS_EXTENSION if from "RFC 5246 A.4.1.
> +///       Hello Messages".
> +///
> +typedef struct {
> +  UINT16                        ExtensionType;
> +  UINT16                        Length;
> +  UINT8                         Data[1];
> +} EFI_TLS_EXTENSION;
> +
> +///
> +/// EFI_TLS_VERIFY
> +/// Use either EFI_TLS_VERIFY_NONE or EFI_TLS_VERIFY_PEER, the last two
> +options /// are 'ORed' with EFI_TLS_VERIFY_PEER if they are desired.
> +///
> +typedef UINT32  EFI_TLS_VERIFY;
> +///
> +/// No certificates will be sent or the TLS/SSLhandshake will be
> +continued regardless /// of the certificate verification result.
> +///
> +#define EFI_TLS_VERIFY_NONE                  0x0
> +///
> +/// The TLS/SSL handshake is immediately terminated with an alert
> +message containing /// the reason for the certificate verification failure.
> +///
> +#define EFI_TLS_VERIFY_PEER                  0x1
> +///
> +/// TLS session will fail peer certificate is absent.
> +///
> +#define EFI_TLS_VERIFY_FAIL_IF_NO_PEER_CERT  0x2 /// /// TLS session
> +only verify client once, and doesn't request cerfificate during ///
> +re-negotiation.
> +///
> +#define EFI_TLS_VERIFY_CLIENT_ONCE           0x4
> +
> +///
> +/// EFI_TLS_RANDOM
> +/// Note: The definition of EFI_TLS_RANDOM is from "RFC 5246 A.4.1.
> +///       Hello Messages".
> +///
> +typedef struct {
> +  UINT32                        GmtUnixTime;
> +  UINT8                         RandomBytes[28];
> +} EFI_TLS_RANDOM;
> +
> +///
> +/// EFI_TLS_MASTER_SECRET
> +/// Note: The definition of EFI_TLS_MASTER_SECRET is from "RFC 5246 8.1.
> +///       Computing the Master Secret".
> +///
> +typedef struct {
> +  UINT8                         Data[48];
> +} EFI_TLS_MASTER_SECRET;
> +
> +///
> +/// EFI_TLS_SESSION_ID
> +/// Note: The definition of EFI_TLS_SESSION_ID is from "RFC 5246 A.4.1.
> Hello Messages".
> +///
> +#define MAX_TLS_SESSION_ID_LENGTH  32
> +typedef struct {
> +  UINT16                        Length;
> +  UINT8                         Data[MAX_TLS_SESSION_ID_LENGTH];
> +} EFI_TLS_SESSION_ID;
> +
> +///
> +/// EFI_TLS_SESSION_STATE
> +///
> +typedef enum {
> +  ///
> +  /// When a new child of TLS protocol is created, the initial state of
> +TLS session
> +  /// is EfiTlsSessionNotStarted.
> +  ///
> +  EfiTlsSessionNotStarted,
> +  ///
> +  /// The consumer can call BuildResponsePacket() with NULL to get
> +ClientHello to
> +  /// start the TLS session. Then the status is EfiTlsSessionHandShaking.
> +  ///
> +  EfiTlsSessionHandShaking,
> +  ///
> +  /// During handshake, the consumer need call BuildResponsePacket()
> +with input
> +  /// data from peer, then get response packet and send to peer. After
> +handshake
> +  /// finish, the TLS session status becomes
> +EfiTlsSessionDataTransferring, and
> +  /// consumer can use ProcessPacket() for data transferring.
> +  ///
> +  EfiTlsSessionDataTransferring,
> +  ///
> +  /// Finally, if consumer wants to active close TLS session, consumer
> +need
> +  /// call SetSessionData to set TLS session state to
> +EfiTlsSessionClosing, and
> +  /// call BuildResponsePacket() with NULL to get CloseNotify alert
> +message,
> +  /// and sent it out.
> +  ///
> +  EfiTlsSessionClosing,
> +  ///
> +  /// If any error happen during parsing ApplicationData content type,
> +EFI_ABORT
> +  /// will be returned by ProcessPacket(), and TLS session state will
> +become
> +  /// EfiTlsSessionError. Then consumer need call BuildResponsePacket()
> +with
> +  /// NULL to get alert message and sent it out.
> +  ///
> +  EfiTlsSessionError,
> +
> +  EfiTlsSessionStateMaximum
> +
> +} EFI_TLS_SESSION_STATE;
> +
> +///
> +/// EFI_TLS_FRAGMENT_DATA
> +///
> +typedef struct {
> +  ///
> +  /// Length of data buffer in the fragment.
> +  ///
> +  UINT32                        FragmentLength;
> +  ///
> +  /// Pointer to the data buffer in the fragment.
> +  ///
> +  VOID                          *FragmentBuffer;
> +} EFI_TLS_FRAGMENT_DATA;
> +
> +///
> +/// EFI_TLS_CRYPT_MODE
> +///
> +typedef enum {
> +  ///
> +  /// Encrypt data provided in the fragment buffers.
> +  ///
> +  EfiTlsEncrypt,
> +  ///
> +  /// Decrypt data provided in the fragment buffers.
> +  ///
> +  EfiTlsDecrypt,
> +} EFI_TLS_CRYPT_MODE;
> +
> +/**
> +  Set TLS session data.
> +
> +  The SetSessionData() function set data for a new TLS session. All
> + session data should  be set before BuildResponsePacket() invoked.
> +
> +  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in]  DataType            TLS session data type.
> +  @param[in]  Data                Pointer to session data.
> +  @param[in]  DataSize            Total size of session data.
> +
> +  @retval EFI_SUCCESS             The TLS session data is set successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  Data is NULL.
> +                                  DataSize is 0.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
> +                                  EfiTlsClientRandom
> +                                  EfiTlsServerRandom
> +                                  EfiTlsKeyMaterial
> +  @retval EFI_NOT_READY           Current TLS session state is NOT
> +                                  EfiTlsSessionStateNotStarted.
> +  @retval EFI_OUT_OF_RESOURCES    Required system resources could not
> be allocated.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_TLS_SET_SESSION_DATA) (
> +  IN EFI_TLS_PROTOCOL                *This,
> +  IN EFI_TLS_SESSION_DATA_TYPE       DataType,
> +  IN VOID                            *Data,
> +  IN UINTN                           DataSize
> +  );
> +
> +/**
> +  Get TLS session data.
> +
> +  The GetSessionData() function return the TLS session information.
> +
> +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in]       DataType       TLS session data type.
> +  @param[in, out]  Data           Pointer to session data.
> +  @param[in, out]  DataSize       Total size of session data. On input, it means
> +                                  the size of Data buffer. On output, it means the size
> +                                  of copied Data buffer if EFI_SUCCESS, and means the
> +                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
> +
> +  @retval EFI_SUCCESS             The TLS session data is got successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  DataSize is NULL.
> +                                  Data is NULL if *DataSize is not zero.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_NOT_FOUND           The TLS session data is not found.
> +  @retval EFI_NOT_READY           The DataType is not ready in current session
> state.
> +  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_TLS_GET_SESSION_DATA) (
> +  IN EFI_TLS_PROTOCOL                *This,
> +  IN EFI_TLS_SESSION_DATA_TYPE       DataType,
> +  IN OUT VOID                        *Data,  OPTIONAL
> +  IN OUT UINTN                       *DataSize
> +  );
> +
> +/**
> +  Build response packet according to TLS state machine. This function
> +is only valid for
> +  alert, handshake and change_cipher_spec content type.
> +
> +  The BuildResponsePacket() function builds TLS response packet in
> + response to the TLS  request packet specified by RequestBuffer and
> + RequestSize. If RequestBuffer is NULL and  RequestSize is 0, and TLS
> + session status is EfiTlsSessionNotStarted, the TLS session  will be
> + initiated and the response packet needs to be ClientHello. If
> + RequestBuffer is  NULL and RequestSize is 0, and TLS session status is
> + EfiTlsSessionClosing, the TLS  session will be closed and response
> + packet needs to be CloseNotify. If RequestBuffer is  NULL and
> + RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS
> session has errors and the response packet needs to be Alert message based
> on error  type.
> +
> +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in]       RequestBuffer  Pointer to the most recently received TLS
> packet. NULL
> +                                  means TLS need initiate the TLS session and response
> +                                  packet need to be ClientHello.
> +  @param[in]       RequestSize    Packet size in bytes for the most recently
> received TLS
> +                                  packet. 0 is only valid when RequestBuffer is NULL.
> +  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
> +  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input,
> it is
> +                                  the buffer size provided by the caller. On output, it
> +                                  is the buffer size in fact needed to contain the
> +                                  packet.
> +
> +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  RequestBuffer is NULL but RequestSize is NOT 0.
> +                                  RequestSize is 0 but RequestBuffer is NOT NULL.
> +                                  BufferSize is NULL.
> +                                  Buffer is NULL if *BufferSize is not zero.
> +  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the
> response packet.
> +  @retval EFI_NOT_READY           Current TLS session state is NOT ready to
> build
> +                                  ResponsePacket.
> +  @retval EFI_ABORTED             Something wrong build response packet.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_TLS_BUILD_RESPONSE_PACKET) (
> +  IN EFI_TLS_PROTOCOL                *This,
> +  IN UINT8                           *RequestBuffer, OPTIONAL
> +  IN UINTN                           RequestSize, OPTIONAL
> +  OUT UINT8                          *Buffer, OPTIONAL
> +  IN OUT UINTN                       *BufferSize
> +  );
> +
> +/**
> +  Decrypt or encrypt TLS packet during session. This function is only
> +valid after
> +  session connected and for application_data content type.
> +
> +  The ProcessPacket () function process each inbound or outbound TLS APP
> packet.
> +
> +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in, out]  FragmentTable  Pointer to a list of fragment. The caller
> will take
> +                                  responsible to handle the original FragmentTable while
> +                                  it may be reallocated in TLS driver. If CryptMode is
> +                                  EfiTlsEncrypt, on input these fragments contain the TLS
> +                                  header and plain text TLS APP payload; on output these
> +                                  fragments contain the TLS header and cypher text TLS
> +                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
> +                                  these fragments contain the TLS header and cypher text
> +                                  TLS APP payload; on output these fragments contain the
> +                                  TLS header and plain text TLS APP payload.
> +  @param[in]       FragmentCount  Number of fragment.
> +  @param[in]       CryptMode      Crypt mode.
> +
> +  @retval EFI_SUCCESS             The operation completed successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  FragmentTable is NULL.
> +                                  FragmentCount is NULL.
> +                                  CryptoMode is invalid.
> +  @retval EFI_NOT_READY           Current TLS session state is NOT
> +                                  EfiTlsSessionDataTransferring.
> +  @retval EFI_ABORTED             Something wrong decryption the message.
> TLS session
> +                                  status will become EfiTlsSessionError. The caller need
> +                                  call BuildResponsePacket() to generate Error Alert
> +                                  message and send it out.
> +  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the
> operation.
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_TLS_PROCESS_PACKET) (
> +  IN EFI_TLS_PROTOCOL                *This,
> +  IN OUT EFI_TLS_FRAGMENT_DATA       **FragmentTable,
> +  IN UINT32                          *FragmentCount,
> +  IN EFI_TLS_CRYPT_MODE              CryptMode
> +  );
> +
> +///
> +/// The EFI_TLS_PROTOCOL is used to create, destroy and manage TLS
> session.
> +/// For detail of TLS, please refer to TLS related RFC.
> +///
> +struct _EFI_TLS_PROTOCOL {
> +  EFI_TLS_SET_SESSION_DATA           SetSessionData;
> +  EFI_TLS_GET_SESSION_DATA           GetSessionData;
> +  EFI_TLS_BUILD_RESPONSE_PACKET      BuildResponsePacket;
> +  EFI_TLS_PROCESS_PACKET             ProcessPacket;
> +};
> +
> +extern EFI_GUID gEfiTlsServiceBindingProtocolGuid;
> +extern EFI_GUID gEfiTlsProtocolGuid;
> +
> +#endif  // __EFI_TLS_PROTOCOL_H__
> diff --git a/MdePkg/Include/Protocol/TlsConfig.h
> b/MdePkg/Include/Protocol/TlsConfig.h
> new file mode 100644
> index 0000000..4b62bf5
> --- /dev/null
> +++ b/MdePkg/Include/Protocol/TlsConfig.h
> @@ -0,0 +1,132 @@
> +/** @file
> +  EFI TLS Configuration Protocol as defined in UEFI 2.5.
> +  The EFI TLS Configuration Protocol provides a way to set and get TLS
> configuration.
> +
> +  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.
> +
> +  @par Revision Reference:
> +  This Protocol is introduced in UEFI Specification 2.5
> +
> +**/
> +#ifndef __EFI_TLS_CONFIGURATION_PROTOCOL_H__
> +#define __EFI_TLS_CONFIGURATION_PROTOCOL_H__
> +
> +///
> +/// The EFI Configuration protocol provides a way to set and get TLS
> configuration.
> +///
> +#define EFI_TLS_CONFIGURATION_PROTOCOL_GUID  \
> +  { \
> +    0x1682fe44, 0xbd7a, 0x4407, { 0xb7, 0xc7, 0xdc, 0xa3, 0x7c, 0xa3,
> +0x92, 0x2d }  \
> +  }
> +
> +typedef struct _EFI_TLS_CONFIGURATION_PROTOCOL
> +EFI_TLS_CONFIGURATION_PROTOCOL;
> +
> +///
> +/// EFI_TLS_CONFIG_DATA_TYPE
> +///
> +typedef enum {
> +  ///
> +  /// Local host configuration data: public certificate data.
> +  /// This data should be DER-encoded binaryX.509 certificate
> +  /// or PEMencoded X.509 certificate.
> +  ///
> +  EfiTlsConfigDataTypeHostPublicCert,
> +  ///
> +  /// Local host configuration data: private key data.
> +  ///
> +  EfiTlsConfigDataTypeHostPrivateKey,
> +  ///
> +  /// CA certificate to verify peer. This data should be PEM-encoded
> +  /// RSA or PKCS#8 private key.
> +  ///
> +  EfiTlsConfigDataTypeCACertificate,
> +  ///
> +  /// CA-supplied Certificate Revocation List data. This data should
> +  /// be DER-encoded CRL data.
> +  ///
> +  EfiTlsConfigDataTypeCertRevocationList,
> +
> +  EfiTlsConfigDataTypeMaximum
> +
> +} EFI_TLS_CONFIG_DATA_TYPE;
> +
> +/**
> +  Set TLS configuration data.
> +
> +  The SetData() function sets TLS configuration to non-volatile storage
> + or volatile  storage.
> +
> +  @param[in]  This                Pointer to the
> EFI_TLS_CONFIGURATION_PROTOCOL instance.
> +  @param[in]  DataType            Configuration data type.
> +  @param[in]  Data                Pointer to configuration data.
> +  @param[in]  DataSize            Total size of configuration data.
> +
> +  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  Data is NULL.
> +                                  DataSize is 0.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_OUT_OF_RESOURCES    Required system resources could not
> be allocated.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_TLS_CONFIGURATION_SET_DATA)(
> +  IN EFI_TLS_CONFIGURATION_PROTOCOL  *This,
> +  IN EFI_TLS_CONFIG_DATA_TYPE        DataType,
> +  IN VOID                            *Data,
> +  IN UINTN                           DataSize
> +  );
> +
> +/**
> +  Get TLS configuration data.
> +
> +  The GetData() function gets TLS configuration.
> +
> +  @param[in]       This           Pointer to the
> EFI_TLS_CONFIGURATION_PROTOCOL instance.
> +  @param[in]       DataType       Configuration data type.
> +  @param[in, out]  Data           Pointer to configuration data.
> +  @param[in, out]  DataSize       Total size of configuration data. On input, it
> means
> +                                  the size of Data buffer. On output, it means the size
> +                                  of copied Data buffer if EFI_SUCCESS, and means the
> +                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
> +
> +  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  DataSize is NULL.
> +                                  Data is NULL if *DataSize is not zero.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
> +  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
> +
> +**/
> +typedef
> +EFI_STATUS
> +(EFIAPI *EFI_TLS_CONFIGURATION_GET_DATA)(
> +  IN EFI_TLS_CONFIGURATION_PROTOCOL  *This,
> +  IN EFI_TLS_CONFIG_DATA_TYPE        DataType,
> +  IN OUT VOID                        *Data,  OPTIONAL
> +  IN OUT UINTN                       *DataSize
> +  );
> +
> +///
> +/// The EFI_TLS_CONFIGURATION_PROTOCOL is designed to provide a way
> to
> +set and get /// TLS configuration, such as Certificate, private key data.
> +///
> +struct _EFI_TLS_CONFIGURATION_PROTOCOL {
> +  EFI_TLS_CONFIGURATION_SET_DATA     SetData;
> +  EFI_TLS_CONFIGURATION_GET_DATA     GetData;
> +};
> +
> +extern EFI_GUID gEfiTlsConfigurationProtocolGuid;
> +
> +#endif  //__EFI_TLS_CONFIGURATION_PROTOCOL_H__
> diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index
> 3e08bed..f2bdb30 100644
> --- a/MdePkg/MdePkg.dec
> +++ b/MdePkg/MdePkg.dec
> @@ -1607,10 +1607,19 @@
>    gEfiHttpProtocolGuid                 = { 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42,
> 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b }}
> 
>    ## Include/Protocol/HttpUtilities.h
>    gEfiHttpUtilitiesProtocolGuid        = { 0x3e35c163, 0x4074, 0x45dd, {0x43,
> 0x1e, 0x23, 0x98, 0x9d, 0xd8, 0x6b, 0x32 }}
> 
> +  ## Include/Protocol/Tls.h
> +  gEfiTlsServiceBindingProtocolGuid   = { 0x952cb795, 0xff36, 0x48cf, {0xa2,
> 0x49, 0x4d, 0xf4, 0x86, 0xd6, 0xab, 0x8d }}
> +
> +  ## Include/Protocol/Tls.h
> +  gEfiTlsProtocolGuid                 = { 0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc, 0xe4,
> 0x6c, 0x47, 0x51, 0x43, 0x90 }}
> +
> +  ## Include/Protocol/TlsConfig.h
> +  gEfiTlsConfigurationProtocolGuid    = { 0x1682fe44, 0xbd7a, 0x4407, { 0xb7,
> 0xc7, 0xdc, 0xa3, 0x7c, 0xa3, 0x92, 0x2d }}
> +
>    ## Include/Protocol/Rest.h
>    gEfiRestProtocolGuid                 =  { 0x0db48a36, 0x4e54, 0xea9c, {0x9b, 0x09,
> 0x1e, 0xa5, 0xbe, 0x3a, 0x66, 0x0b }}
> 
>    ## Include/Protocol/Supplicant.h
>    gEfiSupplicantServiceBindingProtocolGuid  = { 0x45bcd98e, 0x59ad, 0x4174,
> { 0x95, 0x46, 0x34, 0x4a, 0x7, 0x48, 0x58, 0x98 }}
> --
> 1.9.5.msysgit.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 01/10] MdePkg: Add TLS related protocol definition
  2016-12-14  8:36   ` Long, Qin
@ 2016-12-14  8:39     ` Wu, Jiaxin
  2016-12-15  8:34       ` Ye, Ting
  0 siblings, 1 reply; 37+ messages in thread
From: Wu, Jiaxin @ 2016-12-14  8:39 UTC (permalink / raw)
  To: Long, Qin, edk2-devel@lists.01.org
  Cc: Ye, Ting, Fu, Siyuan, Zhang, Lubo, Gao, Liming, Kinney, Michael D,
	Thomas Palmer

Thanks Qin, I will correct it before commit this patch.

Best Regards!
Jiaxin

> -----Original Message-----
> From: Long, Qin
> Sent: Wednesday, December 14, 2016 4:36 PM
> To: Wu, Jiaxin <jiaxin.wu@intel.com>; edk2-devel@lists.01.org
> Cc: Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang,
> Lubo <lubo.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Kinney,
> Michael D <michael.d.kinney@intel.com>; Thomas Palmer
> <thomas.palmer@hpe.com>
> Subject: RE: [Patch 01/10] MdePkg: Add TLS related protocol definition
> 
> Reviewed-by: Qin Long <qin.long@intel.com>
> 
> Please correct some typos later:
> EFI_TLS_EXTENDION  --> EFI_TLS_EXTENSION TLS/SSLhandshake --> TLS/SSL
> handshake cerfificate --> certificate cypher --> cipher
> binaryX.509 --> binary X.509
> PEMencoded --> PEM-encoded
> 
> Best Regards & Thanks,
> LONG, Qin
> 
> > -----Original Message-----
> > From: Wu, Jiaxin
> > Sent: Wednesday, December 14, 2016 3:34 PM
> > To: edk2-devel@lists.01.org
> > Cc: Long, Qin; Ye, Ting; Fu, Siyuan; Zhang, Lubo; Gao, Liming; Kinney,
> > Michael D; Thomas Palmer; Wu, Jiaxin
> > Subject: [Patch 01/10] MdePkg: Add TLS related protocol definition
> >
> > This patch is used to add Tls.h and TlsConfig.h header files to define
> > EFI TLS Configuration Protocol, EFI TLS Service Binding Protocol and
> > EFI TLS Configuration Protocol.
> >
> > Cc: Long Qin <qin.long@intel.com>
> > Cc: Ye Ting <ting.ye@intel.com>
> > Cc: Fu Siyuan <siyuan.fu@intel.com>
> > Cc: Zhang Lubo <lubo.zhang@intel.com>
> > Cc: Liming Gao <liming.gao@intel.com>
> > Cc: Michael D Kinney <michael.d.kinney@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>
> > ---
> >  MdePkg/Include/Protocol/Tls.h       | 460
> > ++++++++++++++++++++++++++++++++++++
> >  MdePkg/Include/Protocol/TlsConfig.h | 132 +++++++++++
> >  MdePkg/MdePkg.dec                   |   9 +
> >  3 files changed, 601 insertions(+)
> >  create mode 100644 MdePkg/Include/Protocol/Tls.h  create mode 100644
> > MdePkg/Include/Protocol/TlsConfig.h
> >
> > diff --git a/MdePkg/Include/Protocol/Tls.h
> > b/MdePkg/Include/Protocol/Tls.h new file mode 100644 index
> > 0000000..51a3cda
> > --- /dev/null
> > +++ b/MdePkg/Include/Protocol/Tls.h
> > @@ -0,0 +1,460 @@
> > +/** @file
> > +  EFI TLS Protocols as defined in UEFI 2.5.
> > +
> > +  The EFI TLS Service Binding Protocol is used to locate EFI TLS
> > + Protocol drivers  to create and destroy child of the driver to
> > + communicate with other host using  TLS protocol.
> > +  The EFI TLS Protocol provides the ability to manage TLS session.
> > +
> > +  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.
> > +
> > +  @par Revision Reference:
> > +  This Protocol is introduced in UEFI Specification 2.5
> > +
> > +**/
> > +
> > +#ifndef __EFI_TLS_PROTOCOL_H__
> > +#define __EFI_TLS_PROTOCOL_H__
> > +
> > +///
> > +/// The EFI TLS Service Binding Protocol is used to locate EFI TLS
> > +Protocol drivers to /// create and destroy child of the driver to
> > +communicate with other host using TLS /// protocol.
> > +///
> > +#define EFI_TLS_SERVICE_BINDING_PROTOCOL_GUID \
> > +  { \
> > +    0x952cb795, 0xff36, 0x48cf, {0xa2, 0x49, 0x4d, 0xf4, 0x86, 0xd6,
> > +0xab, 0x8d } \
> > +  }
> > +
> > +///
> > +/// The EFI TLS protocol provides the ability to manage TLS session.
> > +///
> > +#define EFI_TLS_PROTOCOL_GUID \
> > +  { \
> > +    0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc, 0xe4, 0x6c, 0x47, 0x51,
> > +0x43, 0x90 } \
> > +  }
> > +
> > +typedef struct _EFI_TLS_PROTOCOL EFI_TLS_PROTOCOL;
> > +
> > +///
> > +/// EFI_TLS_SESSION_DATA_TYPE
> > +///
> > +typedef enum {
> > +  ///
> > +  /// Session Configuration
> > +  ///
> > +
> > +  ///
> > +  /// TLS session Version. The corresponding Data is of type
> > EFI_TLS_VERSION.
> > +  ///
> > +  EfiTlsVersion,
> > +  ///
> > +  /// TLS session as client or as server. The corresponding Data is
> > + of /// EFI_TLS_CONNECTION_END.
> > +  ///
> > +  EfiTlsConnectionEnd,
> > +  ///
> > +  /// A priority list of preferred algorithms for the TLS session.
> > +  /// The corresponding Data is a list of EFI_TLS_CIPHER.
> > +  ///
> > +  EfiTlsCipherList,
> > +  ///
> > +  /// TLS session compression method.
> > +  /// The corresponding Data is of type EFI_TLS_COMPRESSION.
> > +  ///
> > +  EfiTlsCompressionMethod,
> > +  ///
> > +  /// TLS session extension data.
> > +  /// The corresponding Data is a list of type EFI_TLS_EXTENDION.
> > +  ///
> > +  EfiTlsExtensionData,
> > +  ///
> > +  /// TLS session verify method.
> > +  /// The corresponding Data is of type EFI_TLS_VERIFY.
> > +  ///
> > +  EfiTlsVerifyMethod,
> > +  ///
> > +  /// TLS session data session ID.
> > +  /// For SetSessionData(), it is TLS session ID used for session resumption.
> > +  /// For GetSessionData(), it is the TLS session ID used for current session.
> > +  /// The corresponding Data is of type EFI_TLS_SESSION_ID.
> > +  ///
> > +  EfiTlsSessionID,
> > +  ///
> > +  /// TLS session data session state.
> > +  /// The corresponding Data is of type EFI_TLS_SESSION_STATE.
> > +  ///
> > +  EfiTlsSessionState,
> > +
> > +  ///
> > +  /// Session information
> > +  ///
> > +
> > +  ///
> > +  /// TLS session data client random.
> > +  /// The corresponding Data is of type EFI_TLS_RANDOM.
> > +  ///
> > +  EfiTlsClientRandom,
> > +  ///
> > +  /// TLS session data server random.
> > +  /// The corresponding Data is of type EFI_TLS_RANDOM.
> > +  ///
> > +  EfiTlsServerRandom,
> > +  ///
> > +  /// TLS session data key material.
> > +  /// The corresponding Data is of type EFI_TLS_MASTER_SECRET.
> > +  ///
> > +  EfiTlsKeyMaterial,
> > +
> > +  EfiTlsSessionDataTypeMaximum
> > +
> > +} EFI_TLS_SESSION_DATA_TYPE;
> > +
> > +///
> > +/// EFI_TLS_VERSION
> > +/// Note: The TLS version definition is from SSL3.0 to the latest TLS (e.g.
> 1.2).
> > +///       SSL2.0 is obsolete and should not be used.
> > +///
> > +typedef struct {
> > +  UINT8                         Major;
> > +  UINT8                         Minor;
> > +} EFI_TLS_VERSION;
> > +
> > +///
> > +/// EFI_TLS_CONNECTION_END to define TLS session as client or server.
> > +///
> > +typedef enum {
> > +  EfiTlsClient,
> > +  EfiTlsServer,
> > +} EFI_TLS_CONNECTION_END;
> > +
> > +///
> > +/// EFI_TLS_CIPHER
> > +/// Note: The definition of EFI_TLS_CIPHER definition is from "RFC
> > +5246,
> > A.4.1.
> > +///       Hello Messages". The value of EFI_TLS_CIPHER is from TLS Cipher
> > +///       Suite Registry of IANA.
> > +///
> > +typedef struct {
> > +  UINT8                         Data1;
> > +  UINT8                         Data2;
> > +} EFI_TLS_CIPHER;
> > +
> > +///
> > +/// EFI_TLS_COMPRESSION
> > +/// Note: The value of EFI_TLS_COMPRESSION definition is from "RFC
> 3749".
> > +///
> > +typedef UINT8 EFI_TLS_COMPRESSION;
> > +
> > +///
> > +/// EFI_TLS_EXTENSION
> > +/// Note: The definition of EFI_TLS_EXTENSION if from "RFC 5246 A.4.1.
> > +///       Hello Messages".
> > +///
> > +typedef struct {
> > +  UINT16                        ExtensionType;
> > +  UINT16                        Length;
> > +  UINT8                         Data[1];
> > +} EFI_TLS_EXTENSION;
> > +
> > +///
> > +/// EFI_TLS_VERIFY
> > +/// Use either EFI_TLS_VERIFY_NONE or EFI_TLS_VERIFY_PEER, the last
> > +two options /// are 'ORed' with EFI_TLS_VERIFY_PEER if they are desired.
> > +///
> > +typedef UINT32  EFI_TLS_VERIFY;
> > +///
> > +/// No certificates will be sent or the TLS/SSLhandshake will be
> > +continued regardless /// of the certificate verification result.
> > +///
> > +#define EFI_TLS_VERIFY_NONE                  0x0
> > +///
> > +/// The TLS/SSL handshake is immediately terminated with an alert
> > +message containing /// the reason for the certificate verification failure.
> > +///
> > +#define EFI_TLS_VERIFY_PEER                  0x1
> > +///
> > +/// TLS session will fail peer certificate is absent.
> > +///
> > +#define EFI_TLS_VERIFY_FAIL_IF_NO_PEER_CERT  0x2 /// /// TLS session
> > +only verify client once, and doesn't request cerfificate during ///
> > +re-negotiation.
> > +///
> > +#define EFI_TLS_VERIFY_CLIENT_ONCE           0x4
> > +
> > +///
> > +/// EFI_TLS_RANDOM
> > +/// Note: The definition of EFI_TLS_RANDOM is from "RFC 5246 A.4.1.
> > +///       Hello Messages".
> > +///
> > +typedef struct {
> > +  UINT32                        GmtUnixTime;
> > +  UINT8                         RandomBytes[28];
> > +} EFI_TLS_RANDOM;
> > +
> > +///
> > +/// EFI_TLS_MASTER_SECRET
> > +/// Note: The definition of EFI_TLS_MASTER_SECRET is from "RFC 5246 8.1.
> > +///       Computing the Master Secret".
> > +///
> > +typedef struct {
> > +  UINT8                         Data[48];
> > +} EFI_TLS_MASTER_SECRET;
> > +
> > +///
> > +/// EFI_TLS_SESSION_ID
> > +/// Note: The definition of EFI_TLS_SESSION_ID is from "RFC 5246 A.4.1.
> > Hello Messages".
> > +///
> > +#define MAX_TLS_SESSION_ID_LENGTH  32 typedef struct {
> > +  UINT16                        Length;
> > +  UINT8                         Data[MAX_TLS_SESSION_ID_LENGTH];
> > +} EFI_TLS_SESSION_ID;
> > +
> > +///
> > +/// EFI_TLS_SESSION_STATE
> > +///
> > +typedef enum {
> > +  ///
> > +  /// When a new child of TLS protocol is created, the initial state
> > +of TLS session
> > +  /// is EfiTlsSessionNotStarted.
> > +  ///
> > +  EfiTlsSessionNotStarted,
> > +  ///
> > +  /// The consumer can call BuildResponsePacket() with NULL to get
> > +ClientHello to
> > +  /// start the TLS session. Then the status is EfiTlsSessionHandShaking.
> > +  ///
> > +  EfiTlsSessionHandShaking,
> > +  ///
> > +  /// During handshake, the consumer need call BuildResponsePacket()
> > +with input
> > +  /// data from peer, then get response packet and send to peer.
> > +After handshake
> > +  /// finish, the TLS session status becomes
> > +EfiTlsSessionDataTransferring, and
> > +  /// consumer can use ProcessPacket() for data transferring.
> > +  ///
> > +  EfiTlsSessionDataTransferring,
> > +  ///
> > +  /// Finally, if consumer wants to active close TLS session,
> > +consumer need
> > +  /// call SetSessionData to set TLS session state to
> > +EfiTlsSessionClosing, and
> > +  /// call BuildResponsePacket() with NULL to get CloseNotify alert
> > +message,
> > +  /// and sent it out.
> > +  ///
> > +  EfiTlsSessionClosing,
> > +  ///
> > +  /// If any error happen during parsing ApplicationData content
> > +type, EFI_ABORT
> > +  /// will be returned by ProcessPacket(), and TLS session state will
> > +become
> > +  /// EfiTlsSessionError. Then consumer need call
> > +BuildResponsePacket() with
> > +  /// NULL to get alert message and sent it out.
> > +  ///
> > +  EfiTlsSessionError,
> > +
> > +  EfiTlsSessionStateMaximum
> > +
> > +} EFI_TLS_SESSION_STATE;
> > +
> > +///
> > +/// EFI_TLS_FRAGMENT_DATA
> > +///
> > +typedef struct {
> > +  ///
> > +  /// Length of data buffer in the fragment.
> > +  ///
> > +  UINT32                        FragmentLength;
> > +  ///
> > +  /// Pointer to the data buffer in the fragment.
> > +  ///
> > +  VOID                          *FragmentBuffer;
> > +} EFI_TLS_FRAGMENT_DATA;
> > +
> > +///
> > +/// EFI_TLS_CRYPT_MODE
> > +///
> > +typedef enum {
> > +  ///
> > +  /// Encrypt data provided in the fragment buffers.
> > +  ///
> > +  EfiTlsEncrypt,
> > +  ///
> > +  /// Decrypt data provided in the fragment buffers.
> > +  ///
> > +  EfiTlsDecrypt,
> > +} EFI_TLS_CRYPT_MODE;
> > +
> > +/**
> > +  Set TLS session data.
> > +
> > +  The SetSessionData() function set data for a new TLS session. All
> > + session data should  be set before BuildResponsePacket() invoked.
> > +
> > +  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
> > +  @param[in]  DataType            TLS session data type.
> > +  @param[in]  Data                Pointer to session data.
> > +  @param[in]  DataSize            Total size of session data.
> > +
> > +  @retval EFI_SUCCESS             The TLS session data is set successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  Data is NULL.
> > +                                  DataSize is 0.
> > +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> > +  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
> > +                                  EfiTlsClientRandom
> > +                                  EfiTlsServerRandom
> > +                                  EfiTlsKeyMaterial
> > +  @retval EFI_NOT_READY           Current TLS session state is NOT
> > +                                  EfiTlsSessionStateNotStarted.
> > +  @retval EFI_OUT_OF_RESOURCES    Required system resources could
> not
> > be allocated.
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_SET_SESSION_DATA) (
> > +  IN EFI_TLS_PROTOCOL                *This,
> > +  IN EFI_TLS_SESSION_DATA_TYPE       DataType,
> > +  IN VOID                            *Data,
> > +  IN UINTN                           DataSize
> > +  );
> > +
> > +/**
> > +  Get TLS session data.
> > +
> > +  The GetSessionData() function return the TLS session information.
> > +
> > +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> > +  @param[in]       DataType       TLS session data type.
> > +  @param[in, out]  Data           Pointer to session data.
> > +  @param[in, out]  DataSize       Total size of session data. On input, it
> means
> > +                                  the size of Data buffer. On output, it means the size
> > +                                  of copied Data buffer if EFI_SUCCESS, and means the
> > +                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
> > +
> > +  @retval EFI_SUCCESS             The TLS session data is got successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  DataSize is NULL.
> > +                                  Data is NULL if *DataSize is not zero.
> > +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> > +  @retval EFI_NOT_FOUND           The TLS session data is not found.
> > +  @retval EFI_NOT_READY           The DataType is not ready in current
> session
> > state.
> > +  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the
> data.
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_GET_SESSION_DATA) (
> > +  IN EFI_TLS_PROTOCOL                *This,
> > +  IN EFI_TLS_SESSION_DATA_TYPE       DataType,
> > +  IN OUT VOID                        *Data,  OPTIONAL
> > +  IN OUT UINTN                       *DataSize
> > +  );
> > +
> > +/**
> > +  Build response packet according to TLS state machine. This function
> > +is only valid for
> > +  alert, handshake and change_cipher_spec content type.
> > +
> > +  The BuildResponsePacket() function builds TLS response packet in
> > + response to the TLS  request packet specified by RequestBuffer and
> > + RequestSize. If RequestBuffer is NULL and  RequestSize is 0, and TLS
> > + session status is EfiTlsSessionNotStarted, the TLS session  will be
> > + initiated and the response packet needs to be ClientHello. If
> > + RequestBuffer is  NULL and RequestSize is 0, and TLS session status
> > + is EfiTlsSessionClosing, the TLS  session will be closed and
> > + response packet needs to be CloseNotify. If RequestBuffer is  NULL
> > + and RequestSize is 0, and TLS session status is EfiTlsSessionError,
> > + the TLS
> > session has errors and the response packet needs to be Alert message
> > based on error  type.
> > +
> > +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> > +  @param[in]       RequestBuffer  Pointer to the most recently received TLS
> > packet. NULL
> > +                                  means TLS need initiate the TLS session and response
> > +                                  packet need to be ClientHello.
> > +  @param[in]       RequestSize    Packet size in bytes for the most recently
> > received TLS
> > +                                  packet. 0 is only valid when RequestBuffer is NULL.
> > +  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
> > +  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On
> input,
> > it is
> > +                                  the buffer size provided by the caller. On output, it
> > +                                  is the buffer size in fact needed to contain the
> > +                                  packet.
> > +
> > +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  RequestBuffer is NULL but RequestSize is NOT 0.
> > +                                  RequestSize is 0 but RequestBuffer is NOT NULL.
> > +                                  BufferSize is NULL.
> > +                                  Buffer is NULL if *BufferSize is not zero.
> > +  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the
> > response packet.
> > +  @retval EFI_NOT_READY           Current TLS session state is NOT ready to
> > build
> > +                                  ResponsePacket.
> > +  @retval EFI_ABORTED             Something wrong build response packet.
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_BUILD_RESPONSE_PACKET) (
> > +  IN EFI_TLS_PROTOCOL                *This,
> > +  IN UINT8                           *RequestBuffer, OPTIONAL
> > +  IN UINTN                           RequestSize, OPTIONAL
> > +  OUT UINT8                          *Buffer, OPTIONAL
> > +  IN OUT UINTN                       *BufferSize
> > +  );
> > +
> > +/**
> > +  Decrypt or encrypt TLS packet during session. This function is only
> > +valid after
> > +  session connected and for application_data content type.
> > +
> > +  The ProcessPacket () function process each inbound or outbound TLS
> > + APP
> > packet.
> > +
> > +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> > +  @param[in, out]  FragmentTable  Pointer to a list of fragment. The
> > + caller
> > will take
> > +                                  responsible to handle the original FragmentTable while
> > +                                  it may be reallocated in TLS driver. If CryptMode is
> > +                                  EfiTlsEncrypt, on input these fragments contain the TLS
> > +                                  header and plain text TLS APP payload; on output these
> > +                                  fragments contain the TLS header and cypher text TLS
> > +                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
> > +                                  these fragments contain the TLS header and cypher text
> > +                                  TLS APP payload; on output these fragments contain the
> > +                                  TLS header and plain text TLS APP payload.
> > +  @param[in]       FragmentCount  Number of fragment.
> > +  @param[in]       CryptMode      Crypt mode.
> > +
> > +  @retval EFI_SUCCESS             The operation completed successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  FragmentTable is NULL.
> > +                                  FragmentCount is NULL.
> > +                                  CryptoMode is invalid.
> > +  @retval EFI_NOT_READY           Current TLS session state is NOT
> > +                                  EfiTlsSessionDataTransferring.
> > +  @retval EFI_ABORTED             Something wrong decryption the message.
> > TLS session
> > +                                  status will become EfiTlsSessionError. The caller need
> > +                                  call BuildResponsePacket() to generate Error Alert
> > +                                  message and send it out.
> > +  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the
> > operation.
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_PROCESS_PACKET) (
> > +  IN EFI_TLS_PROTOCOL                *This,
> > +  IN OUT EFI_TLS_FRAGMENT_DATA       **FragmentTable,
> > +  IN UINT32                          *FragmentCount,
> > +  IN EFI_TLS_CRYPT_MODE              CryptMode
> > +  );
> > +
> > +///
> > +/// The EFI_TLS_PROTOCOL is used to create, destroy and manage TLS
> > session.
> > +/// For detail of TLS, please refer to TLS related RFC.
> > +///
> > +struct _EFI_TLS_PROTOCOL {
> > +  EFI_TLS_SET_SESSION_DATA           SetSessionData;
> > +  EFI_TLS_GET_SESSION_DATA           GetSessionData;
> > +  EFI_TLS_BUILD_RESPONSE_PACKET      BuildResponsePacket;
> > +  EFI_TLS_PROCESS_PACKET             ProcessPacket;
> > +};
> > +
> > +extern EFI_GUID gEfiTlsServiceBindingProtocolGuid;
> > +extern EFI_GUID gEfiTlsProtocolGuid;
> > +
> > +#endif  // __EFI_TLS_PROTOCOL_H__
> > diff --git a/MdePkg/Include/Protocol/TlsConfig.h
> > b/MdePkg/Include/Protocol/TlsConfig.h
> > new file mode 100644
> > index 0000000..4b62bf5
> > --- /dev/null
> > +++ b/MdePkg/Include/Protocol/TlsConfig.h
> > @@ -0,0 +1,132 @@
> > +/** @file
> > +  EFI TLS Configuration Protocol as defined in UEFI 2.5.
> > +  The EFI TLS Configuration Protocol provides a way to set and get
> > +TLS
> > configuration.
> > +
> > +  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.
> > +
> > +  @par Revision Reference:
> > +  This Protocol is introduced in UEFI Specification 2.5
> > +
> > +**/
> > +#ifndef __EFI_TLS_CONFIGURATION_PROTOCOL_H__
> > +#define __EFI_TLS_CONFIGURATION_PROTOCOL_H__
> > +
> > +///
> > +/// The EFI Configuration protocol provides a way to set and get TLS
> > configuration.
> > +///
> > +#define EFI_TLS_CONFIGURATION_PROTOCOL_GUID  \
> > +  { \
> > +    0x1682fe44, 0xbd7a, 0x4407, { 0xb7, 0xc7, 0xdc, 0xa3, 0x7c, 0xa3,
> > +0x92, 0x2d }  \
> > +  }
> > +
> > +typedef struct _EFI_TLS_CONFIGURATION_PROTOCOL
> > +EFI_TLS_CONFIGURATION_PROTOCOL;
> > +
> > +///
> > +/// EFI_TLS_CONFIG_DATA_TYPE
> > +///
> > +typedef enum {
> > +  ///
> > +  /// Local host configuration data: public certificate data.
> > +  /// This data should be DER-encoded binaryX.509 certificate
> > +  /// or PEMencoded X.509 certificate.
> > +  ///
> > +  EfiTlsConfigDataTypeHostPublicCert,
> > +  ///
> > +  /// Local host configuration data: private key data.
> > +  ///
> > +  EfiTlsConfigDataTypeHostPrivateKey,
> > +  ///
> > +  /// CA certificate to verify peer. This data should be PEM-encoded
> > +  /// RSA or PKCS#8 private key.
> > +  ///
> > +  EfiTlsConfigDataTypeCACertificate,
> > +  ///
> > +  /// CA-supplied Certificate Revocation List data. This data should
> > +  /// be DER-encoded CRL data.
> > +  ///
> > +  EfiTlsConfigDataTypeCertRevocationList,
> > +
> > +  EfiTlsConfigDataTypeMaximum
> > +
> > +} EFI_TLS_CONFIG_DATA_TYPE;
> > +
> > +/**
> > +  Set TLS configuration data.
> > +
> > +  The SetData() function sets TLS configuration to non-volatile
> > + storage or volatile  storage.
> > +
> > +  @param[in]  This                Pointer to the
> > EFI_TLS_CONFIGURATION_PROTOCOL instance.
> > +  @param[in]  DataType            Configuration data type.
> > +  @param[in]  Data                Pointer to configuration data.
> > +  @param[in]  DataSize            Total size of configuration data.
> > +
> > +  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  Data is NULL.
> > +                                  DataSize is 0.
> > +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> > +  @retval EFI_OUT_OF_RESOURCES    Required system resources could
> not
> > be allocated.
> > +
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_CONFIGURATION_SET_DATA)(
> > +  IN EFI_TLS_CONFIGURATION_PROTOCOL  *This,
> > +  IN EFI_TLS_CONFIG_DATA_TYPE        DataType,
> > +  IN VOID                            *Data,
> > +  IN UINTN                           DataSize
> > +  );
> > +
> > +/**
> > +  Get TLS configuration data.
> > +
> > +  The GetData() function gets TLS configuration.
> > +
> > +  @param[in]       This           Pointer to the
> > EFI_TLS_CONFIGURATION_PROTOCOL instance.
> > +  @param[in]       DataType       Configuration data type.
> > +  @param[in, out]  Data           Pointer to configuration data.
> > +  @param[in, out]  DataSize       Total size of configuration data. On input, it
> > means
> > +                                  the size of Data buffer. On output, it means the size
> > +                                  of copied Data buffer if EFI_SUCCESS, and means the
> > +                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
> > +
> > +  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  DataSize is NULL.
> > +                                  Data is NULL if *DataSize is not zero.
> > +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> > +  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
> > +  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the
> data.
> > +
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_CONFIGURATION_GET_DATA)(
> > +  IN EFI_TLS_CONFIGURATION_PROTOCOL  *This,
> > +  IN EFI_TLS_CONFIG_DATA_TYPE        DataType,
> > +  IN OUT VOID                        *Data,  OPTIONAL
> > +  IN OUT UINTN                       *DataSize
> > +  );
> > +
> > +///
> > +/// The EFI_TLS_CONFIGURATION_PROTOCOL is designed to provide a
> way
> > to
> > +set and get /// TLS configuration, such as Certificate, private key data.
> > +///
> > +struct _EFI_TLS_CONFIGURATION_PROTOCOL {
> > +  EFI_TLS_CONFIGURATION_SET_DATA     SetData;
> > +  EFI_TLS_CONFIGURATION_GET_DATA     GetData;
> > +};
> > +
> > +extern EFI_GUID gEfiTlsConfigurationProtocolGuid;
> > +
> > +#endif  //__EFI_TLS_CONFIGURATION_PROTOCOL_H__
> > diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index
> > 3e08bed..f2bdb30 100644
> > --- a/MdePkg/MdePkg.dec
> > +++ b/MdePkg/MdePkg.dec
> > @@ -1607,10 +1607,19 @@
> >    gEfiHttpProtocolGuid                 = { 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42,
> > 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b }}
> >
> >    ## Include/Protocol/HttpUtilities.h
> >    gEfiHttpUtilitiesProtocolGuid        = { 0x3e35c163, 0x4074, 0x45dd, {0x43,
> > 0x1e, 0x23, 0x98, 0x9d, 0xd8, 0x6b, 0x32 }}
> >
> > +  ## Include/Protocol/Tls.h
> > +  gEfiTlsServiceBindingProtocolGuid   = { 0x952cb795, 0xff36, 0x48cf, {0xa2,
> > 0x49, 0x4d, 0xf4, 0x86, 0xd6, 0xab, 0x8d }}
> > +
> > +  ## Include/Protocol/Tls.h
> > +  gEfiTlsProtocolGuid                 = { 0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc,
> 0xe4,
> > 0x6c, 0x47, 0x51, 0x43, 0x90 }}
> > +
> > +  ## Include/Protocol/TlsConfig.h
> > +  gEfiTlsConfigurationProtocolGuid    = { 0x1682fe44, 0xbd7a, 0x4407, { 0xb7,
> > 0xc7, 0xdc, 0xa3, 0x7c, 0xa3, 0x92, 0x2d }}
> > +
> >    ## Include/Protocol/Rest.h
> >    gEfiRestProtocolGuid                 =  { 0x0db48a36, 0x4e54, 0xea9c, {0x9b, 0x09,
> > 0x1e, 0xa5, 0xbe, 0x3a, 0x66, 0x0b }}
> >
> >    ## Include/Protocol/Supplicant.h
> >    gEfiSupplicantServiceBindingProtocolGuid  = { 0x45bcd98e, 0x59ad,
> > 0x4174, { 0x95, 0x46, 0x34, 0x4a, 0x7, 0x48, 0x58, 0x98 }}
> > --
> > 1.9.5.msysgit.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL
  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
  0 siblings, 1 reply; 37+ messages in thread
From: Fu, Siyuan @ 2016-12-14  8:41 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Ye, Ting, Zhang, Lubo, Long, Qin, Thomas Palmer

Hi, Jiaxin

Some comments as below:

In TlsImpl.c
	
Should the ASSERT in line 104 be an error handling? I mean is the input buffer coming from external input, and have we checked ContentType within it?

Seems the TempRecordHeader pointer will be modified in the while loop, shouldn't the 3rd parameter be the reminding buffer size of the output buffer?

Should we return error if the TlsCtrlTrafficOut return a failure?

Similar questions for the decrypt packet function.


Best Regards,
Siyuan

-----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 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL

This patch is the implementation of EFI TLS Service Binding
Protocol, EFI TLS Protocol and EFI TLS Configuration Protocol
Interfaces.

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/TlsDxe/TlsConfigProtocol.c | 152 ++++++++
 NetworkPkg/TlsDxe/TlsDriver.c         | 498 +++++++++++++++++++++++++++
 NetworkPkg/TlsDxe/TlsDriver.h         | 237 +++++++++++++
 NetworkPkg/TlsDxe/TlsDxe.inf          |  65 ++++
 NetworkPkg/TlsDxe/TlsDxe.uni          |  25 ++
 NetworkPkg/TlsDxe/TlsDxeExtra.uni     |  18 +
 NetworkPkg/TlsDxe/TlsImpl.c           | 270 +++++++++++++++
 NetworkPkg/TlsDxe/TlsImpl.h           | 315 +++++++++++++++++
 NetworkPkg/TlsDxe/TlsProtocol.c       | 632 ++++++++++++++++++++++++++++++++++
 9 files changed, 2212 insertions(+)
 create mode 100644 NetworkPkg/TlsDxe/TlsConfigProtocol.c
 create mode 100644 NetworkPkg/TlsDxe/TlsDriver.c
 create mode 100644 NetworkPkg/TlsDxe/TlsDriver.h
 create mode 100644 NetworkPkg/TlsDxe/TlsDxe.inf
 create mode 100644 NetworkPkg/TlsDxe/TlsDxe.uni
 create mode 100644 NetworkPkg/TlsDxe/TlsDxeExtra.uni
 create mode 100644 NetworkPkg/TlsDxe/TlsImpl.c
 create mode 100644 NetworkPkg/TlsDxe/TlsImpl.h
 create mode 100644 NetworkPkg/TlsDxe/TlsProtocol.c

diff --git a/NetworkPkg/TlsDxe/TlsConfigProtocol.c b/NetworkPkg/TlsDxe/TlsConfigProtocol.c
new file mode 100644
index 0000000..2ec79c9
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsConfigProtocol.c
@@ -0,0 +1,152 @@
+/** @file
+  Implementation of EFI TLS Configuration Protocol Interfaces.
+
+  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.
+
+**/
+
+#include "TlsImpl.h"
+
+EFI_TLS_CONFIGURATION_PROTOCOL  mTlsConfigurationProtocol = {
+  TlsConfigurationSetData,
+  TlsConfigurationGetData
+};
+
+/**
+  Set TLS configuration data.
+
+  The SetData() function sets TLS configuration to non-volatile storage or volatile
+  storage.
+
+  @param[in]  This                Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]  DataType            Configuration data type.
+  @param[in]  Data                Pointer to configuration data.
+  @param[in]  DataSize            Total size of configuration data.
+
+  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationSetData (
+  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN     VOID                            *Data,
+  IN     UINTN                           DataSize
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+
+  if (This == NULL ||  Data == NULL || DataSize == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This);
+
+  switch (DataType) {
+  case EfiTlsConfigDataTypeCACertificate:
+    Status = TlsSetCaCertificate (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeHostPublicCert:
+    Status = TlsSetHostPublicCert (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeHostPrivateKey:
+    Status = TlsSetHostPrivateKey (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeCertRevocationList:
+    Status = TlsSetCertRevocationList (Data, DataSize);
+    break;
+  default:
+     Status = EFI_UNSUPPORTED;
+  }
+
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  Get TLS configuration data.
+
+  The GetData() function gets TLS configuration.
+
+  @param[in]       This           Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]       DataType       Configuration data type.
+  @param[in, out]  Data           Pointer to configuration data.
+  @param[in, out]  DataSize       Total size of configuration data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationGetData (
+  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN OUT VOID                            *Data, OPTIONAL
+  IN OUT UINTN                           *DataSize
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+
+  if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This);
+
+  switch (DataType) {
+  case EfiTlsConfigDataTypeCACertificate:
+    Status = TlsGetCaCertificate (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeHostPublicCert:
+    Status = TlsGetHostPublicCert (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeHostPrivateKey:
+    Status = TlsGetHostPrivateKey (Instance->TlsConn, Data, DataSize);
+    break;
+  case EfiTlsConfigDataTypeCertRevocationList:
+    Status = TlsGetCertRevocationList (Data, DataSize);
+    break;
+  default:
+    Status = EFI_UNSUPPORTED;
+  }
+
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
diff --git a/NetworkPkg/TlsDxe/TlsDriver.c b/NetworkPkg/TlsDxe/TlsDriver.c
new file mode 100644
index 0000000..0a75c39
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDriver.c
@@ -0,0 +1,498 @@
+/** @file
+  The Driver Binding and Service Binding Protocol for TlsDxe 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.
+
+**/
+
+#include "TlsImpl.h"
+
+EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding = {
+  TlsServiceBindingCreateChild,
+  TlsServiceBindingDestroyChild
+};
+
+/**
+  Release all the resources used by the TLS instance.
+
+  @param[in]  Instance        The TLS instance data.
+
+**/
+VOID
+TlsCleanInstance (
+  IN TLS_INSTANCE           *Instance
+  )
+{
+  if (Instance != NULL) {
+    if (Instance->TlsConn != NULL) {
+      TlsFree (Instance->TlsConn);
+    }
+
+    FreePool (Instance);
+  }
+}
+
+/**
+  Create the TLS instance and initialize it.
+
+  @param[in]  Service              The pointer to the TLS service.
+  @param[out] Instance             The pointer to the TLS instance.
+
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
+  @retval EFI_SUCCESS            The TLS instance is created.
+
+**/
+EFI_STATUS
+TlsCreateInstance (
+  IN  TLS_SERVICE         *Service,
+  OUT TLS_INSTANCE        **Instance
+  )
+{
+  TLS_INSTANCE            *TlsInstance;
+
+  *Instance = NULL;
+
+  TlsInstance = AllocateZeroPool (sizeof (TLS_INSTANCE));
+  if (TlsInstance == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  TlsInstance->Signature = TLS_INSTANCE_SIGNATURE;
+  InitializeListHead (&TlsInstance->Link);
+  TlsInstance->InDestroy = FALSE;
+  TlsInstance->Service   = Service;
+
+  CopyMem (&TlsInstance->Tls, &mTlsProtocol, sizeof (TlsInstance->Tls));
+  CopyMem (&TlsInstance->TlsConfig, &mTlsConfigurationProtocol, sizeof (TlsInstance->TlsConfig));
+
+  TlsInstance->TlsSessionState = EfiTlsSessionNotStarted;
+
+  *Instance = TlsInstance;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Release all the resources used by the TLS service binding instance.
+
+  @param[in]  Service        The TLS service data.
+
+**/
+VOID
+TlsCleanService (
+  IN TLS_SERVICE     *Service
+  )
+{
+  if (Service != NULL) {
+    if (Service->TlsCtx != NULL) {
+      TlsCtxFree (Service->TlsCtx);
+    }
+
+    FreePool (Service);
+  }
+}
+
+/**
+  Create then initialize a TLS service.
+
+  @param[in]  Image                  ImageHandle of the TLS driver
+  @param[out] Service                The service for TLS driver
+
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create the service.
+  @retval EFI_SUCCESS            The service is created for the driver.
+
+**/
+EFI_STATUS
+TlsCreateService (
+  IN  EFI_HANDLE            Image,
+  OUT TLS_SERVICE           **Service
+  )
+{
+  EFI_STATUS             Status;
+  TLS_SERVICE            *TlsService;
+
+  Status = EFI_SUCCESS;
+  *Service = NULL;
+
+  ASSERT (Service != NULL);
+
+  //
+  // Allocate a TLS Service Data
+  //
+  TlsService = AllocateZeroPool (sizeof (TLS_SERVICE));
+  if (TlsService == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize TLS Service Data
+  //
+  TlsService->Signature        = TLS_SERVICE_SIGNATURE;
+  CopyMem (&TlsService->ServiceBinding, &mTlsServiceBinding, sizeof (TlsService->ServiceBinding));
+  TlsService->TlsChildrenNum   = 0;
+  InitializeListHead (&TlsService->TlsChildrenList);
+  TlsService->ImageHandle      = Image;
+
+  *Service = TlsService;
+
+  return Status;
+}
+
+/**
+  Unloads an image.
+
+  @param[in]  ImageHandle           Handle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS                      Status;
+  UINTN                           HandleNum;
+  EFI_HANDLE                      *HandleBuffer;
+  UINT32                          Index;
+  EFI_SERVICE_BINDING_PROTOCOL    *ServiceBinding;
+  TLS_SERVICE                     *TlsService;
+
+  HandleBuffer   = NULL;
+  ServiceBinding = NULL;
+  TlsService     = NULL;
+
+  //
+  // Locate all the handles with Tls service binding protocol.
+  //
+  Status = gBS->LocateHandleBuffer (
+                  ByProtocol,
+                  &gEfiTlsServiceBindingProtocolGuid,
+                  NULL,
+                  &HandleNum,
+                  &HandleBuffer
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  for (Index = 0; Index < HandleNum; Index++) {
+    //
+    // Firstly, find ServiceBinding interface
+    //
+    Status = gBS->OpenProtocol (
+                    HandleBuffer[Index],
+                    &gEfiTlsServiceBindingProtocolGuid,
+                    (VOID **) &ServiceBinding,
+                    ImageHandle,
+                    NULL,
+                    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+                    );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    TlsService = TLS_SERVICE_FROM_THIS (ServiceBinding);
+
+    //
+    // Then, uninstall ServiceBinding interface
+    //
+    Status = gBS->UninstallMultipleProtocolInterfaces (
+                    HandleBuffer[Index],
+                    &gEfiTlsServiceBindingProtocolGuid, ServiceBinding,
+                    NULL
+                    );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+
+    TlsCleanService (TlsService);
+  }
+
+  if (HandleBuffer != NULL) {
+    FreePool (HandleBuffer);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS             Status;
+
+  TLS_SERVICE            *TlsService;
+
+  //
+  // Create TLS Service
+  //
+  Status = TlsCreateService (ImageHandle, &TlsService);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ASSERT (TlsService != NULL);
+
+  //
+  // Initializes the OpenSSL library.
+  //
+  TlsInitialize ();
+
+  //
+  // Create a new SSL_CTX object as framework to establish TLS/SSL enabled
+  // connections. TLS 1.0 is used as the default version.
+  //
+  TlsService->TlsCtx = TlsCtxNew (TLS10_PROTOCOL_VERSION_MAJOR, TLS10_PROTOCOL_VERSION_MINOR);
+  if (TlsService->TlsCtx == NULL) {
+    FreePool (TlsService);
+    return EFI_ABORTED;
+  }
+
+  //
+  // Install the TlsServiceBinding Protocol onto Handle
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &TlsService->Handle,
+                  &gEfiTlsServiceBindingProtocolGuid,
+                  &TlsService->ServiceBinding,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_CLEAN_SERVICE;
+  }
+
+  return Status;
+
+ON_CLEAN_SERVICE:
+  TlsCleanService (TlsService);
+
+  return Status;
+}
+
+/**
+  Creates a child handle and installs a protocol.
+
+  The CreateChild() function installs a protocol on ChildHandle.
+  If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+  If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+  @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+  @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+                         then a new handle is created. If it is a pointer to an existing UEFI handle,
+                         then the protocol is added to the existing UEFI handle.
+
+  @retval EFI_SUCCES            The protocol was added to ChildHandle.
+  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create
+                                the child.
+  @retval other                 The child handle was not created.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingCreateChild (
+  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                    *ChildHandle
+  )
+{
+  TLS_SERVICE         *TlsService;
+  TLS_INSTANCE        *TlsInstance;
+  EFI_STATUS           Status;
+  EFI_TPL              OldTpl;
+
+  if ((This == NULL) || (ChildHandle == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TlsService = TLS_SERVICE_FROM_THIS (This);
+
+  Status = TlsCreateInstance (TlsService, &TlsInstance);
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  ASSERT (TlsInstance != NULL);
+
+  //
+  // Create a new TLS connection object.
+  //
+  TlsInstance->TlsConn = TlsNew (TlsService->TlsCtx);
+  if (TlsInstance->TlsConn == NULL) {
+    Status = EFI_ABORTED;
+    goto ON_ERROR;
+  }
+
+  //
+  // Set default ConnectionEnd to EfiTlsClient
+  //
+  Status = TlsSetConnectionEnd (TlsInstance->TlsConn, EfiTlsClient);
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  //
+  // Install TLS protocol and configuration protocol onto ChildHandle
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  ChildHandle,
+                  &gEfiTlsProtocolGuid,
+                  &TlsInstance->Tls,
+                  &gEfiTlsConfigurationProtocolGuid,
+                  &TlsInstance->TlsConfig,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  TlsInstance->ChildHandle = *ChildHandle;
+
+  //
+  // Add it to the TLS service's child list.
+  //
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  InsertTailList (&TlsService->TlsChildrenList, &TlsInstance->Link);
+  TlsService->TlsChildrenNum++;
+
+  gBS->RestoreTPL (OldTpl);
+
+  return EFI_SUCCESS;
+
+ON_ERROR:
+  TlsCleanInstance (TlsInstance);
+  return Status;
+}
+
+/**
+  Destroys a child handle with a protocol installed on it.
+
+  The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+  that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+  last protocol on ChildHandle, then ChildHandle is destroyed.
+
+  @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+  @param  ChildHandle Handle of the child to destroy.
+
+  @retval EFI_SUCCES            The protocol was removed from ChildHandle.
+  @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.
+  @retval EFI_INVALID_PARAMETER Child handle is NULL.
+  @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle
+                                because its services are being used.
+  @retval other                 The child handle was not destroyed.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingDestroyChild (
+  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                    ChildHandle
+  )
+{
+  TLS_SERVICE                    *TlsService;
+  TLS_INSTANCE                   *TlsInstance;
+
+  EFI_TLS_PROTOCOL               *Tls;
+  EFI_TLS_CONFIGURATION_PROTOCOL *TlsConfig;
+  EFI_STATUS                     Status;
+  EFI_TPL                        OldTpl;
+
+  if ((This == NULL) || (ChildHandle == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  TlsService = TLS_SERVICE_FROM_THIS (This);
+
+  //
+  // Find TLS protocol interface installed in ChildHandle
+  //
+  Status = gBS->OpenProtocol (
+                  ChildHandle,
+                  &gEfiTlsProtocolGuid,
+                  (VOID **) &Tls,
+                  TlsService->ImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  //
+  // Find TLS configuration protocol interface installed in ChildHandle
+  //
+  Status = gBS->OpenProtocol (
+                  ChildHandle,
+                  &gEfiTlsConfigurationProtocolGuid,
+                  (VOID **) &TlsConfig,
+                  TlsService->ImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  TlsInstance  = TLS_INSTANCE_FROM_PROTOCOL_THIS (Tls);
+
+  if (TlsInstance->Service != TlsService) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (TlsInstance->InDestroy) {
+    return EFI_SUCCESS;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  TlsInstance->InDestroy = TRUE;
+
+  //
+  // Uninstall the TLS protocol and TLS Configuration Protocol interface installed in ChildHandle.
+  //
+  Status = gBS->UninstallMultipleProtocolInterfaces (
+                  ChildHandle,
+                  &gEfiTlsProtocolGuid,
+                  Tls,
+                  &gEfiTlsConfigurationProtocolGuid,
+                  TlsConfig,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  RemoveEntryList (&TlsInstance->Link);
+  TlsService->TlsChildrenNum--;
+
+  gBS->RestoreTPL (OldTpl);
+
+  TlsCleanInstance (TlsInstance);
+
+  return EFI_SUCCESS;
+}
diff --git a/NetworkPkg/TlsDxe/TlsDriver.h b/NetworkPkg/TlsDxe/TlsDriver.h
new file mode 100644
index 0000000..c3c30a8
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDriver.h
@@ -0,0 +1,237 @@
+/** @file
+  Header file of the Driver Binding and Service Binding Protocol for TlsDxe 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_TLS_DRIVER_H__
+#define __EFI_TLS_DRIVER_H__
+
+#include <Uefi.h>
+
+//
+// Driver Protocols
+//
+#include <Protocol/ServiceBinding.h>
+
+//
+// Driver Version
+//
+#define TLS_VERSION  0x00000000
+
+#define TLS_SERVICE_SIGNATURE    SIGNATURE_32 ('T', 'L', 'S', 'S')
+
+#define TLS_INSTANCE_SIGNATURE   SIGNATURE_32 ('T', 'L', 'S', 'I')
+
+///
+/// TLS Service Data
+///
+typedef struct _TLS_SERVICE  TLS_SERVICE;
+
+///
+/// TLS Instance Data
+///
+typedef struct _TLS_INSTANCE TLS_INSTANCE;
+
+
+struct _TLS_SERVICE {
+  UINT32                          Signature;
+  EFI_SERVICE_BINDING_PROTOCOL    ServiceBinding;
+
+  UINT16                          TlsChildrenNum;
+  LIST_ENTRY                      TlsChildrenList;
+
+  //
+  // Handle to install TlsServiceBinding protocol.
+  //
+  EFI_HANDLE                      Handle;
+  EFI_HANDLE                      ImageHandle;
+
+  //
+  // Main SSL Context object which is created by a server or client once per program
+  // life-time and which holds mainly default values for the SSL object which are later
+  // created for the connections.
+  //
+  VOID                            *TlsCtx;
+};
+
+struct _TLS_INSTANCE {
+  UINT32                          Signature;
+  LIST_ENTRY                      Link;
+
+  BOOLEAN                         InDestroy;
+
+  TLS_SERVICE                     *Service;
+  EFI_HANDLE                      ChildHandle;
+
+  EFI_TLS_PROTOCOL                Tls;
+  EFI_TLS_CONFIGURATION_PROTOCOL  TlsConfig;
+
+  EFI_TLS_SESSION_STATE           TlsSessionState;
+
+  //
+  // Main SSL Connection which is created by a server or a client
+  // per established connection.
+  //
+  VOID                            *TlsConn;
+};
+
+
+#define TLS_SERVICE_FROM_THIS(a)   \
+  CR (a, TLS_SERVICE, ServiceBinding, TLS_SERVICE_SIGNATURE)
+
+#define TLS_INSTANCE_FROM_PROTOCOL_THIS(a)  \
+  CR (a, TLS_INSTANCE, Tls, TLS_INSTANCE_SIGNATURE)
+
+#define TLS_INSTANCE_FROM_CONFIGURATION_THIS(a)  \
+  CR (a, TLS_INSTANCE, TlsConfig, TLS_INSTANCE_SIGNATURE)
+
+
+/**
+  Release all the resources used by the TLS instance.
+
+  @param[in]  Instance        The TLS instance data.
+
+**/
+VOID
+TlsCleanInstance (
+  IN TLS_INSTANCE           *Instance
+  );
+
+/**
+  Create the TLS instance and initialize it.
+
+  @param[in]  Service              The pointer to the TLS service.
+  @param[out] Instance             The pointer to the TLS instance.
+
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
+  @retval EFI_SUCCESS            The TLS instance is created.
+
+**/
+EFI_STATUS
+TlsCreateInstance (
+  IN  TLS_SERVICE         *Service,
+  OUT TLS_INSTANCE        **Instance
+  );
+
+/**
+  Release all the resources used by the TLS service binding instance.
+
+  @param[in]  Service        The TLS service data.
+
+**/
+VOID
+TlsCleanService (
+  IN TLS_SERVICE     *Service
+  );
+
+/**
+  Create then initialize a TLS service.
+
+  @param[in]  Image                  ImageHandle of the TLS driver
+  @param[out] Service                The service for TLS driver
+
+  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create the service.
+  @retval EFI_SUCCESS            The service is created for the driver.
+
+**/
+EFI_STATUS
+TlsCreateService (
+  IN  EFI_HANDLE            Image,
+  OUT TLS_SERVICE           **Service
+  );
+
+/**
+  Unloads an image.
+
+  @param[in]  ImageHandle       Handle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsUnload (
+  IN EFI_HANDLE  ImageHandle
+  );
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  );
+
+/**
+  Creates a child handle and installs a protocol.
+
+  The CreateChild() function installs a protocol on ChildHandle.
+  If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
+  If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
+
+  @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+  @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
+                         then a new handle is created. If it is a pointer to an existing UEFI handle,
+                         then the protocol is added to the existing UEFI handle.
+
+  @retval EFI_SUCCES            The protocol was added to ChildHandle.
+  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create
+                                the child.
+  @retval other                 The child handle was not created.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingCreateChild (
+  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                    *ChildHandle
+  );
+
+/**
+  Destroys a child handle with a protocol installed on it.
+
+  The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
+  that was installed by CreateChild() from ChildHandle. If the removed protocol is the
+  last protocol on ChildHandle, then ChildHandle is destroyed.
+
+  @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
+  @param  ChildHandle Handle of the child to destroy.
+
+  @retval EFI_SUCCES            The protocol was removed from ChildHandle.
+  @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.
+  @retval EFI_INVALID_PARAMETER Child handle is NULL.
+  @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle
+                                because its services are being used.
+  @retval other                 The child handle was not destroyed.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsServiceBindingDestroyChild (
+  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
+  IN EFI_HANDLE                    ChildHandle
+  );
+
+#endif
diff --git a/NetworkPkg/TlsDxe/TlsDxe.inf b/NetworkPkg/TlsDxe/TlsDxe.inf
new file mode 100644
index 0000000..dba3257
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDxe.inf
@@ -0,0 +1,65 @@
+## @file
+#  This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and
+#  EFI TLS Configuration Protocol.
+#
+#  This module produces EFI TLS (Transport Layer Security) Protocol and EFI TLS
+#  Service Binding Protocol, to provide TLS services.
+#
+#  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.
+#
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = TlsDxe
+  FILE_GUID                 = 3aceb0c0-3c72-11e4-9a56-74d435052646
+  MODULE_TYPE               = UEFI_DRIVER
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = TlsDriverEntryPoint
+  UNLOAD_IMAGE              = TlsUnload
+  MODULE_UNI_FILE           = TlsDxe.uni
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  CryptoPkg/CryptoPkg.dec
+
+[Sources]
+  TlsDriver.h
+  TlsDriver.c
+  TlsProtocol.c
+  TlsConfigProtocol.c
+  TlsImpl.h
+  TlsImpl.c
+
+[LibraryClasses]
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  MemoryAllocationLib
+  BaseMemoryLib
+  BaseLib
+  UefiLib
+  DebugLib
+  NetLib
+  BaseCryptLib
+  TlsLib
+
+[Protocols]
+  gEfiTlsServiceBindingProtocolGuid          ## PRODUCES
+  gEfiTlsProtocolGuid                        ## PRODUCES
+  gEfiTlsConfigurationProtocolGuid           ## PRODUCES
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  TlsDxeExtra.uni
diff --git a/NetworkPkg/TlsDxe/TlsDxe.uni b/NetworkPkg/TlsDxe/TlsDxe.uni
new file mode 100644
index 0000000..98c41ca
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDxe.uni
@@ -0,0 +1,25 @@
+// /** @file
+// This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and
+// EFI TLS Configuration Protocol.
+//
+// This module produces EFI TLS (Transport Layer Security) Protocol, EFI TLS
+// Service Binding Protocol, and EFI TLS Configuration Protocol to provide TLS
+// services.
+//
+// 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.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "UEFI TLS service"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and EFI TLS Configuration Protocol to provide EFI TLS services."
+
diff --git a/NetworkPkg/TlsDxe/TlsDxeExtra.uni b/NetworkPkg/TlsDxe/TlsDxeExtra.uni
new file mode 100644
index 0000000..a38582a
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsDxeExtra.uni
@@ -0,0 +1,18 @@
+// /** @file
+// TlsDxe Localized Strings and Content
+//
+// 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.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"EFI TLS DXE Driver"
diff --git a/NetworkPkg/TlsDxe/TlsImpl.c b/NetworkPkg/TlsDxe/TlsImpl.c
new file mode 100644
index 0000000..5fb1e78
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsImpl.c
@@ -0,0 +1,270 @@
+/** @file
+  The Miscellaneous Routines for TlsDxe 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.
+
+**/
+
+#include "TlsImpl.h"
+
+/**
+  Encrypt the message listed in fragment.
+
+  @param[in]       TlsInstance    The pointer to the TLS instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment.
+                                  On input these fragments contain the TLS header and
+                                  plain text TLS payload;
+                                  On output these fragments contain the TLS header and
+                                  cipher text TLS payload.
+  @param[in]       FragmentCount  Number of fragment.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
+  @retval EFI_ABORTED             TLS session state is incorrect.
+  @retval Others                  Other errors as indicated.
+**/
+EFI_STATUS
+TlsEcryptPacket (
+  IN     TLS_INSTANCE                  *TlsInstance,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount
+  )
+{
+  UINTN               Index;
+  UINT32              BytesCopied;
+  UINT32              BufferInSize;
+  UINT8               *BufferIn;
+  UINT8               *BufferInPtr;
+  TLS_RECORD_HEADER   *RecordHeaderIn;
+  UINT16              ThisPlainMessageSize;
+  TLS_RECORD_HEADER   *TempRecordHeader;
+  UINT16              ThisMessageSize;
+  UINT32              BufferOutSize;
+  UINT8               *BufferOut;
+  INTN                Ret;
+
+  BytesCopied      = 0;
+  BufferInSize     = 0;
+  BufferIn         = NULL;
+  BufferInPtr      = NULL;
+  RecordHeaderIn   = NULL;
+  TempRecordHeader = NULL;
+  BufferOutSize    = 0;
+  BufferOut        = NULL;
+  Ret              = 0;
+
+  //
+  // Calculate the size according to the fragment table.
+  //
+  for (Index = 0; Index < *FragmentCount; Index++) {
+    BufferInSize += (*FragmentTable)[Index].FragmentLength;
+  }
+
+  //
+  // Allocate buffer for processing data.
+  //
+  BufferIn = AllocateZeroPool (BufferInSize);
+  if (BufferIn == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Copy all TLS plain record header and payload into ProcessBuffer.
+  //
+  for (Index = 0; Index < *FragmentCount; Index++) {
+    CopyMem (
+      (BufferIn + BytesCopied),
+      (*FragmentTable)[Index].FragmentBuffer,
+      (*FragmentTable)[Index].FragmentLength
+      );
+    BytesCopied += (*FragmentTable)[Index].FragmentLength;
+  }
+
+  BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE);
+  if (BufferOut == NULL) {
+    FreePool (BufferIn);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Parsing buffer.
+  //
+  BufferInPtr = BufferIn;
+  TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
+  while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
+    RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
+    ASSERT (RecordHeaderIn->ContentType == TLS_CONTENT_TYPE_APPLICATION_DATA);
+    ThisPlainMessageSize = RecordHeaderIn->Length;
+
+    TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), ThisPlainMessageSize);
+    
+    Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader), MAX_BUFFER_SIZE);
+
+    if (Ret > 0) {
+      ThisMessageSize = (UINT16) Ret;
+    } else {
+      ThisMessageSize = 0;
+    }
+
+    BufferOutSize += ThisMessageSize;
+
+    BufferInPtr += RECORD_HEADER_LEN + ThisPlainMessageSize;
+    TempRecordHeader += ThisMessageSize;
+  }
+
+  FreePool (BufferIn);
+
+  //
+  // The caller will take responsible to handle the original fragment table.
+  //
+  *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
+  if (*FragmentTable == NULL) {
+    FreePool (BufferOut);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  (*FragmentTable)[0].FragmentBuffer  = BufferOut;
+  (*FragmentTable)[0].FragmentLength  = BufferOutSize;
+  *FragmentCount                      = 1;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Decrypt the message listed in fragment.
+
+  @param[in]       TlsInstance    The pointer to the TLS instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment.
+                                  On input these fragments contain the TLS header and
+                                  cipher text TLS payload;
+                                  On output these fragments contain the TLS header and
+                                  plain text TLS payload.
+  @param[in]       FragmentCount  Number of fragment.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
+  @retval EFI_ABORTED             TLS session state is incorrect.
+  @retval Others                  Other errors as indicated.
+**/
+EFI_STATUS
+TlsDecryptPacket (
+  IN     TLS_INSTANCE                  *TlsInstance,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount
+  )
+{
+  UINTN               Index;
+  UINT32              BytesCopied;
+  UINT8               *BufferIn;
+  UINT32              BufferInSize;
+  UINT8               *BufferInPtr;
+  TLS_RECORD_HEADER   *RecordHeaderIn;
+  UINT16              ThisCipherMessageSize;
+  TLS_RECORD_HEADER   *TempRecordHeader;
+  UINT16              ThisPlainMessageSize;
+  UINT8               *BufferOut;
+  UINT32              BufferOutSize;
+  INTN                Ret;
+
+  BytesCopied      = 0;
+  BufferIn         = NULL;
+  BufferInSize     = 0;
+  BufferInPtr      = NULL;
+  RecordHeaderIn   = NULL;
+  TempRecordHeader = NULL;
+  BufferOut        = NULL;
+  BufferOutSize    = 0;
+  Ret              = 0;
+
+  //
+  // Calculate the size according to the fragment table.
+  //
+  for (Index = 0; Index < *FragmentCount; Index++) {
+    BufferInSize += (*FragmentTable)[Index].FragmentLength;
+  }
+
+  //
+  // Allocate buffer for processing data
+  //
+  BufferIn = AllocateZeroPool (BufferInSize);
+  if (BufferIn == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Copy all TLS plain record header and payload to ProcessBuffer
+  //
+  for (Index = 0; Index < *FragmentCount; Index++) {
+    CopyMem (
+      (BufferIn + BytesCopied),
+      (*FragmentTable)[Index].FragmentBuffer,
+      (*FragmentTable)[Index].FragmentLength
+      );
+    BytesCopied += (*FragmentTable)[Index].FragmentLength;
+  }
+
+  BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE);
+  if (BufferOut == NULL) {
+    FreePool (BufferIn);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Parsing buffer. Received packet may have multiply TLS record message.
+  //
+  BufferInPtr = BufferIn;
+  TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
+  while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
+    RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
+    ASSERT (RecordHeaderIn->ContentType == TLS_CONTENT_TYPE_APPLICATION_DATA);
+    ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length);
+
+    Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn), RECORD_HEADER_LEN + ThisCipherMessageSize);
+    if (Ret != RECORD_HEADER_LEN + ThisCipherMessageSize) {
+      FreePool (BufferIn);
+      TlsInstance->TlsSessionState = EfiTlsSessionError;
+      return EFI_ABORTED;
+    }
+
+    Ret = 0;
+    Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1), MAX_BUFFER_SIZE);
+
+    if (Ret > 0) {
+      ThisPlainMessageSize = (UINT16) Ret;
+    } else {
+      ThisPlainMessageSize = 0;
+    }
+
+    CopyMem (TempRecordHeader, RecordHeaderIn, RECORD_HEADER_LEN);
+    TempRecordHeader->Length = ThisPlainMessageSize;
+    BufferOutSize += RECORD_HEADER_LEN + ThisPlainMessageSize;
+
+    BufferInPtr += RECORD_HEADER_LEN + ThisCipherMessageSize;
+    TempRecordHeader += RECORD_HEADER_LEN + ThisPlainMessageSize;
+  }
+
+  FreePool (BufferIn);
+
+  //
+  // The caller will take responsible to handle the original fragment table
+  //
+  *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
+  if (*FragmentTable == NULL) {
+    FreePool (BufferOut);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  (*FragmentTable)[0].FragmentBuffer  = BufferOut;
+  (*FragmentTable)[0].FragmentLength  = BufferOutSize;
+  *FragmentCount                      = 1;
+
+  return EFI_SUCCESS;
+}
diff --git a/NetworkPkg/TlsDxe/TlsImpl.h b/NetworkPkg/TlsDxe/TlsImpl.h
new file mode 100644
index 0000000..b0615cb
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsImpl.h
@@ -0,0 +1,315 @@
+/** @file
+  Header file of Miscellaneous Routines for TlsDxe 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_TLS_IMPL_H__
+#define __EFI_TLS_IMPL_H__
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/NetLib.h>
+#include <Library/BaseCryptLib.h>
+#include <Library/TlsLib.h>
+
+//
+// Consumed Protocols
+//
+#include <Protocol/Tls.h>
+#include <Protocol/TlsConfig.h>
+
+#include <IndustryStandard/Tls1.h>
+
+#include "TlsDriver.h"
+
+//
+// Protocol instances
+//
+extern EFI_SERVICE_BINDING_PROTOCOL    mTlsServiceBinding;
+extern EFI_TLS_PROTOCOL                mTlsProtocol;
+extern EFI_TLS_CONFIGURATION_PROTOCOL  mTlsConfigurationProtocol;
+
+#define RECORD_HEADER_LEN 5 /// ContentType(1) + Version(2) + Length(2)
+
+#define MAX_BUFFER_SIZE   32768
+
+/**
+  Encrypt the message listed in fragment.
+
+  @param[in]       TlsInstance    The pointer to the TLS instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment.
+                                  On input these fragments contain the TLS header and
+                                  plain text TLS payload;
+                                  On output these fragments contain the TLS header and
+                                  cipher text TLS payload.
+  @param[in]       FragmentCount  Number of fragment.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
+  @retval EFI_ABORTED             TLS session state is incorrect.
+  @retval Others                  Other errors as indicated.
+**/
+EFI_STATUS
+TlsEcryptPacket (
+  IN     TLS_INSTANCE                  *TlsInstance,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount
+  );
+
+/**
+  Decrypt the message listed in fragment.
+
+  @param[in]       TlsInstance    The pointer to the TLS instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment.
+                                  On input these fragments contain the TLS header and
+                                  cipher text TLS payload;
+                                  On output these fragments contain the TLS header and
+                                  plain text TLS payload.
+  @param[in]       FragmentCount  Number of fragment.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
+  @retval EFI_ABORTED             TLS session state is incorrect.
+  @retval Others                  Other errors as indicated.
+**/
+EFI_STATUS
+TlsDecryptPacket (
+  IN     TLS_INSTANCE                  *TlsInstance,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount
+  );
+
+/**
+  Set TLS session data.
+
+  The SetSessionData() function set data for a new TLS session. All session data should
+  be set before BuildResponsePacket() invoked.
+
+  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]  DataType            TLS session data type.
+  @param[in]  Data                Pointer to session data.
+  @param[in]  DataSize            Total size of session data.
+
+  @retval EFI_SUCCESS             The TLS session data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
+                                  EfiTlsClientRandom
+                                  EfiTlsServerRandom
+                                  EfiTlsKeyMaterial
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionStateNotStarted.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+TlsSetSessionData (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
+  IN     VOID                          *Data,
+  IN     UINTN                         DataSize
+  );
+
+/**
+  Get TLS session data.
+
+  The GetSessionData() function return the TLS session information.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       DataType       TLS session data type.
+  @param[in, out]  Data           Pointer to session data.
+  @param[in, out]  DataSize       Total size of session data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS session data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS session data is not found.
+  @retval EFI_NOT_READY           The DataType is not ready in current session state.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsGetSessionData (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
+  IN OUT VOID                          *Data,  OPTIONAL
+  IN OUT UINTN                         *DataSize
+  );
+
+/**
+  Build response packet according to TLS state machine. This function is only valid for
+  alert, handshake and change_cipher_spec content type.
+
+  The BuildResponsePacket() function builds TLS response packet in response to the TLS
+  request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and
+  RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session
+  will be initiated and the response packet needs to be ClientHello. If RequestBuffer is
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS
+  session will be closed and response packet needs to be CloseNotify. If RequestBuffer is
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS
+  session has errors and the response packet needs to be Alert message based on error
+  type.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       RequestBuffer  Pointer to the most recently received TLS packet. NULL
+                                  means TLS need initiate the TLS session and response
+                                  packet need to be ClientHello.
+  @param[in]       RequestSize    Packet size in bytes for the most recently received TLS
+                                  packet. 0 is only valid when RequestBuffer is NULL.
+  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  RequestBuffer is NULL but RequestSize is NOT 0.
+                                  RequestSize is 0 but RequestBuffer is NOT NULL.
+                                  BufferSize is NULL.
+                                  Buffer is NULL if *BufferSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.
+  @retval EFI_NOT_READY           Current TLS session state is NOT ready to build
+                                  ResponsePacket.
+  @retval EFI_ABORTED             Something wrong build response packet.
+**/
+EFI_STATUS
+EFIAPI
+TlsBuildResponsePacket (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     UINT8                         *RequestBuffer, OPTIONAL
+  IN     UINTN                         RequestSize, OPTIONAL
+     OUT UINT8                         *Buffer, OPTIONAL
+  IN OUT UINTN                         *BufferSize
+  );
+
+/**
+  Decrypt or encrypt TLS packet during session. This function is only valid after
+  session connected and for application_data content type.
+
+  The ProcessPacket () function process each inbound or outbound TLS APP packet.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment. The caller will take
+                                  responsible to handle the original FragmentTable while
+                                  it may be reallocated in TLS driver. If CryptMode is
+                                  EfiTlsEncrypt, on input these fragments contain the TLS
+                                  header and plain text TLS APP payload; on output these
+                                  fragments contain the TLS header and cipher text TLS
+                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
+                                  these fragments contain the TLS header and cipher text
+                                  TLS APP payload; on output these fragments contain the
+                                  TLS header and plain text TLS APP payload.
+  @param[in]       FragmentCount  Number of fragment.
+  @param[in]       CryptMode      Crypt mode.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  FragmentTable is NULL.
+                                  FragmentCount is NULL.
+                                  CryptoMode is invalid.
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionDataTransferring.
+  @retval EFI_ABORTED             Something wrong decryption the message. TLS session
+                                  status will become EfiTlsSessionError. The caller need
+                                  call BuildResponsePacket() to generate Error Alert
+                                  message and send it out.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the operation.
+**/
+EFI_STATUS
+EFIAPI
+TlsProcessPacket (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount,
+  IN     EFI_TLS_CRYPT_MODE            CryptMode
+  );
+
+/**
+  Set TLS configuration data.
+
+  The SetData() function sets TLS configuration to non-volatile storage or volatile
+  storage.
+
+  @param[in]  This                Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]  DataType            Configuration data type.
+  @param[in]  Data                Pointer to configuration data.
+  @param[in]  DataSize            Total size of configuration data.
+
+  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationSetData (
+  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN     VOID                            *Data,
+  IN     UINTN                           DataSize
+  );
+
+/**
+  Get TLS configuration data.
+
+  The GetData() function gets TLS configuration.
+
+  @param[in]       This           Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]       DataType       Configuration data type.
+  @param[in, out]  Data           Pointer to configuration data.
+  @param[in, out]  DataSize       Total size of configuration data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsConfigurationGetData (
+  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN OUT VOID                            *Data, OPTIONAL
+  IN OUT UINTN                           *DataSize
+  );
+
+#endif
diff --git a/NetworkPkg/TlsDxe/TlsProtocol.c b/NetworkPkg/TlsDxe/TlsProtocol.c
new file mode 100644
index 0000000..bc617e1
--- /dev/null
+++ b/NetworkPkg/TlsDxe/TlsProtocol.c
@@ -0,0 +1,632 @@
+/** @file
+  Implementation of EFI TLS Protocol Interfaces.
+
+  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.
+
+**/
+
+#include "TlsImpl.h"
+
+EFI_TLS_PROTOCOL  mTlsProtocol = {
+  TlsSetSessionData,
+  TlsGetSessionData,
+  TlsBuildResponsePacket,
+  TlsProcessPacket
+};
+
+/**
+  Set TLS session data.
+
+  The SetSessionData() function set data for a new TLS session. All session data should
+  be set before BuildResponsePacket() invoked.
+
+  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]  DataType            TLS session data type.
+  @param[in]  Data                Pointer to session data.
+  @param[in]  DataSize            Total size of session data.
+
+  @retval EFI_SUCCESS             The TLS session data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
+                                  EfiTlsClientRandom
+                                  EfiTlsServerRandom
+                                  EfiTlsKeyMaterial
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionStateNotStarted.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+**/
+EFI_STATUS
+EFIAPI
+TlsSetSessionData (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
+  IN     VOID                          *Data,
+  IN     UINTN                         DataSize
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+  UINT16                    *CipherId;
+  UINTN                     Index;
+
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+  CipherId = NULL;
+
+  if (This == NULL || Data == NULL || DataSize == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
+
+  if (DataType != EfiTlsSessionState  && Instance->TlsSessionState != EfiTlsSessionNotStarted){
+    Status = EFI_NOT_READY;
+    goto ON_EXIT;
+  }
+
+  switch (DataType) {
+  //
+  // Session Configuration
+  //
+  case EfiTlsVersion:
+    if (DataSize != sizeof (EFI_TLS_VERSION)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    Status = TlsSetVersion (Instance->TlsConn, ((EFI_TLS_VERSION *) Data)->Major, ((EFI_TLS_VERSION *) Data)->Minor);
+    break;
+  case EfiTlsConnectionEnd:
+    if (DataSize != sizeof (EFI_TLS_CONNECTION_END)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    Status = TlsSetConnectionEnd (Instance->TlsConn, *((EFI_TLS_CONNECTION_END *) Data));
+    break;
+  case EfiTlsCipherList:
+    CipherId = AllocatePool (DataSize);
+    if (CipherId == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ON_EXIT;
+    }
+
+    for (Index = 0; Index < DataSize / sizeof (EFI_TLS_CIPHER); Index++) {
+      *(CipherId +Index) = HTONS (*(((UINT16 *) Data) + Index));
+    }
+
+    Status = TlsSetCipherList (Instance->TlsConn, CipherId, DataSize / sizeof (EFI_TLS_CIPHER));
+
+    FreePool (CipherId);
+    break;
+  case EfiTlsCompressionMethod:
+    //
+    // TLS seems only define one CompressionMethod.null, which specifies that data exchanged via the
+    // record protocol will not be compressed.
+    // More information from OpenSSL: http://www.openssl.org/docs/manmaster/ssl/SSL_COMP_add_compression_method.html
+    // The TLS RFC does however not specify compression methods or their corresponding identifiers,
+    // so there is currently no compatible way to integrate compression with unknown peers.
+    // It is therefore currently not recommended to integrate compression into applications.
+    // Applications for non-public use may agree on certain compression methods.
+    // Using different compression methods with the same identifier will lead to connection failure.
+    //
+    for (Index = 0; Index < DataSize / sizeof (EFI_TLS_COMPRESSION); Index++) {
+      Status = TlsSetCompressionMethod (*((UINT8 *) Data + Index));
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+    }
+
+    break;
+  case EfiTlsExtensionData:
+    Status = EFI_UNSUPPORTED;
+    goto ON_EXIT;
+  case EfiTlsVerifyMethod:
+    if (DataSize != sizeof (EFI_TLS_VERIFY)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    TlsSetVerify (Instance->TlsConn, *((UINT32 *) Data));
+    break;
+  case EfiTlsSessionID:
+    if (DataSize != sizeof (EFI_TLS_SESSION_ID)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    Status = TlsSetSessionId (
+               Instance->TlsConn,
+               ((EFI_TLS_SESSION_ID *) Data)->Data,
+               ((EFI_TLS_SESSION_ID *) Data)->Length
+               );
+    break;
+  case EfiTlsSessionState:
+    if (DataSize != sizeof (EFI_TLS_SESSION_STATE)) {
+      Status = EFI_INVALID_PARAMETER;
+      goto ON_EXIT;
+    }
+
+    Instance->TlsSessionState = *(EFI_TLS_SESSION_STATE *) Data;
+    break;
+  //
+  // Session information
+  //
+  case EfiTlsClientRandom:
+    Status = EFI_ACCESS_DENIED;
+    break;
+  case EfiTlsServerRandom:
+    Status = EFI_ACCESS_DENIED;
+    break;
+  case EfiTlsKeyMaterial:
+    Status = EFI_ACCESS_DENIED;
+    break;
+  //
+  // Unsupported type.
+  //
+  default:
+    Status = EFI_UNSUPPORTED;
+  }
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  Get TLS session data.
+
+  The GetSessionData() function return the TLS session information.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       DataType       TLS session data type.
+  @param[in, out]  Data           Pointer to session data.
+  @param[in, out]  DataSize       Total size of session data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS session data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS session data is not found.
+  @retval EFI_NOT_READY           The DataType is not ready in current session state.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+**/
+EFI_STATUS
+EFIAPI
+TlsGetSessionData (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
+  IN OUT VOID                          *Data,  OPTIONAL
+  IN OUT UINTN                         *DataSize
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+
+  if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
+
+  if (Instance->TlsSessionState == EfiTlsSessionNotStarted &&
+    (DataType == EfiTlsSessionID || DataType == EfiTlsClientRandom ||
+    DataType == EfiTlsServerRandom || DataType == EfiTlsKeyMaterial)) {
+    Status = EFI_NOT_READY;
+    goto ON_EXIT;
+  }
+
+  switch (DataType) {
+  case EfiTlsVersion:
+    if (*DataSize < sizeof (EFI_TLS_VERSION)) {
+      *DataSize = sizeof (EFI_TLS_VERSION);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_VERSION);
+    *((UINT16 *) Data) = HTONS (TlsGetVersion (Instance->TlsConn));
+    break;
+  case EfiTlsConnectionEnd:
+    if (*DataSize < sizeof (EFI_TLS_CONNECTION_END)) {
+      *DataSize = sizeof (EFI_TLS_CONNECTION_END);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_CONNECTION_END);
+    *((UINT8 *) Data) = TlsGetConnectionEnd (Instance->TlsConn);
+    break;
+  case EfiTlsCipherList:
+    //
+    // Get the current session cipher suite.
+    //
+    if (*DataSize < sizeof (EFI_TLS_CIPHER)) {
+      *DataSize = sizeof (EFI_TLS_CIPHER);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof(EFI_TLS_CIPHER);
+    Status = TlsGetCurrentCipher (Instance->TlsConn, (UINT16 *) Data);
+    *((UINT16 *) Data) = HTONS (*((UINT16 *) Data));
+    break;
+  case EfiTlsCompressionMethod:
+    //
+    // Get the current session compression method.
+    //
+    if (*DataSize < sizeof (EFI_TLS_COMPRESSION)) {
+      *DataSize = sizeof (EFI_TLS_COMPRESSION);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_COMPRESSION);
+    Status = TlsGetCurrentCompressionId (Instance->TlsConn, (UINT8 *) Data);
+    break;
+  case EfiTlsExtensionData:
+    Status = EFI_UNSUPPORTED;
+    goto ON_EXIT;
+  case EfiTlsVerifyMethod:
+    if (*DataSize < sizeof (EFI_TLS_VERIFY)) {
+      *DataSize = sizeof (EFI_TLS_VERIFY);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_VERIFY);
+    *((UINT32 *) Data) = TlsGetVerify (Instance->TlsConn);
+    break;
+  case EfiTlsSessionID:
+    if (*DataSize < sizeof (EFI_TLS_SESSION_ID)) {
+      *DataSize = sizeof (EFI_TLS_SESSION_ID);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_SESSION_ID);
+    Status = TlsGetSessionId (
+               Instance->TlsConn,
+               ((EFI_TLS_SESSION_ID *) Data)->Data,
+               &(((EFI_TLS_SESSION_ID *) Data)->Length)
+               );
+    break;
+  case EfiTlsSessionState:
+    if (*DataSize < sizeof (EFI_TLS_SESSION_STATE)) {
+      *DataSize = sizeof (EFI_TLS_SESSION_STATE);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_SESSION_STATE);
+    CopyMem (Data, &Instance->TlsSessionState, *DataSize);
+    break;
+  case EfiTlsClientRandom:
+    if (*DataSize < sizeof (EFI_TLS_RANDOM)) {
+      *DataSize = sizeof (EFI_TLS_RANDOM);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_RANDOM);
+    TlsGetClientRandom (Instance->TlsConn, (UINT8 *) Data);
+    break;
+  case EfiTlsServerRandom:
+    if (*DataSize < sizeof (EFI_TLS_RANDOM)) {
+      *DataSize = sizeof (EFI_TLS_RANDOM);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_RANDOM);
+    TlsGetServerRandom (Instance->TlsConn, (UINT8 *) Data);
+    break;
+  case EfiTlsKeyMaterial:
+    if (*DataSize < sizeof (EFI_TLS_MASTER_SECRET)) {
+      *DataSize = sizeof (EFI_TLS_MASTER_SECRET);
+      Status = EFI_BUFFER_TOO_SMALL;
+      goto ON_EXIT;
+    }
+    *DataSize = sizeof (EFI_TLS_MASTER_SECRET);
+    Status = TlsGetKeyMaterial (Instance->TlsConn, (UINT8 *) Data);
+    break;
+  //
+  // Unsupported type.
+  //
+  default:
+    Status = EFI_UNSUPPORTED;
+  }
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  Build response packet according to TLS state machine. This function is only valid for
+  alert, handshake and change_cipher_spec content type.
+
+  The BuildResponsePacket() function builds TLS response packet in response to the TLS
+  request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and
+  RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session
+  will be initiated and the response packet needs to be ClientHello. If RequestBuffer is
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS
+  session will be closed and response packet needs to be CloseNotify. If RequestBuffer is
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS
+  session has errors and the response packet needs to be Alert message based on error
+  type.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       RequestBuffer  Pointer to the most recently received TLS packet. NULL
+                                  means TLS need initiate the TLS session and response
+                                  packet need to be ClientHello.
+  @param[in]       RequestSize    Packet size in bytes for the most recently received TLS
+                                  packet. 0 is only valid when RequestBuffer is NULL.
+  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  RequestBuffer is NULL but RequestSize is NOT 0.
+                                  RequestSize is 0 but RequestBuffer is NOT NULL.
+                                  BufferSize is NULL.
+                                  Buffer is NULL if *BufferSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.
+  @retval EFI_NOT_READY           Current TLS session state is NOT ready to build
+                                  ResponsePacket.
+  @retval EFI_ABORTED             Something wrong build response packet.
+**/
+EFI_STATUS
+EFIAPI
+TlsBuildResponsePacket (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN     UINT8                         *RequestBuffer, OPTIONAL
+  IN     UINTN                         RequestSize, OPTIONAL
+     OUT UINT8                         *Buffer, OPTIONAL
+  IN OUT UINTN                         *BufferSize
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+
+  if ((This == NULL) || (BufferSize == NULL) ||
+      (RequestBuffer == NULL && RequestSize != 0) ||
+      (RequestBuffer != NULL && RequestSize == 0) ||
+      (Buffer == NULL && *BufferSize !=0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
+
+  if(RequestBuffer == NULL && RequestSize == 0) {
+    switch (Instance->TlsSessionState) {
+    case EfiTlsSessionNotStarted:
+      //
+      // ClientHello.
+      //
+      Status = TlsDoHandshake (
+                 Instance->TlsConn,
+                 NULL,
+                 0,
+                 Buffer,
+                 BufferSize
+                 );
+      if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+      }
+
+      //
+      // *BufferSize should not be zero when ClientHello.
+      //
+      if (*BufferSize == 0) {
+        Status = EFI_ABORTED;
+        goto ON_EXIT;
+      }
+
+      Instance->TlsSessionState = EfiTlsSessionHandShaking;
+
+      break;
+    case EfiTlsSessionClosing:
+      //
+      // TLS session will be closed and response packet needs to be CloseNotify.
+      //
+      Status = TlsCloseNotify (
+                 Instance->TlsConn,
+                 Buffer,
+                 BufferSize
+                 );
+      if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+      }
+
+      //
+      // *BufferSize should not be zero when build CloseNotify message.
+      //
+      if (*BufferSize == 0) {
+        Status = EFI_ABORTED;
+        goto ON_EXIT;
+      }
+
+      break;
+    case EfiTlsSessionError:
+      //
+      // TLS session has errors and the response packet needs to be Alert
+      // message based on error type.
+      //
+      Status = TlsHandeAlert (
+                 Instance->TlsConn,
+                 NULL,
+                 0,
+                 Buffer,
+                 BufferSize
+                 );
+      if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+      }
+
+      break;
+    default:
+      //
+      // Current TLS session state is NOT ready to build ResponsePacket.
+      //
+      Status = EFI_NOT_READY;
+    }
+  } else {
+    //
+    // 1. Received packet may have multiply TLS record messages.
+    // 2. One TLS record message may have multiply handshake protocol.
+    // 3. Some errors may be happened in handshake.
+    // TlsDoHandshake() can handle all of those cases.
+    //
+    if (TlsInHandshake (Instance->TlsConn)) {
+      Status = TlsDoHandshake (
+                 Instance->TlsConn,
+                 RequestBuffer,
+                 RequestSize,
+                 Buffer,
+                 BufferSize
+                 );
+      if (EFI_ERROR (Status)) {
+        goto ON_EXIT;
+      }
+
+      if (!TlsInHandshake (Instance->TlsConn)) {
+        Instance->TlsSessionState = EfiTlsSessionDataTransferring;
+      }
+    } else {
+      //
+      // Must be alert message, Decrypt it and build the ResponsePacket.
+      //
+      ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType == TLS_CONTENT_TYPE_ALERT);
+
+      Status = TlsHandeAlert (
+                 Instance->TlsConn,
+                 RequestBuffer,
+                 RequestSize,
+                 Buffer,
+                 BufferSize
+                 );
+      if (EFI_ERROR (Status)) {
+        if (Status != EFI_BUFFER_TOO_SMALL) {
+          Instance->TlsSessionState = EfiTlsSessionError;
+        }
+
+        goto ON_EXIT;
+      }
+    }
+  }
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
+
+/**
+  Decrypt or encrypt TLS packet during session. This function is only valid after
+  session connected and for application_data content type.
+
+  The ProcessPacket () function process each inbound or outbound TLS APP packet.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment. The caller will take
+                                  responsible to handle the original FragmentTable while
+                                  it may be reallocated in TLS driver. If CryptMode is
+                                  EfiTlsEncrypt, on input these fragments contain the TLS
+                                  header and plain text TLS APP payload; on output these
+                                  fragments contain the TLS header and cipher text TLS
+                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
+                                  these fragments contain the TLS header and cipher text
+                                  TLS APP payload; on output these fragments contain the
+                                  TLS header and plain text TLS APP payload.
+  @param[in]       FragmentCount  Number of fragment.
+  @param[in]       CryptMode      Crypt mode.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  FragmentTable is NULL.
+                                  FragmentCount is NULL.
+                                  CryptoMode is invalid.
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionDataTransferring.
+  @retval EFI_ABORTED             Something wrong decryption the message. TLS session
+                                  status will become EfiTlsSessionError. The caller need
+                                  call BuildResponsePacket() to generate Error Alert
+                                  message and send it out.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the operation.
+**/
+EFI_STATUS
+EFIAPI
+TlsProcessPacket (
+  IN     EFI_TLS_PROTOCOL              *This,
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
+  IN     UINT32                        *FragmentCount,
+  IN     EFI_TLS_CRYPT_MODE            CryptMode
+  )
+{
+  EFI_STATUS                Status;
+  TLS_INSTANCE              *Instance;
+
+  EFI_TPL                   OldTpl;
+
+  Status = EFI_SUCCESS;
+
+  if (This == NULL || FragmentTable == NULL || FragmentCount == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
+
+  if (Instance->TlsSessionState != EfiTlsSessionDataTransferring) {
+    Status = EFI_NOT_READY;
+    goto ON_EXIT;
+  }
+
+  //
+  // Packet sent or received may have multiply TLS record message(Application data type).
+  // So,on input these fragments contain the TLS header and TLS APP payload;
+  // on output these fragments also contain the TLS header and TLS APP payload.
+  //
+  switch (CryptMode) {
+  case EfiTlsEncrypt:
+    Status = TlsEcryptPacket (Instance, FragmentTable, FragmentCount);
+    break;
+  case EfiTlsDecrypt:
+    Status = TlsDecryptPacket (Instance, FragmentTable, FragmentCount);
+    break;
+  default:
+    return EFI_INVALID_PARAMETER;
+  }
+
+ON_EXIT:
+  gBS->RestoreTPL (OldTpl);
+  return Status;
+}
-- 
1.9.5.msysgit.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 02/10] MdePkg: Add a header to standardize TLS definitions
  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
  2 siblings, 0 replies; 37+ messages in thread
From: Long, Qin @ 2016-12-14  8:42 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Ye, Ting, Fu, Siyuan, Zhang, Lubo, Gao, Liming, Kinney, Michael D,
	Thomas Palmer

Reviewed-by: Qin Long <qin.long@intel.com>


> -----Original Message-----
> From: Wu, Jiaxin
> Sent: Wednesday, December 14, 2016 3:34 PM
> To: edk2-devel@lists.01.org
> Cc: Long, Qin; Ye, Ting; Fu, Siyuan; Zhang, Lubo; Gao, Liming; Kinney, Michael
> D; Thomas Palmer; Wu, Jiaxin
> Subject: [Patch 02/10] MdePkg: Add a header to standardize TLS definitions
> 
> This path is used to standardize TLS definitions from related RFCs. Including
> TLS Cipher Suites, TLS Version, TLS Content Type and TLS Record Header, etc.
> 
> Cc: Long Qin <qin.long@intel.com>
> Cc: Ye Ting <ting.ye@intel.com>
> Cc: Fu Siyuan <siyuan.fu@intel.com>
> Cc: Zhang Lubo <lubo.zhang@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Michael D Kinney <michael.d.kinney@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>
> ---
>  MdePkg/Include/IndustryStandard/Tls1.h | 93
> ++++++++++++++++++++++++++++++++++
>  1 file changed, 93 insertions(+)
>  create mode 100644 MdePkg/Include/IndustryStandard/Tls1.h
> 
> diff --git a/MdePkg/Include/IndustryStandard/Tls1.h
> b/MdePkg/Include/IndustryStandard/Tls1.h
> new file mode 100644
> index 0000000..14eb265
> --- /dev/null
> +++ b/MdePkg/Include/IndustryStandard/Tls1.h
> @@ -0,0 +1,93 @@
> +/** @file
> +  Transport Layer Security  -- TLS 1.0/1.1/1.2 Standard definitions, from RFC
> 2246/4346/5246
> +
> +  This file contains common TLS 1.0/1.1/1.2 definitions from RFC
> + 2246/4346/5246
> +
> +  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 __TLS_1_H__
> +#define __TLS_1_H__
> +
> +#pragma pack(1)
> +
> +///
> +/// TLS Cipher Suite, refers to A.5 of rfc-2246, rfc-4346 and rfc-5246.
> +///
> +#define TLS_RSA_WITH_NULL_MD5                    {0x00, 0x01}
> +#define TLS_RSA_WITH_NULL_SHA                    {0x00, 0x02}
> +#define TLS_RSA_WITH_RC4_128_MD5                 {0x00, 0x04}
> +#define TLS_RSA_WITH_RC4_128_SHA                 {0x00, 0x05}
> +#define TLS_RSA_WITH_IDEA_CBC_SHA                {0x00, 0x07}
> +#define TLS_RSA_WITH_DES_CBC_SHA                 {0x00, 0x09}
> +#define TLS_RSA_WITH_3DES_EDE_CBC_SHA            {0x00, 0x0A}
> +#define TLS_DH_DSS_WITH_DES_CBC_SHA              {0x00, 0x0C}
> +#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA         {0x00, 0x0D}
> +#define TLS_DH_RSA_WITH_DES_CBC_SHA              {0x00, 0x0F}
> +#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA         {0x00, 0x10}
> +#define TLS_DHE_DSS_WITH_DES_CBC_SHA             {0x00, 0x12}
> +#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA        {0x00, 0x13}
> +#define TLS_DHE_RSA_WITH_DES_CBC_SHA             {0x00, 0x15}
> +#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA        {0x00, 0x16}
> +#define TLS_RSA_WITH_AES_128_CBC_SHA             {0x00, 0x2F}
> +#define TLS_DH_DSS_WITH_AES_128_CBC_SHA          {0x00, 0x30}
> +#define TLS_DH_RSA_WITH_AES_128_CBC_SHA          {0x00, 0x31}
> +#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA         {0x00, 0x32}
> +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA         {0x00, 0x33}
> +#define TLS_RSA_WITH_AES_256_CBC_SHA             {0x00, 0x35}
> +#define TLS_DH_DSS_WITH_AES_256_CBC_SHA          {0x00, 0x36}
> +#define TLS_DH_RSA_WITH_AES_256_CBC_SHA          {0x00, 0x37}
> +#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA         {0x00, 0x38}
> +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA         {0x00, 0x39}
> +#define TLS_RSA_WITH_NULL_SHA256                 {0x00, 0x3B}
> +#define TLS_RSA_WITH_AES_128_CBC_SHA256          {0x00, 0x3C}
> +#define TLS_RSA_WITH_AES_256_CBC_SHA256          {0x00, 0x3D}
> +#define TLS_DH_DSS_WITH_AES_128_CBC_SHA256       {0x00, 0x3E}
> +#define TLS_DH_RSA_WITH_AES_128_CBC_SHA256       {0x00, 0x3F}
> +#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA256      {0x00, 0x40}
> +#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256      {0x00, 0x67}
> +#define TLS_DH_DSS_WITH_AES_256_CBC_SHA256       {0x00, 0x68}
> +#define TLS_DH_RSA_WITH_AES_256_CBC_SHA256       {0x00, 0x69}
> +#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA256      {0x00, 0x6A}
> +#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256      {0x00, 0x6B}
> +
> +///
> +/// TLS Version, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
> +///
> +#define TLS10_PROTOCOL_VERSION_MAJOR  0x03 #define
> +TLS10_PROTOCOL_VERSION_MINOR  0x01 #define
> TLS11_PROTOCOL_VERSION_MAJOR
> +0x03 #define TLS11_PROTOCOL_VERSION_MINOR  0x02 #define
> +TLS12_PROTOCOL_VERSION_MAJOR  0x03 #define
> TLS12_PROTOCOL_VERSION_MINOR
> +0x03
> +
> +///
> +/// TLS Content Type, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
> +///
> +typedef enum {
> +  TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20,
> +  TLS_CONTENT_TYPE_ALERT              = 21,
> +  TLS_CONTENT_TYPE_HANDSHAKE          = 22,
> +  TLS_CONTENT_TYPE_APPLICATION_DATA   = 23,
> +} TLS_CONTENT_TYPE;
> +
> +///
> +/// TLS Record Header, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
> +///
> +typedef struct {
> +  UINT8                   ContentType;
> +  EFI_TLS_VERSION         Version;
> +  UINT16                  Length;
> +} TLS_RECORD_HEADER;
> +
> +#pragma pack()
> +
> +#endif
> +
> --
> 1.9.5.msysgit.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 01/10] MdePkg: Add TLS related protocol definition
  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:43   ` Fu, Siyuan
  1 sibling, 0 replies; 37+ messages in thread
From: Fu, Siyuan @ 2016-12-14  8:43 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Long, Qin, Ye, Ting, Zhang,  Lubo, Gao, Liming, Kinney, Michael D,
	Thomas Palmer



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: Long, Qin <qin.long@intel.com>; Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>; Wu, Jiaxin <jiaxin.wu@intel.com>
Subject: [Patch 01/10] MdePkg: Add TLS related protocol definition

This patch is used to add Tls.h and TlsConfig.h header files to define EFI TLS Configuration Protocol, EFI TLS Service Binding Protocol and EFI TLS Configuration Protocol.

Cc: Long Qin <qin.long@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@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>
---
 MdePkg/Include/Protocol/Tls.h       | 460 ++++++++++++++++++++++++++++++++++++
 MdePkg/Include/Protocol/TlsConfig.h | 132 +++++++++++
 MdePkg/MdePkg.dec                   |   9 +
 3 files changed, 601 insertions(+)
 create mode 100644 MdePkg/Include/Protocol/Tls.h  create mode 100644 MdePkg/Include/Protocol/TlsConfig.h

diff --git a/MdePkg/Include/Protocol/Tls.h b/MdePkg/Include/Protocol/Tls.h new file mode 100644 index 0000000..51a3cda
--- /dev/null
+++ b/MdePkg/Include/Protocol/Tls.h
@@ -0,0 +1,460 @@
+/** @file
+  EFI TLS Protocols as defined in UEFI 2.5.
+
+  The EFI TLS Service Binding Protocol is used to locate EFI TLS 
+ Protocol drivers  to create and destroy child of the driver to 
+ communicate with other host using  TLS protocol.
+  The EFI TLS Protocol provides the ability to manage TLS session.
+
+  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.
+
+  @par Revision Reference:
+  This Protocol is introduced in UEFI Specification 2.5
+
+**/
+
+#ifndef __EFI_TLS_PROTOCOL_H__
+#define __EFI_TLS_PROTOCOL_H__
+
+///
+/// The EFI TLS Service Binding Protocol is used to locate EFI TLS 
+Protocol drivers to /// create and destroy child of the driver to 
+communicate with other host using TLS /// protocol.
+///
+#define EFI_TLS_SERVICE_BINDING_PROTOCOL_GUID \
+  { \
+    0x952cb795, 0xff36, 0x48cf, {0xa2, 0x49, 0x4d, 0xf4, 0x86, 0xd6, 
+0xab, 0x8d } \
+  }
+
+///
+/// The EFI TLS protocol provides the ability to manage TLS session.
+///
+#define EFI_TLS_PROTOCOL_GUID \
+  { \
+    0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc, 0xe4, 0x6c, 0x47, 0x51, 
+0x43, 0x90 } \
+  }
+
+typedef struct _EFI_TLS_PROTOCOL EFI_TLS_PROTOCOL;
+
+///
+/// EFI_TLS_SESSION_DATA_TYPE
+///
+typedef enum {
+  ///
+  /// Session Configuration
+  ///
+
+  ///
+  /// TLS session Version. The corresponding Data is of type EFI_TLS_VERSION.
+  ///
+  EfiTlsVersion,
+  ///
+  /// TLS session as client or as server. The corresponding Data is of  
+ /// EFI_TLS_CONNECTION_END.
+  ///
+  EfiTlsConnectionEnd,
+  ///
+  /// A priority list of preferred algorithms for the TLS session.
+  /// The corresponding Data is a list of EFI_TLS_CIPHER.
+  ///
+  EfiTlsCipherList,
+  ///
+  /// TLS session compression method.
+  /// The corresponding Data is of type EFI_TLS_COMPRESSION.
+  ///
+  EfiTlsCompressionMethod,
+  ///
+  /// TLS session extension data.
+  /// The corresponding Data is a list of type EFI_TLS_EXTENDION.
+  ///
+  EfiTlsExtensionData,
+  ///
+  /// TLS session verify method.
+  /// The corresponding Data is of type EFI_TLS_VERIFY.
+  ///
+  EfiTlsVerifyMethod,
+  ///
+  /// TLS session data session ID.
+  /// For SetSessionData(), it is TLS session ID used for session resumption.
+  /// For GetSessionData(), it is the TLS session ID used for current session.
+  /// The corresponding Data is of type EFI_TLS_SESSION_ID.
+  ///
+  EfiTlsSessionID,
+  ///
+  /// TLS session data session state.
+  /// The corresponding Data is of type EFI_TLS_SESSION_STATE.
+  ///
+  EfiTlsSessionState,
+
+  ///
+  /// Session information
+  ///
+
+  ///
+  /// TLS session data client random.
+  /// The corresponding Data is of type EFI_TLS_RANDOM.
+  ///
+  EfiTlsClientRandom,
+  ///
+  /// TLS session data server random.
+  /// The corresponding Data is of type EFI_TLS_RANDOM.
+  ///
+  EfiTlsServerRandom,
+  ///
+  /// TLS session data key material.
+  /// The corresponding Data is of type EFI_TLS_MASTER_SECRET.
+  ///
+  EfiTlsKeyMaterial,
+
+  EfiTlsSessionDataTypeMaximum
+
+} EFI_TLS_SESSION_DATA_TYPE;
+
+///
+/// EFI_TLS_VERSION
+/// Note: The TLS version definition is from SSL3.0 to the latest TLS (e.g. 1.2).
+///       SSL2.0 is obsolete and should not be used.
+///
+typedef struct {
+  UINT8                         Major;
+  UINT8                         Minor;
+} EFI_TLS_VERSION;
+
+///
+/// EFI_TLS_CONNECTION_END to define TLS session as client or server.
+///
+typedef enum {
+  EfiTlsClient,
+  EfiTlsServer,
+} EFI_TLS_CONNECTION_END;
+
+///
+/// EFI_TLS_CIPHER
+/// Note: The definition of EFI_TLS_CIPHER definition is from "RFC 5246, A.4.1.
+///       Hello Messages". The value of EFI_TLS_CIPHER is from TLS Cipher
+///       Suite Registry of IANA.
+///
+typedef struct {
+  UINT8                         Data1;
+  UINT8                         Data2;
+} EFI_TLS_CIPHER;
+
+///
+/// EFI_TLS_COMPRESSION
+/// Note: The value of EFI_TLS_COMPRESSION definition is from "RFC 3749".
+///
+typedef UINT8 EFI_TLS_COMPRESSION;
+
+///
+/// EFI_TLS_EXTENSION
+/// Note: The definition of EFI_TLS_EXTENSION if from "RFC 5246 A.4.1.
+///       Hello Messages".
+///
+typedef struct {
+  UINT16                        ExtensionType;
+  UINT16                        Length;
+  UINT8                         Data[1];
+} EFI_TLS_EXTENSION;
+
+///
+/// EFI_TLS_VERIFY
+/// Use either EFI_TLS_VERIFY_NONE or EFI_TLS_VERIFY_PEER, the last two 
+options /// are 'ORed' with EFI_TLS_VERIFY_PEER if they are desired.
+///
+typedef UINT32  EFI_TLS_VERIFY;
+///
+/// No certificates will be sent or the TLS/SSLhandshake will be 
+continued regardless /// of the certificate verification result.
+///
+#define EFI_TLS_VERIFY_NONE                  0x0
+///
+/// The TLS/SSL handshake is immediately terminated with an alert 
+message containing /// the reason for the certificate verification failure.
+///
+#define EFI_TLS_VERIFY_PEER                  0x1
+///
+/// TLS session will fail peer certificate is absent.
+///
+#define EFI_TLS_VERIFY_FAIL_IF_NO_PEER_CERT  0x2 /// /// TLS session 
+only verify client once, and doesn't request cerfificate during /// 
+re-negotiation.
+///
+#define EFI_TLS_VERIFY_CLIENT_ONCE           0x4
+
+///
+/// EFI_TLS_RANDOM
+/// Note: The definition of EFI_TLS_RANDOM is from "RFC 5246 A.4.1.
+///       Hello Messages".
+///
+typedef struct {
+  UINT32                        GmtUnixTime;
+  UINT8                         RandomBytes[28];
+} EFI_TLS_RANDOM;
+
+///
+/// EFI_TLS_MASTER_SECRET
+/// Note: The definition of EFI_TLS_MASTER_SECRET is from "RFC 5246 8.1.
+///       Computing the Master Secret".
+///
+typedef struct {
+  UINT8                         Data[48];
+} EFI_TLS_MASTER_SECRET;
+
+///
+/// EFI_TLS_SESSION_ID
+/// Note: The definition of EFI_TLS_SESSION_ID is from "RFC 5246 A.4.1. Hello Messages".
+///
+#define MAX_TLS_SESSION_ID_LENGTH  32
+typedef struct {
+  UINT16                        Length;
+  UINT8                         Data[MAX_TLS_SESSION_ID_LENGTH];
+} EFI_TLS_SESSION_ID;
+
+///
+/// EFI_TLS_SESSION_STATE
+///
+typedef enum {
+  ///
+  /// When a new child of TLS protocol is created, the initial state of 
+TLS session
+  /// is EfiTlsSessionNotStarted.
+  ///
+  EfiTlsSessionNotStarted,
+  ///
+  /// The consumer can call BuildResponsePacket() with NULL to get 
+ClientHello to
+  /// start the TLS session. Then the status is EfiTlsSessionHandShaking.
+  ///
+  EfiTlsSessionHandShaking,
+  ///
+  /// During handshake, the consumer need call BuildResponsePacket() 
+with input
+  /// data from peer, then get response packet and send to peer. After 
+handshake
+  /// finish, the TLS session status becomes 
+EfiTlsSessionDataTransferring, and
+  /// consumer can use ProcessPacket() for data transferring.
+  ///
+  EfiTlsSessionDataTransferring,
+  ///
+  /// Finally, if consumer wants to active close TLS session, consumer 
+need
+  /// call SetSessionData to set TLS session state to 
+EfiTlsSessionClosing, and
+  /// call BuildResponsePacket() with NULL to get CloseNotify alert 
+message,
+  /// and sent it out.
+  ///
+  EfiTlsSessionClosing,
+  ///
+  /// If any error happen during parsing ApplicationData content type, 
+EFI_ABORT
+  /// will be returned by ProcessPacket(), and TLS session state will 
+become
+  /// EfiTlsSessionError. Then consumer need call BuildResponsePacket() 
+with
+  /// NULL to get alert message and sent it out.
+  ///
+  EfiTlsSessionError,
+
+  EfiTlsSessionStateMaximum
+
+} EFI_TLS_SESSION_STATE;
+
+///
+/// EFI_TLS_FRAGMENT_DATA
+///
+typedef struct {
+  ///
+  /// Length of data buffer in the fragment.
+  ///
+  UINT32                        FragmentLength;
+  ///
+  /// Pointer to the data buffer in the fragment.
+  ///
+  VOID                          *FragmentBuffer;
+} EFI_TLS_FRAGMENT_DATA;
+
+///
+/// EFI_TLS_CRYPT_MODE
+///
+typedef enum {
+  ///
+  /// Encrypt data provided in the fragment buffers.
+  ///
+  EfiTlsEncrypt,
+  ///
+  /// Decrypt data provided in the fragment buffers.
+  ///
+  EfiTlsDecrypt,
+} EFI_TLS_CRYPT_MODE;
+
+/**
+  Set TLS session data.
+
+  The SetSessionData() function set data for a new TLS session. All 
+ session data should  be set before BuildResponsePacket() invoked.
+
+  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]  DataType            TLS session data type.
+  @param[in]  Data                Pointer to session data.
+  @param[in]  DataSize            Total size of session data.
+
+  @retval EFI_SUCCESS             The TLS session data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
+                                  EfiTlsClientRandom
+                                  EfiTlsServerRandom
+                                  EfiTlsKeyMaterial
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionStateNotStarted.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_SET_SESSION_DATA) (
+  IN EFI_TLS_PROTOCOL                *This,
+  IN EFI_TLS_SESSION_DATA_TYPE       DataType,
+  IN VOID                            *Data,
+  IN UINTN                           DataSize
+  );
+
+/**
+  Get TLS session data.
+
+  The GetSessionData() function return the TLS session information.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       DataType       TLS session data type.
+  @param[in, out]  Data           Pointer to session data.
+  @param[in, out]  DataSize       Total size of session data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS session data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS session data is not found.
+  @retval EFI_NOT_READY           The DataType is not ready in current session state.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_GET_SESSION_DATA) (
+  IN EFI_TLS_PROTOCOL                *This,
+  IN EFI_TLS_SESSION_DATA_TYPE       DataType,
+  IN OUT VOID                        *Data,  OPTIONAL
+  IN OUT UINTN                       *DataSize
+  );
+
+/**
+  Build response packet according to TLS state machine. This function 
+is only valid for
+  alert, handshake and change_cipher_spec content type.
+
+  The BuildResponsePacket() function builds TLS response packet in 
+ response to the TLS  request packet specified by RequestBuffer and 
+ RequestSize. If RequestBuffer is NULL and  RequestSize is 0, and TLS 
+ session status is EfiTlsSessionNotStarted, the TLS session  will be 
+ initiated and the response packet needs to be ClientHello. If 
+ RequestBuffer is  NULL and RequestSize is 0, and TLS session status is 
+ EfiTlsSessionClosing, the TLS  session will be closed and response 
+ packet needs to be CloseNotify. If RequestBuffer is  NULL and 
+ RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS  session has errors and the response packet needs to be Alert message based on error  type.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in]       RequestBuffer  Pointer to the most recently received TLS packet. NULL
+                                  means TLS need initiate the TLS session and response
+                                  packet need to be ClientHello.
+  @param[in]       RequestSize    Packet size in bytes for the most recently received TLS
+                                  packet. 0 is only valid when RequestBuffer is NULL.
+  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  RequestBuffer is NULL but RequestSize is NOT 0.
+                                  RequestSize is 0 but RequestBuffer is NOT NULL.
+                                  BufferSize is NULL.
+                                  Buffer is NULL if *BufferSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.
+  @retval EFI_NOT_READY           Current TLS session state is NOT ready to build
+                                  ResponsePacket.
+  @retval EFI_ABORTED             Something wrong build response packet.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_BUILD_RESPONSE_PACKET) (
+  IN EFI_TLS_PROTOCOL                *This,
+  IN UINT8                           *RequestBuffer, OPTIONAL
+  IN UINTN                           RequestSize, OPTIONAL
+  OUT UINT8                          *Buffer, OPTIONAL
+  IN OUT UINTN                       *BufferSize
+  );
+
+/**
+  Decrypt or encrypt TLS packet during session. This function is only 
+valid after
+  session connected and for application_data content type.
+
+  The ProcessPacket () function process each inbound or outbound TLS APP packet.
+
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
+  @param[in, out]  FragmentTable  Pointer to a list of fragment. The caller will take
+                                  responsible to handle the original FragmentTable while
+                                  it may be reallocated in TLS driver. If CryptMode is
+                                  EfiTlsEncrypt, on input these fragments contain the TLS
+                                  header and plain text TLS APP payload; on output these
+                                  fragments contain the TLS header and cypher text TLS
+                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
+                                  these fragments contain the TLS header and cypher text
+                                  TLS APP payload; on output these fragments contain the
+                                  TLS header and plain text TLS APP payload.
+  @param[in]       FragmentCount  Number of fragment.
+  @param[in]       CryptMode      Crypt mode.
+
+  @retval EFI_SUCCESS             The operation completed successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  FragmentTable is NULL.
+                                  FragmentCount is NULL.
+                                  CryptoMode is invalid.
+  @retval EFI_NOT_READY           Current TLS session state is NOT
+                                  EfiTlsSessionDataTransferring.
+  @retval EFI_ABORTED             Something wrong decryption the message. TLS session
+                                  status will become EfiTlsSessionError. The caller need
+                                  call BuildResponsePacket() to generate Error Alert
+                                  message and send it out.
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the operation.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_PROCESS_PACKET) (
+  IN EFI_TLS_PROTOCOL                *This,
+  IN OUT EFI_TLS_FRAGMENT_DATA       **FragmentTable,
+  IN UINT32                          *FragmentCount,
+  IN EFI_TLS_CRYPT_MODE              CryptMode
+  );
+
+///
+/// The EFI_TLS_PROTOCOL is used to create, destroy and manage TLS session.
+/// For detail of TLS, please refer to TLS related RFC.
+///
+struct _EFI_TLS_PROTOCOL {
+  EFI_TLS_SET_SESSION_DATA           SetSessionData;
+  EFI_TLS_GET_SESSION_DATA           GetSessionData;
+  EFI_TLS_BUILD_RESPONSE_PACKET      BuildResponsePacket;
+  EFI_TLS_PROCESS_PACKET             ProcessPacket;
+};
+
+extern EFI_GUID gEfiTlsServiceBindingProtocolGuid;
+extern EFI_GUID gEfiTlsProtocolGuid;
+
+#endif  // __EFI_TLS_PROTOCOL_H__
diff --git a/MdePkg/Include/Protocol/TlsConfig.h b/MdePkg/Include/Protocol/TlsConfig.h
new file mode 100644
index 0000000..4b62bf5
--- /dev/null
+++ b/MdePkg/Include/Protocol/TlsConfig.h
@@ -0,0 +1,132 @@
+/** @file
+  EFI TLS Configuration Protocol as defined in UEFI 2.5.
+  The EFI TLS Configuration Protocol provides a way to set and get TLS configuration.
+
+  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.
+
+  @par Revision Reference:
+  This Protocol is introduced in UEFI Specification 2.5
+
+**/
+#ifndef __EFI_TLS_CONFIGURATION_PROTOCOL_H__
+#define __EFI_TLS_CONFIGURATION_PROTOCOL_H__
+
+///
+/// The EFI Configuration protocol provides a way to set and get TLS configuration.
+///
+#define EFI_TLS_CONFIGURATION_PROTOCOL_GUID  \
+  { \
+    0x1682fe44, 0xbd7a, 0x4407, { 0xb7, 0xc7, 0xdc, 0xa3, 0x7c, 0xa3, 
+0x92, 0x2d }  \
+  }
+
+typedef struct _EFI_TLS_CONFIGURATION_PROTOCOL 
+EFI_TLS_CONFIGURATION_PROTOCOL;
+
+///
+/// EFI_TLS_CONFIG_DATA_TYPE
+///
+typedef enum {
+  ///
+  /// Local host configuration data: public certificate data.
+  /// This data should be DER-encoded binaryX.509 certificate
+  /// or PEMencoded X.509 certificate.
+  ///
+  EfiTlsConfigDataTypeHostPublicCert,
+  ///
+  /// Local host configuration data: private key data.
+  ///
+  EfiTlsConfigDataTypeHostPrivateKey,
+  ///
+  /// CA certificate to verify peer. This data should be PEM-encoded
+  /// RSA or PKCS#8 private key.
+  ///
+  EfiTlsConfigDataTypeCACertificate,
+  ///
+  /// CA-supplied Certificate Revocation List data. This data should
+  /// be DER-encoded CRL data.
+  ///
+  EfiTlsConfigDataTypeCertRevocationList,
+
+  EfiTlsConfigDataTypeMaximum
+
+} EFI_TLS_CONFIG_DATA_TYPE;
+
+/**
+  Set TLS configuration data.
+
+  The SetData() function sets TLS configuration to non-volatile storage 
+ or volatile  storage.
+
+  @param[in]  This                Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]  DataType            Configuration data type.
+  @param[in]  Data                Pointer to configuration data.
+  @param[in]  DataSize            Total size of configuration data.
+
+  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  Data is NULL.
+                                  DataSize is 0.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_CONFIGURATION_SET_DATA)(
+  IN EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN VOID                            *Data,
+  IN UINTN                           DataSize
+  );
+
+/**
+  Get TLS configuration data.
+
+  The GetData() function gets TLS configuration.
+
+  @param[in]       This           Pointer to the EFI_TLS_CONFIGURATION_PROTOCOL instance.
+  @param[in]       DataType       Configuration data type.
+  @param[in, out]  Data           Pointer to configuration data.
+  @param[in, out]  DataSize       Total size of configuration data. On input, it means
+                                  the size of Data buffer. On output, it means the size
+                                  of copied Data buffer if EFI_SUCCESS, and means the
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
+
+  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  This is NULL.
+                                  DataSize is NULL.
+                                  Data is NULL if *DataSize is not zero.
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.
+  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_TLS_CONFIGURATION_GET_DATA)(
+  IN EFI_TLS_CONFIGURATION_PROTOCOL  *This,
+  IN EFI_TLS_CONFIG_DATA_TYPE        DataType,
+  IN OUT VOID                        *Data,  OPTIONAL
+  IN OUT UINTN                       *DataSize
+  );
+
+///
+/// The EFI_TLS_CONFIGURATION_PROTOCOL is designed to provide a way to 
+set and get /// TLS configuration, such as Certificate, private key data.
+///
+struct _EFI_TLS_CONFIGURATION_PROTOCOL {
+  EFI_TLS_CONFIGURATION_SET_DATA     SetData;
+  EFI_TLS_CONFIGURATION_GET_DATA     GetData;
+};
+
+extern EFI_GUID gEfiTlsConfigurationProtocolGuid;
+
+#endif  //__EFI_TLS_CONFIGURATION_PROTOCOL_H__
diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index 3e08bed..f2bdb30 100644
--- a/MdePkg/MdePkg.dec
+++ b/MdePkg/MdePkg.dec
@@ -1607,10 +1607,19 @@
   gEfiHttpProtocolGuid                 = { 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42, 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b }}
 
   ## Include/Protocol/HttpUtilities.h
   gEfiHttpUtilitiesProtocolGuid        = { 0x3e35c163, 0x4074, 0x45dd, {0x43, 0x1e, 0x23, 0x98, 0x9d, 0xd8, 0x6b, 0x32 }}
 
+  ## Include/Protocol/Tls.h
+  gEfiTlsServiceBindingProtocolGuid   = { 0x952cb795, 0xff36, 0x48cf, {0xa2, 0x49, 0x4d, 0xf4, 0x86, 0xd6, 0xab, 0x8d }}
+
+  ## Include/Protocol/Tls.h
+  gEfiTlsProtocolGuid                 = { 0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc, 0xe4, 0x6c, 0x47, 0x51, 0x43, 0x90 }}
+  
+  ## Include/Protocol/TlsConfig.h
+  gEfiTlsConfigurationProtocolGuid    = { 0x1682fe44, 0xbd7a, 0x4407, { 0xb7, 0xc7, 0xdc, 0xa3, 0x7c, 0xa3, 0x92, 0x2d }}
+
   ## Include/Protocol/Rest.h
   gEfiRestProtocolGuid                 =  { 0x0db48a36, 0x4e54, 0xea9c, {0x9b, 0x09, 0x1e, 0xa5, 0xbe, 0x3a, 0x66, 0x0b }}
 
   ## Include/Protocol/Supplicant.h
   gEfiSupplicantServiceBindingProtocolGuid  = { 0x45bcd98e, 0x59ad, 0x4174, { 0x95, 0x46, 0x34, 0x4a, 0x7, 0x48, 0x58, 0x98 }}
--
1.9.5.msysgit.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 02/10] MdePkg: Add a header to standardize TLS definitions
  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
  2 siblings, 0 replies; 37+ messages in thread
From: Fu, Siyuan @ 2016-12-14  8:43 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Long, Qin, Ye, Ting, Zhang,  Lubo, Gao, Liming, Kinney, Michael D,
	Thomas Palmer

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: Long, Qin <qin.long@intel.com>; Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>; Wu, Jiaxin <jiaxin.wu@intel.com>
Subject: [Patch 02/10] MdePkg: Add a header to standardize TLS definitions

This path is used to standardize TLS definitions from related RFCs. Including TLS Cipher Suites, TLS Version, TLS Content Type and TLS Record Header, etc.

Cc: Long Qin <qin.long@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@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>
---
 MdePkg/Include/IndustryStandard/Tls1.h | 93 ++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 MdePkg/Include/IndustryStandard/Tls1.h

diff --git a/MdePkg/Include/IndustryStandard/Tls1.h b/MdePkg/Include/IndustryStandard/Tls1.h
new file mode 100644
index 0000000..14eb265
--- /dev/null
+++ b/MdePkg/Include/IndustryStandard/Tls1.h
@@ -0,0 +1,93 @@
+/** @file
+  Transport Layer Security  -- TLS 1.0/1.1/1.2 Standard definitions, from RFC 2246/4346/5246    
+
+  This file contains common TLS 1.0/1.1/1.2 definitions from RFC 
+ 2246/4346/5246
+
+  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 __TLS_1_H__
+#define __TLS_1_H__
+
+#pragma pack(1)
+
+///
+/// TLS Cipher Suite, refers to A.5 of rfc-2246, rfc-4346 and rfc-5246.
+///
+#define TLS_RSA_WITH_NULL_MD5                    {0x00, 0x01}
+#define TLS_RSA_WITH_NULL_SHA                    {0x00, 0x02}
+#define TLS_RSA_WITH_RC4_128_MD5                 {0x00, 0x04}
+#define TLS_RSA_WITH_RC4_128_SHA                 {0x00, 0x05}
+#define TLS_RSA_WITH_IDEA_CBC_SHA                {0x00, 0x07}
+#define TLS_RSA_WITH_DES_CBC_SHA                 {0x00, 0x09}
+#define TLS_RSA_WITH_3DES_EDE_CBC_SHA            {0x00, 0x0A}
+#define TLS_DH_DSS_WITH_DES_CBC_SHA              {0x00, 0x0C}
+#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA         {0x00, 0x0D}
+#define TLS_DH_RSA_WITH_DES_CBC_SHA              {0x00, 0x0F}
+#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA         {0x00, 0x10}
+#define TLS_DHE_DSS_WITH_DES_CBC_SHA             {0x00, 0x12}
+#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA        {0x00, 0x13}
+#define TLS_DHE_RSA_WITH_DES_CBC_SHA             {0x00, 0x15}
+#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA        {0x00, 0x16}
+#define TLS_RSA_WITH_AES_128_CBC_SHA             {0x00, 0x2F}
+#define TLS_DH_DSS_WITH_AES_128_CBC_SHA          {0x00, 0x30}
+#define TLS_DH_RSA_WITH_AES_128_CBC_SHA          {0x00, 0x31}
+#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA         {0x00, 0x32}
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA         {0x00, 0x33}
+#define TLS_RSA_WITH_AES_256_CBC_SHA             {0x00, 0x35}
+#define TLS_DH_DSS_WITH_AES_256_CBC_SHA          {0x00, 0x36}
+#define TLS_DH_RSA_WITH_AES_256_CBC_SHA          {0x00, 0x37}
+#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA         {0x00, 0x38}
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA         {0x00, 0x39}
+#define TLS_RSA_WITH_NULL_SHA256                 {0x00, 0x3B}
+#define TLS_RSA_WITH_AES_128_CBC_SHA256          {0x00, 0x3C}
+#define TLS_RSA_WITH_AES_256_CBC_SHA256          {0x00, 0x3D}
+#define TLS_DH_DSS_WITH_AES_128_CBC_SHA256       {0x00, 0x3E}
+#define TLS_DH_RSA_WITH_AES_128_CBC_SHA256       {0x00, 0x3F}
+#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA256      {0x00, 0x40}
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256      {0x00, 0x67}
+#define TLS_DH_DSS_WITH_AES_256_CBC_SHA256       {0x00, 0x68}
+#define TLS_DH_RSA_WITH_AES_256_CBC_SHA256       {0x00, 0x69}
+#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA256      {0x00, 0x6A}
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256      {0x00, 0x6B}
+
+///
+/// TLS Version, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
+///
+#define TLS10_PROTOCOL_VERSION_MAJOR  0x03 #define 
+TLS10_PROTOCOL_VERSION_MINOR  0x01 #define TLS11_PROTOCOL_VERSION_MAJOR  
+0x03 #define TLS11_PROTOCOL_VERSION_MINOR  0x02 #define 
+TLS12_PROTOCOL_VERSION_MAJOR  0x03 #define TLS12_PROTOCOL_VERSION_MINOR  
+0x03
+
+///
+/// TLS Content Type, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
+///
+typedef enum {
+  TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20,
+  TLS_CONTENT_TYPE_ALERT              = 21,
+  TLS_CONTENT_TYPE_HANDSHAKE          = 22,
+  TLS_CONTENT_TYPE_APPLICATION_DATA   = 23,
+} TLS_CONTENT_TYPE;
+
+///
+/// TLS Record Header, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
+///
+typedef struct {   
+  UINT8                   ContentType;
+  EFI_TLS_VERSION         Version;
+  UINT16                  Length;
+} TLS_RECORD_HEADER;
+
+#pragma pack()
+
+#endif
+
--
1.9.5.msysgit.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration
  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
  0 siblings, 1 reply; 37+ messages in thread
From: Fu, Siyuan @ 2016-12-15  2:22 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Ye, Ting, Zhang, Lubo, Long, Qin, Thomas Palmer

Hi, Jiaxin

PrintLib support "%g" to print a GUID so you don't need to use "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" in GuidToString(). 
Beside of that, I do see a lot of drivers has similar internal function StringToGuid() or StrToGuid(), do we have a common library interface for this? if not I think it may worth to create one.

Other parts are good with me.
Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>


Best Regards
Siyuan

-----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 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration

This patch provides the UI to support TLS auth configuration.
* EFI_SIGNATURE_LIST format is used for 'TlsCaCertificate'
variable. So, TLS supports multiple certificate configuration.
* The variable attribute is BS with NV, which only target at
preventing runtime phase attack.

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/Include/Guid/TlsAuthConfigHii.h         |   25 +
 NetworkPkg/Include/Guid/TlsAuthentication.h        |   29 +
 NetworkPkg/NetworkPkg.dec                          |    7 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c     |  135 ++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf   |   73 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni   |   21 +
 .../TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni     |   19 +
 .../TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni   |   39 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c    | 1841 ++++++++++++++++++++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h    |  282 +++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h  |   49 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr   |  152 ++
 12 files changed, 2672 insertions(+)
 create mode 100644 NetworkPkg/Include/Guid/TlsAuthConfigHii.h
 create mode 100644 NetworkPkg/Include/Guid/TlsAuthentication.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr

diff --git a/NetworkPkg/Include/Guid/TlsAuthConfigHii.h b/NetworkPkg/Include/Guid/TlsAuthConfigHii.h
new file mode 100644
index 0000000..9d21426
--- /dev/null
+++ b/NetworkPkg/Include/Guid/TlsAuthConfigHii.h
@@ -0,0 +1,25 @@
+/** @file
+  GUIDs used as HII FormSet and HII Package list GUID in TlsAuthConfigDxe 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 that 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 __TLS_AUTH_CONFIG_HII_GUID_H__
+#define __TLS_AUTH_CONFIG_HII_GUID_H__
+
+#define TLS_AUTH_CONFIG_GUID \
+  { \
+    0xb0eae4f8, 0x9a04, 0x4c6d, { 0xa7, 0x48, 0x79, 0x3d, 0xaa, 0xf, 0x65, 0xdf } \
+  }
+
+extern EFI_GUID gTlsAuthConfigGuid;
+
+#endif
diff --git a/NetworkPkg/Include/Guid/TlsAuthentication.h b/NetworkPkg/Include/Guid/TlsAuthentication.h
new file mode 100644
index 0000000..2e800dc
--- /dev/null
+++ b/NetworkPkg/Include/Guid/TlsAuthentication.h
@@ -0,0 +1,29 @@
+/** @file
+  This file defines TlsCaCertificate variable.
+  
+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 that 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 __TLS_AUTHENTICATION_H__
+#define __TLS_AUTHENTICATION_H__
+
+// Private variable for CA Certificate configuration
+//
+#define EFI_TLS_CA_CERTIFICATE_GUID \
+  { \
+    0xfd2340D0, 0x3dab, 0x4349, { 0xa6, 0xc7, 0x3b, 0x4f, 0x12, 0xb4, 0x8e, 0xae } \
+  }
+
+#define EFI_TLS_CA_CERTIFICATE_VARIABLE       L"TlsCaCertificate"
+
+extern EFI_GUID gEfiTlsCaCertificateGuid;
+
+#endif
diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec
index 268188a..24d45f4 100644
--- a/NetworkPkg/NetworkPkg.dec
+++ b/NetworkPkg/NetworkPkg.dec
@@ -38,10 +38,17 @@
   gIScsiConfigGuid              = { 0x4b47d616, 0xa8d6, 0x4552, { 0x9d, 0x44, 0xcc, 0xad, 0x2e, 0xf, 0x4c, 0xf9}}
 
   # Include/Guid/HttpBootConfigHii.h
   gHttpBootConfigGuid           = { 0x4d20583a, 0x7765, 0x4e7a, { 0x8a, 0x67, 0xdc, 0xde, 0x74, 0xee, 0x3e, 0xc5 }}
 
+  # Include/Guid/TlsAuthConfigHii.h
+  gTlsAuthConfigGuid            = { 0xb0eae4f8, 0x9a04, 0x4c6d, { 0xa7, 0x48, 0x79, 0x3d, 0xaa, 0xf, 0x65, 0xdf }}
+  
+  # Include/Guid/TlsAuthentication.h
+  gEfiTlsCaCertificateGuid      = { 0xfd2340D0, 0x3dab, 0x4349, { 0xa6, 0xc7, 0x3b, 0x4f, 0x12, 0xb4, 0x8e, 0xae }}
+  
+
 [PcdsFeatureFlag]
   ## Indicates if the IPsec IKEv2 Certificate Authentication feature is enabled or not.<BR><BR>
   #   TRUE  - Certificate Authentication feature is enabled.<BR>
   #   FALSE - Does not support Certificate Authentication.<BR>
   # @Prompt Enable IPsec IKEv2 Certificate Authentication.
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
new file mode 100644
index 0000000..647bc2f
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
@@ -0,0 +1,135 @@
+/** @file
+  The DriverEntryPoint for TlsAuthConfigDxe 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.
+
+**/
+
+#include "TlsAuthConfigImpl.h"
+
+/**
+  Unloads an image.
+
+  @param  ImageHandle           Handle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS 
+EFIAPI
+TlsAuthConfigDxeUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS                     Status;
+  TLS_AUTH_CONFIG_PRIVATE_DATA   *PrivateData;
+
+  Status = gBS->HandleProtocol (
+                  ImageHandle,
+                  &gEfiCallerIdGuid,
+                  (VOID **) &PrivateData
+                  );  
+  if (EFI_ERROR (Status)) {
+    return Status;  
+  }
+  
+  ASSERT (PrivateData->Signature == TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE);
+
+  gBS->UninstallMultipleProtocolInterfaces (
+         &ImageHandle,
+         &gEfiCallerIdGuid,
+         PrivateData,
+         NULL
+         );
+  
+  TlsAuthConfigFormUnload (PrivateData);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigDxeDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  TLS_AUTH_CONFIG_PRIVATE_DATA   *PrivateData;
+
+  PrivateData = NULL;
+  
+  //
+  // If already started, return.
+  //
+  Status = gBS->OpenProtocol (
+                  ImageHandle,
+                  &gEfiCallerIdGuid,
+                  NULL,
+                  ImageHandle,
+                  ImageHandle,
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                  );
+  if (!EFI_ERROR (Status)) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  //
+  // Initialize the private data structure.
+  //
+  PrivateData = AllocateZeroPool (sizeof (TLS_AUTH_CONFIG_PRIVATE_DATA));
+  if (PrivateData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize the HII configuration form.
+  //
+  Status = TlsAuthConfigFormInit (PrivateData);
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  //
+  // Install private GUID.
+  //    
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &ImageHandle,
+                  &gEfiCallerIdGuid,
+                  PrivateData,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+  
+  return EFI_SUCCESS;
+
+ON_ERROR:
+  TlsAuthConfigFormUnload (PrivateData);
+  FreePool (PrivateData);
+
+  return Status;
+}
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
new file mode 100644
index 0000000..19f095e
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
@@ -0,0 +1,73 @@
+## @file
+#  Provides the capability to configure Tls Authentication in a setup browser
+#  By this module, user may change the content of TlsCaCertificate.
+#
+# 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.
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = TlsAuthConfigDxe
+  MODULE_UNI_FILE           = TlsAuthConfigDxe.uni
+  FILE_GUID                 = 7ca1024f-eb17-11e5-9dba-28d2447c4829
+  MODULE_TYPE               = DXE_DRIVER
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = TlsAuthConfigDxeDriverEntryPoint
+  UNLOAD_IMAGE              = TlsAuthConfigDxeUnload
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+  
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  NetworkPkg/NetworkPkg.dec
+
+[Sources]
+  TlsAuthConfigImpl.c
+  TlsAuthConfigImpl.h
+  TlsAuthConfigNvData.h
+  TlsAuthConfigDxe.c
+  TlsAuthConfigDxeStrings.uni
+  TlsAuthConfigVfr.vfr
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  UefiLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+  DebugLib
+  HiiLib
+  DevicePathLib
+  UefiHiiServicesLib
+  FileExplorerLib
+  PrintLib
+  
+[Protocols]
+  gEfiDevicePathProtocolGuid                    ## PRODUCES
+  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
+  gEfiSimpleFileSystemProtocolGuid              ## SOMETIMES_CONSUMES
+
+[Guids]
+  gTlsAuthConfigGuid                            ## PRODUCES  ## GUID
+  gEfiCertX509Guid                              ## CONSUMES  ## GUID  # Indicate the cert type
+  gEfiIfrTianoGuid                              ## CONSUMES  ## HII
+  gEfiTlsCaCertificateGuid                      ## PRODUCES  ## GUID
+
+[Depex]
+  gEfiHiiConfigRoutingProtocolGuid  AND
+  gEfiHiiDatabaseProtocolGuid
+  
+[UserExtensions.TianoCore."ExtraFiles"]
+  TlsAuthConfigDxeExtra.uni
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
new file mode 100644
index 0000000..f99a14f
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
@@ -0,0 +1,21 @@
+// /** @file
+// Provides the capability to configure Tls Authentication in a setup browser
+//
+// By this module, user may change the content of TlsCaCertificate.
+//
+// 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.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Provides the capability to configure Tls Authentication in a setup browser"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "By this module, user may change the content of TlsCaCertificate."
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
new file mode 100644
index 0000000..ee4c49f
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
@@ -0,0 +1,19 @@
+// /** @file
+// TlsAuthConfigDxe Localized Strings and Content
+//
+// 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.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME 
+#language en-US 
+"TLS Auth Config DXE"
+
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
new file mode 100644
index 0000000..a8f7e43
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
@@ -0,0 +1,39 @@
+/** @file
+  String definitions for Tls Authentication Configuration form.
+
+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.
+
+**/
+
+#langdef en-US "English"
+
+#string STR_TLS_AUTH_CONFIG_TITLE                    #language en-US "Tls Auth Configuration"
+#string STR_TLS_AUTH_CONFIG_HELP                     #language en-US "Press <Enter> to select Tls Auth Configuration."
+
+#string STR_TLS_AUTH_CONFIG_SERVER_CA         		 #language en-US "Server CA Configuration"
+#string STR_TLS_AUTH_CONFIG_SERVER_CA_HELP    		 #language en-US "Press <Enter> to configure Server CA."
+#string STR_TLS_AUTH_CONFIG_CLIENT_CERT         	 #language en-US "Client Cert Configuration"
+#string STR_TLS_AUTH_CONFIG_CLIENT_CERT_HELP    	 #language en-US "Client cert configuration is unsupported currently."
+
+#string STR_TLS_AUTH_CONFIG_ENROLL_CERT              #language en-US "Enroll Cert"    
+#string STR_TLS_AUTH_CONFIG_ENROLL_CERT_HELP         #language en-US "Press <Enter> to enroll cert."
+#string STR_TLS_AUTH_CONFIG_DELETE_CERT              #language en-US "Delete Cert"    
+#string STR_TLS_AUTH_CONFIG_DELETE_CERT_HELP         #language en-US "Press <Enter> to delete cert."
+
+#string STR_TLS_AUTH_CONFIG_ADD_CERT_FILE            #language en-US "Enroll Cert Using File"
+
+#string STR_TLS_AUTH_CONFIG_CERT_GUID                #language en-US "Cert GUID"
+#string STR_TLS_AUTH_CONFIG_CERT_GUID_HELP           #language en-US "Input digit character in 11111111-2222-3333-4444-1234567890ab format."
+#string STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT            #language en-US "Commit Changes and Exit"
+#string STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT         #language en-US "Discard Changes and Exit"
+
+#string STR_CERT_TYPE_PCKS_GUID                      #language en-US "GUID for CERT"
+
+#string STR_NULL                                     #language en-US ""
\ No newline at end of file
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
new file mode 100644
index 0000000..1132cac
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
@@ -0,0 +1,1841 @@
+/** @file
+  The Miscellaneous Routines for TlsAuthConfigDxe 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.
+
+**/
+
+#include "TlsAuthConfigImpl.h"
+
+VOID                    *mStartOpCodeHandle = NULL;
+VOID                    *mEndOpCodeHandle   = NULL;
+EFI_IFR_GUID_LABEL      *mStartLabel        = NULL;
+EFI_IFR_GUID_LABEL      *mEndLabel          = NULL;
+
+
+CHAR16                  mTlsAuthConfigStorageName[] = L"TLS_AUTH_CONFIG_IFR_NVDATA";
+
+TLS_AUTH_CONFIG_PRIVATE_DATA      *mTlsAuthPrivateData = NULL;
+
+HII_VENDOR_DEVICE_PATH  mTlsAuthConfigHiiVendorDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    TLS_AUTH_CONFIG_GUID
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      (UINT8) (END_DEVICE_PATH_LENGTH),
+      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+    }
+  }
+};
+
+//
+// Possible DER-encoded certificate file suffixes, end with NULL pointer.
+//
+CHAR16* mDerPemEncodedSuffix[] = {
+  L".cer",
+  L".der",
+  L".crt",
+  L".pem",
+  NULL
+};
+
+/**
+  This code checks if the FileSuffix is one of the possible DER/PEM-encoded certificate suffix.
+
+  @param[in] FileSuffix            The suffix of the input certificate file
+
+  @retval    TRUE           It's a DER/PEM-encoded certificate.
+  @retval    FALSE          It's NOT a DER/PEM-encoded certificate.
+
+**/
+BOOLEAN
+IsDerPemEncodeCertificate (
+  IN CONST CHAR16         *FileSuffix
+)
+{
+  UINTN     Index;
+  for (Index = 0; mDerPemEncodedSuffix[Index] != NULL; Index++) {
+    if (StrCmp (FileSuffix, mDerPemEncodedSuffix[Index]) == 0) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+  Worker function that prints an EFI_GUID into specified Buffer.
+
+  @param[in]     Guid          Pointer to GUID to print.
+  @param[in]     Buffer        Buffer to print Guid into.
+  @param[in]     BufferSize    Size of Buffer.
+  
+  @retval    Number of characters printed.
+
+**/
+UINTN
+GuidToString (
+  IN  EFI_GUID  *Guid,
+  IN  CHAR16    *Buffer,
+  IN  UINTN     BufferSize
+  )
+{
+  UINTN Size;
+
+  Size = UnicodeSPrint (
+            Buffer,
+            BufferSize, 
+            L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+            (UINTN)Guid->Data1,                    
+            (UINTN)Guid->Data2,
+            (UINTN)Guid->Data3,
+            (UINTN)Guid->Data4[0],
+            (UINTN)Guid->Data4[1],
+            (UINTN)Guid->Data4[2],
+            (UINTN)Guid->Data4[3],
+            (UINTN)Guid->Data4[4],
+            (UINTN)Guid->Data4[5],
+            (UINTN)Guid->Data4[6],
+            (UINTN)Guid->Data4[7]
+            );
+
+  //
+  // SPrint will null terminate the string. The -1 skips the null
+  //
+  return Size - 1;
+}
+
+/**
+  Convert a String to Guid Value.
+
+  @param[in]   Str        Specifies the String to be converted.
+  @param[in]   StrLen     Number of Unicode Characters of String (exclusive \0)
+  @param[out]  Guid       Return the result Guid value.
+
+  @retval    EFI_SUCCESS           The operation is finished successfully.
+  @retval    EFI_NOT_FOUND         Invalid string.
+
+**/
+EFI_STATUS
+StringToGuid (
+  IN   CHAR16           *Str, 
+  IN   UINTN            StrLen, 
+  OUT  EFI_GUID         *Guid
+  )
+{
+  CHAR16             *PtrBuffer;
+  CHAR16             *PtrPosition;
+  UINT16             *Buffer;
+  UINTN              Data;
+  UINTN              Index;
+  UINT16             Digits[3];
+
+  Buffer = (CHAR16 *) AllocateZeroPool (sizeof (CHAR16) * (StrLen + 1));
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  StrCpyS (Buffer, (StrLen + 1), Str);
+
+  //
+  // Data1
+  //
+  PtrBuffer       = Buffer;
+  PtrPosition     = PtrBuffer; 
+  while (*PtrBuffer != L'\0') {
+    if (*PtrBuffer == L'-') {
+      break;
+    }
+    PtrBuffer++;
+  }
+  if (*PtrBuffer == L'\0') {
+    FreePool (Buffer);
+    return EFI_NOT_FOUND;
+  }
+
+  *PtrBuffer      = L'\0';
+  Data            = StrHexToUintn (PtrPosition);
+  Guid->Data1     = (UINT32)Data;
+
+  //
+  // Data2
+  //
+  PtrBuffer++;
+  PtrPosition     = PtrBuffer;
+  while (*PtrBuffer != L'\0') {
+    if (*PtrBuffer == L'-') {
+      break;
+    }
+    PtrBuffer++;
+  }
+  if (*PtrBuffer == L'\0') {
+    FreePool (Buffer);
+    return EFI_NOT_FOUND;
+  }
+  *PtrBuffer      = L'\0';
+  Data            = StrHexToUintn (PtrPosition);
+  Guid->Data2     = (UINT16)Data;
+
+  //
+  // Data3
+  //
+  PtrBuffer++;
+  PtrPosition     = PtrBuffer;
+  while (*PtrBuffer != L'\0') {
+    if (*PtrBuffer == L'-') {
+      break;
+    }
+    PtrBuffer++;
+  }
+  if (*PtrBuffer == L'\0') {
+    FreePool (Buffer);
+    return EFI_NOT_FOUND;
+  }
+  *PtrBuffer      = L'\0';
+  Data            = StrHexToUintn (PtrPosition);
+  Guid->Data3     = (UINT16)Data;
+
+  //
+  // Data4[0..1]
+  //
+  for ( Index = 0 ; Index < 2 ; Index++) {
+    PtrBuffer++;
+    if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {
+      FreePool (Buffer);
+      return EFI_NOT_FOUND;
+    }
+    Digits[0]     = *PtrBuffer;
+    PtrBuffer++;
+    Digits[1]     = *PtrBuffer;
+    Digits[2]     = L'\0';
+    Data          = StrHexToUintn (Digits);
+    Guid->Data4[Index] = (UINT8)Data;
+  }
+
+  //
+  // skip the '-'
+  //
+  PtrBuffer++;
+  if ((*PtrBuffer != L'-' ) || ( *PtrBuffer == L'\0')) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Data4[2..7]
+  //
+  for ( ; Index < 8; Index++) {
+    PtrBuffer++;
+    if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {
+      FreePool (Buffer);
+      return EFI_NOT_FOUND;
+    }
+    Digits[0]     = *PtrBuffer;
+    PtrBuffer++;
+    Digits[1]     = *PtrBuffer;
+    Digits[2]     = L'\0';
+    Data          = StrHexToUintn (Digits);
+    Guid->Data4[Index] = (UINT8)Data;
+  }
+
+  FreePool (Buffer);
+  
+  return EFI_SUCCESS;
+}
+
+
+/**
+  List all cert in specified database by GUID in the page 
+  for user to select and delete as needed.
+
+  @param[in]    PrivateData         Module's private data.
+  @param[in]    VariableName        The variable name of the vendor's signature database.
+  @param[in]    VendorGuid          A unique identifier for the vendor.
+  @param[in]    LabelNumber         Label number to insert opcodes.
+  @param[in]    FormId              Form ID of current page.
+  @param[in]    QuestionIdBase      Base question id of the signature list.
+
+  @retval   EFI_SUCCESS             Success to update the signature list page
+  @retval   EFI_OUT_OF_RESOURCES    Unable to allocate required resources.
+
+**/
+EFI_STATUS
+UpdateDeletePage (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private,
+  IN CHAR16                           *VariableName,
+  IN EFI_GUID                         *VendorGuid,
+  IN UINT16                           LabelNumber,
+  IN EFI_FORM_ID                      FormId,
+  IN EFI_QUESTION_ID                  QuestionIdBase
+  )
+{
+  EFI_STATUS                  Status;
+  UINT32                      Index;
+  UINTN                       CertCount;
+  UINTN                       GuidIndex;
+  VOID                        *StartOpCodeHandle;
+  VOID                        *EndOpCodeHandle;
+  EFI_IFR_GUID_LABEL          *StartLabel;
+  EFI_IFR_GUID_LABEL          *EndLabel;
+  UINTN                       DataSize;
+  UINT8                       *Data;
+  EFI_SIGNATURE_LIST          *CertList;
+  EFI_SIGNATURE_DATA          *Cert;
+  UINT32                      ItemDataSize;
+  CHAR16                      *GuidStr;
+  EFI_STRING_ID               GuidID;
+  EFI_STRING_ID               Help;
+
+  Data     = NULL;
+  CertList = NULL;
+  Cert     = NULL;
+  GuidStr  = NULL;
+  StartOpCodeHandle = NULL;
+  EndOpCodeHandle   = NULL;
+
+  //
+  // Initialize the container for dynamic opcodes.
+  //
+  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (StartOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (EndOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Create Hii Extend Label OpCode.
+  //
+  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                        StartOpCodeHandle,
+                                        &gEfiIfrTianoGuid,
+                                        NULL,
+                                        sizeof (EFI_IFR_GUID_LABEL)
+                                        );
+  StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
+  StartLabel->Number        = LabelNumber;
+
+  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                      EndOpCodeHandle,
+                                      &gEfiIfrTianoGuid,
+                                      NULL,
+                                      sizeof (EFI_IFR_GUID_LABEL)
+                                      );
+  EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
+  EndLabel->Number        = LABEL_END;
+
+  //
+  // Read Variable.
+  //
+  DataSize = 0;
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+    goto ON_EXIT;
+  }
+
+  Data = (UINT8 *) AllocateZeroPool (DataSize);
+  if (Data == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  GuidStr = AllocateZeroPool (100);
+  if (GuidStr == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Enumerate all data.
+  //
+  ItemDataSize = (UINT32) DataSize;
+  CertList = (EFI_SIGNATURE_LIST *) Data;
+  GuidIndex = 0;
+
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
+      Help = STRING_TOKEN (STR_CERT_TYPE_PCKS_GUID);
+    } else {
+      //
+      // The signature type is not supported in current implementation.
+      //
+      ItemDataSize -= CertList->SignatureListSize;
+      CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+      continue;
+    }
+
+    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+    for (Index = 0; Index < CertCount; Index++) {
+      Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList
+                                              + sizeof (EFI_SIGNATURE_LIST)
+                                              + CertList->SignatureHeaderSize
+                                              + Index * CertList->SignatureSize);
+      //
+      // Display GUID and help
+      //
+      GuidToString (&Cert->SignatureOwner, GuidStr, 100);
+      GuidID  = HiiSetString (Private->RegisteredHandle, 0, GuidStr, NULL);
+      HiiCreateCheckBoxOpCode (
+        StartOpCodeHandle,
+        (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),
+        0,
+        0,
+        GuidID,
+        Help,
+        EFI_IFR_FLAG_CALLBACK,
+        0,
+        NULL
+        );
+    }
+
+    ItemDataSize -= CertList->SignatureListSize;
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+  }
+
+ON_EXIT:
+  HiiUpdateForm (
+    Private->RegisteredHandle,
+    &gTlsAuthConfigGuid,
+    FormId,
+    StartOpCodeHandle,
+    EndOpCodeHandle
+    );
+
+  if (StartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (StartOpCodeHandle);
+  }
+
+  if (EndOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (EndOpCodeHandle);
+  }
+
+  if (Data != NULL) {
+    FreePool (Data);
+  }
+
+  if (GuidStr != NULL) {
+    FreePool (GuidStr);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Delete one entry from cert database.
+
+  @param[in]    PrivateData         Module's private data.
+  @param[in]    VariableName        The variable name of the database.
+  @param[in]    VendorGuid          A unique identifier for the vendor.
+  @param[in]    LabelNumber         Label number to insert opcodes.
+  @param[in]    FormId              Form ID of current page.
+  @param[in]    QuestionIdBase      Base question id of the cert list.
+  @param[in]    DeleteIndex         Cert index to delete.
+
+  @retval   EFI_SUCCESS             Delete siganture successfully.
+  @retval   EFI_NOT_FOUND           Can't find the signature item,
+  @retval   EFI_OUT_OF_RESOURCES    Could not allocate needed resources.
+**/
+EFI_STATUS
+DeleteCert (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private,
+  IN CHAR16                           *VariableName,
+  IN EFI_GUID                         *VendorGuid,
+  IN UINT16                           LabelNumber,
+  IN EFI_FORM_ID                      FormId,
+  IN EFI_QUESTION_ID                  QuestionIdBase,
+  IN UINTN                            DeleteIndex
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       DataSize;
+  UINT8                       *Data;
+  UINT8                       *OldData;
+  UINT32                      Attr;
+  UINT32                      Index;
+  EFI_SIGNATURE_LIST          *CertList;
+  EFI_SIGNATURE_LIST          *NewCertList;
+  EFI_SIGNATURE_DATA          *Cert;
+  UINTN                       CertCount;
+  UINT32                      Offset;
+  BOOLEAN                     IsItemFound;
+  UINT32                      ItemDataSize;
+  UINTN                       GuidIndex;
+
+  Data            = NULL;
+  OldData         = NULL;
+  CertList        = NULL;
+  Cert            = NULL;
+  Attr            = 0;
+
+  //
+  // Get original signature list data.
+  //
+  DataSize = 0;
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+    goto ON_EXIT;
+  }
+
+  OldData = (UINT8 *) AllocateZeroPool (DataSize);
+  if (OldData == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);
+  if (EFI_ERROR(Status)) {
+    goto ON_EXIT;
+  }
+
+  //
+  // Allocate space for new variable.
+  //
+  Data = (UINT8*) AllocateZeroPool (DataSize);
+  if (Data == NULL) {
+    Status  =  EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Enumerate all data and erasing the target item.
+  //
+  IsItemFound = FALSE;
+  ItemDataSize = (UINT32) DataSize;
+  CertList = (EFI_SIGNATURE_LIST *) OldData;
+  Offset = 0;
+  GuidIndex = 0;
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
+      //
+      // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
+      //
+      CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
+      NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);
+      Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+      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++) {
+        if (GuidIndex == DeleteIndex) {
+          //
+          // Find it! Skip it!
+          //
+          NewCertList->SignatureListSize -= CertList->SignatureSize;
+          IsItemFound = TRUE;
+        } else {
+          //
+          // This item doesn't match. Copy it to the Data buffer.
+          //
+          CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);
+          Offset += CertList->SignatureSize;
+        }
+        GuidIndex++;
+        Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
+      }
+    } else {
+      //
+      // This List doesn't match. Just copy it to the Data buffer.
+      //
+      CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
+      Offset += CertList->SignatureListSize;
+    }
+
+    ItemDataSize -= CertList->SignatureListSize;
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+  }
+
+  if (!IsItemFound) {
+    //
+    // Doesn't find the signature Item!
+    //
+    Status = EFI_NOT_FOUND;
+    goto ON_EXIT;
+  }
+
+  //
+  // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
+  //
+  ItemDataSize = Offset;
+  CertList = (EFI_SIGNATURE_LIST *) Data;
+  Offset = 0;
+  ZeroMem (OldData, ItemDataSize);
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+    DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));
+    if (CertCount != 0) {
+      CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
+      Offset += CertList->SignatureListSize;
+    }
+    ItemDataSize -= CertList->SignatureListSize;
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+  }
+
+  DataSize = Offset;
+
+  Status = gRT->SetVariable(
+                  VariableName,
+                  VendorGuid,
+                  Attr,
+                  DataSize,
+                  OldData
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+  if (Data != NULL) {
+    FreePool(Data);
+  }
+
+  if (OldData != NULL) {
+    FreePool(OldData);
+  }
+
+  return UpdateDeletePage (
+           Private,
+           VariableName,
+           VendorGuid,
+           LabelNumber,
+           FormId,
+           QuestionIdBase
+           );
+}
+
+
+/**
+  Close an open file handle.
+
+  @param[in] FileHandle           The file handle to close.
+  
+**/
+VOID
+CloseFile (
+  IN EFI_FILE_HANDLE   FileHandle
+  )
+{
+  if (FileHandle != NULL) {
+    FileHandle->Close (FileHandle);  
+  }
+}
+
+/**
+  Read file content into BufferPtr, the size of the allocate buffer 
+  is *FileSize plus AddtionAllocateSize.
+
+  @param[in]       FileHandle            The file to be read.
+  @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.
+  @param[out]      FileSize              Size of input file
+  @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated. 
+                                         In case the buffer need to contain others besides the file content.
+  
+  @retval   EFI_SUCCESS                  The file was read into the buffer.
+  @retval   EFI_INVALID_PARAMETER        A parameter was invalid.
+  @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.
+  @retval   others                       Unexpected error.
+
+**/
+EFI_STATUS
+ReadFileContent (
+  IN      EFI_FILE_HANDLE           FileHandle,
+  IN OUT  VOID                      **BufferPtr,
+     OUT  UINTN                     *FileSize,
+  IN      UINTN                     AddtionAllocateSize
+  )
+
+{
+  UINTN      BufferSize;
+  UINT64     SourceFileSize;
+  VOID       *Buffer;
+  EFI_STATUS Status;
+
+  if ((FileHandle == NULL) || (FileSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Buffer = NULL;
+
+  //
+  // Get the file size
+  //
+  Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+  
+  Status = FileHandle->SetPosition (FileHandle, 0);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  BufferSize = (UINTN) SourceFileSize + AddtionAllocateSize;
+  Buffer =  AllocateZeroPool(BufferSize);
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  BufferSize = (UINTN) SourceFileSize;
+  *FileSize  = BufferSize;
+
+  Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
+  if (EFI_ERROR (Status) || BufferSize != *FileSize) {
+    FreePool (Buffer);
+    Buffer = NULL;
+    Status  = EFI_BAD_BUFFER_SIZE;
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+  
+  *BufferPtr = Buffer;
+  return Status;
+}
+
+/**
+  This function will open a file or directory referenced by DevicePath.
+
+  This function opens a file with the open mode according to the file path. The
+  Attributes is valid only for EFI_FILE_MODE_CREATE.
+
+  @param[in, out]  FilePath        On input, the device path to the file.
+                                   On output, the remaining device path.
+  @param[out]      FileHandle      Pointer to the file handle.
+  @param[in]       OpenMode        The mode to open the file with.
+  @param[in]       Attributes      The file's file attributes.
+
+  @retval EFI_SUCCESS              The information was set.
+  @retval EFI_INVALID_PARAMETER    One of the parameters has an invalid value.
+  @retval EFI_UNSUPPORTED          Could not open the file path.
+  @retval EFI_NOT_FOUND            The specified file could not be found on the
+                                   device or the file system could not be found on
+                                   the device.
+  @retval EFI_NO_MEDIA             The device has no medium.
+  @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the
+                                   medium is no longer supported.
+  @retval EFI_DEVICE_ERROR         The device reported an error.
+  @retval EFI_VOLUME_CORRUPTED     The file system structures are corrupted.
+  @retval EFI_WRITE_PROTECTED      The file or medium is write protected.
+  @retval EFI_ACCESS_DENIED        The file was opened read only.
+  @retval EFI_OUT_OF_RESOURCES     Not enough resources were available to open the
+                                   file.
+  @retval EFI_VOLUME_FULL          The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+OpenFileByDevicePath (
+  IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,
+  OUT EFI_FILE_HANDLE                 *FileHandle,
+  IN UINT64                           OpenMode,
+  IN UINT64                           Attributes
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
+  EFI_FILE_PROTOCOL               *Handle1;
+  EFI_FILE_PROTOCOL               *Handle2;
+  EFI_HANDLE                      DeviceHandle;
+
+  if ((FilePath == NULL || FileHandle == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = gBS->LocateDevicePath (
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  FilePath,
+                  &DeviceHandle
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->OpenProtocol(
+                  DeviceHandle,
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  (VOID**)&EfiSimpleFileSystemProtocol,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
+  if (EFI_ERROR (Status)) {
+    FileHandle = NULL;
+    return Status;
+  }
+
+  //
+  // go down directories one node at a time.
+  //
+  while (!IsDevicePathEnd (*FilePath)) {
+    //
+    // For file system access each node should be a file path component
+    //
+    if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
+        DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
+       ) {
+      FileHandle = NULL;
+      return (EFI_INVALID_PARAMETER);
+    }
+    //
+    // Open this file path node
+    //
+    Handle2  = Handle1;
+    Handle1 = NULL;
+
+    //
+    // Try to test opening an existing file
+    //
+    Status = Handle2->Open (
+                        Handle2,
+                        &Handle1,
+                        ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
+                        OpenMode &~EFI_FILE_MODE_CREATE,
+                        0
+                        );
+
+    //
+    // see if the error was that it needs to be created
+    //
+    if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
+      Status = Handle2->Open (
+                          Handle2,
+                          &Handle1,
+                          ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
+                          OpenMode,
+                          Attributes
+                          );
+    }
+    //
+    // Close the last node
+    //
+    Handle2->Close (Handle2);
+
+    if (EFI_ERROR(Status)) {
+      return (Status);
+    }
+
+    //
+    // Get the next node
+    //
+    *FilePath = NextDevicePathNode (*FilePath);
+  }
+
+  //
+  // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
+  //
+  *FileHandle = (VOID*)Handle1;
+  return EFI_SUCCESS;
+}
+
+/**
+  This function converts an input device structure to a Unicode string.
+
+  @param[in] DevPath                  A pointer to the device path structure.
+
+  @return A new allocated Unicode string that represents the device path.
+
+**/
+CHAR16 *
+EFIAPI
+DevicePathToStr (
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
+  )
+{
+  return ConvertDevicePathToText (
+           DevPath,
+           FALSE,
+           TRUE
+           );
+}
+
+
+/**
+  Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
+  The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL
+  means not enough memory resource.
+
+  @param DevicePath       Device path.
+
+  @retval NULL            Not enough memory resourece for AllocateCopyPool.
+  @retval Other           A new allocated string that represents the file name.
+
+**/
+CHAR16 *
+ExtractFileNameFromDevicePath (
+  IN   EFI_DEVICE_PATH_PROTOCOL *DevicePath
+  )
+{
+  CHAR16          *String;
+  CHAR16          *MatchString;
+  CHAR16          *LastMatch;
+  CHAR16          *FileName;
+  UINTN           Length;
+
+  ASSERT(DevicePath != NULL);
+
+  String = DevicePathToStr(DevicePath);
+  MatchString = String;
+  LastMatch   = String;
+  FileName    = NULL;
+
+  while(MatchString != NULL){
+    LastMatch   = MatchString + 1;
+    MatchString = StrStr(LastMatch,L"\\");
+  }
+
+  Length = StrLen(LastMatch);
+  FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
+  if (FileName != NULL) {
+    *(FileName + Length) = 0;
+  }
+
+  FreePool(String);
+
+  return FileName;
+}
+
+/**
+  Enroll a new X509 certificate into Variable.
+
+  @param[in] PrivateData     The module's private data.
+  @param[in] VariableName    Variable name of CA database.
+
+  @retval   EFI_SUCCESS            New X509 is enrolled successfully.
+  @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
+
+**/
+EFI_STATUS
+EnrollX509toVariable (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA   *Private,
+  IN CHAR16                         *VariableName
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             X509DataSize;
+  VOID                              *X509Data;
+  EFI_SIGNATURE_LIST                *CACert;
+  EFI_SIGNATURE_DATA                *CACertData;
+  VOID                              *Data;
+  UINTN                             DataSize;
+  UINTN                             SigDataSize;
+  UINT32                            Attr;
+
+  X509DataSize  = 0;
+  SigDataSize   = 0;
+  DataSize      = 0;
+  X509Data      = NULL;
+  CACert        = NULL;
+  CACertData    = NULL;
+  Data          = NULL;
+
+  Status = ReadFileContent (
+             Private->FileContext->FHandle,
+             &X509Data,
+             &X509DataSize,
+             0
+             );
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+  ASSERT (X509Data != NULL);
+
+  SigDataSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
+
+  Data = AllocateZeroPool (SigDataSize);
+  if (Data == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Fill Certificate Database parameters.
+  //
+  CACert = (EFI_SIGNATURE_LIST*) Data;
+  CACert->SignatureListSize   = (UINT32) SigDataSize;
+  CACert->SignatureHeaderSize = 0;
+  CACert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
+  CopyGuid (&CACert->SignatureType, &gEfiCertX509Guid);
+
+  CACertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) CACert + sizeof (EFI_SIGNATURE_LIST));
+  CopyGuid (&CACertData->SignatureOwner, Private->CertGuid);
+  CopyMem ((UINT8* ) (CACertData->SignatureData), X509Data, X509DataSize);
+
+  //
+  // Check if signature database entry has been already existed.
+  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
+  // new signature data to original variable
+  //
+  Attr = TLS_AUTH_CONFIG_VAR_BASE_ATTR;
+
+  Status = gRT->GetVariable(
+                  VariableName,
+                  &gEfiTlsCaCertificateGuid,
+                  NULL,
+                  &DataSize,
+                  NULL
+                  );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    Attr |= EFI_VARIABLE_APPEND_WRITE;
+  } else if (Status != EFI_NOT_FOUND) {
+    goto ON_EXIT;
+  }
+
+  Status = gRT->SetVariable(
+                  VariableName,
+                  &gEfiTlsCaCertificateGuid,
+                  Attr,
+                  SigDataSize,
+                  Data
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+
+  CloseFile (Private->FileContext->FHandle);
+  if (Private->FileContext->FileName != NULL) {
+    FreePool(Private->FileContext->FileName);
+    Private->FileContext->FileName = NULL;
+  }
+
+  Private->FileContext->FHandle = NULL;
+
+  if (Private->CertGuid != NULL) {
+    FreePool (Private->CertGuid);
+    Private->CertGuid = NULL;
+  }
+
+  if (Data != NULL) {
+    FreePool (Data);
+  }
+
+  if (X509Data != NULL) {
+    FreePool (X509Data);
+  }
+
+  return Status;
+}
+
+/**
+  Enroll Cert into TlsCaCertificate. The GUID will be Private->CertGuid.
+
+  @param[in] PrivateData     The module's private data.
+  @param[in] VariableName    Variable name of signature database.
+
+  @retval   EFI_SUCCESS            New Cert enrolled successfully.
+  @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
+  @retval   EFI_UNSUPPORTED        The Cert file is unsupported type.
+  @retval   others                 Fail to enroll Cert data.
+
+**/
+EFI_STATUS
+EnrollCertDatabase (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA  *Private,
+  IN CHAR16                        *VariableName
+  )
+{
+  UINT16*      FilePostFix;
+  UINTN        NameLength;
+
+  if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->CertGuid == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Parse the file's postfix.
+  //
+  NameLength = StrLen (Private->FileContext->FileName);
+  if (NameLength <= 4) {
+    return EFI_INVALID_PARAMETER;
+  }
+  FilePostFix = Private->FileContext->FileName + NameLength - 4;
+
+  if (IsDerPemEncodeCertificate (FilePostFix)) {
+    //
+    // Supports DER-encoded X509 certificate.
+    //
+    return EnrollX509toVariable (Private, VariableName);
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Refresh the global UpdateData structure.
+
+**/
+VOID
+RefreshUpdateData (
+  VOID
+  )
+{
+  //
+  // Free current updated date
+  //
+  if (mStartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mStartOpCodeHandle);
+  }
+
+  //
+  // Create new OpCode Handle
+  //
+  mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                         mStartOpCodeHandle,
+                                         &gEfiIfrTianoGuid,
+                                         NULL,
+                                         sizeof (EFI_IFR_GUID_LABEL)
+                                         );
+  mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+}
+
+/**
+  Clean up the dynamic opcode at label and form specified by both LabelId.
+
+  @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.
+  @param[in] PrivateData     Module private data.
+
+**/
+VOID
+CleanUpPage (
+  IN UINT16                           LabelId,
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *PrivateData
+  )
+{
+  RefreshUpdateData ();
+
+  //
+  // Remove all op-codes from dynamic page
+  //
+  mStartLabel->Number = LabelId;
+  HiiUpdateForm (
+    PrivateData->RegisteredHandle,
+    &gTlsAuthConfigGuid,
+    LabelId,
+    mStartOpCodeHandle, // Label LabelId
+    mEndOpCodeHandle    // LABEL_END
+    );
+}
+
+/**
+  Update the form base on the selected file.
+
+  @param FilePath   Point to the file path.
+  @param FormId     The form need to display.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+
+**/
+BOOLEAN
+UpdatePage(
+  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
+  IN  EFI_FORM_ID               FormId
+  )
+{
+  CHAR16                *FileName;
+  EFI_STRING_ID         StringToken;
+
+  FileName = NULL;
+
+  if (FilePath != NULL) {
+    FileName = ExtractFileNameFromDevicePath(FilePath);
+  }
+  if (FileName == NULL) {
+    //
+    // FileName = NULL has two case:
+    // 1. FilePath == NULL, not select file.
+    // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.
+    // In these two case, no need to update the form, and exit the caller function.
+    //
+    return TRUE;
+  }
+  StringToken =  HiiSetString (mTlsAuthPrivateData->RegisteredHandle, 0, FileName, NULL);
+
+  mTlsAuthPrivateData->FileContext->FileName = FileName;
+
+  OpenFileByDevicePath (
+    &FilePath,
+    &mTlsAuthPrivateData->FileContext->FHandle,
+    EFI_FILE_MODE_READ,
+    0
+    );
+  //
+  // Create Subtitle op-code for the display string of the option.
+  //
+  RefreshUpdateData ();
+  mStartLabel->Number = FormId;
+
+  HiiCreateSubTitleOpCode (
+    mStartOpCodeHandle,
+    StringToken,
+    0,
+    0,
+    0
+   );
+
+  HiiUpdateForm (
+    mTlsAuthPrivateData->RegisteredHandle,
+    &gTlsAuthConfigGuid,
+    FormId,
+    mStartOpCodeHandle, /// Label FormId
+    mEndOpCodeHandle    /// LABEL_END
+    );
+
+  return TRUE;
+}
+
+/**
+  Update the form base on the input file path info.
+
+  @param FilePath    Point to the file path.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+**/
+BOOLEAN
+UpdateCAFromFile (
+  IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
+  )
+{
+  return UpdatePage(FilePath, TLS_AUTH_CONFIG_FORMID4_FORM);
+}
+
+/**
+  Unload the configuration form, this includes: delete all the configuration
+  entries, uninstall the form callback protocol, and free the resources used.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is unloaded.
+  @retval Others                  Failed to unload the form.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormUnload (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  )
+{
+  if (Private->DriverHandle != NULL) {
+    //
+    // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
+    //
+    gBS->UninstallMultipleProtocolInterfaces (
+           Private->DriverHandle,
+           &gEfiDevicePathProtocolGuid,
+           &mTlsAuthConfigHiiVendorDevicePath,
+           &gEfiHiiConfigAccessProtocolGuid,
+           &Private->ConfigAccess,
+           NULL
+           );
+    Private->DriverHandle = NULL;
+  }
+
+  if (Private->RegisteredHandle != NULL) {
+    //
+    // Remove HII package list
+    //
+    HiiRemovePackages (Private->RegisteredHandle);
+    Private->RegisteredHandle = NULL;
+  }
+
+  if (Private->CertGuid != NULL) {
+    FreePool (Private->CertGuid);
+  }
+
+  if (Private->FileContext != NULL) {
+    FreePool (Private->FileContext);
+  }
+
+  FreePool (Private);
+
+  if (mStartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mStartOpCodeHandle);
+  }
+
+  if (mEndOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mEndOpCodeHandle);
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Initialize the configuration form.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is initialized.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormInit (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  )
+{
+  EFI_STATUS                        Status;
+
+  Private->Signature = TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE;
+  
+  Private->ConfigAccess.ExtractConfig = TlsAuthConfigAccessExtractConfig;
+  Private->ConfigAccess.RouteConfig   = TlsAuthConfigAccessRouteConfig;
+  Private->ConfigAccess.Callback      = TlsAuthConfigAccessCallback;
+
+  //
+  // Install Device Path Protocol and Config Access protocol to driver handle.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Private->DriverHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  &mTlsAuthConfigHiiVendorDevicePath,
+                  &gEfiHiiConfigAccessProtocolGuid,
+                  &Private->ConfigAccess,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  
+  //
+  // Publish our HII data.
+  //
+  Private->RegisteredHandle = HiiAddPackages (
+                                &gTlsAuthConfigGuid,
+                                Private->DriverHandle,
+                                TlsAuthConfigDxeStrings,
+                                TlsAuthConfigVfrBin,
+                                NULL
+                                );
+  if (Private->RegisteredHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  Private->FileContext = AllocateZeroPool (sizeof (TLS_AUTH_CONFIG_FILE_CONTEXT));
+  if (Private->FileContext == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  //
+  // Init OpCode Handle and Allocate space for creation of Buffer
+  //
+  mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (mStartOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (mEndOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                         mStartOpCodeHandle,
+                                         &gEfiIfrTianoGuid,
+                                         NULL,
+                                         sizeof (EFI_IFR_GUID_LABEL)
+                                         );
+  mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+
+  //
+  // Create Hii Extend Label OpCode as the end opcode
+  //
+  mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                       mEndOpCodeHandle,
+                                       &gEfiIfrTianoGuid,
+                                       NULL,
+                                       sizeof (EFI_IFR_GUID_LABEL)
+                                       );
+  mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  mEndLabel->Number       = LABEL_END;
+
+  return EFI_SUCCESS;
+  
+Error:
+  TlsAuthConfigFormUnload (Private);
+  return Status;
+}
+
+/**
+   
+  This function allows the caller to request the current
+  configuration for one or more named elements. The resulting
+  string is in <ConfigAltResp> format. Any and all alternative
+  configuration strings shall also be appended to the end of the
+  current configuration string. If they are, they must appear
+  after the current configuration. They must contain the same
+  routing (GUID, NAME, PATH) as the current configuration string.
+  They must have an additional description indicating the type of
+  alternative configuration the string represents,
+  "ALTCFG=<StringToken>". That <StringToken> (when
+  converted from Hex UNICODE to binary) is a reference to a
+  string in the associated string pack.
+
+  @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Request    A null-terminated Unicode string in
+                    <ConfigRequest> format. Note that this
+                    includes the routing information as well as
+                    the configurable name / value pairs. It is
+                    invalid for this string to be in
+                    <MultiConfigRequest> format. 
+                    If a NULL is passed in for the Request field, 
+                    all of the settings being abstracted by this function 
+                    will be returned in the Results field.  In addition, 
+                    if a ConfigHdr is passed in with no request elements, 
+                    all of the settings being abstracted for that particular 
+                    ConfigHdr reference will be returned in the Results Field.
+
+  @param Progress   On return, points to a character in the
+                    Request string. Points to the string's null
+                    terminator if request was successful. Points
+                    to the most recent "&" before the first
+                    failing name / value pair (or the beginning
+                    of the string if the failure is in the first
+                    name / value pair) if the request was not
+                    successful.
+
+  @param Results    A null-terminated Unicode string in
+                    <MultiConfigAltResp> format which has all values
+                    filled in for the names in the Request string.
+                    String to be allocated by the called function.
+
+  @retval EFI_SUCCESS             The Results string is filled with the
+                                  values corresponding to all requested
+                                  names.
+
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+
+  @retval EFI_NOT_FOUND           Routing data doesn't match any
+                                  known driver. Progress set to the
+                                  first character in the routing header.
+                                  Note: There is no requirement that the
+                                  driver validate the routing data. It
+                                  must skip the <ConfigHdr> in order to
+                                  process the names.
+
+  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
+                                  to most recent "&" before the
+                                  error or the beginning of the
+                                  string.
+
+  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
+                                  to the & before the name in
+                                  question.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessExtractConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Request,
+  OUT       EFI_STRING                      *Progress,
+  OUT       EFI_STRING                      *Results
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             BufferSize;
+  UINTN                             Size;
+  EFI_STRING                        ConfigRequest;
+  EFI_STRING                        ConfigRequestHdr;
+  TLS_AUTH_CONFIG_PRIVATE_DATA      *Private;
+  BOOLEAN                           AllocatedRequest;
+
+  if (Progress == NULL || Results == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AllocatedRequest = FALSE;
+  ConfigRequestHdr = NULL;
+  ConfigRequest    = NULL;
+  Size             = 0;
+
+  Private          = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
+
+  BufferSize       = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+  ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
+  
+  *Progress        = Request;
+
+  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+  
+  ConfigRequest = Request;
+  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+    //
+    // Request is set to NULL or OFFSET is NULL, construct full request string.
+    //
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+    //
+    ConfigRequestHdr = HiiConstructConfigHdr (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, Private->DriverHandle);
+    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+    ConfigRequest = AllocateZeroPool (Size);
+    ASSERT (ConfigRequest != NULL);
+    AllocatedRequest = TRUE;
+    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+    FreePool (ConfigRequestHdr);
+    ConfigRequestHdr = NULL;
+  }
+
+  Status = gHiiConfigRouting->BlockToConfig (
+                                gHiiConfigRouting,
+                                ConfigRequest,
+                                (UINT8 *) &Private->TlsAuthConfigNvData,
+                                BufferSize,
+                                Results,
+                                Progress
+                                );
+
+  //
+  // Free the allocated config request string.
+  //
+  if (AllocatedRequest) {
+    FreePool (ConfigRequest);
+  }
+
+  //
+  // Set Progress string to the original request string.
+  //
+  if (Request == NULL) {
+    *Progress = NULL;
+  } else if (StrStr (Request, L"OFFSET") == NULL) {
+    *Progress = Request + StrLen (Request);
+  }
+
+  return Status;
+}
+
+/**
+   
+  This function applies changes in a driver's configuration.
+  Input is a Configuration, which has the routing data for this
+  driver followed by name / value configuration pairs. The driver
+  must apply those pairs to its configurable storage. If the
+  driver's configuration is stored in a linear block of data
+  and the driver's name / value pairs are in <BlockConfig>
+  format, it may use the ConfigToBlock helper function (above) to
+  simplify the job.
+
+  @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Configuration  A null-terminated Unicode string in
+                        <ConfigString> format. 
+  
+  @param Progress       A pointer to a string filled in with the
+                        offset of the most recent '&' before the
+                        first failing name / value pair (or the
+                        beginn ing of the string if the failure
+                        is in the first name / value pair) or
+                        the terminating NULL if all was
+                        successful.
+
+  @retval EFI_SUCCESS             The results have been distributed or are
+                                  awaiting distribution.
+  
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+  
+  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
+                                  Results parameter would result
+                                  in this type of error.
+  
+  @retval EFI_NOT_FOUND           Target for the specified routing data
+                                  was not found
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessRouteConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Configuration,
+  OUT       EFI_STRING                      *Progress
+  )
+{
+  EFI_STATUS                       Status;
+  UINTN                            BufferSize;
+  TLS_AUTH_CONFIG_PRIVATE_DATA     *Private;
+
+  if (Progress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  *Progress = Configuration;
+
+  if (Configuration == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check routing data in <ConfigHdr>.
+  // Note: there is no name for Name/Value storage, only GUID will be checked
+  //
+  if (!HiiIsConfigHdrMatch (Configuration, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+
+  Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
+  
+  BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+  ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
+
+  Status = gHiiConfigRouting->ConfigToBlock (
+                                gHiiConfigRouting,
+                                Configuration,
+                                (UINT8 *) &Private->TlsAuthConfigNvData,
+                                &BufferSize,
+                                Progress
+                                );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return Status;
+}  
+
+/**
+   
+  This function is called to provide results data to the driver.
+  This data consists of a unique key that is used to identify
+  which data is either being passed back or being asked for.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  QuestionId             A unique value which is sent to the original
+                                 exporting driver so that it can identify the type
+                                 of data to expect. The format of the data tends to 
+                                 vary based on the opcode that generated the callback.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  ActionRequest          On return, points to the action requested by the
+                                 callback function.
+
+  @retval EFI_SUCCESS            The callback successfully handled the action.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
+                                 variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
+                                 callback.
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessCallback (
+  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN     EFI_BROWSER_ACTION                     Action,
+  IN     EFI_QUESTION_ID                        QuestionId,
+  IN     UINT8                                  Type,
+  IN OUT EFI_IFR_TYPE_VALUE                     *Value,
+  OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
+  )
+{
+  EFI_INPUT_KEY                   Key;
+  EFI_STATUS                      Status;
+  TLS_AUTH_CONFIG_PRIVATE_DATA    *Private;
+  UINTN                           BufferSize;
+  TLS_AUTH_CONFIG_IFR_NVDATA      *IfrNvData;
+  UINT16                          LabelId;
+  EFI_DEVICE_PATH_PROTOCOL        *File;
+
+  Status           = EFI_SUCCESS;
+  File             = NULL;
+
+  if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
+
+  mTlsAuthPrivateData = Private;
+
+  //
+  // Retrieve uncommitted data from Browser
+  //
+  BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+  IfrNvData = AllocateZeroPool (BufferSize);
+  if (IfrNvData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  HiiGetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8 *) IfrNvData);
+
+  if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
+      (Action != EFI_BROWSER_ACTION_CHANGING)) {
+    Status = EFI_UNSUPPORTED;
+    goto EXIT;
+  }
+
+  if (Action == EFI_BROWSER_ACTION_CHANGING) {
+    switch (QuestionId) {
+    case KEY_TLS_AUTH_CONFIG_CLIENT_CERT:
+    case KEY_TLS_AUTH_CONFIG_SERVER_CA:
+      //
+      // Clear Cert GUID.
+      //
+      ZeroMem (IfrNvData->CertGuid, sizeof (IfrNvData->CertGuid));
+      if (Private->CertGuid == NULL) {
+        Private->CertGuid = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));
+        if (Private->CertGuid == NULL) {
+          return EFI_OUT_OF_RESOURCES;
+        }
+      }
+      if (QuestionId == KEY_TLS_AUTH_CONFIG_CLIENT_CERT) {
+        LabelId = TLS_AUTH_CONFIG_FORMID3_FORM;
+      } else if (QuestionId == KEY_TLS_AUTH_CONFIG_SERVER_CA) {
+        LabelId = TLS_AUTH_CONFIG_FORMID4_FORM;
+      }
+
+      //
+      // Refresh selected file.
+      //
+      CleanUpPage (LabelId, Private);
+      break;
+    case KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE:
+      ChooseFile( NULL, NULL, (CHOOSE_HANDLER) UpdateCAFromFile, &File);
+      break;
+
+    case KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT:
+      Status = EnrollCertDatabase (Private, EFI_TLS_CA_CERTIFICATE_VARIABLE);
+      if (EFI_ERROR (Status)) {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"ERROR: Enroll Cert Failure!",
+          NULL
+          );
+      }
+      break;
+
+    case KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT:
+      if (Private->FileContext->FHandle != NULL) {
+        CloseFile (Private->FileContext->FHandle);
+        Private->FileContext->FHandle = NULL;
+        if (Private->FileContext->FileName!= NULL){
+          FreePool(Private->FileContext->FileName);
+          Private->FileContext->FileName = NULL;
+        }
+      }
+
+      if (Private->CertGuid!= NULL) {
+        FreePool (Private->CertGuid);
+        Private->CertGuid = NULL;
+      }
+      break;
+
+    case KEY_TLS_AUTH_CONFIG_DELETE_CERT:
+      UpdateDeletePage (
+        Private,
+        EFI_TLS_CA_CERTIFICATE_VARIABLE,
+        &gEfiTlsCaCertificateGuid,
+        LABEL_CA_DELETE,
+        TLS_AUTH_CONFIG_FORMID5_FORM,
+        OPTION_DEL_CA_ESTION_ID
+        );
+       break;
+      
+    default:
+      if ((QuestionId >= OPTION_DEL_CA_ESTION_ID) &&
+                 (QuestionId < (OPTION_DEL_CA_ESTION_ID + OPTION_CONFIG_RANGE)))  {
+        DeleteCert (
+          Private,
+          EFI_TLS_CA_CERTIFICATE_VARIABLE,
+          &gEfiTlsCaCertificateGuid,
+          LABEL_CA_DELETE,
+          TLS_AUTH_CONFIG_FORMID5_FORM,
+          OPTION_DEL_CA_ESTION_ID,
+          QuestionId - OPTION_DEL_CA_ESTION_ID
+          );
+      }
+      break;
+    }
+  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
+    switch (QuestionId) {
+    case KEY_TLS_AUTH_CONFIG_CERT_GUID:
+      ASSERT (Private->CertGuid != NULL);
+      Status = StringToGuid (
+                 IfrNvData->CertGuid,
+                 StrLen (IfrNvData->CertGuid),
+                 Private->CertGuid
+                 );
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+      break;
+    default:
+      break;
+    }
+  }
+  
+EXIT:
+
+  if (!EFI_ERROR (Status)) {
+    BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+    HiiSetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8*) IfrNvData, NULL);
+  }
+
+  FreePool (IfrNvData);
+
+  if (File != NULL){
+    FreePool(File);
+    File = NULL;
+  }
+
+  return EFI_SUCCESS;
+
+}
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
new file mode 100644
index 0000000..398f7b6
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
@@ -0,0 +1,282 @@
+/** @file
+  Header file of Miscellaneous Routines for TlsAuthConfigDxe 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 __TLS_AUTH_CONFIG_IMPL_H__
+#define __TLS_AUTH_CONFIG_IMPL_H__
+
+#include <Uefi.h>
+
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/SimpleFileSystem.h>
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/FileExplorerLib.h>
+#include <Library/PrintLib.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/ImageAuthentication.h>
+#include <Guid/TlsAuthentication.h>
+
+
+//
+// Include files with function prototypes
+//
+#include "TlsAuthConfigNvData.h"
+
+extern   UINT8       TlsAuthConfigDxeStrings[];
+extern   UINT8       TlsAuthConfigVfrBin[];
+
+#define TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE    SIGNATURE_32 ('T', 'A', 'C', 'D')
+#define TLS_AUTH_CONFIG_PRIVATE_FROM_THIS(a)      CR (a, TLS_AUTH_CONFIG_PRIVATE_DATA, ConfigAccess, TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE)
+
+#define TLS_AUTH_CONFIG_VAR_BASE_ATTR  (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)
+
+typedef struct _TLS_AUTH_CONFIG_PRIVATE_DATA      TLS_AUTH_CONFIG_PRIVATE_DATA;
+typedef struct _TLS_AUTH_CONFIG_FILE_CONTEXT      TLS_AUTH_CONFIG_FILE_CONTEXT;
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+  VENDOR_DEVICE_PATH                VendorDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL          End;
+} HII_VENDOR_DEVICE_PATH;
+
+struct _TLS_AUTH_CONFIG_FILE_CONTEXT {
+  EFI_FILE_HANDLE                   FHandle;
+  UINT16                            *FileName;
+};
+
+struct _TLS_AUTH_CONFIG_PRIVATE_DATA {
+  UINTN                             Signature;
+
+  EFI_HANDLE                        DriverHandle;
+  EFI_HII_HANDLE                    RegisteredHandle;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL    ConfigAccess;
+  TLS_AUTH_CONFIG_IFR_NVDATA        TlsAuthConfigNvData;
+
+  TLS_AUTH_CONFIG_FILE_CONTEXT      *FileContext;
+
+  EFI_GUID                          *CertGuid;
+};
+
+/**
+  Unload the configuration form, this includes: delete all the configuration
+  entries, uninstall the form callback protocol, and free the resources used.
+  The form will only be unload completely when both IP4 and IP6 stack are stopped.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is unloaded.
+  @retval Others                  Failed to unload the form.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormUnload (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  );
+
+/**
+  Initialize the configuration form.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is initialized.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormInit (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  );
+
+/**
+   
+  This function allows the caller to request the current
+  configuration for one or more named elements. The resulting
+  string is in <ConfigAltResp> format. Any and all alternative
+  configuration strings shall also be appended to the end of the
+  current configuration string. If they are, they must appear
+  after the current configuration. They must contain the same
+  routing (GUID, NAME, PATH) as the current configuration string.
+  They must have an additional description indicating the type of
+  alternative configuration the string represents,
+  "ALTCFG=<StringToken>". That <StringToken> (when
+  converted from Hex UNICODE to binary) is a reference to a
+  string in the associated string pack.
+
+  @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Request    A null-terminated Unicode string in
+                    <ConfigRequest> format. Note that this
+                    includes the routing information as well as
+                    the configurable name / value pairs. It is
+                    invalid for this string to be in
+                    <MultiConfigRequest> format. 
+                    If a NULL is passed in for the Request field, 
+                    all of the settings being abstracted by this function 
+                    will be returned in the Results field.  In addition, 
+                    if a ConfigHdr is passed in with no request elements, 
+                    all of the settings being abstracted for that particular 
+                    ConfigHdr reference will be returned in the Results Field.
+
+  @param Progress   On return, points to a character in the
+                    Request string. Points to the string's null
+                    terminator if request was successful. Points
+                    to the most recent "&" before the first
+                    failing name / value pair (or the beginning
+                    of the string if the failure is in the first
+                    name / value pair) if the request was not
+                    successful.
+
+  @param Results    A null-terminated Unicode string in
+                    <MultiConfigAltResp> format which has all values
+                    filled in for the names in the Request string.
+                    String to be allocated by the called function.
+
+  @retval EFI_SUCCESS             The Results string is filled with the
+                                  values corresponding to all requested
+                                  names.
+
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+
+  @retval EFI_NOT_FOUND           Routing data doesn't match any
+                                  known driver. Progress set to the
+                                  first character in the routing header.
+                                  Note: There is no requirement that the
+                                  driver validate the routing data. It
+                                  must skip the <ConfigHdr> in order to
+                                  process the names.
+
+  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
+                                  to most recent "&" before the
+                                  error or the beginning of the
+                                  string.
+
+  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
+                                  to the & before the name in
+                                  question.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessExtractConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Request,
+  OUT       EFI_STRING                      *Progress,
+  OUT       EFI_STRING                      *Results
+  );
+
+/**
+   
+  This function applies changes in a driver's configuration.
+  Input is a Configuration, which has the routing data for this
+  driver followed by name / value configuration pairs. The driver
+  must apply those pairs to its configurable storage. If the
+  driver's configuration is stored in a linear block of data
+  and the driver's name / value pairs are in <BlockConfig>
+  format, it may use the ConfigToBlock helper function (above) to
+  simplify the job.
+
+  @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Configuration  A null-terminated Unicode string in
+                        <ConfigString> format. 
+  
+  @param Progress       A pointer to a string filled in with the
+                        offset of the most recent '&' before the
+                        first failing name / value pair (or the
+                        beginn ing of the string if the failure
+                        is in the first name / value pair) or
+                        the terminating NULL if all was
+                        successful.
+
+  @retval EFI_SUCCESS             The results have been distributed or are
+                                  awaiting distribution.
+  
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+  
+  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
+                                  Results parameter would result
+                                  in this type of error.
+  
+  @retval EFI_NOT_FOUND           Target for the specified routing data
+                                  was not found
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessRouteConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Configuration,
+  OUT       EFI_STRING                      *Progress
+  );  
+
+/**
+   
+  This function is called to provide results data to the driver.
+  This data consists of a unique key that is used to identify
+  which data is either being passed back or being asked for.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  QuestionId             A unique value which is sent to the original
+                                 exporting driver so that it can identify the type
+                                 of data to expect. The format of the data tends to 
+                                 vary based on the opcode that generated the callback.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  ActionRequest          On return, points to the action requested by the
+                                 callback function.
+
+  @retval EFI_SUCCESS            The callback successfully handled the action.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
+                                 variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
+                                 callback.
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessCallback (
+  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN     EFI_BROWSER_ACTION                     Action,
+  IN     EFI_QUESTION_ID                        QuestionId,
+  IN     UINT8                                  Type,
+  IN OUT EFI_IFR_TYPE_VALUE                     *Value,
+  OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
+  );
+
+#endif
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
new file mode 100644
index 0000000..f453201
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
@@ -0,0 +1,49 @@
+/** @file
+  Header file for NV data structure definition.
+
+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 __TLS_AUTH_CONFIG_NV_DATA_H__
+#define __TLS_AUTH_CONFIG_NV_DATA_H__
+
+#include <Guid/TlsAuthConfigHii.h>
+
+#define TLS_AUTH_CONFIG_GUID_SIZE                 36
+#define TLS_AUTH_CONFIG_GUID_STORAGE_SIZE         37
+
+#define TLS_AUTH_CONFIG_FORMID1_FORM              1
+#define TLS_AUTH_CONFIG_FORMID2_FORM              2
+#define TLS_AUTH_CONFIG_FORMID3_FORM              3
+#define TLS_AUTH_CONFIG_FORMID4_FORM              4
+#define TLS_AUTH_CONFIG_FORMID5_FORM              5
+
+
+#define KEY_TLS_AUTH_CONFIG_SERVER_CA                  0x1000
+#define KEY_TLS_AUTH_CONFIG_CLIENT_CERT                0x1001
+#define KEY_TLS_AUTH_CONFIG_ENROLL_CERT                0x1002
+#define KEY_TLS_AUTH_CONFIG_DELETE_CERT                0x1003
+#define KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE      0x1004
+#define KEY_TLS_AUTH_CONFIG_CERT_GUID                  0x1005
+#define KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT        0x1006
+#define KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT     0x1007
+
+#define OPTION_DEL_CA_ESTION_ID                        0x2000
+#define OPTION_CONFIG_RANGE                            0x1000
+
+#define LABEL_CA_DELETE                                0x1101
+#define LABEL_END                                      0xffff
+
+typedef struct {
+  CHAR16    CertGuid[TLS_AUTH_CONFIG_GUID_STORAGE_SIZE];
+} TLS_AUTH_CONFIG_IFR_NVDATA;
+
+#endif
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
new file mode 100644
index 0000000..fb130d9
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
@@ -0,0 +1,152 @@
+/** @file
+  VFR file used by TlsAuthConfigDxe 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.
+
+**/
+
+#include "TlsAuthConfigNvData.h"
+
+formset
+  guid   = TLS_AUTH_CONFIG_GUID,
+  title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_TITLE),
+  help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_HELP),
+
+  varstore TLS_AUTH_CONFIG_IFR_NVDATA,
+    name = TLS_AUTH_CONFIG_IFR_NVDATA,
+    guid = TLS_AUTH_CONFIG_GUID;
+
+  //
+  // ##1 Form1: Main form for Tls Auth configration
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID1_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_TITLE);
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+    
+    //
+    // Display Server CA configration
+    //
+    goto TLS_AUTH_CONFIG_FORMID2_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_SERVER_CA;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    //
+    // Display Client cert configration
+    //
+    grayoutif TRUE; /// Current unsupported.
+    goto TLS_AUTH_CONFIG_FORMID3_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_CLIENT_CERT;
+    endif;
+  endform; 
+
+  //
+  // ##2 Form2: CA configuration
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID2_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA);
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID4_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_ENROLL_CERT;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID5_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_DELETE_CERT;
+  endform;
+
+  //
+  // ##3 Form3 : Client cert configuration
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID3_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT);
+    
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+  //
+  // TODO...
+  //
+  endform;
+
+  //
+  // ##4 Form4: Enroll cert for CA
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID4_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT);
+    
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID4_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ADD_CERT_FILE),
+         help = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ADD_CERT_FILE),
+         flags = INTERACTIVE,
+         key = KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+    label TLS_AUTH_CONFIG_FORMID4_FORM;
+    label LABEL_END;
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    string  varid   = TLS_AUTH_CONFIG_IFR_NVDATA.CertGuid,
+            prompt  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CERT_GUID),
+            help    = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CERT_GUID_HELP),
+            flags   = INTERACTIVE,
+            key     = KEY_TLS_AUTH_CONFIG_CERT_GUID,
+            minsize = TLS_AUTH_CONFIG_GUID_SIZE,
+            maxsize = TLS_AUTH_CONFIG_GUID_SIZE,
+    endstring;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID1_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT;
+
+    goto TLS_AUTH_CONFIG_FORMID1_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT;
+         
+  endform;
+
+  //
+  // ##5 Form5: Delete cert for CA
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID5_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT);
+
+    label LABEL_CA_DELETE;
+    label LABEL_END;
+    
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+  endform;
+  
+endformset;
-- 
1.9.5.msysgit.1


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6
  2016-12-14  7:34 ` [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6 Jiaxin Wu
@ 2016-12-15  2:39   ` Fu, Siyuan
  2016-12-15  7:14     ` Wu, Jiaxin
  2016-12-22  7:33   ` Ye, Ting
  1 sibling, 1 reply; 37+ messages in thread
From: Fu, Siyuan @ 2016-12-15  2:39 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Ye, Ting, Zhang, Lubo, Long, Qin, Thomas Palmer

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


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 08/10] NetworkPkg/NetworkPkg.dsc: Enable TlsDxe and TlsAuthConfigDxe module
  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
  1 sibling, 0 replies; 37+ messages in thread
From: Fu, Siyuan @ 2016-12-15  2:39 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Ye, Ting, Zhang, Lubo, Long, Qin, Thomas Palmer



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 08/10] NetworkPkg/NetworkPkg.dsc: Enable TlsDxe and TlsAuthConfigDxe module

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/NetworkPkg.dsc | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/NetworkPkg/NetworkPkg.dsc b/NetworkPkg/NetworkPkg.dsc index 1ef353e..3d881e9 100644
--- a/NetworkPkg/NetworkPkg.dsc
+++ b/NetworkPkg/NetworkPkg.dsc
@@ -53,12 +53,14 @@
   TcpIoLib|MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf
   HttpLib|MdeModulePkg/Library/DxeHttpLib/DxeHttpLib.inf
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
   IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+  TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
   DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf  
   FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+  
+ FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.i
+ nf
   SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
 
 [LibraryClasses.common.UEFI_DRIVER]
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
@@ -111,10 +113,12 @@
   NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf
   NetworkPkg/DnsDxe/DnsDxe.inf
   NetworkPkg/HttpDxe/HttpDxe.inf
   NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
   NetworkPkg/HttpBootDxe/HttpBootDxe.inf
+  NetworkPkg/TlsDxe/TlsDxe.inf
+  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
 
   NetworkPkg/Application/IfConfig6/IfConfig6.inf
   NetworkPkg/Application/IpsecConfig/IpSecConfig.inf
   NetworkPkg/Application/VConfig/VConfig.inf
 
--
1.9.5.msysgit.1


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6
  2016-12-15  2:39   ` Fu, Siyuan
@ 2016-12-15  7:14     ` Wu, Jiaxin
  0 siblings, 0 replies; 37+ messages in thread
From: Wu, Jiaxin @ 2016-12-15  7:14 UTC (permalink / raw)
  To: Fu, Siyuan, edk2-devel@lists.01.org
  Cc: Ye, Ting, Zhang, Lubo, Long, Qin, Thomas Palmer

Good suggestion, I will change the flag to "https://" before commit the patch.

Even we have a library to get the URI scheme, we still need check whether it's http or https.

Thanks,
Jiaxin


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


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL
  2016-12-14  8:41   ` Fu, Siyuan
@ 2016-12-15  7:24     ` Wu, Jiaxin
  0 siblings, 0 replies; 37+ messages in thread
From: Wu, Jiaxin @ 2016-12-15  7:24 UTC (permalink / raw)
  To: Fu, Siyuan, edk2-devel@lists.01.org
  Cc: Ye, Ting, Zhang, Lubo, Long, Qin, Thomas Palmer

Thanks Siyuan, I have refined the TlsEcryptPacket/TlsDecryptPacket function according your feedback.

[PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL

Thanks,
Jiaxin

> -----Original Message-----
> From: Fu, Siyuan
> Sent: Wednesday, December 14, 2016 4:41 PM
> To: Wu, Jiaxin <jiaxin.wu@intel.com>; edk2-devel@lists.01.org
> Cc: Ye, Ting <ting.ye@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>;
> Long, Qin <qin.long@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>
> Subject: RE: [Patch 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation
> over OpenSSL
> 
> Hi, Jiaxin
> 
> Some comments as below:
> 
> In TlsImpl.c
> 
> Should the ASSERT in line 104 be an error handling? I mean is the input buffer
> coming from external input, and have we checked ContentType within it?
> 
> Seems the TempRecordHeader pointer will be modified in the while loop,
> shouldn't the 3rd parameter be the reminding buffer size of the output
> buffer?
> 
> Should we return error if the TlsCtrlTrafficOut return a failure?
> 
> Similar questions for the decrypt packet function.
> 
> 
> Best Regards,
> Siyuan
> 
> -----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 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation
> over OpenSSL
> 
> This patch is the implementation of EFI TLS Service Binding
> Protocol, EFI TLS Protocol and EFI TLS Configuration Protocol
> Interfaces.
> 
> 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/TlsDxe/TlsConfigProtocol.c | 152 ++++++++
>  NetworkPkg/TlsDxe/TlsDriver.c         | 498
> +++++++++++++++++++++++++++
>  NetworkPkg/TlsDxe/TlsDriver.h         | 237 +++++++++++++
>  NetworkPkg/TlsDxe/TlsDxe.inf          |  65 ++++
>  NetworkPkg/TlsDxe/TlsDxe.uni          |  25 ++
>  NetworkPkg/TlsDxe/TlsDxeExtra.uni     |  18 +
>  NetworkPkg/TlsDxe/TlsImpl.c           | 270 +++++++++++++++
>  NetworkPkg/TlsDxe/TlsImpl.h           | 315 +++++++++++++++++
>  NetworkPkg/TlsDxe/TlsProtocol.c       | 632
> ++++++++++++++++++++++++++++++++++
>  9 files changed, 2212 insertions(+)
>  create mode 100644 NetworkPkg/TlsDxe/TlsConfigProtocol.c
>  create mode 100644 NetworkPkg/TlsDxe/TlsDriver.c
>  create mode 100644 NetworkPkg/TlsDxe/TlsDriver.h
>  create mode 100644 NetworkPkg/TlsDxe/TlsDxe.inf
>  create mode 100644 NetworkPkg/TlsDxe/TlsDxe.uni
>  create mode 100644 NetworkPkg/TlsDxe/TlsDxeExtra.uni
>  create mode 100644 NetworkPkg/TlsDxe/TlsImpl.c
>  create mode 100644 NetworkPkg/TlsDxe/TlsImpl.h
>  create mode 100644 NetworkPkg/TlsDxe/TlsProtocol.c
> 
> diff --git a/NetworkPkg/TlsDxe/TlsConfigProtocol.c
> b/NetworkPkg/TlsDxe/TlsConfigProtocol.c
> new file mode 100644
> index 0000000..2ec79c9
> --- /dev/null
> +++ b/NetworkPkg/TlsDxe/TlsConfigProtocol.c
> @@ -0,0 +1,152 @@
> +/** @file
> +  Implementation of EFI TLS Configuration Protocol Interfaces.
> +
> +  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.
> +
> +**/
> +
> +#include "TlsImpl.h"
> +
> +EFI_TLS_CONFIGURATION_PROTOCOL  mTlsConfigurationProtocol = {
> +  TlsConfigurationSetData,
> +  TlsConfigurationGetData
> +};
> +
> +/**
> +  Set TLS configuration data.
> +
> +  The SetData() function sets TLS configuration to non-volatile storage or
> volatile
> +  storage.
> +
> +  @param[in]  This                Pointer to the
> EFI_TLS_CONFIGURATION_PROTOCOL instance.
> +  @param[in]  DataType            Configuration data type.
> +  @param[in]  Data                Pointer to configuration data.
> +  @param[in]  DataSize            Total size of configuration data.
> +
> +  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  Data is NULL.
> +                                  DataSize is 0.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_OUT_OF_RESOURCES    Required system resources could not
> be allocated.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsConfigurationSetData (
> +  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
> +  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
> +  IN     VOID                            *Data,
> +  IN     UINTN                           DataSize
> +  )
> +{
> +  EFI_STATUS                Status;
> +  TLS_INSTANCE              *Instance;
> +  EFI_TPL                   OldTpl;
> +
> +  Status = EFI_SUCCESS;
> +
> +  if (This == NULL ||  Data == NULL || DataSize == 0) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> +  Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This);
> +
> +  switch (DataType) {
> +  case EfiTlsConfigDataTypeCACertificate:
> +    Status = TlsSetCaCertificate (Instance->TlsConn, Data, DataSize);
> +    break;
> +  case EfiTlsConfigDataTypeHostPublicCert:
> +    Status = TlsSetHostPublicCert (Instance->TlsConn, Data, DataSize);
> +    break;
> +  case EfiTlsConfigDataTypeHostPrivateKey:
> +    Status = TlsSetHostPrivateKey (Instance->TlsConn, Data, DataSize);
> +    break;
> +  case EfiTlsConfigDataTypeCertRevocationList:
> +    Status = TlsSetCertRevocationList (Data, DataSize);
> +    break;
> +  default:
> +     Status = EFI_UNSUPPORTED;
> +  }
> +
> +  gBS->RestoreTPL (OldTpl);
> +  return Status;
> +}
> +
> +/**
> +  Get TLS configuration data.
> +
> +  The GetData() function gets TLS configuration.
> +
> +  @param[in]       This           Pointer to the
> EFI_TLS_CONFIGURATION_PROTOCOL instance.
> +  @param[in]       DataType       Configuration data type.
> +  @param[in, out]  Data           Pointer to configuration data.
> +  @param[in, out]  DataSize       Total size of configuration data. On input, it
> means
> +                                  the size of Data buffer. On output, it means the size
> +                                  of copied Data buffer if EFI_SUCCESS, and means the
> +                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
> +
> +  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  DataSize is NULL.
> +                                  Data is NULL if *DataSize is not zero.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
> +  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsConfigurationGetData (
> +  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
> +  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
> +  IN OUT VOID                            *Data, OPTIONAL
> +  IN OUT UINTN                           *DataSize
> +  )
> +{
> +  EFI_STATUS                Status;
> +  TLS_INSTANCE              *Instance;
> +
> +  EFI_TPL                   OldTpl;
> +
> +  Status = EFI_SUCCESS;
> +
> +  if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0))
> {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> +  Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This);
> +
> +  switch (DataType) {
> +  case EfiTlsConfigDataTypeCACertificate:
> +    Status = TlsGetCaCertificate (Instance->TlsConn, Data, DataSize);
> +    break;
> +  case EfiTlsConfigDataTypeHostPublicCert:
> +    Status = TlsGetHostPublicCert (Instance->TlsConn, Data, DataSize);
> +    break;
> +  case EfiTlsConfigDataTypeHostPrivateKey:
> +    Status = TlsGetHostPrivateKey (Instance->TlsConn, Data, DataSize);
> +    break;
> +  case EfiTlsConfigDataTypeCertRevocationList:
> +    Status = TlsGetCertRevocationList (Data, DataSize);
> +    break;
> +  default:
> +    Status = EFI_UNSUPPORTED;
> +  }
> +
> +  gBS->RestoreTPL (OldTpl);
> +  return Status;
> +}
> diff --git a/NetworkPkg/TlsDxe/TlsDriver.c b/NetworkPkg/TlsDxe/TlsDriver.c
> new file mode 100644
> index 0000000..0a75c39
> --- /dev/null
> +++ b/NetworkPkg/TlsDxe/TlsDriver.c
> @@ -0,0 +1,498 @@
> +/** @file
> +  The Driver Binding and Service Binding Protocol for TlsDxe 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.
> +
> +**/
> +
> +#include "TlsImpl.h"
> +
> +EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding = {
> +  TlsServiceBindingCreateChild,
> +  TlsServiceBindingDestroyChild
> +};
> +
> +/**
> +  Release all the resources used by the TLS instance.
> +
> +  @param[in]  Instance        The TLS instance data.
> +
> +**/
> +VOID
> +TlsCleanInstance (
> +  IN TLS_INSTANCE           *Instance
> +  )
> +{
> +  if (Instance != NULL) {
> +    if (Instance->TlsConn != NULL) {
> +      TlsFree (Instance->TlsConn);
> +    }
> +
> +    FreePool (Instance);
> +  }
> +}
> +
> +/**
> +  Create the TLS instance and initialize it.
> +
> +  @param[in]  Service              The pointer to the TLS service.
> +  @param[out] Instance             The pointer to the TLS instance.
> +
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
> +  @retval EFI_SUCCESS            The TLS instance is created.
> +
> +**/
> +EFI_STATUS
> +TlsCreateInstance (
> +  IN  TLS_SERVICE         *Service,
> +  OUT TLS_INSTANCE        **Instance
> +  )
> +{
> +  TLS_INSTANCE            *TlsInstance;
> +
> +  *Instance = NULL;
> +
> +  TlsInstance = AllocateZeroPool (sizeof (TLS_INSTANCE));
> +  if (TlsInstance == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  TlsInstance->Signature = TLS_INSTANCE_SIGNATURE;
> +  InitializeListHead (&TlsInstance->Link);
> +  TlsInstance->InDestroy = FALSE;
> +  TlsInstance->Service   = Service;
> +
> +  CopyMem (&TlsInstance->Tls, &mTlsProtocol, sizeof (TlsInstance->Tls));
> +  CopyMem (&TlsInstance->TlsConfig, &mTlsConfigurationProtocol, sizeof
> (TlsInstance->TlsConfig));
> +
> +  TlsInstance->TlsSessionState = EfiTlsSessionNotStarted;
> +
> +  *Instance = TlsInstance;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Release all the resources used by the TLS service binding instance.
> +
> +  @param[in]  Service        The TLS service data.
> +
> +**/
> +VOID
> +TlsCleanService (
> +  IN TLS_SERVICE     *Service
> +  )
> +{
> +  if (Service != NULL) {
> +    if (Service->TlsCtx != NULL) {
> +      TlsCtxFree (Service->TlsCtx);
> +    }
> +
> +    FreePool (Service);
> +  }
> +}
> +
> +/**
> +  Create then initialize a TLS service.
> +
> +  @param[in]  Image                  ImageHandle of the TLS driver
> +  @param[out] Service                The service for TLS driver
> +
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create
> the service.
> +  @retval EFI_SUCCESS            The service is created for the driver.
> +
> +**/
> +EFI_STATUS
> +TlsCreateService (
> +  IN  EFI_HANDLE            Image,
> +  OUT TLS_SERVICE           **Service
> +  )
> +{
> +  EFI_STATUS             Status;
> +  TLS_SERVICE            *TlsService;
> +
> +  Status = EFI_SUCCESS;
> +  *Service = NULL;
> +
> +  ASSERT (Service != NULL);
> +
> +  //
> +  // Allocate a TLS Service Data
> +  //
> +  TlsService = AllocateZeroPool (sizeof (TLS_SERVICE));
> +  if (TlsService == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Initialize TLS Service Data
> +  //
> +  TlsService->Signature        = TLS_SERVICE_SIGNATURE;
> +  CopyMem (&TlsService->ServiceBinding, &mTlsServiceBinding, sizeof
> (TlsService->ServiceBinding));
> +  TlsService->TlsChildrenNum   = 0;
> +  InitializeListHead (&TlsService->TlsChildrenList);
> +  TlsService->ImageHandle      = Image;
> +
> +  *Service = TlsService;
> +
> +  return Status;
> +}
> +
> +/**
> +  Unloads an image.
> +
> +  @param[in]  ImageHandle           Handle that identifies the image to be
> unloaded.
> +
> +  @retval EFI_SUCCESS           The image has been unloaded.
> +  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image
> handle.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsUnload (
> +  IN EFI_HANDLE  ImageHandle
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  UINTN                           HandleNum;
> +  EFI_HANDLE                      *HandleBuffer;
> +  UINT32                          Index;
> +  EFI_SERVICE_BINDING_PROTOCOL    *ServiceBinding;
> +  TLS_SERVICE                     *TlsService;
> +
> +  HandleBuffer   = NULL;
> +  ServiceBinding = NULL;
> +  TlsService     = NULL;
> +
> +  //
> +  // Locate all the handles with Tls service binding protocol.
> +  //
> +  Status = gBS->LocateHandleBuffer (
> +                  ByProtocol,
> +                  &gEfiTlsServiceBindingProtocolGuid,
> +                  NULL,
> +                  &HandleNum,
> +                  &HandleBuffer
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  for (Index = 0; Index < HandleNum; Index++) {
> +    //
> +    // Firstly, find ServiceBinding interface
> +    //
> +    Status = gBS->OpenProtocol (
> +                    HandleBuffer[Index],
> +                    &gEfiTlsServiceBindingProtocolGuid,
> +                    (VOID **) &ServiceBinding,
> +                    ImageHandle,
> +                    NULL,
> +                    EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    TlsService = TLS_SERVICE_FROM_THIS (ServiceBinding);
> +
> +    //
> +    // Then, uninstall ServiceBinding interface
> +    //
> +    Status = gBS->UninstallMultipleProtocolInterfaces (
> +                    HandleBuffer[Index],
> +                    &gEfiTlsServiceBindingProtocolGuid, ServiceBinding,
> +                    NULL
> +                    );
> +    if (EFI_ERROR (Status)) {
> +      return Status;
> +    }
> +
> +    TlsCleanService (TlsService);
> +  }
> +
> +  if (HandleBuffer != NULL) {
> +    FreePool (HandleBuffer);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This is the declaration of an EFI image entry point. This entry point is
> +  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
> +  both device drivers and bus drivers.
> +
> +  @param  ImageHandle           The firmware allocated handle for the UEFI
> image.
> +  @param  SystemTable           A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval Others                An unexpected error occurred.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsDriverEntryPoint (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS             Status;
> +
> +  TLS_SERVICE            *TlsService;
> +
> +  //
> +  // Create TLS Service
> +  //
> +  Status = TlsCreateService (ImageHandle, &TlsService);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ASSERT (TlsService != NULL);
> +
> +  //
> +  // Initializes the OpenSSL library.
> +  //
> +  TlsInitialize ();
> +
> +  //
> +  // Create a new SSL_CTX object as framework to establish TLS/SSL enabled
> +  // connections. TLS 1.0 is used as the default version.
> +  //
> +  TlsService->TlsCtx = TlsCtxNew (TLS10_PROTOCOL_VERSION_MAJOR,
> TLS10_PROTOCOL_VERSION_MINOR);
> +  if (TlsService->TlsCtx == NULL) {
> +    FreePool (TlsService);
> +    return EFI_ABORTED;
> +  }
> +
> +  //
> +  // Install the TlsServiceBinding Protocol onto Handle
> +  //
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &TlsService->Handle,
> +                  &gEfiTlsServiceBindingProtocolGuid,
> +                  &TlsService->ServiceBinding,
> +                  NULL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto ON_CLEAN_SERVICE;
> +  }
> +
> +  return Status;
> +
> +ON_CLEAN_SERVICE:
> +  TlsCleanService (TlsService);
> +
> +  return Status;
> +}
> +
> +/**
> +  Creates a child handle and installs a protocol.
> +
> +  The CreateChild() function installs a protocol on ChildHandle.
> +  If ChildHandle is a pointer to NULL, then a new handle is created and
> returned in ChildHandle.
> +  If ChildHandle is not a pointer to NULL, then the protocol installs on the
> existing ChildHandle.
> +
> +  @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL
> instance.
> +  @param[in] ChildHandle Pointer to the handle of the child to create. If it is
> NULL,
> +                         then a new handle is created. If it is a pointer to an existing
> UEFI handle,
> +                         then the protocol is added to the existing UEFI handle.
> +
> +  @retval EFI_SUCCES            The protocol was added to ChildHandle.
> +  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
> +  @retval EFI_OUT_OF_RESOURCES  There are not enough resources
> available to create
> +                                the child.
> +  @retval other                 The child handle was not created.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsServiceBindingCreateChild (
> +  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                    *ChildHandle
> +  )
> +{
> +  TLS_SERVICE         *TlsService;
> +  TLS_INSTANCE        *TlsInstance;
> +  EFI_STATUS           Status;
> +  EFI_TPL              OldTpl;
> +
> +  if ((This == NULL) || (ChildHandle == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TlsService = TLS_SERVICE_FROM_THIS (This);
> +
> +  Status = TlsCreateInstance (TlsService, &TlsInstance);
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ASSERT (TlsInstance != NULL);
> +
> +  //
> +  // Create a new TLS connection object.
> +  //
> +  TlsInstance->TlsConn = TlsNew (TlsService->TlsCtx);
> +  if (TlsInstance->TlsConn == NULL) {
> +    Status = EFI_ABORTED;
> +    goto ON_ERROR;
> +  }
> +
> +  //
> +  // Set default ConnectionEnd to EfiTlsClient
> +  //
> +  Status = TlsSetConnectionEnd (TlsInstance->TlsConn, EfiTlsClient);
> +  if (EFI_ERROR (Status)) {
> +    goto ON_ERROR;
> +  }
> +
> +  //
> +  // Install TLS protocol and configuration protocol onto ChildHandle
> +  //
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  ChildHandle,
> +                  &gEfiTlsProtocolGuid,
> +                  &TlsInstance->Tls,
> +                  &gEfiTlsConfigurationProtocolGuid,
> +                  &TlsInstance->TlsConfig,
> +                  NULL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto ON_ERROR;
> +  }
> +
> +  TlsInstance->ChildHandle = *ChildHandle;
> +
> +  //
> +  // Add it to the TLS service's child list.
> +  //
> +  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> +  InsertTailList (&TlsService->TlsChildrenList, &TlsInstance->Link);
> +  TlsService->TlsChildrenNum++;
> +
> +  gBS->RestoreTPL (OldTpl);
> +
> +  return EFI_SUCCESS;
> +
> +ON_ERROR:
> +  TlsCleanInstance (TlsInstance);
> +  return Status;
> +}
> +
> +/**
> +  Destroys a child handle with a protocol installed on it.
> +
> +  The DestroyChild() function does the opposite of CreateChild(). It removes
> a protocol
> +  that was installed by CreateChild() from ChildHandle. If the removed
> protocol is the
> +  last protocol on ChildHandle, then ChildHandle is destroyed.
> +
> +  @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL
> instance.
> +  @param  ChildHandle Handle of the child to destroy.
> +
> +  @retval EFI_SUCCES            The protocol was removed from ChildHandle.
> +  @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol
> that is being removed.
> +  @retval EFI_INVALID_PARAMETER Child handle is NULL.
> +  @retval EFI_ACCESS_DENIED     The protocol could not be removed from
> the ChildHandle
> +                                because its services are being used.
> +  @retval other                 The child handle was not destroyed.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsServiceBindingDestroyChild (
> +  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                    ChildHandle
> +  )
> +{
> +  TLS_SERVICE                    *TlsService;
> +  TLS_INSTANCE                   *TlsInstance;
> +
> +  EFI_TLS_PROTOCOL               *Tls;
> +  EFI_TLS_CONFIGURATION_PROTOCOL *TlsConfig;
> +  EFI_STATUS                     Status;
> +  EFI_TPL                        OldTpl;
> +
> +  if ((This == NULL) || (ChildHandle == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  TlsService = TLS_SERVICE_FROM_THIS (This);
> +
> +  //
> +  // Find TLS protocol interface installed in ChildHandle
> +  //
> +  Status = gBS->OpenProtocol (
> +                  ChildHandle,
> +                  &gEfiTlsProtocolGuid,
> +                  (VOID **) &Tls,
> +                  TlsService->ImageHandle,
> +                  NULL,
> +                  EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Find TLS configuration protocol interface installed in ChildHandle
> +  //
> +  Status = gBS->OpenProtocol (
> +                  ChildHandle,
> +                  &gEfiTlsConfigurationProtocolGuid,
> +                  (VOID **) &TlsConfig,
> +                  TlsService->ImageHandle,
> +                  NULL,
> +                  EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  TlsInstance  = TLS_INSTANCE_FROM_PROTOCOL_THIS (Tls);
> +
> +  if (TlsInstance->Service != TlsService) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (TlsInstance->InDestroy) {
> +    return EFI_SUCCESS;
> +  }
> +
> +  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> +  TlsInstance->InDestroy = TRUE;
> +
> +  //
> +  // Uninstall the TLS protocol and TLS Configuration Protocol interface
> installed in ChildHandle.
> +  //
> +  Status = gBS->UninstallMultipleProtocolInterfaces (
> +                  ChildHandle,
> +                  &gEfiTlsProtocolGuid,
> +                  Tls,
> +                  &gEfiTlsConfigurationProtocolGuid,
> +                  TlsConfig,
> +                  NULL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  RemoveEntryList (&TlsInstance->Link);
> +  TlsService->TlsChildrenNum--;
> +
> +  gBS->RestoreTPL (OldTpl);
> +
> +  TlsCleanInstance (TlsInstance);
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/NetworkPkg/TlsDxe/TlsDriver.h b/NetworkPkg/TlsDxe/TlsDriver.h
> new file mode 100644
> index 0000000..c3c30a8
> --- /dev/null
> +++ b/NetworkPkg/TlsDxe/TlsDriver.h
> @@ -0,0 +1,237 @@
> +/** @file
> +  Header file of the Driver Binding and Service Binding Protocol for TlsDxe
> 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_TLS_DRIVER_H__
> +#define __EFI_TLS_DRIVER_H__
> +
> +#include <Uefi.h>
> +
> +//
> +// Driver Protocols
> +//
> +#include <Protocol/ServiceBinding.h>
> +
> +//
> +// Driver Version
> +//
> +#define TLS_VERSION  0x00000000
> +
> +#define TLS_SERVICE_SIGNATURE    SIGNATURE_32 ('T', 'L', 'S', 'S')
> +
> +#define TLS_INSTANCE_SIGNATURE   SIGNATURE_32 ('T', 'L', 'S', 'I')
> +
> +///
> +/// TLS Service Data
> +///
> +typedef struct _TLS_SERVICE  TLS_SERVICE;
> +
> +///
> +/// TLS Instance Data
> +///
> +typedef struct _TLS_INSTANCE TLS_INSTANCE;
> +
> +
> +struct _TLS_SERVICE {
> +  UINT32                          Signature;
> +  EFI_SERVICE_BINDING_PROTOCOL    ServiceBinding;
> +
> +  UINT16                          TlsChildrenNum;
> +  LIST_ENTRY                      TlsChildrenList;
> +
> +  //
> +  // Handle to install TlsServiceBinding protocol.
> +  //
> +  EFI_HANDLE                      Handle;
> +  EFI_HANDLE                      ImageHandle;
> +
> +  //
> +  // Main SSL Context object which is created by a server or client once per
> program
> +  // life-time and which holds mainly default values for the SSL object which
> are later
> +  // created for the connections.
> +  //
> +  VOID                            *TlsCtx;
> +};
> +
> +struct _TLS_INSTANCE {
> +  UINT32                          Signature;
> +  LIST_ENTRY                      Link;
> +
> +  BOOLEAN                         InDestroy;
> +
> +  TLS_SERVICE                     *Service;
> +  EFI_HANDLE                      ChildHandle;
> +
> +  EFI_TLS_PROTOCOL                Tls;
> +  EFI_TLS_CONFIGURATION_PROTOCOL  TlsConfig;
> +
> +  EFI_TLS_SESSION_STATE           TlsSessionState;
> +
> +  //
> +  // Main SSL Connection which is created by a server or a client
> +  // per established connection.
> +  //
> +  VOID                            *TlsConn;
> +};
> +
> +
> +#define TLS_SERVICE_FROM_THIS(a)   \
> +  CR (a, TLS_SERVICE, ServiceBinding, TLS_SERVICE_SIGNATURE)
> +
> +#define TLS_INSTANCE_FROM_PROTOCOL_THIS(a)  \
> +  CR (a, TLS_INSTANCE, Tls, TLS_INSTANCE_SIGNATURE)
> +
> +#define TLS_INSTANCE_FROM_CONFIGURATION_THIS(a)  \
> +  CR (a, TLS_INSTANCE, TlsConfig, TLS_INSTANCE_SIGNATURE)
> +
> +
> +/**
> +  Release all the resources used by the TLS instance.
> +
> +  @param[in]  Instance        The TLS instance data.
> +
> +**/
> +VOID
> +TlsCleanInstance (
> +  IN TLS_INSTANCE           *Instance
> +  );
> +
> +/**
> +  Create the TLS instance and initialize it.
> +
> +  @param[in]  Service              The pointer to the TLS service.
> +  @param[out] Instance             The pointer to the TLS instance.
> +
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resources.
> +  @retval EFI_SUCCESS            The TLS instance is created.
> +
> +**/
> +EFI_STATUS
> +TlsCreateInstance (
> +  IN  TLS_SERVICE         *Service,
> +  OUT TLS_INSTANCE        **Instance
> +  );
> +
> +/**
> +  Release all the resources used by the TLS service binding instance.
> +
> +  @param[in]  Service        The TLS service data.
> +
> +**/
> +VOID
> +TlsCleanService (
> +  IN TLS_SERVICE     *Service
> +  );
> +
> +/**
> +  Create then initialize a TLS service.
> +
> +  @param[in]  Image                  ImageHandle of the TLS driver
> +  @param[out] Service                The service for TLS driver
> +
> +  @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource to create
> the service.
> +  @retval EFI_SUCCESS            The service is created for the driver.
> +
> +**/
> +EFI_STATUS
> +TlsCreateService (
> +  IN  EFI_HANDLE            Image,
> +  OUT TLS_SERVICE           **Service
> +  );
> +
> +/**
> +  Unloads an image.
> +
> +  @param[in]  ImageHandle       Handle that identifies the image to be
> unloaded.
> +
> +  @retval EFI_SUCCESS           The image has been unloaded.
> +  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image
> handle.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsUnload (
> +  IN EFI_HANDLE  ImageHandle
> +  );
> +
> +/**
> +  This is the declaration of an EFI image entry point. This entry point is
> +  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
> +  both device drivers and bus drivers.
> +
> +  @param  ImageHandle           The firmware allocated handle for the UEFI
> image.
> +  @param  SystemTable           A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval Others                An unexpected error occurred.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsDriverEntryPoint (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  );
> +
> +/**
> +  Creates a child handle and installs a protocol.
> +
> +  The CreateChild() function installs a protocol on ChildHandle.
> +  If ChildHandle is a pointer to NULL, then a new handle is created and
> returned in ChildHandle.
> +  If ChildHandle is not a pointer to NULL, then the protocol installs on the
> existing ChildHandle.
> +
> +  @param[in] This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL
> instance.
> +  @param[in] ChildHandle Pointer to the handle of the child to create. If it is
> NULL,
> +                         then a new handle is created. If it is a pointer to an existing
> UEFI handle,
> +                         then the protocol is added to the existing UEFI handle.
> +
> +  @retval EFI_SUCCES            The protocol was added to ChildHandle.
> +  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
> +  @retval EFI_OUT_OF_RESOURCES  There are not enough resources
> available to create
> +                                the child.
> +  @retval other                 The child handle was not created.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsServiceBindingCreateChild (
> +  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                    *ChildHandle
> +  );
> +
> +/**
> +  Destroys a child handle with a protocol installed on it.
> +
> +  The DestroyChild() function does the opposite of CreateChild(). It removes
> a protocol
> +  that was installed by CreateChild() from ChildHandle. If the removed
> protocol is the
> +  last protocol on ChildHandle, then ChildHandle is destroyed.
> +
> +  @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL
> instance.
> +  @param  ChildHandle Handle of the child to destroy.
> +
> +  @retval EFI_SUCCES            The protocol was removed from ChildHandle.
> +  @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol
> that is being removed.
> +  @retval EFI_INVALID_PARAMETER Child handle is NULL.
> +  @retval EFI_ACCESS_DENIED     The protocol could not be removed from
> the ChildHandle
> +                                because its services are being used.
> +  @retval other                 The child handle was not destroyed.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsServiceBindingDestroyChild (
> +  IN EFI_SERVICE_BINDING_PROTOCOL  *This,
> +  IN EFI_HANDLE                    ChildHandle
> +  );
> +
> +#endif
> diff --git a/NetworkPkg/TlsDxe/TlsDxe.inf b/NetworkPkg/TlsDxe/TlsDxe.inf
> new file mode 100644
> index 0000000..dba3257
> --- /dev/null
> +++ b/NetworkPkg/TlsDxe/TlsDxe.inf
> @@ -0,0 +1,65 @@
> +## @file
> +#  This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol
> and
> +#  EFI TLS Configuration Protocol.
> +#
> +#  This module produces EFI TLS (Transport Layer Security) Protocol and EFI
> TLS
> +#  Service Binding Protocol, to provide TLS services.
> +#
> +#  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.
> +#
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION               = 0x00010005
> +  BASE_NAME                 = TlsDxe
> +  FILE_GUID                 = 3aceb0c0-3c72-11e4-9a56-74d435052646
> +  MODULE_TYPE               = UEFI_DRIVER
> +  VERSION_STRING            = 1.0
> +  ENTRY_POINT               = TlsDriverEntryPoint
> +  UNLOAD_IMAGE              = TlsUnload
> +  MODULE_UNI_FILE           = TlsDxe.uni
> +
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  CryptoPkg/CryptoPkg.dec
> +
> +[Sources]
> +  TlsDriver.h
> +  TlsDriver.c
> +  TlsProtocol.c
> +  TlsConfigProtocol.c
> +  TlsImpl.h
> +  TlsImpl.c
> +
> +[LibraryClasses]
> +  UefiDriverEntryPoint
> +  UefiBootServicesTableLib
> +  MemoryAllocationLib
> +  BaseMemoryLib
> +  BaseLib
> +  UefiLib
> +  DebugLib
> +  NetLib
> +  BaseCryptLib
> +  TlsLib
> +
> +[Protocols]
> +  gEfiTlsServiceBindingProtocolGuid          ## PRODUCES
> +  gEfiTlsProtocolGuid                        ## PRODUCES
> +  gEfiTlsConfigurationProtocolGuid           ## PRODUCES
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  TlsDxeExtra.uni
> diff --git a/NetworkPkg/TlsDxe/TlsDxe.uni b/NetworkPkg/TlsDxe/TlsDxe.uni
> new file mode 100644
> index 0000000..98c41ca
> --- /dev/null
> +++ b/NetworkPkg/TlsDxe/TlsDxe.uni
> @@ -0,0 +1,25 @@
> +// /** @file
> +// This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol
> and
> +// EFI TLS Configuration Protocol.
> +//
> +// This module produces EFI TLS (Transport Layer Security) Protocol, EFI TLS
> +// Service Binding Protocol, and EFI TLS Configuration Protocol to provide
> TLS
> +// services.
> +//
> +// 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.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "UEFI TLS service"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This module
> produces EFI TLS Protocol, EFI TLS Service Binding Protocol and EFI TLS
> Configuration Protocol to provide EFI TLS services."
> +
> diff --git a/NetworkPkg/TlsDxe/TlsDxeExtra.uni
> b/NetworkPkg/TlsDxe/TlsDxeExtra.uni
> new file mode 100644
> index 0000000..a38582a
> --- /dev/null
> +++ b/NetworkPkg/TlsDxe/TlsDxeExtra.uni
> @@ -0,0 +1,18 @@
> +// /** @file
> +// TlsDxe Localized Strings and Content
> +//
> +// 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.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"EFI TLS DXE Driver"
> diff --git a/NetworkPkg/TlsDxe/TlsImpl.c b/NetworkPkg/TlsDxe/TlsImpl.c
> new file mode 100644
> index 0000000..5fb1e78
> --- /dev/null
> +++ b/NetworkPkg/TlsDxe/TlsImpl.c
> @@ -0,0 +1,270 @@
> +/** @file
> +  The Miscellaneous Routines for TlsDxe 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.
> +
> +**/
> +
> +#include "TlsImpl.h"
> +
> +/**
> +  Encrypt the message listed in fragment.
> +
> +  @param[in]       TlsInstance    The pointer to the TLS instance.
> +  @param[in, out]  FragmentTable  Pointer to a list of fragment.
> +                                  On input these fragments contain the TLS header and
> +                                  plain text TLS payload;
> +                                  On output these fragments contain the TLS header and
> +                                  cipher text TLS payload.
> +  @param[in]       FragmentCount  Number of fragment.
> +
> +  @retval EFI_SUCCESS             The operation completed successfully.
> +  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
> +  @retval EFI_ABORTED             TLS session state is incorrect.
> +  @retval Others                  Other errors as indicated.
> +**/
> +EFI_STATUS
> +TlsEcryptPacket (
> +  IN     TLS_INSTANCE                  *TlsInstance,
> +  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
> +  IN     UINT32                        *FragmentCount
> +  )
> +{
> +  UINTN               Index;
> +  UINT32              BytesCopied;
> +  UINT32              BufferInSize;
> +  UINT8               *BufferIn;
> +  UINT8               *BufferInPtr;
> +  TLS_RECORD_HEADER   *RecordHeaderIn;
> +  UINT16              ThisPlainMessageSize;
> +  TLS_RECORD_HEADER   *TempRecordHeader;
> +  UINT16              ThisMessageSize;
> +  UINT32              BufferOutSize;
> +  UINT8               *BufferOut;
> +  INTN                Ret;
> +
> +  BytesCopied      = 0;
> +  BufferInSize     = 0;
> +  BufferIn         = NULL;
> +  BufferInPtr      = NULL;
> +  RecordHeaderIn   = NULL;
> +  TempRecordHeader = NULL;
> +  BufferOutSize    = 0;
> +  BufferOut        = NULL;
> +  Ret              = 0;
> +
> +  //
> +  // Calculate the size according to the fragment table.
> +  //
> +  for (Index = 0; Index < *FragmentCount; Index++) {
> +    BufferInSize += (*FragmentTable)[Index].FragmentLength;
> +  }
> +
> +  //
> +  // Allocate buffer for processing data.
> +  //
> +  BufferIn = AllocateZeroPool (BufferInSize);
> +  if (BufferIn == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Copy all TLS plain record header and payload into ProcessBuffer.
> +  //
> +  for (Index = 0; Index < *FragmentCount; Index++) {
> +    CopyMem (
> +      (BufferIn + BytesCopied),
> +      (*FragmentTable)[Index].FragmentBuffer,
> +      (*FragmentTable)[Index].FragmentLength
> +      );
> +    BytesCopied += (*FragmentTable)[Index].FragmentLength;
> +  }
> +
> +  BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE);
> +  if (BufferOut == NULL) {
> +    FreePool (BufferIn);
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Parsing buffer.
> +  //
> +  BufferInPtr = BufferIn;
> +  TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
> +  while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
> +    RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
> +    ASSERT (RecordHeaderIn->ContentType ==
> TLS_CONTENT_TYPE_APPLICATION_DATA);
> +    ThisPlainMessageSize = RecordHeaderIn->Length;
> +
> +    TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1),
> ThisPlainMessageSize);
> +
> +    Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8
> *)(TempRecordHeader), MAX_BUFFER_SIZE);
> +
> +    if (Ret > 0) {
> +      ThisMessageSize = (UINT16) Ret;
> +    } else {
> +      ThisMessageSize = 0;
> +    }
> +
> +    BufferOutSize += ThisMessageSize;
> +
> +    BufferInPtr += RECORD_HEADER_LEN + ThisPlainMessageSize;
> +    TempRecordHeader += ThisMessageSize;
> +  }
> +
> +  FreePool (BufferIn);
> +
> +  //
> +  // The caller will take responsible to handle the original fragment table.
> +  //
> +  *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
> +  if (*FragmentTable == NULL) {
> +    FreePool (BufferOut);
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  (*FragmentTable)[0].FragmentBuffer  = BufferOut;
> +  (*FragmentTable)[0].FragmentLength  = BufferOutSize;
> +  *FragmentCount                      = 1;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Decrypt the message listed in fragment.
> +
> +  @param[in]       TlsInstance    The pointer to the TLS instance.
> +  @param[in, out]  FragmentTable  Pointer to a list of fragment.
> +                                  On input these fragments contain the TLS header and
> +                                  cipher text TLS payload;
> +                                  On output these fragments contain the TLS header and
> +                                  plain text TLS payload.
> +  @param[in]       FragmentCount  Number of fragment.
> +
> +  @retval EFI_SUCCESS             The operation completed successfully.
> +  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
> +  @retval EFI_ABORTED             TLS session state is incorrect.
> +  @retval Others                  Other errors as indicated.
> +**/
> +EFI_STATUS
> +TlsDecryptPacket (
> +  IN     TLS_INSTANCE                  *TlsInstance,
> +  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
> +  IN     UINT32                        *FragmentCount
> +  )
> +{
> +  UINTN               Index;
> +  UINT32              BytesCopied;
> +  UINT8               *BufferIn;
> +  UINT32              BufferInSize;
> +  UINT8               *BufferInPtr;
> +  TLS_RECORD_HEADER   *RecordHeaderIn;
> +  UINT16              ThisCipherMessageSize;
> +  TLS_RECORD_HEADER   *TempRecordHeader;
> +  UINT16              ThisPlainMessageSize;
> +  UINT8               *BufferOut;
> +  UINT32              BufferOutSize;
> +  INTN                Ret;
> +
> +  BytesCopied      = 0;
> +  BufferIn         = NULL;
> +  BufferInSize     = 0;
> +  BufferInPtr      = NULL;
> +  RecordHeaderIn   = NULL;
> +  TempRecordHeader = NULL;
> +  BufferOut        = NULL;
> +  BufferOutSize    = 0;
> +  Ret              = 0;
> +
> +  //
> +  // Calculate the size according to the fragment table.
> +  //
> +  for (Index = 0; Index < *FragmentCount; Index++) {
> +    BufferInSize += (*FragmentTable)[Index].FragmentLength;
> +  }
> +
> +  //
> +  // Allocate buffer for processing data
> +  //
> +  BufferIn = AllocateZeroPool (BufferInSize);
> +  if (BufferIn == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Copy all TLS plain record header and payload to ProcessBuffer
> +  //
> +  for (Index = 0; Index < *FragmentCount; Index++) {
> +    CopyMem (
> +      (BufferIn + BytesCopied),
> +      (*FragmentTable)[Index].FragmentBuffer,
> +      (*FragmentTable)[Index].FragmentLength
> +      );
> +    BytesCopied += (*FragmentTable)[Index].FragmentLength;
> +  }
> +
> +  BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE);
> +  if (BufferOut == NULL) {
> +    FreePool (BufferIn);
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Parsing buffer. Received packet may have multiply TLS record message.
> +  //
> +  BufferInPtr = BufferIn;
> +  TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut;
> +  while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) {
> +    RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr;
> +    ASSERT (RecordHeaderIn->ContentType ==
> TLS_CONTENT_TYPE_APPLICATION_DATA);
> +    ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length);
> +
> +    Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn),
> RECORD_HEADER_LEN + ThisCipherMessageSize);
> +    if (Ret != RECORD_HEADER_LEN + ThisCipherMessageSize) {
> +      FreePool (BufferIn);
> +      TlsInstance->TlsSessionState = EfiTlsSessionError;
> +      return EFI_ABORTED;
> +    }
> +
> +    Ret = 0;
> +    Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1),
> MAX_BUFFER_SIZE);
> +
> +    if (Ret > 0) {
> +      ThisPlainMessageSize = (UINT16) Ret;
> +    } else {
> +      ThisPlainMessageSize = 0;
> +    }
> +
> +    CopyMem (TempRecordHeader, RecordHeaderIn,
> RECORD_HEADER_LEN);
> +    TempRecordHeader->Length = ThisPlainMessageSize;
> +    BufferOutSize += RECORD_HEADER_LEN + ThisPlainMessageSize;
> +
> +    BufferInPtr += RECORD_HEADER_LEN + ThisCipherMessageSize;
> +    TempRecordHeader += RECORD_HEADER_LEN + ThisPlainMessageSize;
> +  }
> +
> +  FreePool (BufferIn);
> +
> +  //
> +  // The caller will take responsible to handle the original fragment table
> +  //
> +  *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
> +  if (*FragmentTable == NULL) {
> +    FreePool (BufferOut);
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  (*FragmentTable)[0].FragmentBuffer  = BufferOut;
> +  (*FragmentTable)[0].FragmentLength  = BufferOutSize;
> +  *FragmentCount                      = 1;
> +
> +  return EFI_SUCCESS;
> +}
> diff --git a/NetworkPkg/TlsDxe/TlsImpl.h b/NetworkPkg/TlsDxe/TlsImpl.h
> new file mode 100644
> index 0000000..b0615cb
> --- /dev/null
> +++ b/NetworkPkg/TlsDxe/TlsImpl.h
> @@ -0,0 +1,315 @@
> +/** @file
> +  Header file of Miscellaneous Routines for TlsDxe 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_TLS_IMPL_H__
> +#define __EFI_TLS_IMPL_H__
> +
> +//
> +// Libraries
> +//
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/NetLib.h>
> +#include <Library/BaseCryptLib.h>
> +#include <Library/TlsLib.h>
> +
> +//
> +// Consumed Protocols
> +//
> +#include <Protocol/Tls.h>
> +#include <Protocol/TlsConfig.h>
> +
> +#include <IndustryStandard/Tls1.h>
> +
> +#include "TlsDriver.h"
> +
> +//
> +// Protocol instances
> +//
> +extern EFI_SERVICE_BINDING_PROTOCOL    mTlsServiceBinding;
> +extern EFI_TLS_PROTOCOL                mTlsProtocol;
> +extern EFI_TLS_CONFIGURATION_PROTOCOL  mTlsConfigurationProtocol;
> +
> +#define RECORD_HEADER_LEN 5 /// ContentType(1) + Version(2) +
> Length(2)
> +
> +#define MAX_BUFFER_SIZE   32768
> +
> +/**
> +  Encrypt the message listed in fragment.
> +
> +  @param[in]       TlsInstance    The pointer to the TLS instance.
> +  @param[in, out]  FragmentTable  Pointer to a list of fragment.
> +                                  On input these fragments contain the TLS header and
> +                                  plain text TLS payload;
> +                                  On output these fragments contain the TLS header and
> +                                  cipher text TLS payload.
> +  @param[in]       FragmentCount  Number of fragment.
> +
> +  @retval EFI_SUCCESS             The operation completed successfully.
> +  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
> +  @retval EFI_ABORTED             TLS session state is incorrect.
> +  @retval Others                  Other errors as indicated.
> +**/
> +EFI_STATUS
> +TlsEcryptPacket (
> +  IN     TLS_INSTANCE                  *TlsInstance,
> +  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
> +  IN     UINT32                        *FragmentCount
> +  );
> +
> +/**
> +  Decrypt the message listed in fragment.
> +
> +  @param[in]       TlsInstance    The pointer to the TLS instance.
> +  @param[in, out]  FragmentTable  Pointer to a list of fragment.
> +                                  On input these fragments contain the TLS header and
> +                                  cipher text TLS payload;
> +                                  On output these fragments contain the TLS header and
> +                                  plain text TLS payload.
> +  @param[in]       FragmentCount  Number of fragment.
> +
> +  @retval EFI_SUCCESS             The operation completed successfully.
> +  @retval EFI_OUT_OF_RESOURCES    Can't allocate memory resources.
> +  @retval EFI_ABORTED             TLS session state is incorrect.
> +  @retval Others                  Other errors as indicated.
> +**/
> +EFI_STATUS
> +TlsDecryptPacket (
> +  IN     TLS_INSTANCE                  *TlsInstance,
> +  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
> +  IN     UINT32                        *FragmentCount
> +  );
> +
> +/**
> +  Set TLS session data.
> +
> +  The SetSessionData() function set data for a new TLS session. All session
> data should
> +  be set before BuildResponsePacket() invoked.
> +
> +  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in]  DataType            TLS session data type.
> +  @param[in]  Data                Pointer to session data.
> +  @param[in]  DataSize            Total size of session data.
> +
> +  @retval EFI_SUCCESS             The TLS session data is set successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  Data is NULL.
> +                                  DataSize is 0.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
> +                                  EfiTlsClientRandom
> +                                  EfiTlsServerRandom
> +                                  EfiTlsKeyMaterial
> +  @retval EFI_NOT_READY           Current TLS session state is NOT
> +                                  EfiTlsSessionStateNotStarted.
> +  @retval EFI_OUT_OF_RESOURCES    Required system resources could not
> be allocated.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetSessionData (
> +  IN     EFI_TLS_PROTOCOL              *This,
> +  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
> +  IN     VOID                          *Data,
> +  IN     UINTN                         DataSize
> +  );
> +
> +/**
> +  Get TLS session data.
> +
> +  The GetSessionData() function return the TLS session information.
> +
> +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in]       DataType       TLS session data type.
> +  @param[in, out]  Data           Pointer to session data.
> +  @param[in, out]  DataSize       Total size of session data. On input, it means
> +                                  the size of Data buffer. On output, it means the size
> +                                  of copied Data buffer if EFI_SUCCESS, and means the
> +                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
> +
> +  @retval EFI_SUCCESS             The TLS session data is got successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  DataSize is NULL.
> +                                  Data is NULL if *DataSize is not zero.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_NOT_FOUND           The TLS session data is not found.
> +  @retval EFI_NOT_READY           The DataType is not ready in current session
> state.
> +  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetSessionData (
> +  IN     EFI_TLS_PROTOCOL              *This,
> +  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
> +  IN OUT VOID                          *Data,  OPTIONAL
> +  IN OUT UINTN                         *DataSize
> +  );
> +
> +/**
> +  Build response packet according to TLS state machine. This function is only
> valid for
> +  alert, handshake and change_cipher_spec content type.
> +
> +  The BuildResponsePacket() function builds TLS response packet in
> response to the TLS
> +  request packet specified by RequestBuffer and RequestSize. If
> RequestBuffer is NULL and
> +  RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS
> session
> +  will be initiated and the response packet needs to be ClientHello. If
> RequestBuffer is
> +  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing,
> the TLS
> +  session will be closed and response packet needs to be CloseNotify. If
> RequestBuffer is
> +  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the
> TLS
> +  session has errors and the response packet needs to be Alert message
> based on error
> +  type.
> +
> +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in]       RequestBuffer  Pointer to the most recently received TLS
> packet. NULL
> +                                  means TLS need initiate the TLS session and response
> +                                  packet need to be ClientHello.
> +  @param[in]       RequestSize    Packet size in bytes for the most recently
> received TLS
> +                                  packet. 0 is only valid when RequestBuffer is NULL.
> +  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
> +  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input,
> it is
> +                                  the buffer size provided by the caller. On output, it
> +                                  is the buffer size in fact needed to contain the
> +                                  packet.
> +
> +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  RequestBuffer is NULL but RequestSize is NOT 0.
> +                                  RequestSize is 0 but RequestBuffer is NOT NULL.
> +                                  BufferSize is NULL.
> +                                  Buffer is NULL if *BufferSize is not zero.
> +  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the
> response packet.
> +  @retval EFI_NOT_READY           Current TLS session state is NOT ready to
> build
> +                                  ResponsePacket.
> +  @retval EFI_ABORTED             Something wrong build response packet.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsBuildResponsePacket (
> +  IN     EFI_TLS_PROTOCOL              *This,
> +  IN     UINT8                         *RequestBuffer, OPTIONAL
> +  IN     UINTN                         RequestSize, OPTIONAL
> +     OUT UINT8                         *Buffer, OPTIONAL
> +  IN OUT UINTN                         *BufferSize
> +  );
> +
> +/**
> +  Decrypt or encrypt TLS packet during session. This function is only valid
> after
> +  session connected and for application_data content type.
> +
> +  The ProcessPacket () function process each inbound or outbound TLS APP
> packet.
> +
> +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in, out]  FragmentTable  Pointer to a list of fragment. The caller
> will take
> +                                  responsible to handle the original FragmentTable while
> +                                  it may be reallocated in TLS driver. If CryptMode is
> +                                  EfiTlsEncrypt, on input these fragments contain the TLS
> +                                  header and plain text TLS APP payload; on output these
> +                                  fragments contain the TLS header and cipher text TLS
> +                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
> +                                  these fragments contain the TLS header and cipher text
> +                                  TLS APP payload; on output these fragments contain the
> +                                  TLS header and plain text TLS APP payload.
> +  @param[in]       FragmentCount  Number of fragment.
> +  @param[in]       CryptMode      Crypt mode.
> +
> +  @retval EFI_SUCCESS             The operation completed successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  FragmentTable is NULL.
> +                                  FragmentCount is NULL.
> +                                  CryptoMode is invalid.
> +  @retval EFI_NOT_READY           Current TLS session state is NOT
> +                                  EfiTlsSessionDataTransferring.
> +  @retval EFI_ABORTED             Something wrong decryption the message.
> TLS session
> +                                  status will become EfiTlsSessionError. The caller need
> +                                  call BuildResponsePacket() to generate Error Alert
> +                                  message and send it out.
> +  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the
> operation.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsProcessPacket (
> +  IN     EFI_TLS_PROTOCOL              *This,
> +  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
> +  IN     UINT32                        *FragmentCount,
> +  IN     EFI_TLS_CRYPT_MODE            CryptMode
> +  );
> +
> +/**
> +  Set TLS configuration data.
> +
> +  The SetData() function sets TLS configuration to non-volatile storage or
> volatile
> +  storage.
> +
> +  @param[in]  This                Pointer to the
> EFI_TLS_CONFIGURATION_PROTOCOL instance.
> +  @param[in]  DataType            Configuration data type.
> +  @param[in]  Data                Pointer to configuration data.
> +  @param[in]  DataSize            Total size of configuration data.
> +
> +  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  Data is NULL.
> +                                  DataSize is 0.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_OUT_OF_RESOURCES    Required system resources could not
> be allocated.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsConfigurationSetData (
> +  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
> +  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
> +  IN     VOID                            *Data,
> +  IN     UINTN                           DataSize
> +  );
> +
> +/**
> +  Get TLS configuration data.
> +
> +  The GetData() function gets TLS configuration.
> +
> +  @param[in]       This           Pointer to the
> EFI_TLS_CONFIGURATION_PROTOCOL instance.
> +  @param[in]       DataType       Configuration data type.
> +  @param[in, out]  Data           Pointer to configuration data.
> +  @param[in, out]  DataSize       Total size of configuration data. On input, it
> means
> +                                  the size of Data buffer. On output, it means the size
> +                                  of copied Data buffer if EFI_SUCCESS, and means the
> +                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
> +
> +  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  DataSize is NULL.
> +                                  Data is NULL if *DataSize is not zero.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
> +  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsConfigurationGetData (
> +  IN     EFI_TLS_CONFIGURATION_PROTOCOL  *This,
> +  IN     EFI_TLS_CONFIG_DATA_TYPE        DataType,
> +  IN OUT VOID                            *Data, OPTIONAL
> +  IN OUT UINTN                           *DataSize
> +  );
> +
> +#endif
> diff --git a/NetworkPkg/TlsDxe/TlsProtocol.c
> b/NetworkPkg/TlsDxe/TlsProtocol.c
> new file mode 100644
> index 0000000..bc617e1
> --- /dev/null
> +++ b/NetworkPkg/TlsDxe/TlsProtocol.c
> @@ -0,0 +1,632 @@
> +/** @file
> +  Implementation of EFI TLS Protocol Interfaces.
> +
> +  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.
> +
> +**/
> +
> +#include "TlsImpl.h"
> +
> +EFI_TLS_PROTOCOL  mTlsProtocol = {
> +  TlsSetSessionData,
> +  TlsGetSessionData,
> +  TlsBuildResponsePacket,
> +  TlsProcessPacket
> +};
> +
> +/**
> +  Set TLS session data.
> +
> +  The SetSessionData() function set data for a new TLS session. All session
> data should
> +  be set before BuildResponsePacket() invoked.
> +
> +  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in]  DataType            TLS session data type.
> +  @param[in]  Data                Pointer to session data.
> +  @param[in]  DataSize            Total size of session data.
> +
> +  @retval EFI_SUCCESS             The TLS session data is set successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  Data is NULL.
> +                                  DataSize is 0.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
> +                                  EfiTlsClientRandom
> +                                  EfiTlsServerRandom
> +                                  EfiTlsKeyMaterial
> +  @retval EFI_NOT_READY           Current TLS session state is NOT
> +                                  EfiTlsSessionStateNotStarted.
> +  @retval EFI_OUT_OF_RESOURCES    Required system resources could not
> be allocated.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetSessionData (
> +  IN     EFI_TLS_PROTOCOL              *This,
> +  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
> +  IN     VOID                          *Data,
> +  IN     UINTN                         DataSize
> +  )
> +{
> +  EFI_STATUS                Status;
> +  TLS_INSTANCE              *Instance;
> +  UINT16                    *CipherId;
> +  UINTN                     Index;
> +
> +  EFI_TPL                   OldTpl;
> +
> +  Status = EFI_SUCCESS;
> +  CipherId = NULL;
> +
> +  if (This == NULL || Data == NULL || DataSize == 0) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> +  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
> +
> +  if (DataType != EfiTlsSessionState  && Instance->TlsSessionState !=
> EfiTlsSessionNotStarted){
> +    Status = EFI_NOT_READY;
> +    goto ON_EXIT;
> +  }
> +
> +  switch (DataType) {
> +  //
> +  // Session Configuration
> +  //
> +  case EfiTlsVersion:
> +    if (DataSize != sizeof (EFI_TLS_VERSION)) {
> +      Status = EFI_INVALID_PARAMETER;
> +      goto ON_EXIT;
> +    }
> +
> +    Status = TlsSetVersion (Instance->TlsConn, ((EFI_TLS_VERSION *) Data)-
> >Major, ((EFI_TLS_VERSION *) Data)->Minor);
> +    break;
> +  case EfiTlsConnectionEnd:
> +    if (DataSize != sizeof (EFI_TLS_CONNECTION_END)) {
> +      Status = EFI_INVALID_PARAMETER;
> +      goto ON_EXIT;
> +    }
> +
> +    Status = TlsSetConnectionEnd (Instance->TlsConn,
> *((EFI_TLS_CONNECTION_END *) Data));
> +    break;
> +  case EfiTlsCipherList:
> +    CipherId = AllocatePool (DataSize);
> +    if (CipherId == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ON_EXIT;
> +    }
> +
> +    for (Index = 0; Index < DataSize / sizeof (EFI_TLS_CIPHER); Index++) {
> +      *(CipherId +Index) = HTONS (*(((UINT16 *) Data) + Index));
> +    }
> +
> +    Status = TlsSetCipherList (Instance->TlsConn, CipherId, DataSize / sizeof
> (EFI_TLS_CIPHER));
> +
> +    FreePool (CipherId);
> +    break;
> +  case EfiTlsCompressionMethod:
> +    //
> +    // TLS seems only define one CompressionMethod.null, which specifies
> that data exchanged via the
> +    // record protocol will not be compressed.
> +    // More information from OpenSSL:
> http://www.openssl.org/docs/manmaster/ssl/SSL_COMP_add_compressio
> n_method.html
> +    // The TLS RFC does however not specify compression methods or their
> corresponding identifiers,
> +    // so there is currently no compatible way to integrate compression with
> unknown peers.
> +    // It is therefore currently not recommended to integrate compression
> into applications.
> +    // Applications for non-public use may agree on certain compression
> methods.
> +    // Using different compression methods with the same identifier will lead
> to connection failure.
> +    //
> +    for (Index = 0; Index < DataSize / sizeof (EFI_TLS_COMPRESSION);
> Index++) {
> +      Status = TlsSetCompressionMethod (*((UINT8 *) Data + Index));
> +      if (EFI_ERROR (Status)) {
> +        break;
> +      }
> +    }
> +
> +    break;
> +  case EfiTlsExtensionData:
> +    Status = EFI_UNSUPPORTED;
> +    goto ON_EXIT;
> +  case EfiTlsVerifyMethod:
> +    if (DataSize != sizeof (EFI_TLS_VERIFY)) {
> +      Status = EFI_INVALID_PARAMETER;
> +      goto ON_EXIT;
> +    }
> +
> +    TlsSetVerify (Instance->TlsConn, *((UINT32 *) Data));
> +    break;
> +  case EfiTlsSessionID:
> +    if (DataSize != sizeof (EFI_TLS_SESSION_ID)) {
> +      Status = EFI_INVALID_PARAMETER;
> +      goto ON_EXIT;
> +    }
> +
> +    Status = TlsSetSessionId (
> +               Instance->TlsConn,
> +               ((EFI_TLS_SESSION_ID *) Data)->Data,
> +               ((EFI_TLS_SESSION_ID *) Data)->Length
> +               );
> +    break;
> +  case EfiTlsSessionState:
> +    if (DataSize != sizeof (EFI_TLS_SESSION_STATE)) {
> +      Status = EFI_INVALID_PARAMETER;
> +      goto ON_EXIT;
> +    }
> +
> +    Instance->TlsSessionState = *(EFI_TLS_SESSION_STATE *) Data;
> +    break;
> +  //
> +  // Session information
> +  //
> +  case EfiTlsClientRandom:
> +    Status = EFI_ACCESS_DENIED;
> +    break;
> +  case EfiTlsServerRandom:
> +    Status = EFI_ACCESS_DENIED;
> +    break;
> +  case EfiTlsKeyMaterial:
> +    Status = EFI_ACCESS_DENIED;
> +    break;
> +  //
> +  // Unsupported type.
> +  //
> +  default:
> +    Status = EFI_UNSUPPORTED;
> +  }
> +
> +ON_EXIT:
> +  gBS->RestoreTPL (OldTpl);
> +  return Status;
> +}
> +
> +/**
> +  Get TLS session data.
> +
> +  The GetSessionData() function return the TLS session information.
> +
> +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in]       DataType       TLS session data type.
> +  @param[in, out]  Data           Pointer to session data.
> +  @param[in, out]  DataSize       Total size of session data. On input, it means
> +                                  the size of Data buffer. On output, it means the size
> +                                  of copied Data buffer if EFI_SUCCESS, and means the
> +                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
> +
> +  @retval EFI_SUCCESS             The TLS session data is got successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  DataSize is NULL.
> +                                  Data is NULL if *DataSize is not zero.
> +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> +  @retval EFI_NOT_FOUND           The TLS session data is not found.
> +  @retval EFI_NOT_READY           The DataType is not ready in current session
> state.
> +  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetSessionData (
> +  IN     EFI_TLS_PROTOCOL              *This,
> +  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,
> +  IN OUT VOID                          *Data,  OPTIONAL
> +  IN OUT UINTN                         *DataSize
> +  )
> +{
> +  EFI_STATUS                Status;
> +  TLS_INSTANCE              *Instance;
> +
> +  EFI_TPL                   OldTpl;
> +
> +  Status = EFI_SUCCESS;
> +
> +  if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0))
> {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> +  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
> +
> +  if (Instance->TlsSessionState == EfiTlsSessionNotStarted &&
> +    (DataType == EfiTlsSessionID || DataType == EfiTlsClientRandom ||
> +    DataType == EfiTlsServerRandom || DataType == EfiTlsKeyMaterial)) {
> +    Status = EFI_NOT_READY;
> +    goto ON_EXIT;
> +  }
> +
> +  switch (DataType) {
> +  case EfiTlsVersion:
> +    if (*DataSize < sizeof (EFI_TLS_VERSION)) {
> +      *DataSize = sizeof (EFI_TLS_VERSION);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      goto ON_EXIT;
> +    }
> +    *DataSize = sizeof (EFI_TLS_VERSION);
> +    *((UINT16 *) Data) = HTONS (TlsGetVersion (Instance->TlsConn));
> +    break;
> +  case EfiTlsConnectionEnd:
> +    if (*DataSize < sizeof (EFI_TLS_CONNECTION_END)) {
> +      *DataSize = sizeof (EFI_TLS_CONNECTION_END);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      goto ON_EXIT;
> +    }
> +    *DataSize = sizeof (EFI_TLS_CONNECTION_END);
> +    *((UINT8 *) Data) = TlsGetConnectionEnd (Instance->TlsConn);
> +    break;
> +  case EfiTlsCipherList:
> +    //
> +    // Get the current session cipher suite.
> +    //
> +    if (*DataSize < sizeof (EFI_TLS_CIPHER)) {
> +      *DataSize = sizeof (EFI_TLS_CIPHER);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      goto ON_EXIT;
> +    }
> +    *DataSize = sizeof(EFI_TLS_CIPHER);
> +    Status = TlsGetCurrentCipher (Instance->TlsConn, (UINT16 *) Data);
> +    *((UINT16 *) Data) = HTONS (*((UINT16 *) Data));
> +    break;
> +  case EfiTlsCompressionMethod:
> +    //
> +    // Get the current session compression method.
> +    //
> +    if (*DataSize < sizeof (EFI_TLS_COMPRESSION)) {
> +      *DataSize = sizeof (EFI_TLS_COMPRESSION);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      goto ON_EXIT;
> +    }
> +    *DataSize = sizeof (EFI_TLS_COMPRESSION);
> +    Status = TlsGetCurrentCompressionId (Instance->TlsConn, (UINT8 *)
> Data);
> +    break;
> +  case EfiTlsExtensionData:
> +    Status = EFI_UNSUPPORTED;
> +    goto ON_EXIT;
> +  case EfiTlsVerifyMethod:
> +    if (*DataSize < sizeof (EFI_TLS_VERIFY)) {
> +      *DataSize = sizeof (EFI_TLS_VERIFY);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      goto ON_EXIT;
> +    }
> +    *DataSize = sizeof (EFI_TLS_VERIFY);
> +    *((UINT32 *) Data) = TlsGetVerify (Instance->TlsConn);
> +    break;
> +  case EfiTlsSessionID:
> +    if (*DataSize < sizeof (EFI_TLS_SESSION_ID)) {
> +      *DataSize = sizeof (EFI_TLS_SESSION_ID);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      goto ON_EXIT;
> +    }
> +    *DataSize = sizeof (EFI_TLS_SESSION_ID);
> +    Status = TlsGetSessionId (
> +               Instance->TlsConn,
> +               ((EFI_TLS_SESSION_ID *) Data)->Data,
> +               &(((EFI_TLS_SESSION_ID *) Data)->Length)
> +               );
> +    break;
> +  case EfiTlsSessionState:
> +    if (*DataSize < sizeof (EFI_TLS_SESSION_STATE)) {
> +      *DataSize = sizeof (EFI_TLS_SESSION_STATE);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      goto ON_EXIT;
> +    }
> +    *DataSize = sizeof (EFI_TLS_SESSION_STATE);
> +    CopyMem (Data, &Instance->TlsSessionState, *DataSize);
> +    break;
> +  case EfiTlsClientRandom:
> +    if (*DataSize < sizeof (EFI_TLS_RANDOM)) {
> +      *DataSize = sizeof (EFI_TLS_RANDOM);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      goto ON_EXIT;
> +    }
> +    *DataSize = sizeof (EFI_TLS_RANDOM);
> +    TlsGetClientRandom (Instance->TlsConn, (UINT8 *) Data);
> +    break;
> +  case EfiTlsServerRandom:
> +    if (*DataSize < sizeof (EFI_TLS_RANDOM)) {
> +      *DataSize = sizeof (EFI_TLS_RANDOM);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      goto ON_EXIT;
> +    }
> +    *DataSize = sizeof (EFI_TLS_RANDOM);
> +    TlsGetServerRandom (Instance->TlsConn, (UINT8 *) Data);
> +    break;
> +  case EfiTlsKeyMaterial:
> +    if (*DataSize < sizeof (EFI_TLS_MASTER_SECRET)) {
> +      *DataSize = sizeof (EFI_TLS_MASTER_SECRET);
> +      Status = EFI_BUFFER_TOO_SMALL;
> +      goto ON_EXIT;
> +    }
> +    *DataSize = sizeof (EFI_TLS_MASTER_SECRET);
> +    Status = TlsGetKeyMaterial (Instance->TlsConn, (UINT8 *) Data);
> +    break;
> +  //
> +  // Unsupported type.
> +  //
> +  default:
> +    Status = EFI_UNSUPPORTED;
> +  }
> +
> +ON_EXIT:
> +  gBS->RestoreTPL (OldTpl);
> +  return Status;
> +}
> +
> +/**
> +  Build response packet according to TLS state machine. This function is only
> valid for
> +  alert, handshake and change_cipher_spec content type.
> +
> +  The BuildResponsePacket() function builds TLS response packet in
> response to the TLS
> +  request packet specified by RequestBuffer and RequestSize. If
> RequestBuffer is NULL and
> +  RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS
> session
> +  will be initiated and the response packet needs to be ClientHello. If
> RequestBuffer is
> +  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing,
> the TLS
> +  session will be closed and response packet needs to be CloseNotify. If
> RequestBuffer is
> +  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the
> TLS
> +  session has errors and the response packet needs to be Alert message
> based on error
> +  type.
> +
> +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in]       RequestBuffer  Pointer to the most recently received TLS
> packet. NULL
> +                                  means TLS need initiate the TLS session and response
> +                                  packet need to be ClientHello.
> +  @param[in]       RequestSize    Packet size in bytes for the most recently
> received TLS
> +                                  packet. 0 is only valid when RequestBuffer is NULL.
> +  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
> +  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input,
> it is
> +                                  the buffer size provided by the caller. On output, it
> +                                  is the buffer size in fact needed to contain the
> +                                  packet.
> +
> +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  RequestBuffer is NULL but RequestSize is NOT 0.
> +                                  RequestSize is 0 but RequestBuffer is NOT NULL.
> +                                  BufferSize is NULL.
> +                                  Buffer is NULL if *BufferSize is not zero.
> +  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the
> response packet.
> +  @retval EFI_NOT_READY           Current TLS session state is NOT ready to
> build
> +                                  ResponsePacket.
> +  @retval EFI_ABORTED             Something wrong build response packet.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsBuildResponsePacket (
> +  IN     EFI_TLS_PROTOCOL              *This,
> +  IN     UINT8                         *RequestBuffer, OPTIONAL
> +  IN     UINTN                         RequestSize, OPTIONAL
> +     OUT UINT8                         *Buffer, OPTIONAL
> +  IN OUT UINTN                         *BufferSize
> +  )
> +{
> +  EFI_STATUS                Status;
> +  TLS_INSTANCE              *Instance;
> +  EFI_TPL                   OldTpl;
> +
> +  Status = EFI_SUCCESS;
> +
> +  if ((This == NULL) || (BufferSize == NULL) ||
> +      (RequestBuffer == NULL && RequestSize != 0) ||
> +      (RequestBuffer != NULL && RequestSize == 0) ||
> +      (Buffer == NULL && *BufferSize !=0)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> +  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
> +
> +  if(RequestBuffer == NULL && RequestSize == 0) {
> +    switch (Instance->TlsSessionState) {
> +    case EfiTlsSessionNotStarted:
> +      //
> +      // ClientHello.
> +      //
> +      Status = TlsDoHandshake (
> +                 Instance->TlsConn,
> +                 NULL,
> +                 0,
> +                 Buffer,
> +                 BufferSize
> +                 );
> +      if (EFI_ERROR (Status)) {
> +        goto ON_EXIT;
> +      }
> +
> +      //
> +      // *BufferSize should not be zero when ClientHello.
> +      //
> +      if (*BufferSize == 0) {
> +        Status = EFI_ABORTED;
> +        goto ON_EXIT;
> +      }
> +
> +      Instance->TlsSessionState = EfiTlsSessionHandShaking;
> +
> +      break;
> +    case EfiTlsSessionClosing:
> +      //
> +      // TLS session will be closed and response packet needs to be
> CloseNotify.
> +      //
> +      Status = TlsCloseNotify (
> +                 Instance->TlsConn,
> +                 Buffer,
> +                 BufferSize
> +                 );
> +      if (EFI_ERROR (Status)) {
> +        goto ON_EXIT;
> +      }
> +
> +      //
> +      // *BufferSize should not be zero when build CloseNotify message.
> +      //
> +      if (*BufferSize == 0) {
> +        Status = EFI_ABORTED;
> +        goto ON_EXIT;
> +      }
> +
> +      break;
> +    case EfiTlsSessionError:
> +      //
> +      // TLS session has errors and the response packet needs to be Alert
> +      // message based on error type.
> +      //
> +      Status = TlsHandeAlert (
> +                 Instance->TlsConn,
> +                 NULL,
> +                 0,
> +                 Buffer,
> +                 BufferSize
> +                 );
> +      if (EFI_ERROR (Status)) {
> +        goto ON_EXIT;
> +      }
> +
> +      break;
> +    default:
> +      //
> +      // Current TLS session state is NOT ready to build ResponsePacket.
> +      //
> +      Status = EFI_NOT_READY;
> +    }
> +  } else {
> +    //
> +    // 1. Received packet may have multiply TLS record messages.
> +    // 2. One TLS record message may have multiply handshake protocol.
> +    // 3. Some errors may be happened in handshake.
> +    // TlsDoHandshake() can handle all of those cases.
> +    //
> +    if (TlsInHandshake (Instance->TlsConn)) {
> +      Status = TlsDoHandshake (
> +                 Instance->TlsConn,
> +                 RequestBuffer,
> +                 RequestSize,
> +                 Buffer,
> +                 BufferSize
> +                 );
> +      if (EFI_ERROR (Status)) {
> +        goto ON_EXIT;
> +      }
> +
> +      if (!TlsInHandshake (Instance->TlsConn)) {
> +        Instance->TlsSessionState = EfiTlsSessionDataTransferring;
> +      }
> +    } else {
> +      //
> +      // Must be alert message, Decrypt it and build the ResponsePacket.
> +      //
> +      ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType ==
> TLS_CONTENT_TYPE_ALERT);
> +
> +      Status = TlsHandeAlert (
> +                 Instance->TlsConn,
> +                 RequestBuffer,
> +                 RequestSize,
> +                 Buffer,
> +                 BufferSize
> +                 );
> +      if (EFI_ERROR (Status)) {
> +        if (Status != EFI_BUFFER_TOO_SMALL) {
> +          Instance->TlsSessionState = EfiTlsSessionError;
> +        }
> +
> +        goto ON_EXIT;
> +      }
> +    }
> +  }
> +
> +ON_EXIT:
> +  gBS->RestoreTPL (OldTpl);
> +  return Status;
> +}
> +
> +/**
> +  Decrypt or encrypt TLS packet during session. This function is only valid
> after
> +  session connected and for application_data content type.
> +
> +  The ProcessPacket () function process each inbound or outbound TLS APP
> packet.
> +
> +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> +  @param[in, out]  FragmentTable  Pointer to a list of fragment. The caller
> will take
> +                                  responsible to handle the original FragmentTable while
> +                                  it may be reallocated in TLS driver. If CryptMode is
> +                                  EfiTlsEncrypt, on input these fragments contain the TLS
> +                                  header and plain text TLS APP payload; on output these
> +                                  fragments contain the TLS header and cipher text TLS
> +                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
> +                                  these fragments contain the TLS header and cipher text
> +                                  TLS APP payload; on output these fragments contain the
> +                                  TLS header and plain text TLS APP payload.
> +  @param[in]       FragmentCount  Number of fragment.
> +  @param[in]       CryptMode      Crypt mode.
> +
> +  @retval EFI_SUCCESS             The operation completed successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  This is NULL.
> +                                  FragmentTable is NULL.
> +                                  FragmentCount is NULL.
> +                                  CryptoMode is invalid.
> +  @retval EFI_NOT_READY           Current TLS session state is NOT
> +                                  EfiTlsSessionDataTransferring.
> +  @retval EFI_ABORTED             Something wrong decryption the message.
> TLS session
> +                                  status will become EfiTlsSessionError. The caller need
> +                                  call BuildResponsePacket() to generate Error Alert
> +                                  message and send it out.
> +  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the
> operation.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsProcessPacket (
> +  IN     EFI_TLS_PROTOCOL              *This,
> +  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,
> +  IN     UINT32                        *FragmentCount,
> +  IN     EFI_TLS_CRYPT_MODE            CryptMode
> +  )
> +{
> +  EFI_STATUS                Status;
> +  TLS_INSTANCE              *Instance;
> +
> +  EFI_TPL                   OldTpl;
> +
> +  Status = EFI_SUCCESS;
> +
> +  if (This == NULL || FragmentTable == NULL || FragmentCount == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
> +
> +  Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This);
> +
> +  if (Instance->TlsSessionState != EfiTlsSessionDataTransferring) {
> +    Status = EFI_NOT_READY;
> +    goto ON_EXIT;
> +  }
> +
> +  //
> +  // Packet sent or received may have multiply TLS record
> message(Application data type).
> +  // So,on input these fragments contain the TLS header and TLS APP
> payload;
> +  // on output these fragments also contain the TLS header and TLS APP
> payload.
> +  //
> +  switch (CryptMode) {
> +  case EfiTlsEncrypt:
> +    Status = TlsEcryptPacket (Instance, FragmentTable, FragmentCount);
> +    break;
> +  case EfiTlsDecrypt:
> +    Status = TlsDecryptPacket (Instance, FragmentTable, FragmentCount);
> +    break;
> +  default:
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +ON_EXIT:
> +  gBS->RestoreTPL (OldTpl);
> +  return Status;
> +}
> --
> 1.9.5.msysgit.1


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 09/10] Nt32Pkg/Nt32Pkg.dsc: Remove the flag for OpensslLib and BaseCryptLib
  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
  2 siblings, 0 replies; 37+ messages in thread
From: Long, Qin @ 2016-12-15  8:25 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Ni, Ruiyu, Ye, Ting, Fu, Siyuan, Zhang, Lubo, Thomas Palmer

Reviewed-by: Qin Long <qin.long@intel.com>


Best Regards & Thanks,
LONG, Qin

> -----Original Message-----
> From: Wu, Jiaxin
> Sent: Wednesday, December 14, 2016 3:34 PM
> To: edk2-devel@lists.01.org
> Cc: Long, Qin; Ni, Ruiyu; Ye, Ting; Fu, Siyuan; Zhang, Lubo; Thomas Palmer;
> Wu, Jiaxin
> Subject: [Patch 09/10] Nt32Pkg/Nt32Pkg.dsc: Remove the flag for OpensslLib
> and BaseCryptLib
> 
> This patch is used to remove the 'SECURE_BOOT_ENABLE' flag for OpensslLib
> and BaseCryptLib modules.
> 
> Cc: Long Qin <qin.long@intel.com>
> Cc: Ni Ruiyu <ruiyu.ni@intel.com>
> Cc: Ye Ting <ting.ye@intel.com>
> Cc: Fu Siyuan <siyuan.fu@intel.com>
> Cc: Zhang Lubo <lubo.zhang@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>
> ---
>  Nt32Pkg/Nt32Pkg.dsc | 10 ++--------
>  1 file changed, 2 insertions(+), 8 deletions(-)
> 
> diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc index
> 4458c02..79ab2f7 100644
> --- a/Nt32Pkg/Nt32Pkg.dsc
> +++ b/Nt32Pkg/Nt32Pkg.dsc
> @@ -131,15 +131,15 @@
> 
> DebugPrintErrorLevelLib|MdeModulePkg/Library/DxeDebugPrintErrorLevelL
> ib/DxeDebugPrintErrorLevelLib.inf
> 
> PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanc
> eLibNull.inf
> 
> DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLi
> bNull.inf
> 
> CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibN
> ull/CpuExceptionHandlerLibNull.inf
>    LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
> +  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
> +  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
> 
>  !if $(SECURE_BOOT_ENABLE) == TRUE
> 
> PlatformSecureLib|Nt32Pkg/Library/PlatformSecureLib/PlatformSecureLib.in
> f
> -  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
> -  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
> 
> TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTp
> mMeasurementLib.inf
>    AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
>  !else
> 
> TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/Tp
> mMeasurementLibNull.inf
> 
> AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableL
> ibNull.inf
> @@ -173,13 +173,11 @@
> 
> OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibN
> ull/OemHookStatusCodeLibNull.inf
> 
>  [LibraryClasses.common.PEIM]
>    PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
> 
> OemHookStatusCodeLib|Nt32Pkg/Library/PeiNt32OemHookStatusCodeLib/
> PeiNt32OemHookStatusCodeLib.inf
> -!if $(SECURE_BOOT_ENABLE) == TRUE
>    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> -!endif
> 
>  [LibraryClasses.common]
>    #
>    # DXE phase common
>    #
> @@ -190,13 +188,11 @@
> 
> ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/Dx
> eReportStatusCodeLib.inf
> 
> OemHookStatusCodeLib|Nt32Pkg/Library/DxeNt32OemHookStatusCodeLib/
> DxeNt32OemHookStatusCodeLib.inf
> 
> PeCoffExtraActionLib|Nt32Pkg/Library/DxeNt32PeCoffExtraActionLib/DxeNt
> 32PeCoffExtraActionLib.inf
> 
> ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeE
> xtractGuidedSectionLib.inf
>    WinNtLib|Nt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.inf
> -!if $(SECURE_BOOT_ENABLE) == TRUE
>    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> -!endif
> 
>  [LibraryClasses.common.DXE_CORE]
>    HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
> 
> MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLi
> b/DxeCoreMemoryAllocationLib.inf
>    PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
> @@ -213,13 +209,11 @@
> 
>  [LibraryClasses.common.DXE_RUNTIME_DRIVER]
>    #
>    # Runtime
>    #
> -!if $(SECURE_BOOT_ENABLE) == TRUE
>    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> -!endif
> 
> 
> ##########################################################
> ######################
>  #
>  # Pcd Section - list of all EDK II PCD Entries defined by this Platform  #
> --
> 1.9.5.msysgit.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 01/10] MdePkg: Add TLS related protocol definition
  2016-12-14  8:39     ` Wu, Jiaxin
@ 2016-12-15  8:34       ` Ye, Ting
  0 siblings, 0 replies; 37+ messages in thread
From: Ye, Ting @ 2016-12-15  8:34 UTC (permalink / raw)
  To: Wu, Jiaxin, Long, Qin, edk2-devel@lists.01.org
  Cc: Fu, Siyuan, Zhang, Lubo, Gao, Liming, Kinney, Michael D,
	Thomas Palmer

Reviewed-by: Ye Ting <ting.ye@intel.com> 

-----Original Message-----
From: Wu, Jiaxin 
Sent: Wednesday, December 14, 2016 4:39 PM
To: Long, Qin <qin.long@intel.com>; edk2-devel@lists.01.org
Cc: Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>
Subject: RE: [Patch 01/10] MdePkg: Add TLS related protocol definition

Thanks Qin, I will correct it before commit this patch.

Best Regards!
Jiaxin

> -----Original Message-----
> From: Long, Qin
> Sent: Wednesday, December 14, 2016 4:36 PM
> To: Wu, Jiaxin <jiaxin.wu@intel.com>; edk2-devel@lists.01.org
> Cc: Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; 
> Zhang, Lubo <lubo.zhang@intel.com>; Gao, Liming 
> <liming.gao@intel.com>; Kinney, Michael D 
> <michael.d.kinney@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>
> Subject: RE: [Patch 01/10] MdePkg: Add TLS related protocol definition
> 
> Reviewed-by: Qin Long <qin.long@intel.com>
> 
> Please correct some typos later:
> EFI_TLS_EXTENDION  --> EFI_TLS_EXTENSION TLS/SSLhandshake --> TLS/SSL 
> handshake cerfificate --> certificate cypher --> cipher
> binaryX.509 --> binary X.509
> PEMencoded --> PEM-encoded
> 
> Best Regards & Thanks,
> LONG, Qin
> 
> > -----Original Message-----
> > From: Wu, Jiaxin
> > Sent: Wednesday, December 14, 2016 3:34 PM
> > To: edk2-devel@lists.01.org
> > Cc: Long, Qin; Ye, Ting; Fu, Siyuan; Zhang, Lubo; Gao, Liming; 
> > Kinney, Michael D; Thomas Palmer; Wu, Jiaxin
> > Subject: [Patch 01/10] MdePkg: Add TLS related protocol definition
> >
> > This patch is used to add Tls.h and TlsConfig.h header files to 
> > define EFI TLS Configuration Protocol, EFI TLS Service Binding 
> > Protocol and EFI TLS Configuration Protocol.
> >
> > Cc: Long Qin <qin.long@intel.com>
> > Cc: Ye Ting <ting.ye@intel.com>
> > Cc: Fu Siyuan <siyuan.fu@intel.com>
> > Cc: Zhang Lubo <lubo.zhang@intel.com>
> > Cc: Liming Gao <liming.gao@intel.com>
> > Cc: Michael D Kinney <michael.d.kinney@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>
> > ---
> >  MdePkg/Include/Protocol/Tls.h       | 460
> > ++++++++++++++++++++++++++++++++++++
> >  MdePkg/Include/Protocol/TlsConfig.h | 132 +++++++++++
> >  MdePkg/MdePkg.dec                   |   9 +
> >  3 files changed, 601 insertions(+)
> >  create mode 100644 MdePkg/Include/Protocol/Tls.h  create mode 
> > 100644 MdePkg/Include/Protocol/TlsConfig.h
> >
> > diff --git a/MdePkg/Include/Protocol/Tls.h 
> > b/MdePkg/Include/Protocol/Tls.h new file mode 100644 index 
> > 0000000..51a3cda
> > --- /dev/null
> > +++ b/MdePkg/Include/Protocol/Tls.h
> > @@ -0,0 +1,460 @@
> > +/** @file
> > +  EFI TLS Protocols as defined in UEFI 2.5.
> > +
> > +  The EFI TLS Service Binding Protocol is used to locate EFI TLS 
> > + Protocol drivers  to create and destroy child of the driver to 
> > + communicate with other host using  TLS protocol.
> > +  The EFI TLS Protocol provides the ability to manage TLS session.
> > +
> > +  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.
> > +
> > +  @par Revision Reference:
> > +  This Protocol is introduced in UEFI Specification 2.5
> > +
> > +**/
> > +
> > +#ifndef __EFI_TLS_PROTOCOL_H__
> > +#define __EFI_TLS_PROTOCOL_H__
> > +
> > +///
> > +/// The EFI TLS Service Binding Protocol is used to locate EFI TLS 
> > +Protocol drivers to /// create and destroy child of the driver to 
> > +communicate with other host using TLS /// protocol.
> > +///
> > +#define EFI_TLS_SERVICE_BINDING_PROTOCOL_GUID \
> > +  { \
> > +    0x952cb795, 0xff36, 0x48cf, {0xa2, 0x49, 0x4d, 0xf4, 0x86, 
> > +0xd6, 0xab, 0x8d } \
> > +  }
> > +
> > +///
> > +/// The EFI TLS protocol provides the ability to manage TLS session.
> > +///
> > +#define EFI_TLS_PROTOCOL_GUID \
> > +  { \
> > +    0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc, 0xe4, 0x6c, 0x47, 0x51, 
> > +0x43, 0x90 } \
> > +  }
> > +
> > +typedef struct _EFI_TLS_PROTOCOL EFI_TLS_PROTOCOL;
> > +
> > +///
> > +/// EFI_TLS_SESSION_DATA_TYPE
> > +///
> > +typedef enum {
> > +  ///
> > +  /// Session Configuration
> > +  ///
> > +
> > +  ///
> > +  /// TLS session Version. The corresponding Data is of type
> > EFI_TLS_VERSION.
> > +  ///
> > +  EfiTlsVersion,
> > +  ///
> > +  /// TLS session as client or as server. The corresponding Data is 
> > + of /// EFI_TLS_CONNECTION_END.
> > +  ///
> > +  EfiTlsConnectionEnd,
> > +  ///
> > +  /// A priority list of preferred algorithms for the TLS session.
> > +  /// The corresponding Data is a list of EFI_TLS_CIPHER.
> > +  ///
> > +  EfiTlsCipherList,
> > +  ///
> > +  /// TLS session compression method.
> > +  /// The corresponding Data is of type EFI_TLS_COMPRESSION.
> > +  ///
> > +  EfiTlsCompressionMethod,
> > +  ///
> > +  /// TLS session extension data.
> > +  /// The corresponding Data is a list of type EFI_TLS_EXTENDION.
> > +  ///
> > +  EfiTlsExtensionData,
> > +  ///
> > +  /// TLS session verify method.
> > +  /// The corresponding Data is of type EFI_TLS_VERIFY.
> > +  ///
> > +  EfiTlsVerifyMethod,
> > +  ///
> > +  /// TLS session data session ID.
> > +  /// For SetSessionData(), it is TLS session ID used for session resumption.
> > +  /// For GetSessionData(), it is the TLS session ID used for current session.
> > +  /// The corresponding Data is of type EFI_TLS_SESSION_ID.
> > +  ///
> > +  EfiTlsSessionID,
> > +  ///
> > +  /// TLS session data session state.
> > +  /// The corresponding Data is of type EFI_TLS_SESSION_STATE.
> > +  ///
> > +  EfiTlsSessionState,
> > +
> > +  ///
> > +  /// Session information
> > +  ///
> > +
> > +  ///
> > +  /// TLS session data client random.
> > +  /// The corresponding Data is of type EFI_TLS_RANDOM.
> > +  ///
> > +  EfiTlsClientRandom,
> > +  ///
> > +  /// TLS session data server random.
> > +  /// The corresponding Data is of type EFI_TLS_RANDOM.
> > +  ///
> > +  EfiTlsServerRandom,
> > +  ///
> > +  /// TLS session data key material.
> > +  /// The corresponding Data is of type EFI_TLS_MASTER_SECRET.
> > +  ///
> > +  EfiTlsKeyMaterial,
> > +
> > +  EfiTlsSessionDataTypeMaximum
> > +
> > +} EFI_TLS_SESSION_DATA_TYPE;
> > +
> > +///
> > +/// EFI_TLS_VERSION
> > +/// Note: The TLS version definition is from SSL3.0 to the latest TLS (e.g.
> 1.2).
> > +///       SSL2.0 is obsolete and should not be used.
> > +///
> > +typedef struct {
> > +  UINT8                         Major;
> > +  UINT8                         Minor;
> > +} EFI_TLS_VERSION;
> > +
> > +///
> > +/// EFI_TLS_CONNECTION_END to define TLS session as client or server.
> > +///
> > +typedef enum {
> > +  EfiTlsClient,
> > +  EfiTlsServer,
> > +} EFI_TLS_CONNECTION_END;
> > +
> > +///
> > +/// EFI_TLS_CIPHER
> > +/// Note: The definition of EFI_TLS_CIPHER definition is from "RFC 
> > +5246,
> > A.4.1.
> > +///       Hello Messages". The value of EFI_TLS_CIPHER is from TLS Cipher
> > +///       Suite Registry of IANA.
> > +///
> > +typedef struct {
> > +  UINT8                         Data1;
> > +  UINT8                         Data2;
> > +} EFI_TLS_CIPHER;
> > +
> > +///
> > +/// EFI_TLS_COMPRESSION
> > +/// Note: The value of EFI_TLS_COMPRESSION definition is from "RFC
> 3749".
> > +///
> > +typedef UINT8 EFI_TLS_COMPRESSION;
> > +
> > +///
> > +/// EFI_TLS_EXTENSION
> > +/// Note: The definition of EFI_TLS_EXTENSION if from "RFC 5246 A.4.1.
> > +///       Hello Messages".
> > +///
> > +typedef struct {
> > +  UINT16                        ExtensionType;
> > +  UINT16                        Length;
> > +  UINT8                         Data[1];
> > +} EFI_TLS_EXTENSION;
> > +
> > +///
> > +/// EFI_TLS_VERIFY
> > +/// Use either EFI_TLS_VERIFY_NONE or EFI_TLS_VERIFY_PEER, the last 
> > +two options /// are 'ORed' with EFI_TLS_VERIFY_PEER if they are desired.
> > +///
> > +typedef UINT32  EFI_TLS_VERIFY;
> > +///
> > +/// No certificates will be sent or the TLS/SSLhandshake will be 
> > +continued regardless /// of the certificate verification result.
> > +///
> > +#define EFI_TLS_VERIFY_NONE                  0x0
> > +///
> > +/// The TLS/SSL handshake is immediately terminated with an alert 
> > +message containing /// the reason for the certificate verification failure.
> > +///
> > +#define EFI_TLS_VERIFY_PEER                  0x1
> > +///
> > +/// TLS session will fail peer certificate is absent.
> > +///
> > +#define EFI_TLS_VERIFY_FAIL_IF_NO_PEER_CERT  0x2 /// /// TLS 
> > +session only verify client once, and doesn't request cerfificate 
> > +during /// re-negotiation.
> > +///
> > +#define EFI_TLS_VERIFY_CLIENT_ONCE           0x4
> > +
> > +///
> > +/// EFI_TLS_RANDOM
> > +/// Note: The definition of EFI_TLS_RANDOM is from "RFC 5246 A.4.1.
> > +///       Hello Messages".
> > +///
> > +typedef struct {
> > +  UINT32                        GmtUnixTime;
> > +  UINT8                         RandomBytes[28];
> > +} EFI_TLS_RANDOM;
> > +
> > +///
> > +/// EFI_TLS_MASTER_SECRET
> > +/// Note: The definition of EFI_TLS_MASTER_SECRET is from "RFC 5246 8.1.
> > +///       Computing the Master Secret".
> > +///
> > +typedef struct {
> > +  UINT8                         Data[48];
> > +} EFI_TLS_MASTER_SECRET;
> > +
> > +///
> > +/// EFI_TLS_SESSION_ID
> > +/// Note: The definition of EFI_TLS_SESSION_ID is from "RFC 5246 A.4.1.
> > Hello Messages".
> > +///
> > +#define MAX_TLS_SESSION_ID_LENGTH  32 typedef struct {
> > +  UINT16                        Length;
> > +  UINT8                         Data[MAX_TLS_SESSION_ID_LENGTH];
> > +} EFI_TLS_SESSION_ID;
> > +
> > +///
> > +/// EFI_TLS_SESSION_STATE
> > +///
> > +typedef enum {
> > +  ///
> > +  /// When a new child of TLS protocol is created, the initial 
> > +state of TLS session
> > +  /// is EfiTlsSessionNotStarted.
> > +  ///
> > +  EfiTlsSessionNotStarted,
> > +  ///
> > +  /// The consumer can call BuildResponsePacket() with NULL to get 
> > +ClientHello to
> > +  /// start the TLS session. Then the status is EfiTlsSessionHandShaking.
> > +  ///
> > +  EfiTlsSessionHandShaking,
> > +  ///
> > +  /// During handshake, the consumer need call 
> > +BuildResponsePacket() with input
> > +  /// data from peer, then get response packet and send to peer.
> > +After handshake
> > +  /// finish, the TLS session status becomes 
> > +EfiTlsSessionDataTransferring, and
> > +  /// consumer can use ProcessPacket() for data transferring.
> > +  ///
> > +  EfiTlsSessionDataTransferring,
> > +  ///
> > +  /// Finally, if consumer wants to active close TLS session, 
> > +consumer need
> > +  /// call SetSessionData to set TLS session state to 
> > +EfiTlsSessionClosing, and
> > +  /// call BuildResponsePacket() with NULL to get CloseNotify alert 
> > +message,
> > +  /// and sent it out.
> > +  ///
> > +  EfiTlsSessionClosing,
> > +  ///
> > +  /// If any error happen during parsing ApplicationData content 
> > +type, EFI_ABORT
> > +  /// will be returned by ProcessPacket(), and TLS session state 
> > +will become
> > +  /// EfiTlsSessionError. Then consumer need call
> > +BuildResponsePacket() with
> > +  /// NULL to get alert message and sent it out.
> > +  ///
> > +  EfiTlsSessionError,
> > +
> > +  EfiTlsSessionStateMaximum
> > +
> > +} EFI_TLS_SESSION_STATE;
> > +
> > +///
> > +/// EFI_TLS_FRAGMENT_DATA
> > +///
> > +typedef struct {
> > +  ///
> > +  /// Length of data buffer in the fragment.
> > +  ///
> > +  UINT32                        FragmentLength;
> > +  ///
> > +  /// Pointer to the data buffer in the fragment.
> > +  ///
> > +  VOID                          *FragmentBuffer;
> > +} EFI_TLS_FRAGMENT_DATA;
> > +
> > +///
> > +/// EFI_TLS_CRYPT_MODE
> > +///
> > +typedef enum {
> > +  ///
> > +  /// Encrypt data provided in the fragment buffers.
> > +  ///
> > +  EfiTlsEncrypt,
> > +  ///
> > +  /// Decrypt data provided in the fragment buffers.
> > +  ///
> > +  EfiTlsDecrypt,
> > +} EFI_TLS_CRYPT_MODE;
> > +
> > +/**
> > +  Set TLS session data.
> > +
> > +  The SetSessionData() function set data for a new TLS session. All 
> > + session data should  be set before BuildResponsePacket() invoked.
> > +
> > +  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.
> > +  @param[in]  DataType            TLS session data type.
> > +  @param[in]  Data                Pointer to session data.
> > +  @param[in]  DataSize            Total size of session data.
> > +
> > +  @retval EFI_SUCCESS             The TLS session data is set successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  Data is NULL.
> > +                                  DataSize is 0.
> > +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> > +  @retval EFI_ACCESS_DENIED       If the DataType is one of below:
> > +                                  EfiTlsClientRandom
> > +                                  EfiTlsServerRandom
> > +                                  EfiTlsKeyMaterial
> > +  @retval EFI_NOT_READY           Current TLS session state is NOT
> > +                                  EfiTlsSessionStateNotStarted.
> > +  @retval EFI_OUT_OF_RESOURCES    Required system resources could
> not
> > be allocated.
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_SET_SESSION_DATA) (
> > +  IN EFI_TLS_PROTOCOL                *This,
> > +  IN EFI_TLS_SESSION_DATA_TYPE       DataType,
> > +  IN VOID                            *Data,
> > +  IN UINTN                           DataSize
> > +  );
> > +
> > +/**
> > +  Get TLS session data.
> > +
> > +  The GetSessionData() function return the TLS session information.
> > +
> > +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> > +  @param[in]       DataType       TLS session data type.
> > +  @param[in, out]  Data           Pointer to session data.
> > +  @param[in, out]  DataSize       Total size of session data. On input, it
> means
> > +                                  the size of Data buffer. On output, it means the size
> > +                                  of copied Data buffer if EFI_SUCCESS, and means the
> > +                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
> > +
> > +  @retval EFI_SUCCESS             The TLS session data is got successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  DataSize is NULL.
> > +                                  Data is NULL if *DataSize is not zero.
> > +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> > +  @retval EFI_NOT_FOUND           The TLS session data is not found.
> > +  @retval EFI_NOT_READY           The DataType is not ready in current
> session
> > state.
> > +  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the
> data.
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_GET_SESSION_DATA) (
> > +  IN EFI_TLS_PROTOCOL                *This,
> > +  IN EFI_TLS_SESSION_DATA_TYPE       DataType,
> > +  IN OUT VOID                        *Data,  OPTIONAL
> > +  IN OUT UINTN                       *DataSize
> > +  );
> > +
> > +/**
> > +  Build response packet according to TLS state machine. This 
> > +function is only valid for
> > +  alert, handshake and change_cipher_spec content type.
> > +
> > +  The BuildResponsePacket() function builds TLS response packet in 
> > + response to the TLS  request packet specified by RequestBuffer and 
> > + RequestSize. If RequestBuffer is NULL and  RequestSize is 0, and 
> > + TLS session status is EfiTlsSessionNotStarted, the TLS session  
> > + will be initiated and the response packet needs to be ClientHello. 
> > + If RequestBuffer is  NULL and RequestSize is 0, and TLS session 
> > + status is EfiTlsSessionClosing, the TLS  session will be closed 
> > + and response packet needs to be CloseNotify. If RequestBuffer is  
> > + NULL and RequestSize is 0, and TLS session status is 
> > + EfiTlsSessionError, the TLS
> > session has errors and the response packet needs to be Alert message 
> > based on error  type.
> > +
> > +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> > +  @param[in]       RequestBuffer  Pointer to the most recently received TLS
> > packet. NULL
> > +                                  means TLS need initiate the TLS session and response
> > +                                  packet need to be ClientHello.
> > +  @param[in]       RequestSize    Packet size in bytes for the most recently
> > received TLS
> > +                                  packet. 0 is only valid when RequestBuffer is NULL.
> > +  @param[out]      Buffer         Pointer to the buffer to hold the built packet.
> > +  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On
> input,
> > it is
> > +                                  the buffer size provided by the caller. On output, it
> > +                                  is the buffer size in fact needed to contain the
> > +                                  packet.
> > +
> > +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  RequestBuffer is NULL but RequestSize is NOT 0.
> > +                                  RequestSize is 0 but RequestBuffer is NOT NULL.
> > +                                  BufferSize is NULL.
> > +                                  Buffer is NULL if *BufferSize is not zero.
> > +  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the
> > response packet.
> > +  @retval EFI_NOT_READY           Current TLS session state is NOT ready to
> > build
> > +                                  ResponsePacket.
> > +  @retval EFI_ABORTED             Something wrong build response packet.
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_BUILD_RESPONSE_PACKET) (
> > +  IN EFI_TLS_PROTOCOL                *This,
> > +  IN UINT8                           *RequestBuffer, OPTIONAL
> > +  IN UINTN                           RequestSize, OPTIONAL
> > +  OUT UINT8                          *Buffer, OPTIONAL
> > +  IN OUT UINTN                       *BufferSize
> > +  );
> > +
> > +/**
> > +  Decrypt or encrypt TLS packet during session. This function is 
> > +only valid after
> > +  session connected and for application_data content type.
> > +
> > +  The ProcessPacket () function process each inbound or outbound 
> > + TLS APP
> > packet.
> > +
> > +  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.
> > +  @param[in, out]  FragmentTable  Pointer to a list of fragment. 
> > + The caller
> > will take
> > +                                  responsible to handle the original FragmentTable while
> > +                                  it may be reallocated in TLS driver. If CryptMode is
> > +                                  EfiTlsEncrypt, on input these fragments contain the TLS
> > +                                  header and plain text TLS APP payload; on output these
> > +                                  fragments contain the TLS header and cypher text TLS
> > +                                  APP payload. If CryptMode is EfiTlsDecrypt, on input
> > +                                  these fragments contain the TLS header and cypher text
> > +                                  TLS APP payload; on output these fragments contain the
> > +                                  TLS header and plain text TLS APP payload.
> > +  @param[in]       FragmentCount  Number of fragment.
> > +  @param[in]       CryptMode      Crypt mode.
> > +
> > +  @retval EFI_SUCCESS             The operation completed successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  FragmentTable is NULL.
> > +                                  FragmentCount is NULL.
> > +                                  CryptoMode is invalid.
> > +  @retval EFI_NOT_READY           Current TLS session state is NOT
> > +                                  EfiTlsSessionDataTransferring.
> > +  @retval EFI_ABORTED             Something wrong decryption the message.
> > TLS session
> > +                                  status will become EfiTlsSessionError. The caller need
> > +                                  call BuildResponsePacket() to generate Error Alert
> > +                                  message and send it out.
> > +  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the
> > operation.
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_PROCESS_PACKET) (
> > +  IN EFI_TLS_PROTOCOL                *This,
> > +  IN OUT EFI_TLS_FRAGMENT_DATA       **FragmentTable,
> > +  IN UINT32                          *FragmentCount,
> > +  IN EFI_TLS_CRYPT_MODE              CryptMode
> > +  );
> > +
> > +///
> > +/// The EFI_TLS_PROTOCOL is used to create, destroy and manage TLS
> > session.
> > +/// For detail of TLS, please refer to TLS related RFC.
> > +///
> > +struct _EFI_TLS_PROTOCOL {
> > +  EFI_TLS_SET_SESSION_DATA           SetSessionData;
> > +  EFI_TLS_GET_SESSION_DATA           GetSessionData;
> > +  EFI_TLS_BUILD_RESPONSE_PACKET      BuildResponsePacket;
> > +  EFI_TLS_PROCESS_PACKET             ProcessPacket;
> > +};
> > +
> > +extern EFI_GUID gEfiTlsServiceBindingProtocolGuid;
> > +extern EFI_GUID gEfiTlsProtocolGuid;
> > +
> > +#endif  // __EFI_TLS_PROTOCOL_H__
> > diff --git a/MdePkg/Include/Protocol/TlsConfig.h
> > b/MdePkg/Include/Protocol/TlsConfig.h
> > new file mode 100644
> > index 0000000..4b62bf5
> > --- /dev/null
> > +++ b/MdePkg/Include/Protocol/TlsConfig.h
> > @@ -0,0 +1,132 @@
> > +/** @file
> > +  EFI TLS Configuration Protocol as defined in UEFI 2.5.
> > +  The EFI TLS Configuration Protocol provides a way to set and get 
> > +TLS
> > configuration.
> > +
> > +  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.
> > +
> > +  @par Revision Reference:
> > +  This Protocol is introduced in UEFI Specification 2.5
> > +
> > +**/
> > +#ifndef __EFI_TLS_CONFIGURATION_PROTOCOL_H__
> > +#define __EFI_TLS_CONFIGURATION_PROTOCOL_H__
> > +
> > +///
> > +/// The EFI Configuration protocol provides a way to set and get 
> > +TLS
> > configuration.
> > +///
> > +#define EFI_TLS_CONFIGURATION_PROTOCOL_GUID  \
> > +  { \
> > +    0x1682fe44, 0xbd7a, 0x4407, { 0xb7, 0xc7, 0xdc, 0xa3, 0x7c, 
> > +0xa3, 0x92, 0x2d }  \
> > +  }
> > +
> > +typedef struct _EFI_TLS_CONFIGURATION_PROTOCOL 
> > +EFI_TLS_CONFIGURATION_PROTOCOL;
> > +
> > +///
> > +/// EFI_TLS_CONFIG_DATA_TYPE
> > +///
> > +typedef enum {
> > +  ///
> > +  /// Local host configuration data: public certificate data.
> > +  /// This data should be DER-encoded binaryX.509 certificate
> > +  /// or PEMencoded X.509 certificate.
> > +  ///
> > +  EfiTlsConfigDataTypeHostPublicCert,
> > +  ///
> > +  /// Local host configuration data: private key data.
> > +  ///
> > +  EfiTlsConfigDataTypeHostPrivateKey,
> > +  ///
> > +  /// CA certificate to verify peer. This data should be 
> > +PEM-encoded
> > +  /// RSA or PKCS#8 private key.
> > +  ///
> > +  EfiTlsConfigDataTypeCACertificate,
> > +  ///
> > +  /// CA-supplied Certificate Revocation List data. This data 
> > +should
> > +  /// be DER-encoded CRL data.
> > +  ///
> > +  EfiTlsConfigDataTypeCertRevocationList,
> > +
> > +  EfiTlsConfigDataTypeMaximum
> > +
> > +} EFI_TLS_CONFIG_DATA_TYPE;
> > +
> > +/**
> > +  Set TLS configuration data.
> > +
> > +  The SetData() function sets TLS configuration to non-volatile 
> > + storage or volatile  storage.
> > +
> > +  @param[in]  This                Pointer to the
> > EFI_TLS_CONFIGURATION_PROTOCOL instance.
> > +  @param[in]  DataType            Configuration data type.
> > +  @param[in]  Data                Pointer to configuration data.
> > +  @param[in]  DataSize            Total size of configuration data.
> > +
> > +  @retval EFI_SUCCESS             The TLS configuration data is set successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  Data is NULL.
> > +                                  DataSize is 0.
> > +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> > +  @retval EFI_OUT_OF_RESOURCES    Required system resources could
> not
> > be allocated.
> > +
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_CONFIGURATION_SET_DATA)(
> > +  IN EFI_TLS_CONFIGURATION_PROTOCOL  *This,
> > +  IN EFI_TLS_CONFIG_DATA_TYPE        DataType,
> > +  IN VOID                            *Data,
> > +  IN UINTN                           DataSize
> > +  );
> > +
> > +/**
> > +  Get TLS configuration data.
> > +
> > +  The GetData() function gets TLS configuration.
> > +
> > +  @param[in]       This           Pointer to the
> > EFI_TLS_CONFIGURATION_PROTOCOL instance.
> > +  @param[in]       DataType       Configuration data type.
> > +  @param[in, out]  Data           Pointer to configuration data.
> > +  @param[in, out]  DataSize       Total size of configuration data. On input, it
> > means
> > +                                  the size of Data buffer. On output, it means the size
> > +                                  of copied Data buffer if EFI_SUCCESS, and means the
> > +                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.
> > +
> > +  @retval EFI_SUCCESS             The TLS configuration data is got successfully.
> > +  @retval EFI_INVALID_PARAMETER   One or more of the following
> > conditions is TRUE:
> > +                                  This is NULL.
> > +                                  DataSize is NULL.
> > +                                  Data is NULL if *DataSize is not zero.
> > +  @retval EFI_UNSUPPORTED         The DataType is unsupported.
> > +  @retval EFI_NOT_FOUND           The TLS configuration data is not found.
> > +  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the
> data.
> > +
> > +**/
> > +typedef
> > +EFI_STATUS
> > +(EFIAPI *EFI_TLS_CONFIGURATION_GET_DATA)(
> > +  IN EFI_TLS_CONFIGURATION_PROTOCOL  *This,
> > +  IN EFI_TLS_CONFIG_DATA_TYPE        DataType,
> > +  IN OUT VOID                        *Data,  OPTIONAL
> > +  IN OUT UINTN                       *DataSize
> > +  );
> > +
> > +///
> > +/// The EFI_TLS_CONFIGURATION_PROTOCOL is designed to provide a
> way
> > to
> > +set and get /// TLS configuration, such as Certificate, private key data.
> > +///
> > +struct _EFI_TLS_CONFIGURATION_PROTOCOL {
> > +  EFI_TLS_CONFIGURATION_SET_DATA     SetData;
> > +  EFI_TLS_CONFIGURATION_GET_DATA     GetData;
> > +};
> > +
> > +extern EFI_GUID gEfiTlsConfigurationProtocolGuid;
> > +
> > +#endif  //__EFI_TLS_CONFIGURATION_PROTOCOL_H__
> > diff --git a/MdePkg/MdePkg.dec b/MdePkg/MdePkg.dec index
> > 3e08bed..f2bdb30 100644
> > --- a/MdePkg/MdePkg.dec
> > +++ b/MdePkg/MdePkg.dec
> > @@ -1607,10 +1607,19 @@
> >    gEfiHttpProtocolGuid                 = { 0x7a59b29b, 0x910b, 0x4171, {0x82, 0x42,
> > 0xa8, 0x5a, 0x0d, 0xf2, 0x5b, 0x5b }}
> >
> >    ## Include/Protocol/HttpUtilities.h
> >    gEfiHttpUtilitiesProtocolGuid        = { 0x3e35c163, 0x4074, 0x45dd, {0x43,
> > 0x1e, 0x23, 0x98, 0x9d, 0xd8, 0x6b, 0x32 }}
> >
> > +  ## Include/Protocol/Tls.h
> > +  gEfiTlsServiceBindingProtocolGuid   = { 0x952cb795, 0xff36, 0x48cf, {0xa2,
> > 0x49, 0x4d, 0xf4, 0x86, 0xd6, 0xab, 0x8d }}
> > +
> > +  ## Include/Protocol/Tls.h
> > +  gEfiTlsProtocolGuid                 = { 0xca959f, 0x6cfa, 0x4db1, {0x95, 0xbc,
> 0xe4,
> > 0x6c, 0x47, 0x51, 0x43, 0x90 }}
> > +
> > +  ## Include/Protocol/TlsConfig.h
> > +  gEfiTlsConfigurationProtocolGuid    = { 0x1682fe44, 0xbd7a, 0x4407, { 0xb7,
> > 0xc7, 0xdc, 0xa3, 0x7c, 0xa3, 0x92, 0x2d }}
> > +
> >    ## Include/Protocol/Rest.h
> >    gEfiRestProtocolGuid                 =  { 0x0db48a36, 0x4e54, 0xea9c, {0x9b, 0x09,
> > 0x1e, 0xa5, 0xbe, 0x3a, 0x66, 0x0b }}
> >
> >    ## Include/Protocol/Supplicant.h
> >    gEfiSupplicantServiceBindingProtocolGuid  = { 0x45bcd98e, 0x59ad, 
> > 0x4174, { 0x95, 0x46, 0x34, 0x4a, 0x7, 0x48, 0x58, 0x98 }}
> > --
> > 1.9.5.msysgit.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 02/10] MdePkg: Add a header to standardize TLS definitions
  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
  2 siblings, 0 replies; 37+ messages in thread
From: Ye, Ting @ 2016-12-15  8:35 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Long, Qin, Fu, Siyuan, Zhang, Lubo, Gao, Liming,
	Kinney, Michael D, Thomas Palmer

Reviewed-by: Ye Ting <ting.ye@intel.com>


-----Original Message-----
From: Wu, Jiaxin 
Sent: Wednesday, December 14, 2016 3:34 PM
To: edk2-devel@lists.01.org
Cc: Long, Qin <qin.long@intel.com>; Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; Gao, Liming <liming.gao@intel.com>; Kinney, Michael D <michael.d.kinney@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>; Wu, Jiaxin <jiaxin.wu@intel.com>
Subject: [Patch 02/10] MdePkg: Add a header to standardize TLS definitions

This path is used to standardize TLS definitions from related RFCs. Including TLS Cipher Suites, TLS Version, TLS Content Type and TLS Record Header, etc.

Cc: Long Qin <qin.long@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Michael D Kinney <michael.d.kinney@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>
---
 MdePkg/Include/IndustryStandard/Tls1.h | 93 ++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)
 create mode 100644 MdePkg/Include/IndustryStandard/Tls1.h

diff --git a/MdePkg/Include/IndustryStandard/Tls1.h b/MdePkg/Include/IndustryStandard/Tls1.h
new file mode 100644
index 0000000..14eb265
--- /dev/null
+++ b/MdePkg/Include/IndustryStandard/Tls1.h
@@ -0,0 +1,93 @@
+/** @file
+  Transport Layer Security  -- TLS 1.0/1.1/1.2 Standard definitions, from RFC 2246/4346/5246    
+
+  This file contains common TLS 1.0/1.1/1.2 definitions from RFC 
+ 2246/4346/5246
+
+  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 __TLS_1_H__
+#define __TLS_1_H__
+
+#pragma pack(1)
+
+///
+/// TLS Cipher Suite, refers to A.5 of rfc-2246, rfc-4346 and rfc-5246.
+///
+#define TLS_RSA_WITH_NULL_MD5                    {0x00, 0x01}
+#define TLS_RSA_WITH_NULL_SHA                    {0x00, 0x02}
+#define TLS_RSA_WITH_RC4_128_MD5                 {0x00, 0x04}
+#define TLS_RSA_WITH_RC4_128_SHA                 {0x00, 0x05}
+#define TLS_RSA_WITH_IDEA_CBC_SHA                {0x00, 0x07}
+#define TLS_RSA_WITH_DES_CBC_SHA                 {0x00, 0x09}
+#define TLS_RSA_WITH_3DES_EDE_CBC_SHA            {0x00, 0x0A}
+#define TLS_DH_DSS_WITH_DES_CBC_SHA              {0x00, 0x0C}
+#define TLS_DH_DSS_WITH_3DES_EDE_CBC_SHA         {0x00, 0x0D}
+#define TLS_DH_RSA_WITH_DES_CBC_SHA              {0x00, 0x0F}
+#define TLS_DH_RSA_WITH_3DES_EDE_CBC_SHA         {0x00, 0x10}
+#define TLS_DHE_DSS_WITH_DES_CBC_SHA             {0x00, 0x12}
+#define TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA        {0x00, 0x13}
+#define TLS_DHE_RSA_WITH_DES_CBC_SHA             {0x00, 0x15}
+#define TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA        {0x00, 0x16}
+#define TLS_RSA_WITH_AES_128_CBC_SHA             {0x00, 0x2F}
+#define TLS_DH_DSS_WITH_AES_128_CBC_SHA          {0x00, 0x30}
+#define TLS_DH_RSA_WITH_AES_128_CBC_SHA          {0x00, 0x31}
+#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA         {0x00, 0x32}
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA         {0x00, 0x33}
+#define TLS_RSA_WITH_AES_256_CBC_SHA             {0x00, 0x35}
+#define TLS_DH_DSS_WITH_AES_256_CBC_SHA          {0x00, 0x36}
+#define TLS_DH_RSA_WITH_AES_256_CBC_SHA          {0x00, 0x37}
+#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA         {0x00, 0x38}
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA         {0x00, 0x39}
+#define TLS_RSA_WITH_NULL_SHA256                 {0x00, 0x3B}
+#define TLS_RSA_WITH_AES_128_CBC_SHA256          {0x00, 0x3C}
+#define TLS_RSA_WITH_AES_256_CBC_SHA256          {0x00, 0x3D}
+#define TLS_DH_DSS_WITH_AES_128_CBC_SHA256       {0x00, 0x3E}
+#define TLS_DH_RSA_WITH_AES_128_CBC_SHA256       {0x00, 0x3F}
+#define TLS_DHE_DSS_WITH_AES_128_CBC_SHA256      {0x00, 0x40}
+#define TLS_DHE_RSA_WITH_AES_128_CBC_SHA256      {0x00, 0x67}
+#define TLS_DH_DSS_WITH_AES_256_CBC_SHA256       {0x00, 0x68}
+#define TLS_DH_RSA_WITH_AES_256_CBC_SHA256       {0x00, 0x69}
+#define TLS_DHE_DSS_WITH_AES_256_CBC_SHA256      {0x00, 0x6A}
+#define TLS_DHE_RSA_WITH_AES_256_CBC_SHA256      {0x00, 0x6B}
+
+///
+/// TLS Version, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
+///
+#define TLS10_PROTOCOL_VERSION_MAJOR  0x03 #define 
+TLS10_PROTOCOL_VERSION_MINOR  0x01 #define TLS11_PROTOCOL_VERSION_MAJOR  
+0x03 #define TLS11_PROTOCOL_VERSION_MINOR  0x02 #define 
+TLS12_PROTOCOL_VERSION_MAJOR  0x03 #define TLS12_PROTOCOL_VERSION_MINOR  
+0x03
+
+///
+/// TLS Content Type, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
+///
+typedef enum {
+  TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20,
+  TLS_CONTENT_TYPE_ALERT              = 21,
+  TLS_CONTENT_TYPE_HANDSHAKE          = 22,
+  TLS_CONTENT_TYPE_APPLICATION_DATA   = 23,
+} TLS_CONTENT_TYPE;
+
+///
+/// TLS Record Header, refers to A.1 of rfc-2246, rfc-4346 and rfc-5246.
+///
+typedef struct {   
+  UINT8                   ContentType;
+  EFI_TLS_VERSION         Version;
+  UINT16                  Length;
+} TLS_RECORD_HEADER;
+
+#pragma pack()
+
+#endif
+
--
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 03/10] CryptoPkg: Enable ssl build in OpensslLib directly
  2016-12-14  7:34 ` [Patch 03/10] CryptoPkg: Enable ssl build in OpensslLib directly Jiaxin Wu
@ 2016-12-15  8:37   ` Ye, Ting
  0 siblings, 0 replies; 37+ messages in thread
From: Ye, Ting @ 2016-12-15  8:37 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Long, Qin, Fu, Siyuan, Zhang, Lubo, Thomas Palmer

Reviewed-by: Ye Ting <ting.ye@intel.com>


-----Original Message-----
From: Wu, Jiaxin 
Sent: Wednesday, December 14, 2016 3:34 PM
To: edk2-devel@lists.01.org
Cc: Wu, Jiaxin <jiaxin.wu@intel.com>; Ye, Ting <ting.ye@intel.com>; Long, Qin <qin.long@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>
Subject: [Patch 03/10] CryptoPkg: Enable ssl build in OpensslLib directly

This patch is used to enable ssl build in OpensslLib module directly.

Cc: Wu Jiaxin <jiaxin.wu@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Long Qin <qin.long@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@intel.com>
Cc: Thomas Palmer <thomas.palmer@hpe.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Long Qin <qin.long@intel.com>
Reviewed-by: Wu Jiaxin <jiaxin.wu@intel.com>
Tested-by: Wu Jiaxin <jiaxin.wu@intel.com>
---
 CryptoPkg/Include/OpenSslSupport.h                 | 11 ++++-
 .../Library/BaseCryptLib/SysCall/CrtWrapper.c      | 10 +++++
 CryptoPkg/Library/OpensslLib/Install.cmd           |  1 +
 CryptoPkg/Library/OpensslLib/Install.sh            |  1 +
 CryptoPkg/Library/OpensslLib/OpensslLib.inf        | 52 +++++++++++++++++++++-
 CryptoPkg/Library/OpensslLib/process_files.sh      |  7 +--
 6 files changed, 75 insertions(+), 7 deletions(-)

diff --git a/CryptoPkg/Include/OpenSslSupport.h b/CryptoPkg/Include/OpenSslSupport.h
index dad40e4..600578e 100644
--- a/CryptoPkg/Include/OpenSslSupport.h
+++ b/CryptoPkg/Include/OpenSslSupport.h
@@ -1,9 +1,9 @@
 /** @file
   Root include file to support building OpenSSL Crypto Library.
 
-Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 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
 
@@ -116,10 +116,12 @@ typedef UINT32         ino_t;
 typedef UINT32         dev_t;
 typedef UINT16         nlink_t;
 typedef int            pid_t;
 typedef void           *DIR;
 typedef void           __sighandler_t (int);
+typedef UINT8          __uint8_t;
+typedef UINT8          sa_family_t;
 
 //
 // Structures from EFI Application Toolkit required to build Open SSL  //  struct tm { @@ -170,10 +172,16 @@ struct stat {
   UINT32   st_gen;          /* file generation number */
   INT32    st_lspare;
   INT64    st_qspare[2];
 };
 
+struct sockaddr {
+  __uint8_t sa_len;         /* total length */
+  sa_family_t sa_family;    /* address family */
+  char    sa_data[14];      /* actually longer; address value */
+};
+
 //
 // Externs from EFI Application Toolkit required to build Open SSL  //  extern int errno;
 
@@ -271,7 +279,8 @@ extern FILE  *stdout;
 #define abort()                           ASSERT (FALSE)
 #define assert(expression)
 #define localtime(timer)                  NULL
 #define gmtime_r(timer,result)            (result = NULL)
 #define atoi(nptr)                        AsciiStrDecimalToUintn(nptr)
+#define gettimeofday(tvp,tz)              do { (tvp)->tv_sec = time(NULL); (tvp)->tv_usec = 0; } while (0)
 
 #endif
diff --git a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
index c0ccc0e..a2386bc 100644
--- a/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
+++ b/CryptoPkg/Library/BaseCryptLib/SysCall/CrtWrapper.c
@@ -382,10 +382,15 @@ FILE *fopen (const char *c, const char *m)  size_t fread (void *b, size_t c, size_t i, FILE *f)  {
   return 0;
 }
 
+int fputs (const char *s, FILE *f)
+{
+  return 0;
+}
+
 int fprintf (FILE *f, const char *s, ...)  {
   return 0;
 }
 
@@ -446,5 +451,10 @@ void syslog (int a, const char *c, ...)
 
 ssize_t write (int f, const void *b, size_t l)  {
   return 0;
 }
+
+int printf (char const *fmt, ...)
+{
+  return 0;
+}
diff --git a/CryptoPkg/Library/OpensslLib/Install.cmd b/CryptoPkg/Library/OpensslLib/Install.cmd
index 3d86bc7..093414d 100755
--- a/CryptoPkg/Library/OpensslLib/Install.cmd
+++ b/CryptoPkg/Library/OpensslLib/Install.cmd
@@ -6,10 +6,11 @@ copy crypto\crypto.h            include\openssl
 copy crypto\opensslv.h          include\openssl
 copy crypto\opensslconf.h       include\openssl
 copy crypto\ebcdic.h            include\openssl
 copy crypto\symhacks.h          include\openssl
 copy crypto\ossl_typ.h          include\openssl
+copy crypto\o_dir.h             include
 copy crypto\objects\objects.h   include\openssl
 copy crypto\objects\obj_mac.h   include\openssl
 copy crypto\md4\md4.h           include\openssl
 copy crypto\md5\md5.h           include\openssl
 copy crypto\sha\sha.h           include\openssl
diff --git a/CryptoPkg/Library/OpensslLib/Install.sh b/CryptoPkg/Library/OpensslLib/Install.sh
index e6703d1..7bd55f6 100755
--- a/CryptoPkg/Library/OpensslLib/Install.sh
+++ b/CryptoPkg/Library/OpensslLib/Install.sh
@@ -8,10 +8,11 @@ cp crypto/crypto.h            include/openssl
 cp crypto/opensslv.h          include/openssl
 cp crypto/opensslconf.h       include/openssl
 cp crypto/ebcdic.h            include/openssl
 cp crypto/symhacks.h          include/openssl
 cp crypto/ossl_typ.h          include/openssl
+cp crypto/o_dir.h             include
 cp crypto/objects/objects.h   include/openssl
 cp crypto/objects/obj_mac.h   include/openssl
 cp crypto/md4/md4.h           include/openssl
 cp crypto/md5/md5.h           include/openssl
 cp crypto/sha/sha.h           include/openssl
diff --git a/CryptoPkg/Library/OpensslLib/OpensslLib.inf b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
index 8121e83..c14e36d 100644
--- a/CryptoPkg/Library/OpensslLib/OpensslLib.inf
+++ b/CryptoPkg/Library/OpensslLib/OpensslLib.inf
@@ -468,13 +468,63 @@
   $(OPENSSL_PATH)/crypto/ocsp/ocsp_srv.c
   $(OPENSSL_PATH)/crypto/ocsp/ocsp_prn.c
   $(OPENSSL_PATH)/crypto/ocsp/ocsp_vfy.c
   $(OPENSSL_PATH)/crypto/ocsp/ocsp_err.c
   $(OPENSSL_PATH)/crypto/krb5/krb5_asn.c
+  $(OPENSSL_PATH)/crypto/pqueue/pqueue.c
   $(OPENSSL_PATH)/crypto/cmac/cmac.c
   $(OPENSSL_PATH)/crypto/cmac/cm_ameth.c
   $(OPENSSL_PATH)/crypto/cmac/cm_pmeth.c
+  $(OPENSSL_PATH)/ssl/s2_meth.c
+  $(OPENSSL_PATH)/ssl/s2_srvr.c
+  $(OPENSSL_PATH)/ssl/s2_clnt.c
+  $(OPENSSL_PATH)/ssl/s2_lib.c
+  $(OPENSSL_PATH)/ssl/s2_enc.c
+  $(OPENSSL_PATH)/ssl/s2_pkt.c
+  $(OPENSSL_PATH)/ssl/s3_meth.c
+  $(OPENSSL_PATH)/ssl/s3_srvr.c
+  $(OPENSSL_PATH)/ssl/s3_clnt.c
+  $(OPENSSL_PATH)/ssl/s3_lib.c
+  $(OPENSSL_PATH)/ssl/s3_enc.c
+  $(OPENSSL_PATH)/ssl/s3_pkt.c
+  $(OPENSSL_PATH)/ssl/s3_both.c
+  $(OPENSSL_PATH)/ssl/s3_cbc.c
+  $(OPENSSL_PATH)/ssl/s23_meth.c
+  $(OPENSSL_PATH)/ssl/s23_srvr.c
+  $(OPENSSL_PATH)/ssl/s23_clnt.c
+  $(OPENSSL_PATH)/ssl/s23_lib.c
+  $(OPENSSL_PATH)/ssl/s23_pkt.c
+  $(OPENSSL_PATH)/ssl/t1_meth.c
+  $(OPENSSL_PATH)/ssl/t1_srvr.c
+  $(OPENSSL_PATH)/ssl/t1_clnt.c
+  $(OPENSSL_PATH)/ssl/t1_lib.c
+  $(OPENSSL_PATH)/ssl/t1_enc.c
+  $(OPENSSL_PATH)/ssl/t1_ext.c
+  $(OPENSSL_PATH)/ssl/d1_meth.c
+  $(OPENSSL_PATH)/ssl/d1_srvr.c
+  $(OPENSSL_PATH)/ssl/d1_clnt.c
+  $(OPENSSL_PATH)/ssl/d1_lib.c
+  $(OPENSSL_PATH)/ssl/d1_pkt.c
+  $(OPENSSL_PATH)/ssl/d1_both.c
+  $(OPENSSL_PATH)/ssl/d1_srtp.c
+  $(OPENSSL_PATH)/ssl/ssl_lib.c
+  $(OPENSSL_PATH)/ssl/ssl_err2.c
+  $(OPENSSL_PATH)/ssl/ssl_cert.c
+  $(OPENSSL_PATH)/ssl/ssl_sess.c
+  $(OPENSSL_PATH)/ssl/ssl_ciph.c
+  $(OPENSSL_PATH)/ssl/ssl_stat.c
+  $(OPENSSL_PATH)/ssl/ssl_rsa.c
+  $(OPENSSL_PATH)/ssl/ssl_asn1.c
+  $(OPENSSL_PATH)/ssl/ssl_txt.c
+  $(OPENSSL_PATH)/ssl/ssl_algs.c
+  $(OPENSSL_PATH)/ssl/bio_ssl.c
+  $(OPENSSL_PATH)/ssl/ssl_err.c
+  $(OPENSSL_PATH)/ssl/kssl.c
+  $(OPENSSL_PATH)/ssl/t1_reneg.c
+  $(OPENSSL_PATH)/ssl/tls_srp.c
+  $(OPENSSL_PATH)/ssl/t1_trce.c
+  $(OPENSSL_PATH)/ssl/ssl_utst.c
 
 # Autogenerated files list ends here
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -498,11 +548,11 @@
   # C4305: truncation from type1 to type2 of smaller size
   # C4306: conversion from type1 to type2 of greater size
   # C4702: Potentially uninitialized local variable name used
   # C4311: pointer truncation from 'type' to 'type'
   #
-  MSFT:*_*_IA32_CC_FLAGS    = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4244 /wd4701 /wd4702 /wd4706
+  MSFT:*_*_IA32_CC_FLAGS    = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4244 /wd4245 /wd4701 /wd4702 /wd4706
   MSFT:*_*_X64_CC_FLAGS     = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4133 /wd4244 /wd4245 /wd4267 /wd4701 /wd4305 /wd4306 /wd4702 /wd4706 /wd4311
   MSFT:*_*_IPF_CC_FLAGS     = -U_WIN32 -U_WIN64 -U_MSC_VER $(OPENSSL_FLAGS) /wd4133 /wd4244 /wd4245 /wd4267 /wd4701 /wd4305 /wd4306 /wd4702 /wd4706
 
   INTEL:*_*_IA32_CC_FLAGS   = -U_WIN32 -U_WIN64 -U_MSC_VER -U__ICC $(OPENSSL_FLAGS) /w
   INTEL:*_*_X64_CC_FLAGS    = -U_WIN32 -U_WIN64 -U_MSC_VER -U__ICC $(OPENSSL_FLAGS) /w
diff --git a/CryptoPkg/Library/OpensslLib/process_files.sh b/CryptoPkg/Library/OpensslLib/process_files.sh
index 885adf3..6f069ce 100755
--- a/CryptoPkg/Library/OpensslLib/process_files.sh
+++ b/CryptoPkg/Library/OpensslLib/process_files.sh
@@ -40,11 +40,10 @@ fi
 	no-jpake \
 	no-krb5 \
 	no-locking \
 	no-mdc2 \
 	no-posix-io \
-	no-pqueue \
 	no-rc2 \
 	no-rcs \
 	no-rfc3779 \
 	no-ripemd \
 	no-scrypt \
@@ -75,17 +74,15 @@ function filelist ()
 	    RELATIVE_DIRECTORY=*)
 		eval "$LINE"
 		;;
 	    LIBSRC=*)
 		LIBSRC=$(echo "$LINE" | sed s/^LIBSRC=//)
-		if [ "$RELATIVE_DIRECTORY" != "ssl" ]; then
-		    for FILE in $LIBSRC; do
+		for FILE in $LIBSRC; do
 			if [ "$FILE" != "b_print.c" ]; then
 			    echo -e '  $(OPENSSL_PATH)/'$RELATIVE_DIRECTORY/$FILE\\r\\
 			fi
-		    done
-		fi
+		done
 		;;
 	esac
     done
     echo -e \\r
 }
--
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 04/10] CryptoPkg: Add new TlsLib library
  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
  0 siblings, 1 reply; 37+ messages in thread
From: Ye, Ting @ 2016-12-16  2:10 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Long, Qin, Fu, Siyuan, Zhang, Lubo, Thomas Palmer

Hi Jiaxin,

Some comments included as following:

1.  In TlsGetHostPublicCert, line 1892:
	The status is set to EFI_NOT_FOUND but not returned. Does it make sense to update *DataSize in that case?	
2.  TlsDoHandshake uses EFI_PROTOCOL_ERROR but not record in function header.
3.  TlsGetCurrentCompressionId uses EFI_UNSUPPROTED but not record in function header. 
4.  Typo in TlsHandeAlert, should be TlsHandleAlert? Please also update the function description.

Others look good to me.

Reviewed-by: Ye Ting <ting.ye@intel.com>

Thanks,
Ting


-----Original Message-----
From: Wu, Jiaxin 
Sent: Wednesday, December 14, 2016 3:34 PM
To: edk2-devel@lists.01.org
Cc: Ye, Ting <ting.ye@intel.com>; Long, Qin <qin.long@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>; Wu, Jiaxin <jiaxin.wu@intel.com>
Subject: [Patch 04/10] CryptoPkg: Add new TlsLib library

This patch is used to add new TlsLib library, which is wrapped
over OpenSSL. The implementation provides TLS library functions
for EFI TLS protocol and EFI TLS Configuration Protocol.

Cc: Ye Ting <ting.ye@intel.com>
Cc: Long Qin <qin.long@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@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>
---
 CryptoPkg/CryptoPkg.dec                   |    4 +
 CryptoPkg/CryptoPkg.dsc                   |    1 +
 CryptoPkg/Include/Library/TlsLib.h        |  785 +++++++++++++++++++++
 CryptoPkg/Library/TlsLib/InternalTlsLib.h |   35 +
 CryptoPkg/Library/TlsLib/TlsConfig.c      | 1055 +++++++++++++++++++++++++++++
 CryptoPkg/Library/TlsLib/TlsInit.c        |  291 ++++++++
 CryptoPkg/Library/TlsLib/TlsLib.inf       |   49 ++
 CryptoPkg/Library/TlsLib/TlsLib.uni       |   19 +
 CryptoPkg/Library/TlsLib/TlsProcess.c     |  461 +++++++++++++
 9 files changed, 2700 insertions(+)
 create mode 100644 CryptoPkg/Include/Library/TlsLib.h
 create mode 100644 CryptoPkg/Library/TlsLib/InternalTlsLib.h
 create mode 100644 CryptoPkg/Library/TlsLib/TlsConfig.c
 create mode 100644 CryptoPkg/Library/TlsLib/TlsInit.c
 create mode 100644 CryptoPkg/Library/TlsLib/TlsLib.inf
 create mode 100644 CryptoPkg/Library/TlsLib/TlsLib.uni
 create mode 100644 CryptoPkg/Library/TlsLib/TlsProcess.c

diff --git a/CryptoPkg/CryptoPkg.dec b/CryptoPkg/CryptoPkg.dec
index 80579b7..eee26cb 100644
--- a/CryptoPkg/CryptoPkg.dec
+++ b/CryptoPkg/CryptoPkg.dec
@@ -29,10 +29,14 @@
 [LibraryClasses]
   ##  @libraryclass  Provides basic library functions for cryptographic primitives.
   ##
   BaseCryptLib|Include/Library/BaseCryptLib.h
 
+  ##  @libraryclass  Provides TLS library functions for EFI TLS protocol.
+  ##
+  TlsLib|Include/Library/TlsLib.h
+
 [Protocols]
   ## Include/Protocol/RuntimeCrypt.h
   gEfiRuntimeCryptProtocolGuid = { 0xe1475e0c, 0x1746, 0x4802, {0x86, 0x2e, 0x1, 0x1c, 0x2c, 0x2d, 0x9d, 0x86 }}
 
 [UserExtensions.TianoCore."ExtraFiles"]
diff --git a/CryptoPkg/CryptoPkg.dsc b/CryptoPkg/CryptoPkg.dsc
index 3c3e444..468e60b 100644
--- a/CryptoPkg/CryptoPkg.dsc
+++ b/CryptoPkg/CryptoPkg.dsc
@@ -121,10 +121,11 @@
 ###################################################################################################
 [Components]
   CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
   CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+  CryptoPkg/Library/TlsLib/TlsLib.inf
 
   CryptoPkg/Application/Cryptest/Cryptest.inf
 
   CryptoPkg/CryptRuntimeDxe/CryptRuntimeDxe.inf
 
diff --git a/CryptoPkg/Include/Library/TlsLib.h b/CryptoPkg/Include/Library/TlsLib.h
new file mode 100644
index 0000000..38b861e
--- /dev/null
+++ b/CryptoPkg/Include/Library/TlsLib.h
@@ -0,0 +1,785 @@
+/** @file
+  Defines TLS Library APIs.
+
+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 __TLS_LIB_H__
+#define __TLS_LIB_H__
+
+/**
+  Initializes the OpenSSL library.
+
+  This function registers ciphers and digests used directly and indirectly
+  by SSL/TLS, and initializes the readable error messages.
+  This function must be called before any other action takes places.
+
+**/
+VOID
+EFIAPI
+TlsInitialize (
+  VOID
+  );
+
+/**
+  Free an allocated SSL_CTX object.
+
+  @param[in]  TlsCtx    Pointer to the SSL_CTX object to be released.
+
+**/
+VOID
+EFIAPI
+TlsCtxFree (
+  IN   VOID                  *TlsCtx
+  );
+
+/**
+  Creates a new SSL_CTX object as framework to establish TLS/SSL enabled
+  connections.
+
+  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
+  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
+
+  @return  Pointer to an allocated SSL_CTX object.
+           If the creation failed, TlsCtxNew() returns NULL.
+
+**/
+VOID *
+EFIAPI
+TlsCtxNew (
+  IN     UINT8                    MajorVer,
+  IN     UINT8                    MinorVer
+  );
+
+/**
+  Free an allocated TLS object.
+
+  This function removes the TLS object pointed to by Tls and frees up the
+  allocated memory. If Tls is NULL, nothing is done.
+
+  @param[in]  Tls    Pointer to the TLS object to be freed.
+
+**/
+VOID
+EFIAPI
+TlsFree (
+  IN     VOID                     *Tls
+  );
+
+/**
+  Create a new TLS object for a connection.
+
+  This function creates a new TLS object for a connection. The new object
+  inherits the setting of the underlying context TlsCtx: connection method,
+  options, verification setting.
+
+  @param[in]  TlsCtx    Pointer to the SSL_CTX object.
+
+  @return  Pointer to an allocated SSL object.
+           If the creation failed, TlsNew() returns NULL.
+
+**/
+VOID *
+EFIAPI
+TlsNew (
+  IN     VOID                     *TlsCtx
+  );
+
+/**
+  Checks if the TLS handshake was done.
+
+  This function will check if the specified TLS handshake was done.
+
+  @param[in]  Tls    Pointer to the TLS object for handshake state checking.
+
+  @retval  TRUE     The TLS handshake was done.
+  @retval  FALSE    The TLS handshake was not done.
+
+**/
+BOOLEAN
+EFIAPI
+TlsInHandshake (
+  IN     VOID                     *Tls
+  );
+
+/**
+  Perform a TLS/SSL handshake.
+
+  This function will perform a TLS/SSL handshake.
+
+  @param[in]       Tls            Pointer to the TLS object for handshake operation.
+  @param[in]       BufferIn       Pointer to the most recently received TLS Handshake packet.
+  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS
+                                  Handshake packet.
+  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferIn is NULL but BufferInSize is NOT 0.
+                                  BufferInSize is 0 but BufferIn is NOT NULL.
+                                  BufferOutSize is NULL.
+                                  BufferOut is NULL if *BufferOutSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsDoHandshake (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *BufferIn, OPTIONAL
+  IN     UINTN                    BufferInSize, OPTIONAL
+     OUT UINT8                    *BufferOut, OPTIONAL
+  IN OUT UINTN                    *BufferOutSize
+  );
+
+/**
+  Hande Alert message recorded in BufferIn. If BufferIn is NULL and BufferInSize is zero,
+  TLS session has errors and the response packet needs to be Alert message based on error type.
+
+  @param[in]       Tls            Pointer to the TLS object for state checking.
+  @param[in]       BufferIn       Pointer to the most recently received TLS Alert packet.
+  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS
+                                  Alert packet.
+  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferIn is NULL but BufferInSize is NOT 0.
+                                  BufferInSize is 0 but BufferIn is NOT NULL.
+                                  BufferOutSize is NULL.
+                                  BufferOut is NULL if *BufferOutSize is not zero.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsHandeAlert (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *BufferIn, OPTIONAL
+  IN     UINTN                    BufferInSize, OPTIONAL
+     OUT UINT8                    *BufferOut, OPTIONAL
+  IN OUT UINTN                    *BufferOutSize
+  );
+
+/**
+  Build the CloseNotify packet.
+
+  @param[in]       Tls            Pointer to the TLS object for state checking.
+  @param[in, out]  Buffer         Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferSize is NULL.
+                                  Buffer is NULL if *BufferSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsCloseNotify (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *Buffer,
+  IN OUT UINTN                    *BufferSize
+  );
+
+/**
+  Attempts to read bytes from one TLS object and places the data in Buffer.
+
+  This function will attempt to read BufferSize bytes from the TLS object
+  and places the data in Buffer.
+
+  @param[in]      Tls           Pointer to the TLS object.
+  @param[in,out]  Buffer        Pointer to the buffer to store the data.
+  @param[in]      BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The amount of data successfully read from the TLS object.
+  @retval  <=0   No data was successfully read.
+
+**/
+INTN
+EFIAPI
+TlsCtrlTrafficOut (
+  IN     VOID                     *Tls,
+  IN OUT VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  );
+
+/**
+  Attempts to write data from the buffer to TLS object.
+
+  This function will attempt to write BufferSize bytes data from the Buffer
+  to the TLS object.
+
+  @param[in]  Tls           Pointer to the TLS object.
+  @param[in]  Buffer        Pointer to the data buffer.
+  @param[in]  BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The amount of data successfully written to the TLS object.
+  @retval <=0    No data was successfully written.
+
+**/
+INTN
+EFIAPI
+TlsCtrlTrafficIn (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  );
+
+/**
+  Attempts to read bytes from the specified TLS connection into the buffer.
+
+  This function tries to read BufferSize bytes data from the specified TLS
+  connection into the Buffer.
+
+  @param[in]      Tls           Pointer to the TLS connection for data reading.
+  @param[in,out]  Buffer        Pointer to the data buffer.
+  @param[in]      BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The read operation was successful, and return value is the
+                 number of bytes actually read from the TLS connection.
+  @retval  <=0   The read operation was not successful.
+
+**/
+INTN
+EFIAPI
+TlsRead (
+  IN     VOID                     *Tls,
+  IN OUT VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  );
+
+/**
+  Attempts to write data to a TLS connection.
+
+  This function tries to write BufferSize bytes data from the Buffer into the
+  specified TLS connection.
+
+  @param[in]  Tls           Pointer to the TLS connection for data writing.
+  @param[in]  Buffer        Pointer to the data buffer.
+  @param[in]  BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The write operation was successful, and return value is the
+                 number of bytes actually written to the TLS connection.
+  @retval <=0    The write operation was not successful.
+
+**/
+INTN
+EFIAPI
+TlsWrite (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  );
+
+/**
+  Set a new TLS/SSL method for a particular TLS object.
+
+  This function sets a new TLS/SSL method for a particular TLS object.
+
+  @param[in]  Tls         Pointer to a TLS object.
+  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
+  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
+
+  @retval  EFI_SUCCESS           The TLS/SSL method was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetVersion (
+  IN     VOID                     *Tls,
+  IN     UINT8                    MajorVer,
+  IN     UINT8                    MinorVer
+  );
+
+/**
+  Set TLS object to work in client or server mode.
+
+  This function prepares a TLS object to work in client or server mode.
+
+  @param[in]  Tls         Pointer to a TLS object.
+  @param[in]  IsServer    Work in server mode.
+
+  @retval  EFI_SUCCESS           The TLS/SSL work mode was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL work mode.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetConnectionEnd (
+  IN     VOID                     *Tls,
+  IN     BOOLEAN                  IsServer
+  );
+
+/**
+  Set the ciphers list to be used by the TLS object.
+
+  This function sets the ciphers for use by a specified TLS object.
+
+  @param[in]  Tls          Pointer to a TLS object.
+  @param[in]  CipherId     Pointer to a string that contains one or more
+                           ciphers separated by a colon.
+  @param[in]  CipherNum    The number of cipher in the list.
+
+  @retval  EFI_SUCCESS           The ciphers list was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS cipher in the list.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCipherList (
+  IN     VOID                     *Tls,
+  IN     UINT16                   *CipherId,
+  IN     UINTN                    CipherNum
+  );
+
+/**
+  Set the compression method for TLS/SSL operations.
+
+  This function handles TLS/SSL integrated compression methods.
+
+  @param[in]  CompMethod    The compression method ID.
+
+  @retval  EFI_SUCCESS        The compression method for the communication was
+                              set successfully.
+  @retval  EFI_UNSUPPORTED    Unsupported compression method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCompressionMethod (
+  IN     UINT8                    CompMethod
+  );
+
+/**
+  Set peer certificate verification mode for the TLS connection.
+
+  This function sets the verification mode flags for the TLS connection.
+
+  @param[in]  Tls           Pointer to the TLS object.
+  @param[in]  VerifyMode    A set of logically or'ed verification mode flags.
+
+**/
+VOID
+EFIAPI
+TlsSetVerify (
+  IN     VOID                     *Tls,
+  IN     UINT32                   VerifyMode
+  );
+
+/**
+  Sets a TLS/SSL session ID to be used during TLS/SSL connect.
+
+  This function sets a session ID to be used when the TLS/SSL connection is
+  to be established.
+
+  @param[in]  Tls             Pointer to the TLS object.
+  @param[in]  SessionId       Session ID data used for session resumption.
+  @param[in]  SessionIdLen    Length of Session ID in bytes.
+
+  @retval  EFI_SUCCESS           Session ID was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       No available session for ID setting.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetSessionId (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *SessionId,
+  IN     UINT16                   SessionIdLen
+  );
+
+/**
+  Adds the CA to the cert store when requesting Server or Client authentication.
+
+  This function adds the CA certificate to the list of CAs when requesting
+  Server or Client authentication for the chosen TLS connection.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
+                          X.509 certificate or PEM-encoded X.509 certificate.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be allocated.
+  @retval  EFI_ABORTED             Invalid X.509 certificate.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCaCertificate (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  );
+
+/**
+  Loads the local public certificate into the specified TLS object.
+
+  This function loads the X.509 certificate into the specified TLS object
+  for TLS negotiation.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
+                          X.509 certificate or PEM-encoded X.509 certificate.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be allocated.
+  @retval  EFI_ABORTED             Invalid X.509 certificate.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetHostPublicCert (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  );
+
+/**
+  Adds the local private key to the specified TLS object.
+
+  This function adds the local private key (PEM-encoded RSA or PKCS#8 private
+  key) into the specified TLS object for TLS negotiation.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a PEM-encoded RSA
+                          or PKCS#8 private key.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS     The operation succeeded.
+  @retval  EFI_UNSUPPORTED This function is not supported.
+  @retval  EFI_ABORTED     Invalid private key data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetHostPrivateKey (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  );
+
+/**
+  Adds the CA-supplied certificate revocation list for certificate validation.
+
+  This function adds the CA-supplied certificate revocation list data for
+  certificate validity checking.
+
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded CRL data.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS     The operation succeeded.
+  @retval  EFI_UNSUPPORTED This function is not supported.
+  @retval  EFI_ABORTED     Invalid CRL data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCertRevocationList (
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  );
+
+/**
+  Gets the protocol version used by the specified TLS connection.
+
+  This function returns the protocol version used by the specified TLS
+  connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The protocol version of the specified TLS connection.
+
+**/
+UINT16
+EFIAPI
+TlsGetVersion (
+  IN     VOID                     *Tls
+  );
+
+/**
+  Gets the connection end of the specified TLS connection.
+
+  This function returns the connection end (as client or as server) used by
+  the specified TLS connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The connection end used by the specified TLS connection.
+
+**/
+UINT8
+EFIAPI
+TlsGetConnectionEnd (
+  IN     VOID                     *Tls
+  );
+
+/**
+  Gets the cipher suite used by the specified TLS connection.
+
+  This function returns current cipher suite used by the specified
+  TLS connection.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[in,out]  CipherId    The cipher suite used by the TLS object.
+
+  @retval  EFI_SUCCESS           The cipher suite was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported cipher suite.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCurrentCipher (
+  IN     VOID                     *Tls,
+  IN OUT UINT16                   *CipherId
+  );
+
+/**
+  Gets the compression methods used by the specified TLS connection.
+
+  This function returns current integrated compression methods used by
+  the specified TLS connection.
+
+  @param[in]      Tls              Pointer to the TLS object.
+  @param[in,out]  CompressionId    The current compression method used by
+                                   the TLS object.
+
+  @retval  EFI_SUCCESS           The compression method was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_ABORTED           Invalid Compression method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCurrentCompressionId (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *CompressionId
+  );
+
+/**
+  Gets the verification mode currently set in the TLS connection.
+
+  This function returns the peer verification mode currently set in the
+  specified TLS connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The verification mode set in the specified TLS connection.
+
+**/
+UINT32
+EFIAPI
+TlsGetVerify (
+  IN     VOID                     *Tls
+  );
+
+/**
+  Gets the session ID used by the specified TLS connection.
+
+  This function returns the TLS/SSL session ID currently used by the
+  specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  SessionId       Buffer to contain the returned session ID.
+  @param[in,out]  SessionIdLen    The length of Session ID in bytes.
+
+  @retval  EFI_SUCCESS           The Session ID was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetSessionId (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *SessionId,
+  IN OUT UINT16                   *SessionIdLen
+  );
+
+/**
+  Gets the client random data used in the specified TLS connection.
+
+  This function returns the TLS/SSL client random data currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  ClientRandom    Buffer to contain the returned client
+                                  random data (32 bytes).
+
+**/
+VOID
+EFIAPI
+TlsGetClientRandom (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *ClientRandom
+  );
+
+/**
+  Gets the server random data used in the specified TLS connection.
+
+  This function returns the TLS/SSL server random data currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  ServerRandom    Buffer to contain the returned server
+                                  random data (32 bytes).
+
+**/
+VOID
+EFIAPI
+TlsGetServerRandom (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *ServerRandom
+  );
+
+/**
+  Gets the master key data used in the specified TLS connection.
+
+  This function returns the TLS/SSL master key material currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls            Pointer to the TLS object.
+  @param[in,out]  KeyMaterial    Buffer to contain the returned key material.
+
+  @retval  EFI_SUCCESS           Key material was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetKeyMaterial (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *KeyMaterial
+  );
+
+/**
+  Gets the CA Certificate from the cert store.
+
+  This function returns the CA certificate for the chosen
+  TLS connection.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the CA
+                              certificate data sent to the client.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCaCertificate (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  );
+
+/**
+  Gets the local public Certificate set in the specified TLS object.
+
+  This function returns the local public certificate which was currently set
+  in the specified TLS object.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the local
+                              public certificate.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_NOT_FOUND           The certificate is not found.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetHostPublicCert (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  );
+
+/**
+  Gets the local private key set in the specified TLS object.
+
+  This function returns the local private key data which was currently set
+  in the specified TLS object.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the local
+                              private key data.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetHostPrivateKey (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  );
+
+/**
+  Gets the CA-supplied certificate revocation list data set in the specified
+  TLS object.
+
+  This function returns the CA-supplied certificate revocation list data which
+  was currently set in the specified TLS object.
+
+  @param[out]     Data        Pointer to the data buffer to receive the CRL data.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCertRevocationList (
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  );
+
+#endif // __TLS_LIB_H__
diff --git a/CryptoPkg/Library/TlsLib/InternalTlsLib.h b/CryptoPkg/Library/TlsLib/InternalTlsLib.h
new file mode 100644
index 0000000..2438de9
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/InternalTlsLib.h
@@ -0,0 +1,35 @@
+/** @file
+  Internal include file for TlsLib.
+
+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.
+
+**/
+
+#include <Library/BaseCryptLib.h>
+#include <openssl/ssl.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+
+typedef struct {
+  //
+  // Main SSL Connection which is created by a server or a client
+  // per established connection.
+  //
+  SSL                             *Ssl;
+  //
+  // Memory BIO for the TLS/SSL Reading operations.
+  //
+  BIO                             *InBio;
+  //
+  // Memory BIO for the TLS/SSL Writing operations.
+  //
+  BIO                             *OutBio;
+} TLS_CONNECTION;
+
diff --git a/CryptoPkg/Library/TlsLib/TlsConfig.c b/CryptoPkg/Library/TlsLib/TlsConfig.c
new file mode 100644
index 0000000..31220b3
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/TlsConfig.c
@@ -0,0 +1,1055 @@
+/** @file
+  SSL/TLS Configuration Library Wrapper Implementation over OpenSSL.
+
+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 "InternalTlsLib.h"
+
+typedef struct {
+  //
+  // IANA/IETF defined Cipher Suite ID
+  //
+  UINT16                          IanaCipher;
+  //
+  // OpenSSL-used Cipher Suite String
+  //
+  CONST CHAR8                     *OpensslCipher;
+} TLS_CIPHER_PAIR;
+
+//
+// The mapping table between IANA/IETF Cipher Suite definitions and
+// OpenSSL-used Cipher Suite name.
+//
+STATIC CONST TLS_CIPHER_PAIR TlsCipherMappingTable[] = {
+  { 0x0001, "NULL-MD5" },                 /// TLS_RSA_WITH_NULL_MD5
+  { 0x0002, "NULL-SHA" },                 /// TLS_RSA_WITH_NULL_SHA
+  { 0x0004, "RC4-MD5" },                  /// TLS_RSA_WITH_RC4_128_MD5
+  { 0x0005, "RC4-SHA" },                  /// TLS_RSA_WITH_RC4_128_SHA
+  { 0x000A, "DES-CBC3-SHA" },             /// TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1
+  { 0x0016, "DHE-RSA-DES-CBC3-SHA" },     /// TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
+  { 0x002F, "AES128-SHA" },               /// TLS_RSA_WITH_AES_128_CBC_SHA, mandatory TLS 1.2
+  { 0x0030, "DH-DSS-AES128-SHA" },        /// TLS_DH_DSS_WITH_AES_128_CBC_SHA
+  { 0x0031, "DH-RSA-AES128-SHA" },        /// TLS_DH_RSA_WITH_AES_128_CBC_SHA
+  { 0x0033, "DHE-RSA-AES128-SHA" },       /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA
+  { 0x0035, "AES256-SHA" },               /// TLS_RSA_WITH_AES_256_CBC_SHA
+  { 0x0036, "DH-DSS-AES256-SHA" },        /// TLS_DH_DSS_WITH_AES_256_CBC_SHA
+  { 0x0037, "DH-RSA-AES256-SHA" },        /// TLS_DH_RSA_WITH_AES_256_CBC_SHA
+  { 0x0039, "DHE-RSA-AES256-SHA" },       /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA
+  { 0x003B, "NULL-SHA256" },              /// TLS_RSA_WITH_NULL_SHA256
+  { 0x003C, "AES128-SHA256" },            /// TLS_RSA_WITH_AES_128_CBC_SHA256
+  { 0x003D, "AES256-SHA256" },            /// TLS_RSA_WITH_AES_256_CBC_SHA256
+  { 0x003E, "DH-DSS-AES128-SHA256" },     /// TLS_DH_DSS_WITH_AES_128_CBC_SHA256
+  { 0x003F, "DH-RSA-AES128-SHA256" },     /// TLS_DH_RSA_WITH_AES_128_CBC_SHA256
+  { 0x0067, "DHE-RSA-AES128-SHA256" },    /// TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
+  { 0x0068, "DH-DSS-AES256-SHA256" },     /// TLS_DH_DSS_WITH_AES_256_CBC_SHA256
+  { 0x0069, "DH-RSA-AES256-SHA256" },     /// TLS_DH_RSA_WITH_AES_256_CBC_SHA256
+  { 0x006B, "DHE-RSA-AES256-SHA256" }     /// TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
+};
+
+/**
+  Gets the OpenSSL cipher suite string for the supplied IANA TLS cipher suite.
+
+  @param[in]  CipherId    The supplied IANA TLS cipher suite ID.
+
+  @return  The corresponding OpenSSL cipher suite string if found,
+           NULL otherwise.
+
+**/
+STATIC
+CONST CHAR8 *
+TlsGetCipherString (
+  IN     UINT16                   CipherId
+  )
+{
+  CONST TLS_CIPHER_PAIR  *CipherEntry;
+  UINTN                  TableSize;
+  UINTN                  Index;
+
+  CipherEntry = TlsCipherMappingTable;
+  TableSize = sizeof (TlsCipherMappingTable) / sizeof (TLS_CIPHER_PAIR);
+
+  //
+  // Search Cipher Mapping Table for IANA-OpenSSL Cipher Translation
+  //
+  for (Index = 0; Index < TableSize; Index++, CipherEntry++) {
+    //
+    // Translate IANA cipher suite name to OpenSSL name.
+    //
+    if (CipherEntry->IanaCipher == CipherId) {
+      return CipherEntry->OpensslCipher;
+    }
+  }
+
+  //
+  // No Cipher Mapping found, return NULL.
+  //
+  return NULL;
+}
+
+/**
+  Set a new TLS/SSL method for a particular TLS object.
+
+  This function sets a new TLS/SSL method for a particular TLS object.
+
+  @param[in]  Tls         Pointer to a TLS object.
+  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
+  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
+
+  @retval  EFI_SUCCESS           The TLS/SSL method was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetVersion (
+  IN     VOID                     *Tls,
+  IN     UINT8                    MajorVer,
+  IN     UINT8                    MinorVer
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  UINT16          ProtoVersion;
+
+  TlsConn = (TLS_CONNECTION *)Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  ProtoVersion = (MajorVer << 8) | MinorVer;
+
+  switch (ProtoVersion) {
+  case TLS1_VERSION:
+    //
+    // TLS 1.0
+    //
+    SSL_set_ssl_method (TlsConn->Ssl, TLSv1_method ());
+    break;
+  case TLS1_1_VERSION:
+    //
+    // TLS 1.1
+    //
+    SSL_set_ssl_method (TlsConn->Ssl, TLSv1_1_method ());
+    break;
+  case TLS1_2_VERSION:
+    //
+    // TLS 1.2
+    //
+    SSL_set_ssl_method (TlsConn->Ssl, TLSv1_2_method ());
+    break;
+  default:
+    //
+    // Unsupported Protocol Version
+    //
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;;
+}
+
+/**
+  Set TLS object to work in client or server mode.
+
+  This function prepares a TLS object to work in client or server mode.
+
+  @param[in]  Tls         Pointer to a TLS object.
+  @param[in]  IsServer    Work in server mode.
+
+  @retval  EFI_SUCCESS           The TLS/SSL work mode was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL work mode.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetConnectionEnd (
+  IN     VOID                     *Tls,
+  IN     BOOLEAN                  IsServer
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if (!IsServer) {
+    //
+    // Set TLS to work in Client mode.
+    //
+    SSL_set_connect_state (TlsConn->Ssl);
+  } else {
+    //
+    // Set TLS to work in Server mode.
+    // It is unsupported for UEFI version currently.
+    //
+    //SSL_set_accept_state (TlsConn->Ssl);
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set the ciphers list to be used by the TLS object.
+
+  This function sets the ciphers for use by a specified TLS object.
+
+  @param[in]  Tls          Pointer to a TLS object.
+  @param[in]  CipherId     Pointer to a UINT16 cipher Id.
+  @param[in]  CipherNum    The number of cipher in the list.
+
+  @retval  EFI_SUCCESS           The ciphers list was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported TLS cipher in the list.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCipherList (
+  IN     VOID                     *Tls,
+  IN     UINT16                   *CipherId,
+  IN     UINTN                    CipherNum
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  UINTN           Index;
+  CONST CHAR8     *MappingName;
+  CHAR8           CipherString[500];
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  MappingName = NULL;
+
+  memset (CipherString, 0, sizeof (CipherString));
+
+  for (Index = 0; Index < CipherNum; Index++) {
+    //
+    // Handling OpenSSL / RFC Cipher name mapping.
+    //
+    MappingName = TlsGetCipherString (*(CipherId + Index));
+    if (MappingName == NULL) {
+      return EFI_UNSUPPORTED;
+    }
+
+    if (Index != 0) {
+      //
+      // The ciphers were separated by a colon.
+      //
+      AsciiStrCatS (CipherString, sizeof (CipherString), ":");
+    }
+
+    AsciiStrCatS (CipherString, sizeof (CipherString), MappingName);
+  }
+
+  AsciiStrCatS (CipherString, sizeof (CipherString), ":@STRENGTH");
+
+  //
+  // Sets the ciphers for use by the Tls object.
+  //
+  if (SSL_set_cipher_list (TlsConn->Ssl, CipherString) <= 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set the compression method for TLS/SSL operations.
+
+  This function handles TLS/SSL integrated compression methods.
+
+  @param[in]  CompMethod    The compression method ID.
+
+  @retval  EFI_SUCCESS        The compression method for the communication was
+                              set successfully.
+  @retval  EFI_UNSUPPORTED    Unsupported compression method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCompressionMethod (
+  IN     UINT8                    CompMethod
+  )
+{
+  COMP_METHOD  *Cm;
+  INTN         Ret;
+
+  Cm  = NULL;
+  Ret = 0;
+
+  if (CompMethod == 0) {
+    //
+    // TLS defines one standard compression method, CompressionMethod.null (0),
+    // which specifies that data exchanged via the record protocol will not be compressed.
+    // So, return EFI_SUCCESS directly (RFC 3749).
+    //
+    return EFI_SUCCESS;
+  } else if (CompMethod == 1) {
+    Cm = COMP_zlib();
+  } else {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Adds the compression method to the list of available
+  // compression methods.
+  //
+  Ret = SSL_COMP_add_compression_method (CompMethod, Cm);
+  if (Ret != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set peer certificate verification mode for the TLS connection.
+
+  This function sets the verification mode flags for the TLS connection.
+
+  @param[in]  Tls           Pointer to the TLS object.
+  @param[in]  VerifyMode    A set of logically or'ed verification mode flags.
+
+**/
+VOID
+EFIAPI
+TlsSetVerify (
+  IN     VOID                     *Tls,
+  IN     UINT32                   VerifyMode
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return;
+  }
+
+  //
+  // Set peer certificate verification parameters with NULL callback.
+  //
+  SSL_set_verify (TlsConn->Ssl, VerifyMode, NULL);
+}
+
+/**
+  Sets a TLS/SSL session ID to be used during TLS/SSL connect.
+
+  This function sets a session ID to be used when the TLS/SSL connection is
+  to be established.
+
+  @param[in]  Tls             Pointer to the TLS object.
+  @param[in]  SessionId       Session ID data used for session resumption.
+  @param[in]  SessionIdLen    Length of Session ID in bytes.
+
+  @retval  EFI_SUCCESS           Session ID was set successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       No available session for ID setting.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetSessionId (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *SessionId,
+  IN     UINT16                   SessionIdLen
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  SSL_SESSION     *Session;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  Session = NULL;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Session = SSL_get_session (TlsConn->Ssl);
+  if (Session == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Session->session_id_length = SessionIdLen;
+  CopyMem (Session->session_id, SessionId, Session->session_id_length);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Adds the CA to the cert store when requesting Server or Client authentication.
+
+  This function adds the CA certificate to the list of CAs when requesting
+  Server or Client authentication for the chosen TLS connection.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
+                          X.509 certificate or PEM-encoded X.509 certificate.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be allocated.
+  @retval  EFI_ABORTED             Invalid X.509 certificate.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCaCertificate (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  )
+{
+  BIO             *BioCert;
+  X509            *Cert;
+  X509_STORE      *X509Store;
+  EFI_STATUS      Status;
+  TLS_CONNECTION  *TlsConn;
+  SSL_CTX         *SslCtx;
+  INTN            Ret;
+  unsigned long   ErrorCode;
+
+  BioCert   = NULL;
+  Cert      = NULL;
+  X509Store = NULL;
+  Status    = EFI_SUCCESS;
+  TlsConn   = (TLS_CONNECTION *) Tls;
+  Ret       = 0;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
+  // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
+  //
+  Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize);
+  if (Cert == NULL) {
+    //
+    // Certificate is from PEM encoding.
+    //
+    BioCert = BIO_new (BIO_s_mem ());
+    if (BioCert == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ON_EXIT;
+    }
+
+    if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+    }
+
+    Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
+    if (Cert == NULL) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+    }
+  }
+
+  SslCtx    = SSL_get_SSL_CTX (TlsConn->Ssl);
+  X509Store = SSL_CTX_get_cert_store (SslCtx);
+  if (X509Store == NULL) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+  }
+
+  //
+  // Add certificate to X509 store
+  //
+  Ret = X509_STORE_add_cert (X509Store, Cert);
+  if (Ret != 1) {
+    ErrorCode = ERR_peek_last_error ();
+    //
+    // Ignore "already in table" errors
+    //
+    if (!(ERR_GET_FUNC (ErrorCode) == X509_F_X509_STORE_ADD_CERT &&
+        ERR_GET_REASON (ErrorCode) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+    }
+  }
+
+ON_EXIT:
+  if (BioCert != NULL) {
+    BIO_free (BioCert);
+  }
+
+  if (Cert != NULL) {
+    X509_free (Cert);
+  }
+
+  return Status;
+}
+
+/**
+  Loads the local public certificate into the specified TLS object.
+
+  This function loads the X.509 certificate into the specified TLS object
+  for TLS negotiation.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
+                          X.509 certificate or PEM-encoded X.509 certificate.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be allocated.
+  @retval  EFI_ABORTED             Invalid X.509 certificate.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetHostPublicCert (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  )
+{
+  BIO             *BioCert;
+  X509            *Cert;
+  EFI_STATUS      Status;
+  TLS_CONNECTION  *TlsConn;
+
+  BioCert = NULL;
+  Cert    = NULL;
+  Status  = EFI_SUCCESS;
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize == 0) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
+  // Determine whether certificate is from DER encoding, if so, translate it to X509 structure.
+  //
+  Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize);
+  if (Cert == NULL) {
+    //
+    // Certificate is from PEM encoding.
+    //
+    BioCert = BIO_new (BIO_s_mem ());
+    if (BioCert == NULL) {
+      Status = EFI_OUT_OF_RESOURCES;
+      goto ON_EXIT;
+    }
+
+    if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+    }
+
+    Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
+    if (Cert == NULL) {
+      Status = EFI_ABORTED;
+      goto ON_EXIT;
+    }
+  }
+
+  if (SSL_use_certificate (TlsConn->Ssl, Cert) != 1) {
+    Status = EFI_ABORTED;
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+  if (BioCert != NULL) {
+    BIO_free (BioCert);
+  }
+
+  if (Cert != NULL) {
+    X509_free (Cert);
+  }
+
+  return Status;
+}
+
+/**
+  Adds the local private key to the specified TLS object.
+
+  This function adds the local private key (PEM-encoded RSA or PKCS#8 private
+  key) into the specified TLS object for TLS negotiation.
+
+  @param[in]  Tls         Pointer to the TLS object.
+  @param[in]  Data        Pointer to the data buffer of a PEM-encoded RSA
+                          or PKCS#8 private key.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS     The operation succeeded.
+  @retval  EFI_UNSUPPORTED This function is not supported.
+  @retval  EFI_ABORTED     Invalid private key data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetHostPrivateKey (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Adds the CA-supplied certificate revocation list for certificate validation.
+
+  This function adds the CA-supplied certificate revocation list data for
+  certificate validity checking.
+
+  @param[in]  Data        Pointer to the data buffer of a DER-encoded CRL data.
+  @param[in]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS     The operation succeeded.
+  @retval  EFI_UNSUPPORTED This function is not supported.
+  @retval  EFI_ABORTED     Invalid CRL data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsSetCertRevocationList (
+  IN     VOID                     *Data,
+  IN     UINTN                    DataSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Gets the protocol version used by the specified TLS connection.
+
+  This function returns the protocol version used by the specified TLS
+  connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The protocol version of the specified TLS connection.
+
+**/
+UINT16
+EFIAPI
+TlsGetVersion (
+  IN     VOID                     *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  ASSERT (TlsConn != NULL);
+
+  return (UINT16)(SSL_version (TlsConn->Ssl));
+}
+
+/**
+  Gets the connection end of the specified TLS connection.
+
+  This function returns the connection end (as client or as server) used by
+  the specified TLS connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The connection end used by the specified TLS connection.
+
+**/
+UINT8
+EFIAPI
+TlsGetConnectionEnd (
+  IN     VOID                     *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  ASSERT (TlsConn != NULL);
+
+  return (UINT8)SSL_is_server (TlsConn->Ssl);
+}
+
+/**
+  Gets the cipher suite used by the specified TLS connection.
+
+  This function returns current cipher suite used by the specified
+  TLS connection.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[in,out]  CipherId    The cipher suite used by the TLS object.
+
+  @retval  EFI_SUCCESS           The cipher suite was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Unsupported cipher suite.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCurrentCipher (
+  IN     VOID                     *Tls,
+  IN OUT UINT16                   *CipherId
+  )
+{
+  TLS_CONNECTION    *TlsConn;
+  CONST SSL_CIPHER  *Cipher;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  Cipher  = NULL;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Cipher = SSL_get_current_cipher (TlsConn->Ssl);
+  if (Cipher == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  *CipherId = (SSL_CIPHER_get_id (Cipher)) & 0xFFFF;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets the compression methods used by the specified TLS connection.
+
+  This function returns current integrated compression methods used by
+  the specified TLS connection.
+
+  @param[in]      Tls              Pointer to the TLS object.
+  @param[in,out]  CompressionId    The current compression method used by
+                                   the TLS object.
+
+  @retval  EFI_SUCCESS           The compression method was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_ABORTED           Invalid Compression method.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCurrentCompressionId (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *CompressionId
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Gets the verification mode currently set in the TLS connection.
+
+  This function returns the peer verification mode currently set in the
+  specified TLS connection.
+
+  @param[in]  Tls    Pointer to the TLS object.
+
+  @return  The verification mode set in the specified TLS connection.
+
+**/
+UINT32
+EFIAPI
+TlsGetVerify (
+  IN     VOID                     *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  ASSERT (TlsConn != NULL);
+
+  return SSL_get_verify_mode (TlsConn->Ssl);
+}
+
+/**
+  Gets the session ID used by the specified TLS connection.
+
+  This function returns the TLS/SSL session ID currently used by the
+  specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  SessionId       Buffer to contain the returned session ID.
+  @param[in,out]  SessionIdLen    The length of Session ID in bytes.
+
+  @retval  EFI_SUCCESS           The Session ID was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetSessionId (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *SessionId,
+  IN OUT UINT16                   *SessionIdLen
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  SSL_SESSION     *Session;
+  CONST UINT8     *SslSessionId;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  Session = NULL;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL || SessionIdLen == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Session = SSL_get_session (TlsConn->Ssl);
+  if (Session == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  SslSessionId = SSL_SESSION_get_id (Session, (unsigned int *)SessionIdLen);
+  CopyMem (SessionId, SslSessionId, *SessionIdLen);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets the client random data used in the specified TLS connection.
+
+  This function returns the TLS/SSL client random data currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  ClientRandom    Buffer to contain the returned client
+                                  random data (32 bytes).
+
+**/
+VOID
+EFIAPI
+TlsGetClientRandom (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *ClientRandom
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || ClientRandom == NULL) {
+    return;
+  }
+
+  CopyMem (ClientRandom, TlsConn->Ssl->s3->client_random, SSL3_RANDOM_SIZE);
+}
+
+/**
+  Gets the server random data used in the specified TLS connection.
+
+  This function returns the TLS/SSL server random data currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls             Pointer to the TLS object.
+  @param[in,out]  ServerRandom    Buffer to contain the returned server
+                                  random data (32 bytes).
+
+**/
+VOID
+EFIAPI
+TlsGetServerRandom (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *ServerRandom
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || ServerRandom == NULL) {
+    return;
+  }
+
+  CopyMem (ServerRandom, TlsConn->Ssl->s3->server_random, SSL3_RANDOM_SIZE);
+}
+
+/**
+  Gets the master key data used in the specified TLS connection.
+
+  This function returns the TLS/SSL master key material currently used in
+  the specified TLS connection.
+
+  @param[in]      Tls            Pointer to the TLS object.
+  @param[in,out]  KeyMaterial    Buffer to contain the returned key material.
+
+  @retval  EFI_SUCCESS           Key material was returned successfully.
+  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
+  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetKeyMaterial (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *KeyMaterial
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  SSL_SESSION     *Session;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  Session = NULL;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || KeyMaterial == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Session = SSL_get_session (TlsConn->Ssl);
+
+  if (Session == NULL) {
+    return EFI_UNSUPPORTED;
+  }
+
+  CopyMem (KeyMaterial, Session->master_key, Session->master_key_length);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Gets the CA Certificate from the cert store.
+
+  This function returns the CA certificate for the chosen
+  TLS connection.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the CA
+                              certificate data sent to the client.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCaCertificate (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Gets the local public Certificate set in the specified TLS object.
+
+  This function returns the local public certificate which was currently set
+  in the specified TLS object.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the local
+                              public certificate.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
+  @retval  EFI_NOT_FOUND           The certificate is not found.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetHostPublicCert (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  )
+{
+  X509            *Cert;
+  EFI_STATUS      Status;
+  TLS_CONNECTION  *TlsConn;
+
+  Cert    = NULL;
+  Status  = EFI_SUCCESS;
+  TlsConn = (TLS_CONNECTION *) Tls;
+
+  if (TlsConn == NULL || TlsConn->Ssl == NULL || DataSize == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Cert = SSL_get_certificate(TlsConn->Ssl);
+  if (Cert == NULL) {
+    Status = EFI_NOT_FOUND;
+  }
+
+  //
+  // Only DER encoding is supported currently.
+  //
+  if (*DataSize < (UINTN) i2d_X509 (Cert, NULL)) {
+    *DataSize = (UINTN) i2d_X509 (Cert, NULL);
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  *DataSize = (UINTN) i2d_X509 (Cert, (unsigned char **) &Data);
+
+  return Status;
+}
+
+/**
+  Gets the local private key set in the specified TLS object.
+
+  This function returns the local private key data which was currently set
+  in the specified TLS object.
+
+  @param[in]      Tls         Pointer to the TLS object.
+  @param[out]     Data        Pointer to the data buffer to receive the local
+                              private key data.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetHostPrivateKey (
+  IN     VOID                     *Tls,
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Gets the CA-supplied certificate revocation list data set in the specified
+  TLS object.
+
+  This function returns the CA-supplied certificate revocation list data which
+  was currently set in the specified TLS object.
+
+  @param[out]     Data        Pointer to the data buffer to receive the CRL data.
+  @param[in,out]  DataSize    The size of data buffer in bytes.
+
+  @retval  EFI_SUCCESS             The operation succeeded.
+  @retval  EFI_UNSUPPORTED         This function is not supported.
+  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsGetCertRevocationList (
+  OUT    VOID                     *Data,
+  IN OUT UINTN                    *DataSize
+  )
+{
+  return EFI_UNSUPPORTED;
+}
diff --git a/CryptoPkg/Library/TlsLib/TlsInit.c b/CryptoPkg/Library/TlsLib/TlsInit.c
new file mode 100644
index 0000000..6b1fd93
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/TlsInit.c
@@ -0,0 +1,291 @@
+/** @file
+  SSL/TLS Initialization Library Wrapper Implementation over OpenSSL.
+
+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 "InternalTlsLib.h"
+
+/**
+  Initializes the OpenSSL library.
+
+  This function registers ciphers and digests used directly and indirectly
+  by SSL/TLS, and initializes the readable error messages.
+  This function must be called before any other action takes places.
+
+**/
+VOID
+EFIAPI
+TlsInitialize (
+  VOID
+  )
+{
+  //
+  // Performs initialization of crypto and ssl library, and loads required
+  // algorithms.
+  //
+  SSL_library_init ();
+
+  //
+  // Loads error strings from both crypto and ssl library.
+  //
+  SSL_load_error_strings ();
+
+  /// OpenSSL_add_all_algorithms();
+
+  //
+  // Initialize the pseudorandom number generator.
+  //
+  RandomSeed (NULL, 0);
+}
+
+/**
+  Free an allocated SSL_CTX object.
+
+  @param[in]  TlsCtx    Pointer to the SSL_CTX object to be released.
+
+**/
+VOID
+EFIAPI
+TlsCtxFree (
+  IN   VOID                  *TlsCtx
+  )
+{
+  if (TlsCtx == NULL) {
+    return;
+  }
+
+  if (TlsCtx != NULL) {
+    SSL_CTX_free ((SSL_CTX *) (TlsCtx));
+  }
+}
+
+/**
+  Creates a new SSL_CTX object as framework to establish TLS/SSL enabled
+  connections.
+
+  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
+  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
+
+  @return  Pointer to an allocated SSL_CTX object.
+           If the creation failed, TlsCtxNew() returns NULL.
+
+**/
+VOID *
+EFIAPI
+TlsCtxNew (
+  IN     UINT8                    MajorVer,
+  IN     UINT8                    MinorVer
+  )
+{
+  SSL_CTX  *TlsCtx;
+  UINT16   ProtoVersion;
+
+  ProtoVersion = (MajorVer << 8) | MinorVer;
+
+  TlsCtx = SSL_CTX_new (SSLv23_client_method ());
+  if (TlsCtx == NULL) {
+    return NULL;
+  }
+
+  //
+  // Ensure SSLv3 is disabled
+  //
+  SSL_CTX_set_options (TlsCtx, SSL_OP_NO_SSLv3);
+
+  //
+  // Treat as minimum accepted versions.  Client can use higher
+  // TLS version if server supports it
+  //
+  switch (ProtoVersion) {
+  case TLS1_VERSION:
+    //
+    // TLS 1.0
+    //
+    break;
+  case TLS1_1_VERSION:
+    //
+    // TLS 1.1
+    //
+    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1);
+    break;
+  case TLS1_2_VERSION:
+    //
+    // TLS 1.2
+    //
+    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1);
+    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1_1);
+    break;
+  default:
+    //
+    // Unsupported TLS/SSL Protocol Version.
+    //
+    break;
+  }
+
+  return (VOID *) TlsCtx;
+}
+
+/**
+  Free an allocated TLS object.
+
+  This function removes the TLS object pointed to by Tls and frees up the
+  allocated memory. If Tls is NULL, nothing is done.
+
+  @param[in]  Tls    Pointer to the TLS object to be freed.
+
+**/
+VOID
+EFIAPI
+TlsFree (
+  IN     VOID                     *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL) {
+    return;
+  }
+
+  //
+  // Free the internal TLS and BIO objects.
+  //
+  if (TlsConn->Ssl != NULL) {
+    SSL_free (TlsConn->Ssl);
+  }
+
+  if (TlsConn->InBio != NULL) {
+    BIO_free (TlsConn->InBio);
+  }
+
+  if (TlsConn->OutBio != NULL) {
+    BIO_free (TlsConn->OutBio);
+  }
+
+  OPENSSL_free (Tls);
+}
+
+/**
+  Create a new TLS object for a connection.
+
+  This function creates a new TLS object for a connection. The new object
+  inherits the setting of the underlying context TlsCtx: connection method,
+  options, verification setting.
+
+  @param[in]  TlsCtx    Pointer to the SSL_CTX object.
+
+  @return  Pointer to an allocated SSL object.
+           If the creation failed, TlsNew() returns NULL.
+
+**/
+VOID *
+EFIAPI
+TlsNew (
+  IN     VOID                     *TlsCtx
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  SSL_CTX         *SslCtx;
+  X509_STORE      *X509Store;
+
+  TlsConn = NULL;
+
+  //
+  // Allocate one new TLS_CONNECTION object
+  //
+  TlsConn = (TLS_CONNECTION *) OPENSSL_malloc (sizeof (TLS_CONNECTION));
+  if (TlsConn == NULL) {
+    return NULL;
+  }
+
+  TlsConn->Ssl = NULL;
+
+  //
+  // Create a new SSL Object
+  //
+  TlsConn->Ssl = SSL_new ((SSL_CTX *) TlsCtx);
+  if (TlsConn->Ssl == NULL) {
+    TlsFree ((VOID *) TlsConn);
+    return NULL;
+  }
+
+  //
+  // Initialize the created SSL Object
+  //
+  SSL_set_info_callback (TlsConn->Ssl, NULL);
+
+  TlsConn->InBio = NULL;
+
+  //
+  // Set up Reading BIO for TLS connection
+  //
+  TlsConn->InBio = BIO_new (BIO_s_mem ());
+  if (TlsConn->InBio == NULL) {
+    TlsFree ((VOID *) TlsConn);
+    return NULL;
+  }
+
+  //
+  // Sets the behaviour of memory BIO when it is empty. It will set the
+  // read retry flag.
+  //
+  BIO_set_mem_eof_return (TlsConn->InBio, -1);
+
+  TlsConn->OutBio = NULL;
+
+  //
+  // Set up Writing BIO for TLS connection
+  //
+  TlsConn->OutBio = BIO_new (BIO_s_mem ());
+  if (TlsConn->OutBio == NULL) {
+    TlsFree ((VOID *) TlsConn);
+    return NULL;
+  }
+
+  //
+  // Sets the behaviour of memory BIO when it is empty. It will set the
+  // write retry flag.
+  //
+  BIO_set_mem_eof_return (TlsConn->OutBio, -1);
+
+  ASSERT (TlsConn->Ssl != NULL && TlsConn->InBio != NULL && TlsConn->OutBio != NULL);
+
+  //
+  // Connects the InBio and OutBio for the read and write operations.
+  //
+  SSL_set_bio (TlsConn->Ssl, TlsConn->InBio, TlsConn->OutBio);
+
+  //
+  // Create new X509 store if needed
+  //
+  SslCtx    = SSL_get_SSL_CTX (TlsConn->Ssl);
+  X509Store = SSL_CTX_get_cert_store (SslCtx);
+  if (X509Store == NULL) {
+    X509Store = X509_STORE_new ();
+    if (X509Store == NULL) {
+      TlsFree ((VOID *) TlsConn);
+      return NULL;
+    }
+    SSL_CTX_set1_verify_cert_store (SslCtx, X509Store);
+    X509_STORE_free (X509Store);
+  }
+
+  //
+  // Set X509_STORE flags used in certificate validation
+  //
+  X509_STORE_set_flags (
+    X509Store,
+    X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME
+    );
+  return (VOID *) TlsConn;
+}
diff --git a/CryptoPkg/Library/TlsLib/TlsLib.inf b/CryptoPkg/Library/TlsLib/TlsLib.inf
new file mode 100644
index 0000000..2122b3b
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/TlsLib.inf
@@ -0,0 +1,49 @@
+## @file
+#  SSL/TLS Wrapper Library Instance based on OpenSSL.
+#
+#  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.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = TlsLib
+  MODULE_UNI_FILE                = TlsLib.uni
+  FILE_GUID                      = CC729DC5-4E21-0B36-1A00-3A8E1B86A155
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = TlsLib|DXE_DRIVER DXE_CORE UEFI_APPLICATION UEFI_DRIVER
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF ARM AARCH64
+#
+
+[Sources]
+  InternalTlsLib.h
+  TlsInit.c
+  TlsConfig.c
+  TlsProcess.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  CryptoPkg/CryptoPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  UefiRuntimeServicesTableLib
+  DebugLib
+  OpensslLib
+  IntrinsicLib
+  PrintLib
diff --git a/CryptoPkg/Library/TlsLib/TlsLib.uni b/CryptoPkg/Library/TlsLib/TlsLib.uni
new file mode 100644
index 0000000..9b79287
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/TlsLib.uni
@@ -0,0 +1,19 @@
+// /** @file
+// SSL/TLS Wrapper Library Instance based on OpenSSL.
+//
+// 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.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "SSL/TLS Wrapper Library Instance"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This module provides SSL/TLS Wrapper Library Instance."
\ No newline at end of file
diff --git a/CryptoPkg/Library/TlsLib/TlsProcess.c b/CryptoPkg/Library/TlsLib/TlsProcess.c
new file mode 100644
index 0000000..52b55d7
--- /dev/null
+++ b/CryptoPkg/Library/TlsLib/TlsProcess.c
@@ -0,0 +1,461 @@
+/** @file
+  SSL/TLS Process Library Wrapper Implementation over OpenSSL.
+  The process includes the TLS handshake and packet I/O.
+
+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 "InternalTlsLib.h"
+
+#define MAX_BUFFER_SIZE   32768
+
+/**
+  Checks if the TLS handshake was done.
+
+  This function will check if the specified TLS handshake was done.
+
+  @param[in]  Tls    Pointer to the TLS object for handshake state checking.
+
+  @retval  TRUE     The TLS handshake was done.
+  @retval  FALSE    The TLS handshake was not done.
+
+**/
+BOOLEAN
+EFIAPI
+TlsInHandshake (
+  IN     VOID                     *Tls
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return FALSE;
+  }
+
+  //
+  // Return the status which indicates if the TLS handshake was done.
+  //
+  return !SSL_is_init_finished (TlsConn->Ssl);
+}
+
+/**
+  Perform a TLS/SSL handshake.
+
+  This function will perform a TLS/SSL handshake.
+
+  @param[in]       Tls            Pointer to the TLS object for handshake operation.
+  @param[in]       BufferIn       Pointer to the most recently received TLS Handshake packet.
+  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS
+                                  Handshake packet.
+  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferIn is NULL but BufferInSize is NOT 0.
+                                  BufferInSize is 0 but BufferIn is NOT NULL.
+                                  BufferOutSize is NULL.
+                                  BufferOut is NULL if *BufferOutSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsDoHandshake (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *BufferIn, OPTIONAL
+  IN     UINTN                    BufferInSize, OPTIONAL
+     OUT UINT8                    *BufferOut, OPTIONAL
+  IN OUT UINTN                    *BufferOutSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  UINTN           PendingBufferSize;
+  INTN            Ret;
+  unsigned long   ErrorCode;
+
+  TlsConn           = (TLS_CONNECTION *) Tls;
+  PendingBufferSize = 0;
+  Ret               = 1;
+
+  if (TlsConn == NULL || \
+    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \
+    BufferOutSize == NULL || \
+    (BufferIn == NULL && BufferInSize != 0) || \
+    (BufferIn != NULL && BufferInSize == 0) || \
+    (BufferOut == NULL && *BufferOutSize != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  if(BufferIn == NULL && BufferInSize == 0) {
+    //
+    // If RequestBuffer is NULL and RequestSize is 0, and TLS session
+    // status is EfiTlsSessionNotStarted, the TLS session will be initiated
+    // and the response packet needs to be ClientHello.
+    //
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+    if (PendingBufferSize == 0) {
+      SSL_set_connect_state (TlsConn->Ssl);
+      Ret = SSL_do_handshake (TlsConn->Ssl);
+      PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+    }
+  } else {
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+    if (PendingBufferSize == 0) {
+      BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);
+      Ret = SSL_do_handshake (TlsConn->Ssl);
+      PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+    }
+  }
+
+  if (Ret < 1) {
+    Ret = SSL_get_error (TlsConn->Ssl, (int) Ret);
+    if (Ret == SSL_ERROR_SSL ||
+        Ret == SSL_ERROR_SYSCALL ||
+        Ret == SSL_ERROR_ZERO_RETURN) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "%a SSL_HANDSHAKE_ERROR State=0x%x SSL_ERROR_%a\n",
+        __FUNCTION__,
+        SSL_get_state (TlsConn->Ssl),
+        Ret == SSL_ERROR_SSL ? "SSL" : Ret == SSL_ERROR_SYSCALL ? "SYSCALL" : "ZERO_RETURN"
+        ));
+      DEBUG_CODE_BEGIN ();
+        while (TRUE) {
+          ErrorCode = ERR_get_error ();
+          if (ErrorCode == 0) {
+            break;
+          }
+          DEBUG ((
+            DEBUG_ERROR,
+            "%a ERROR 0x%x=L%x:F%x:R%x\n",
+            __FUNCTION__,
+            ErrorCode,
+            ERR_GET_LIB (ErrorCode),
+            ERR_GET_FUNC (ErrorCode),
+            ERR_GET_REASON (ErrorCode)
+            ));
+        }
+      DEBUG_CODE_END ();
+      return EFI_PROTOCOL_ERROR;
+    }
+  }
+
+  if (PendingBufferSize > *BufferOutSize) {
+    *BufferOutSize = PendingBufferSize;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (PendingBufferSize > 0) {
+    *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize);
+  } else {
+    *BufferOutSize = 0;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Hande Alert message recorded in BufferIn. If BufferIn is NULL and BufferInSize is zero,
+  TLS session has errors and the response packet needs to be Alert message based on error type.
+
+  @param[in]       Tls            Pointer to the TLS object for state checking.
+  @param[in]       BufferIn       Pointer to the most recently received TLS Alert packet.
+  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS
+                                  Alert packet.
+  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferIn is NULL but BufferInSize is NOT 0.
+                                  BufferInSize is 0 but BufferIn is NOT NULL.
+                                  BufferOutSize is NULL.
+                                  BufferOut is NULL if *BufferOutSize is not zero.
+  @retval EFI_ABORTED             An error occurred.
+  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsHandeAlert (
+  IN     VOID                     *Tls,
+  IN     UINT8                    *BufferIn, OPTIONAL
+  IN     UINTN                    BufferInSize, OPTIONAL
+     OUT UINT8                    *BufferOut, OPTIONAL
+  IN OUT UINTN                    *BufferOutSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  UINTN           PendingBufferSize;
+  UINT8           *TempBuffer;
+  INTN            Ret;
+
+  TlsConn           = (TLS_CONNECTION *) Tls;
+  PendingBufferSize = 0;
+  TempBuffer        = NULL;
+  Ret               = 0;
+
+  if (TlsConn == NULL || \
+    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \
+    BufferOutSize == NULL || \
+    (BufferIn == NULL && BufferInSize != 0) || \
+    (BufferIn != NULL && BufferInSize == 0) || \
+    (BufferOut == NULL && *BufferOutSize != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+  if (PendingBufferSize == 0 && BufferIn != NULL && BufferInSize != 0) {
+    Ret = BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);
+    if (Ret != (INTN) BufferInSize) {
+      return EFI_ABORTED;
+    }
+
+    TempBuffer = (UINT8 *) OPENSSL_malloc (MAX_BUFFER_SIZE);
+
+    //
+    // ssl3_send_alert() will be called in ssl3_read_bytes() function.
+    // TempBuffer is invalid since it's a Alert message, so just ignore it.
+    //
+    SSL_read (TlsConn->Ssl, TempBuffer, MAX_BUFFER_SIZE);
+
+    OPENSSL_free (TempBuffer);
+
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+  }
+
+  if (PendingBufferSize > *BufferOutSize) {
+    *BufferOutSize = PendingBufferSize;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (PendingBufferSize > 0) {
+    *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize);
+  } else {
+    *BufferOutSize = 0;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Build the CloseNotify packet.
+
+  @param[in]       Tls            Pointer to the TLS object for state checking.
+  @param[in, out]  Buffer         Pointer to the buffer to hold the built packet.
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is
+                                  the buffer size provided by the caller. On output, it
+                                  is the buffer size in fact needed to contain the
+                                  packet.
+
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:
+                                  Tls is NULL.
+                                  BufferSize is NULL.
+                                  Buffer is NULL if *BufferSize is not zero.
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsCloseNotify (
+  IN     VOID                     *Tls,
+  IN OUT UINT8                    *Buffer,
+  IN OUT UINTN                    *BufferSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+  UINTN           PendingBufferSize;
+
+  TlsConn           = (TLS_CONNECTION *) Tls;
+  PendingBufferSize = 0;
+
+  if (TlsConn == NULL || \
+    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \
+    BufferSize == NULL || \
+    (Buffer == NULL && *BufferSize != 0)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+  if (PendingBufferSize == 0) {
+    //
+    // ssl3_send_alert() and ssl3_dispatch_alert() function will be called.
+    //
+    SSL_shutdown (TlsConn->Ssl);
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
+  }
+
+  if (PendingBufferSize > *BufferSize) {
+    *BufferSize = PendingBufferSize;
+    return EFI_BUFFER_TOO_SMALL;
+  }
+
+  if (PendingBufferSize > 0) {
+    *BufferSize = BIO_read (TlsConn->OutBio, Buffer, (UINT32) PendingBufferSize);
+  } else {
+    *BufferSize = 0;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Attempts to read bytes from one TLS object and places the data in Buffer.
+
+  This function will attempt to read BufferSize bytes from the TLS object
+  and places the data in Buffer.
+
+  @param[in]      Tls           Pointer to the TLS object.
+  @param[in,out]  Buffer        Pointer to the buffer to store the data.
+  @param[in]      BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The amount of data successfully read from the TLS object.
+  @retval  <=0   No data was successfully read.
+
+**/
+INTN
+EFIAPI
+TlsCtrlTrafficOut (
+  IN     VOID                     *Tls,
+  IN OUT VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->OutBio == 0) {
+    return -1;
+  }
+
+  //
+  // Read and return the amount of data from the BIO.
+  //
+  return BIO_read (TlsConn->OutBio, Buffer, (UINT32) BufferSize);
+}
+
+/**
+  Attempts to write data from the buffer to TLS object.
+
+  This function will attempt to write BufferSize bytes data from the Buffer
+  to the TLS object.
+
+  @param[in]  Tls           Pointer to the TLS object.
+  @param[in]  Buffer        Pointer to the data buffer.
+  @param[in]  BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The amount of data successfully written to the TLS object.
+  @retval <=0    No data was successfully written.
+
+**/
+INTN
+EFIAPI
+TlsCtrlTrafficIn (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->InBio == 0) {
+    return -1;
+  }
+
+  //
+  // Write and return the amount of data to the BIO.
+  //
+  return BIO_write (TlsConn->InBio, Buffer, (UINT32) BufferSize);
+}
+/**
+  Attempts to read bytes from the specified TLS connection into the buffer.
+
+  This function tries to read BufferSize bytes data from the specified TLS
+  connection into the Buffer.
+
+  @param[in]      Tls           Pointer to the TLS connection for data reading.
+  @param[in,out]  Buffer        Pointer to the data buffer.
+  @param[in]      BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The read operation was successful, and return value is the
+                 number of bytes actually read from the TLS connection.
+  @retval  <=0   The read operation was not successful.
+
+**/
+INTN
+EFIAPI
+TlsRead (
+  IN     VOID                     *Tls,
+  IN OUT VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return -1;
+  }
+
+  //
+  // Read bytes from the specified TLS connection.
+  //
+  return SSL_read (TlsConn->Ssl, Buffer, (UINT32) BufferSize);
+}
+
+/**
+  Attempts to write data to a TLS connection.
+
+  This function tries to write BufferSize bytes data from the Buffer into the
+  specified TLS connection.
+
+  @param[in]  Tls           Pointer to the TLS connection for data writing.
+  @param[in]  Buffer        Pointer to the data buffer.
+  @param[in]  BufferSize    The size of Buffer in bytes.
+
+  @retval  >0    The write operation was successful, and return value is the
+                 number of bytes actually written to the TLS connection.
+  @retval <=0    The write operation was not successful.
+
+**/
+INTN
+EFIAPI
+TlsWrite (
+  IN     VOID                     *Tls,
+  IN     VOID                     *Buffer,
+  IN     UINTN                    BufferSize
+  )
+{
+  TLS_CONNECTION  *TlsConn;
+
+  TlsConn = (TLS_CONNECTION *) Tls;
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
+    return -1;
+  }
+
+  //
+  // Write bytes to the specified TLS connection.
+  //
+  return SSL_write (TlsConn->Ssl, Buffer, (UINT32) BufferSize);
+}
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 04/10] CryptoPkg: Add new TlsLib library
  2016-12-16  2:10   ` Ye, Ting
@ 2016-12-16  2:51     ` Wu, Jiaxin
  0 siblings, 0 replies; 37+ messages in thread
From: Wu, Jiaxin @ 2016-12-16  2:51 UTC (permalink / raw)
  To: Ye, Ting, edk2-devel@lists.01.org
  Cc: Long, Qin, Fu, Siyuan, Zhang, Lubo, Thomas Palmer


> Some comments included as following:
> 
> 1.  In TlsGetHostPublicCert, line 1892:
> 	The status is set to EFI_NOT_FOUND but not returned. Does it make
> sense to update *DataSize in that case?

You are right, EFI_NOT_FOUND should be returned directly.

> 2.  TlsDoHandshake uses EFI_PROTOCOL_ERROR but not record in function
> header.
> 3.  TlsGetCurrentCompressionId uses EFI_UNSUPPROTED but not record in
> function header.
> 4.  Typo in TlsHandeAlert, should be TlsHandleAlert? Please also update the
> function description.

It's the typo. Thanks for the correction.

> 
> Others look good to me.
> 
> Reviewed-by: Ye Ting <ting.ye@intel.com>

Thanks Ting, I will correct it before commit the patch. 

> 
> Thanks,
> Ting
> 
> 
> -----Original Message-----
> From: Wu, Jiaxin
> Sent: Wednesday, December 14, 2016 3:34 PM
> To: edk2-devel@lists.01.org
> Cc: Ye, Ting <ting.ye@intel.com>; Long, Qin <qin.long@intel.com>; Fu, Siyuan
> <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; Thomas
> Palmer <thomas.palmer@hpe.com>; Wu, Jiaxin <jiaxin.wu@intel.com>
> Subject: [Patch 04/10] CryptoPkg: Add new TlsLib library
> 
> This patch is used to add new TlsLib library, which is wrapped
> over OpenSSL. The implementation provides TLS library functions
> for EFI TLS protocol and EFI TLS Configuration Protocol.
> 
> Cc: Ye Ting <ting.ye@intel.com>
> Cc: Long Qin <qin.long@intel.com>
> Cc: Fu Siyuan <siyuan.fu@intel.com>
> Cc: Zhang Lubo <lubo.zhang@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>
> ---
>  CryptoPkg/CryptoPkg.dec                   |    4 +
>  CryptoPkg/CryptoPkg.dsc                   |    1 +
>  CryptoPkg/Include/Library/TlsLib.h        |  785 +++++++++++++++++++++
>  CryptoPkg/Library/TlsLib/InternalTlsLib.h |   35 +
>  CryptoPkg/Library/TlsLib/TlsConfig.c      | 1055
> +++++++++++++++++++++++++++++
>  CryptoPkg/Library/TlsLib/TlsInit.c        |  291 ++++++++
>  CryptoPkg/Library/TlsLib/TlsLib.inf       |   49 ++
>  CryptoPkg/Library/TlsLib/TlsLib.uni       |   19 +
>  CryptoPkg/Library/TlsLib/TlsProcess.c     |  461 +++++++++++++
>  9 files changed, 2700 insertions(+)
>  create mode 100644 CryptoPkg/Include/Library/TlsLib.h
>  create mode 100644 CryptoPkg/Library/TlsLib/InternalTlsLib.h
>  create mode 100644 CryptoPkg/Library/TlsLib/TlsConfig.c
>  create mode 100644 CryptoPkg/Library/TlsLib/TlsInit.c
>  create mode 100644 CryptoPkg/Library/TlsLib/TlsLib.inf
>  create mode 100644 CryptoPkg/Library/TlsLib/TlsLib.uni
>  create mode 100644 CryptoPkg/Library/TlsLib/TlsProcess.c
> 
> diff --git a/CryptoPkg/CryptoPkg.dec b/CryptoPkg/CryptoPkg.dec
> index 80579b7..eee26cb 100644
> --- a/CryptoPkg/CryptoPkg.dec
> +++ b/CryptoPkg/CryptoPkg.dec
> @@ -29,10 +29,14 @@
>  [LibraryClasses]
>    ##  @libraryclass  Provides basic library functions for cryptographic
> primitives.
>    ##
>    BaseCryptLib|Include/Library/BaseCryptLib.h
> 
> +  ##  @libraryclass  Provides TLS library functions for EFI TLS protocol.
> +  ##
> +  TlsLib|Include/Library/TlsLib.h
> +
>  [Protocols]
>    ## Include/Protocol/RuntimeCrypt.h
>    gEfiRuntimeCryptProtocolGuid = { 0xe1475e0c, 0x1746, 0x4802, {0x86, 0x2e,
> 0x1, 0x1c, 0x2c, 0x2d, 0x9d, 0x86 }}
> 
>  [UserExtensions.TianoCore."ExtraFiles"]
> diff --git a/CryptoPkg/CryptoPkg.dsc b/CryptoPkg/CryptoPkg.dsc
> index 3c3e444..468e60b 100644
> --- a/CryptoPkg/CryptoPkg.dsc
> +++ b/CryptoPkg/CryptoPkg.dsc
> @@ -121,10 +121,11 @@
> 
> ##########################################################
> #########################################
>  [Components]
>    CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
>    CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
>    CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> +  CryptoPkg/Library/TlsLib/TlsLib.inf
> 
>    CryptoPkg/Application/Cryptest/Cryptest.inf
> 
>    CryptoPkg/CryptRuntimeDxe/CryptRuntimeDxe.inf
> 
> diff --git a/CryptoPkg/Include/Library/TlsLib.h
> b/CryptoPkg/Include/Library/TlsLib.h
> new file mode 100644
> index 0000000..38b861e
> --- /dev/null
> +++ b/CryptoPkg/Include/Library/TlsLib.h
> @@ -0,0 +1,785 @@
> +/** @file
> +  Defines TLS Library APIs.
> +
> +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 __TLS_LIB_H__
> +#define __TLS_LIB_H__
> +
> +/**
> +  Initializes the OpenSSL library.
> +
> +  This function registers ciphers and digests used directly and indirectly
> +  by SSL/TLS, and initializes the readable error messages.
> +  This function must be called before any other action takes places.
> +
> +**/
> +VOID
> +EFIAPI
> +TlsInitialize (
> +  VOID
> +  );
> +
> +/**
> +  Free an allocated SSL_CTX object.
> +
> +  @param[in]  TlsCtx    Pointer to the SSL_CTX object to be released.
> +
> +**/
> +VOID
> +EFIAPI
> +TlsCtxFree (
> +  IN   VOID                  *TlsCtx
> +  );
> +
> +/**
> +  Creates a new SSL_CTX object as framework to establish TLS/SSL enabled
> +  connections.
> +
> +  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
> +  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
> +
> +  @return  Pointer to an allocated SSL_CTX object.
> +           If the creation failed, TlsCtxNew() returns NULL.
> +
> +**/
> +VOID *
> +EFIAPI
> +TlsCtxNew (
> +  IN     UINT8                    MajorVer,
> +  IN     UINT8                    MinorVer
> +  );
> +
> +/**
> +  Free an allocated TLS object.
> +
> +  This function removes the TLS object pointed to by Tls and frees up the
> +  allocated memory. If Tls is NULL, nothing is done.
> +
> +  @param[in]  Tls    Pointer to the TLS object to be freed.
> +
> +**/
> +VOID
> +EFIAPI
> +TlsFree (
> +  IN     VOID                     *Tls
> +  );
> +
> +/**
> +  Create a new TLS object for a connection.
> +
> +  This function creates a new TLS object for a connection. The new object
> +  inherits the setting of the underlying context TlsCtx: connection method,
> +  options, verification setting.
> +
> +  @param[in]  TlsCtx    Pointer to the SSL_CTX object.
> +
> +  @return  Pointer to an allocated SSL object.
> +           If the creation failed, TlsNew() returns NULL.
> +
> +**/
> +VOID *
> +EFIAPI
> +TlsNew (
> +  IN     VOID                     *TlsCtx
> +  );
> +
> +/**
> +  Checks if the TLS handshake was done.
> +
> +  This function will check if the specified TLS handshake was done.
> +
> +  @param[in]  Tls    Pointer to the TLS object for handshake state checking.
> +
> +  @retval  TRUE     The TLS handshake was done.
> +  @retval  FALSE    The TLS handshake was not done.
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +TlsInHandshake (
> +  IN     VOID                     *Tls
> +  );
> +
> +/**
> +  Perform a TLS/SSL handshake.
> +
> +  This function will perform a TLS/SSL handshake.
> +
> +  @param[in]       Tls            Pointer to the TLS object for handshake operation.
> +  @param[in]       BufferIn       Pointer to the most recently received TLS
> Handshake packet.
> +  @param[in]       BufferInSize   Packet size in bytes for the most recently
> received TLS
> +                                  Handshake packet.
> +  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
> +  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On
> input, it is
> +                                  the buffer size provided by the caller. On output, it
> +                                  is the buffer size in fact needed to contain the
> +                                  packet.
> +
> +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  Tls is NULL.
> +                                  BufferIn is NULL but BufferInSize is NOT 0.
> +                                  BufferInSize is 0 but BufferIn is NOT NULL.
> +                                  BufferOutSize is NULL.
> +                                  BufferOut is NULL if *BufferOutSize is not zero.
> +  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the
> response packet.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsDoHandshake (
> +  IN     VOID                     *Tls,
> +  IN     UINT8                    *BufferIn, OPTIONAL
> +  IN     UINTN                    BufferInSize, OPTIONAL
> +     OUT UINT8                    *BufferOut, OPTIONAL
> +  IN OUT UINTN                    *BufferOutSize
> +  );
> +
> +/**
> +  Hande Alert message recorded in BufferIn. If BufferIn is NULL and
> BufferInSize is zero,
> +  TLS session has errors and the response packet needs to be Alert message
> based on error type.
> +
> +  @param[in]       Tls            Pointer to the TLS object for state checking.
> +  @param[in]       BufferIn       Pointer to the most recently received TLS Alert
> packet.
> +  @param[in]       BufferInSize   Packet size in bytes for the most recently
> received TLS
> +                                  Alert packet.
> +  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
> +  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On
> input, it is
> +                                  the buffer size provided by the caller. On output, it
> +                                  is the buffer size in fact needed to contain the
> +                                  packet.
> +
> +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  Tls is NULL.
> +                                  BufferIn is NULL but BufferInSize is NOT 0.
> +                                  BufferInSize is 0 but BufferIn is NOT NULL.
> +                                  BufferOutSize is NULL.
> +                                  BufferOut is NULL if *BufferOutSize is not zero.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the
> response packet.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsHandeAlert (
> +  IN     VOID                     *Tls,
> +  IN     UINT8                    *BufferIn, OPTIONAL
> +  IN     UINTN                    BufferInSize, OPTIONAL
> +     OUT UINT8                    *BufferOut, OPTIONAL
> +  IN OUT UINTN                    *BufferOutSize
> +  );
> +
> +/**
> +  Build the CloseNotify packet.
> +
> +  @param[in]       Tls            Pointer to the TLS object for state checking.
> +  @param[in, out]  Buffer         Pointer to the buffer to hold the built packet.
> +  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input,
> it is
> +                                  the buffer size provided by the caller. On output, it
> +                                  is the buffer size in fact needed to contain the
> +                                  packet.
> +
> +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  Tls is NULL.
> +                                  BufferSize is NULL.
> +                                  Buffer is NULL if *BufferSize is not zero.
> +  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the
> response packet.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsCloseNotify (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *Buffer,
> +  IN OUT UINTN                    *BufferSize
> +  );
> +
> +/**
> +  Attempts to read bytes from one TLS object and places the data in Buffer.
> +
> +  This function will attempt to read BufferSize bytes from the TLS object
> +  and places the data in Buffer.
> +
> +  @param[in]      Tls           Pointer to the TLS object.
> +  @param[in,out]  Buffer        Pointer to the buffer to store the data.
> +  @param[in]      BufferSize    The size of Buffer in bytes.
> +
> +  @retval  >0    The amount of data successfully read from the TLS object.
> +  @retval  <=0   No data was successfully read.
> +
> +**/
> +INTN
> +EFIAPI
> +TlsCtrlTrafficOut (
> +  IN     VOID                     *Tls,
> +  IN OUT VOID                     *Buffer,
> +  IN     UINTN                    BufferSize
> +  );
> +
> +/**
> +  Attempts to write data from the buffer to TLS object.
> +
> +  This function will attempt to write BufferSize bytes data from the Buffer
> +  to the TLS object.
> +
> +  @param[in]  Tls           Pointer to the TLS object.
> +  @param[in]  Buffer        Pointer to the data buffer.
> +  @param[in]  BufferSize    The size of Buffer in bytes.
> +
> +  @retval  >0    The amount of data successfully written to the TLS object.
> +  @retval <=0    No data was successfully written.
> +
> +**/
> +INTN
> +EFIAPI
> +TlsCtrlTrafficIn (
> +  IN     VOID                     *Tls,
> +  IN     VOID                     *Buffer,
> +  IN     UINTN                    BufferSize
> +  );
> +
> +/**
> +  Attempts to read bytes from the specified TLS connection into the buffer.
> +
> +  This function tries to read BufferSize bytes data from the specified TLS
> +  connection into the Buffer.
> +
> +  @param[in]      Tls           Pointer to the TLS connection for data reading.
> +  @param[in,out]  Buffer        Pointer to the data buffer.
> +  @param[in]      BufferSize    The size of Buffer in bytes.
> +
> +  @retval  >0    The read operation was successful, and return value is the
> +                 number of bytes actually read from the TLS connection.
> +  @retval  <=0   The read operation was not successful.
> +
> +**/
> +INTN
> +EFIAPI
> +TlsRead (
> +  IN     VOID                     *Tls,
> +  IN OUT VOID                     *Buffer,
> +  IN     UINTN                    BufferSize
> +  );
> +
> +/**
> +  Attempts to write data to a TLS connection.
> +
> +  This function tries to write BufferSize bytes data from the Buffer into the
> +  specified TLS connection.
> +
> +  @param[in]  Tls           Pointer to the TLS connection for data writing.
> +  @param[in]  Buffer        Pointer to the data buffer.
> +  @param[in]  BufferSize    The size of Buffer in bytes.
> +
> +  @retval  >0    The write operation was successful, and return value is the
> +                 number of bytes actually written to the TLS connection.
> +  @retval <=0    The write operation was not successful.
> +
> +**/
> +INTN
> +EFIAPI
> +TlsWrite (
> +  IN     VOID                     *Tls,
> +  IN     VOID                     *Buffer,
> +  IN     UINTN                    BufferSize
> +  );
> +
> +/**
> +  Set a new TLS/SSL method for a particular TLS object.
> +
> +  This function sets a new TLS/SSL method for a particular TLS object.
> +
> +  @param[in]  Tls         Pointer to a TLS object.
> +  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
> +  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
> +
> +  @retval  EFI_SUCCESS           The TLS/SSL method was set successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL method.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetVersion (
> +  IN     VOID                     *Tls,
> +  IN     UINT8                    MajorVer,
> +  IN     UINT8                    MinorVer
> +  );
> +
> +/**
> +  Set TLS object to work in client or server mode.
> +
> +  This function prepares a TLS object to work in client or server mode.
> +
> +  @param[in]  Tls         Pointer to a TLS object.
> +  @param[in]  IsServer    Work in server mode.
> +
> +  @retval  EFI_SUCCESS           The TLS/SSL work mode was set successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL work mode.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetConnectionEnd (
> +  IN     VOID                     *Tls,
> +  IN     BOOLEAN                  IsServer
> +  );
> +
> +/**
> +  Set the ciphers list to be used by the TLS object.
> +
> +  This function sets the ciphers for use by a specified TLS object.
> +
> +  @param[in]  Tls          Pointer to a TLS object.
> +  @param[in]  CipherId     Pointer to a string that contains one or more
> +                           ciphers separated by a colon.
> +  @param[in]  CipherNum    The number of cipher in the list.
> +
> +  @retval  EFI_SUCCESS           The ciphers list was set successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Unsupported TLS cipher in the list.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetCipherList (
> +  IN     VOID                     *Tls,
> +  IN     UINT16                   *CipherId,
> +  IN     UINTN                    CipherNum
> +  );
> +
> +/**
> +  Set the compression method for TLS/SSL operations.
> +
> +  This function handles TLS/SSL integrated compression methods.
> +
> +  @param[in]  CompMethod    The compression method ID.
> +
> +  @retval  EFI_SUCCESS        The compression method for the communication
> was
> +                              set successfully.
> +  @retval  EFI_UNSUPPORTED    Unsupported compression method.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetCompressionMethod (
> +  IN     UINT8                    CompMethod
> +  );
> +
> +/**
> +  Set peer certificate verification mode for the TLS connection.
> +
> +  This function sets the verification mode flags for the TLS connection.
> +
> +  @param[in]  Tls           Pointer to the TLS object.
> +  @param[in]  VerifyMode    A set of logically or'ed verification mode flags.
> +
> +**/
> +VOID
> +EFIAPI
> +TlsSetVerify (
> +  IN     VOID                     *Tls,
> +  IN     UINT32                   VerifyMode
> +  );
> +
> +/**
> +  Sets a TLS/SSL session ID to be used during TLS/SSL connect.
> +
> +  This function sets a session ID to be used when the TLS/SSL connection is
> +  to be established.
> +
> +  @param[in]  Tls             Pointer to the TLS object.
> +  @param[in]  SessionId       Session ID data used for session resumption.
> +  @param[in]  SessionIdLen    Length of Session ID in bytes.
> +
> +  @retval  EFI_SUCCESS           Session ID was set successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       No available session for ID setting.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetSessionId (
> +  IN     VOID                     *Tls,
> +  IN     UINT8                    *SessionId,
> +  IN     UINT16                   SessionIdLen
> +  );
> +
> +/**
> +  Adds the CA to the cert store when requesting Server or Client
> authentication.
> +
> +  This function adds the CA certificate to the list of CAs when requesting
> +  Server or Client authentication for the chosen TLS connection.
> +
> +  @param[in]  Tls         Pointer to the TLS object.
> +  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
> +                          X.509 certificate or PEM-encoded X.509 certificate.
> +  @param[in]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
> +  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be
> allocated.
> +  @retval  EFI_ABORTED             Invalid X.509 certificate.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetCaCertificate (
> +  IN     VOID                     *Tls,
> +  IN     VOID                     *Data,
> +  IN     UINTN                    DataSize
> +  );
> +
> +/**
> +  Loads the local public certificate into the specified TLS object.
> +
> +  This function loads the X.509 certificate into the specified TLS object
> +  for TLS negotiation.
> +
> +  @param[in]  Tls         Pointer to the TLS object.
> +  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
> +                          X.509 certificate or PEM-encoded X.509 certificate.
> +  @param[in]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
> +  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be
> allocated.
> +  @retval  EFI_ABORTED             Invalid X.509 certificate.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetHostPublicCert (
> +  IN     VOID                     *Tls,
> +  IN     VOID                     *Data,
> +  IN     UINTN                    DataSize
> +  );
> +
> +/**
> +  Adds the local private key to the specified TLS object.
> +
> +  This function adds the local private key (PEM-encoded RSA or PKCS#8
> private
> +  key) into the specified TLS object for TLS negotiation.
> +
> +  @param[in]  Tls         Pointer to the TLS object.
> +  @param[in]  Data        Pointer to the data buffer of a PEM-encoded RSA
> +                          or PKCS#8 private key.
> +  @param[in]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS     The operation succeeded.
> +  @retval  EFI_UNSUPPORTED This function is not supported.
> +  @retval  EFI_ABORTED     Invalid private key data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetHostPrivateKey (
> +  IN     VOID                     *Tls,
> +  IN     VOID                     *Data,
> +  IN     UINTN                    DataSize
> +  );
> +
> +/**
> +  Adds the CA-supplied certificate revocation list for certificate validation.
> +
> +  This function adds the CA-supplied certificate revocation list data for
> +  certificate validity checking.
> +
> +  @param[in]  Data        Pointer to the data buffer of a DER-encoded CRL data.
> +  @param[in]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS     The operation succeeded.
> +  @retval  EFI_UNSUPPORTED This function is not supported.
> +  @retval  EFI_ABORTED     Invalid CRL data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetCertRevocationList (
> +  IN     VOID                     *Data,
> +  IN     UINTN                    DataSize
> +  );
> +
> +/**
> +  Gets the protocol version used by the specified TLS connection.
> +
> +  This function returns the protocol version used by the specified TLS
> +  connection.
> +
> +  @param[in]  Tls    Pointer to the TLS object.
> +
> +  @return  The protocol version of the specified TLS connection.
> +
> +**/
> +UINT16
> +EFIAPI
> +TlsGetVersion (
> +  IN     VOID                     *Tls
> +  );
> +
> +/**
> +  Gets the connection end of the specified TLS connection.
> +
> +  This function returns the connection end (as client or as server) used by
> +  the specified TLS connection.
> +
> +  @param[in]  Tls    Pointer to the TLS object.
> +
> +  @return  The connection end used by the specified TLS connection.
> +
> +**/
> +UINT8
> +EFIAPI
> +TlsGetConnectionEnd (
> +  IN     VOID                     *Tls
> +  );
> +
> +/**
> +  Gets the cipher suite used by the specified TLS connection.
> +
> +  This function returns current cipher suite used by the specified
> +  TLS connection.
> +
> +  @param[in]      Tls         Pointer to the TLS object.
> +  @param[in,out]  CipherId    The cipher suite used by the TLS object.
> +
> +  @retval  EFI_SUCCESS           The cipher suite was returned successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Unsupported cipher suite.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetCurrentCipher (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT16                   *CipherId
> +  );
> +
> +/**
> +  Gets the compression methods used by the specified TLS connection.
> +
> +  This function returns current integrated compression methods used by
> +  the specified TLS connection.
> +
> +  @param[in]      Tls              Pointer to the TLS object.
> +  @param[in,out]  CompressionId    The current compression method used
> by
> +                                   the TLS object.
> +
> +  @retval  EFI_SUCCESS           The compression method was returned
> successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_ABORTED           Invalid Compression method.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetCurrentCompressionId (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *CompressionId
> +  );
> +
> +/**
> +  Gets the verification mode currently set in the TLS connection.
> +
> +  This function returns the peer verification mode currently set in the
> +  specified TLS connection.
> +
> +  @param[in]  Tls    Pointer to the TLS object.
> +
> +  @return  The verification mode set in the specified TLS connection.
> +
> +**/
> +UINT32
> +EFIAPI
> +TlsGetVerify (
> +  IN     VOID                     *Tls
> +  );
> +
> +/**
> +  Gets the session ID used by the specified TLS connection.
> +
> +  This function returns the TLS/SSL session ID currently used by the
> +  specified TLS connection.
> +
> +  @param[in]      Tls             Pointer to the TLS object.
> +  @param[in,out]  SessionId       Buffer to contain the returned session ID.
> +  @param[in,out]  SessionIdLen    The length of Session ID in bytes.
> +
> +  @retval  EFI_SUCCESS           The Session ID was returned successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetSessionId (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *SessionId,
> +  IN OUT UINT16                   *SessionIdLen
> +  );
> +
> +/**
> +  Gets the client random data used in the specified TLS connection.
> +
> +  This function returns the TLS/SSL client random data currently used in
> +  the specified TLS connection.
> +
> +  @param[in]      Tls             Pointer to the TLS object.
> +  @param[in,out]  ClientRandom    Buffer to contain the returned client
> +                                  random data (32 bytes).
> +
> +**/
> +VOID
> +EFIAPI
> +TlsGetClientRandom (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *ClientRandom
> +  );
> +
> +/**
> +  Gets the server random data used in the specified TLS connection.
> +
> +  This function returns the TLS/SSL server random data currently used in
> +  the specified TLS connection.
> +
> +  @param[in]      Tls             Pointer to the TLS object.
> +  @param[in,out]  ServerRandom    Buffer to contain the returned server
> +                                  random data (32 bytes).
> +
> +**/
> +VOID
> +EFIAPI
> +TlsGetServerRandom (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *ServerRandom
> +  );
> +
> +/**
> +  Gets the master key data used in the specified TLS connection.
> +
> +  This function returns the TLS/SSL master key material currently used in
> +  the specified TLS connection.
> +
> +  @param[in]      Tls            Pointer to the TLS object.
> +  @param[in,out]  KeyMaterial    Buffer to contain the returned key material.
> +
> +  @retval  EFI_SUCCESS           Key material was returned successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetKeyMaterial (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *KeyMaterial
> +  );
> +
> +/**
> +  Gets the CA Certificate from the cert store.
> +
> +  This function returns the CA certificate for the chosen
> +  TLS connection.
> +
> +  @param[in]      Tls         Pointer to the TLS object.
> +  @param[out]     Data        Pointer to the data buffer to receive the CA
> +                              certificate data sent to the client.
> +  @param[in,out]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_UNSUPPORTED         This function is not supported.
> +  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetCaCertificate (
> +  IN     VOID                     *Tls,
> +  OUT    VOID                     *Data,
> +  IN OUT UINTN                    *DataSize
> +  );
> +
> +/**
> +  Gets the local public Certificate set in the specified TLS object.
> +
> +  This function returns the local public certificate which was currently set
> +  in the specified TLS object.
> +
> +  @param[in]      Tls         Pointer to the TLS object.
> +  @param[out]     Data        Pointer to the data buffer to receive the local
> +                              public certificate.
> +  @param[in,out]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
> +  @retval  EFI_NOT_FOUND           The certificate is not found.
> +  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetHostPublicCert (
> +  IN     VOID                     *Tls,
> +  OUT    VOID                     *Data,
> +  IN OUT UINTN                    *DataSize
> +  );
> +
> +/**
> +  Gets the local private key set in the specified TLS object.
> +
> +  This function returns the local private key data which was currently set
> +  in the specified TLS object.
> +
> +  @param[in]      Tls         Pointer to the TLS object.
> +  @param[out]     Data        Pointer to the data buffer to receive the local
> +                              private key data.
> +  @param[in,out]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_UNSUPPORTED         This function is not supported.
> +  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetHostPrivateKey (
> +  IN     VOID                     *Tls,
> +  OUT    VOID                     *Data,
> +  IN OUT UINTN                    *DataSize
> +  );
> +
> +/**
> +  Gets the CA-supplied certificate revocation list data set in the specified
> +  TLS object.
> +
> +  This function returns the CA-supplied certificate revocation list data which
> +  was currently set in the specified TLS object.
> +
> +  @param[out]     Data        Pointer to the data buffer to receive the CRL data.
> +  @param[in,out]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_UNSUPPORTED         This function is not supported.
> +  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetCertRevocationList (
> +  OUT    VOID                     *Data,
> +  IN OUT UINTN                    *DataSize
> +  );
> +
> +#endif // __TLS_LIB_H__
> diff --git a/CryptoPkg/Library/TlsLib/InternalTlsLib.h
> b/CryptoPkg/Library/TlsLib/InternalTlsLib.h
> new file mode 100644
> index 0000000..2438de9
> --- /dev/null
> +++ b/CryptoPkg/Library/TlsLib/InternalTlsLib.h
> @@ -0,0 +1,35 @@
> +/** @file
> +  Internal include file for TlsLib.
> +
> +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.
> +
> +**/
> +
> +#include <Library/BaseCryptLib.h>
> +#include <openssl/ssl.h>
> +#include <openssl/bio.h>
> +#include <openssl/err.h>
> +
> +typedef struct {
> +  //
> +  // Main SSL Connection which is created by a server or a client
> +  // per established connection.
> +  //
> +  SSL                             *Ssl;
> +  //
> +  // Memory BIO for the TLS/SSL Reading operations.
> +  //
> +  BIO                             *InBio;
> +  //
> +  // Memory BIO for the TLS/SSL Writing operations.
> +  //
> +  BIO                             *OutBio;
> +} TLS_CONNECTION;
> +
> diff --git a/CryptoPkg/Library/TlsLib/TlsConfig.c
> b/CryptoPkg/Library/TlsLib/TlsConfig.c
> new file mode 100644
> index 0000000..31220b3
> --- /dev/null
> +++ b/CryptoPkg/Library/TlsLib/TlsConfig.c
> @@ -0,0 +1,1055 @@
> +/** @file
> +  SSL/TLS Configuration Library Wrapper Implementation over OpenSSL.
> +
> +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 "InternalTlsLib.h"
> +
> +typedef struct {
> +  //
> +  // IANA/IETF defined Cipher Suite ID
> +  //
> +  UINT16                          IanaCipher;
> +  //
> +  // OpenSSL-used Cipher Suite String
> +  //
> +  CONST CHAR8                     *OpensslCipher;
> +} TLS_CIPHER_PAIR;
> +
> +//
> +// The mapping table between IANA/IETF Cipher Suite definitions and
> +// OpenSSL-used Cipher Suite name.
> +//
> +STATIC CONST TLS_CIPHER_PAIR TlsCipherMappingTable[] = {
> +  { 0x0001, "NULL-MD5" },                 /// TLS_RSA_WITH_NULL_MD5
> +  { 0x0002, "NULL-SHA" },                 /// TLS_RSA_WITH_NULL_SHA
> +  { 0x0004, "RC4-MD5" },                  /// TLS_RSA_WITH_RC4_128_MD5
> +  { 0x0005, "RC4-SHA" },                  /// TLS_RSA_WITH_RC4_128_SHA
> +  { 0x000A, "DES-CBC3-SHA" },             ///
> TLS_RSA_WITH_3DES_EDE_CBC_SHA, mandatory TLS 1.1
> +  { 0x0016, "DHE-RSA-DES-CBC3-SHA" },     ///
> TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
> +  { 0x002F, "AES128-SHA" },               /// TLS_RSA_WITH_AES_128_CBC_SHA,
> mandatory TLS 1.2
> +  { 0x0030, "DH-DSS-AES128-SHA" },        ///
> TLS_DH_DSS_WITH_AES_128_CBC_SHA
> +  { 0x0031, "DH-RSA-AES128-SHA" },        ///
> TLS_DH_RSA_WITH_AES_128_CBC_SHA
> +  { 0x0033, "DHE-RSA-AES128-SHA" },       ///
> TLS_DHE_RSA_WITH_AES_128_CBC_SHA
> +  { 0x0035, "AES256-SHA" },               /// TLS_RSA_WITH_AES_256_CBC_SHA
> +  { 0x0036, "DH-DSS-AES256-SHA" },        ///
> TLS_DH_DSS_WITH_AES_256_CBC_SHA
> +  { 0x0037, "DH-RSA-AES256-SHA" },        ///
> TLS_DH_RSA_WITH_AES_256_CBC_SHA
> +  { 0x0039, "DHE-RSA-AES256-SHA" },       ///
> TLS_DHE_RSA_WITH_AES_256_CBC_SHA
> +  { 0x003B, "NULL-SHA256" },              /// TLS_RSA_WITH_NULL_SHA256
> +  { 0x003C, "AES128-SHA256" },            ///
> TLS_RSA_WITH_AES_128_CBC_SHA256
> +  { 0x003D, "AES256-SHA256" },            ///
> TLS_RSA_WITH_AES_256_CBC_SHA256
> +  { 0x003E, "DH-DSS-AES128-SHA256" },     ///
> TLS_DH_DSS_WITH_AES_128_CBC_SHA256
> +  { 0x003F, "DH-RSA-AES128-SHA256" },     ///
> TLS_DH_RSA_WITH_AES_128_CBC_SHA256
> +  { 0x0067, "DHE-RSA-AES128-SHA256" },    ///
> TLS_DHE_RSA_WITH_AES_128_CBC_SHA256
> +  { 0x0068, "DH-DSS-AES256-SHA256" },     ///
> TLS_DH_DSS_WITH_AES_256_CBC_SHA256
> +  { 0x0069, "DH-RSA-AES256-SHA256" },     ///
> TLS_DH_RSA_WITH_AES_256_CBC_SHA256
> +  { 0x006B, "DHE-RSA-AES256-SHA256" }     ///
> TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
> +};
> +
> +/**
> +  Gets the OpenSSL cipher suite string for the supplied IANA TLS cipher suite.
> +
> +  @param[in]  CipherId    The supplied IANA TLS cipher suite ID.
> +
> +  @return  The corresponding OpenSSL cipher suite string if found,
> +           NULL otherwise.
> +
> +**/
> +STATIC
> +CONST CHAR8 *
> +TlsGetCipherString (
> +  IN     UINT16                   CipherId
> +  )
> +{
> +  CONST TLS_CIPHER_PAIR  *CipherEntry;
> +  UINTN                  TableSize;
> +  UINTN                  Index;
> +
> +  CipherEntry = TlsCipherMappingTable;
> +  TableSize = sizeof (TlsCipherMappingTable) / sizeof (TLS_CIPHER_PAIR);
> +
> +  //
> +  // Search Cipher Mapping Table for IANA-OpenSSL Cipher Translation
> +  //
> +  for (Index = 0; Index < TableSize; Index++, CipherEntry++) {
> +    //
> +    // Translate IANA cipher suite name to OpenSSL name.
> +    //
> +    if (CipherEntry->IanaCipher == CipherId) {
> +      return CipherEntry->OpensslCipher;
> +    }
> +  }
> +
> +  //
> +  // No Cipher Mapping found, return NULL.
> +  //
> +  return NULL;
> +}
> +
> +/**
> +  Set a new TLS/SSL method for a particular TLS object.
> +
> +  This function sets a new TLS/SSL method for a particular TLS object.
> +
> +  @param[in]  Tls         Pointer to a TLS object.
> +  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
> +  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
> +
> +  @retval  EFI_SUCCESS           The TLS/SSL method was set successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL method.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetVersion (
> +  IN     VOID                     *Tls,
> +  IN     UINT8                    MajorVer,
> +  IN     UINT8                    MinorVer
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +  UINT16          ProtoVersion;
> +
> +  TlsConn = (TLS_CONNECTION *)Tls;
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  ProtoVersion = (MajorVer << 8) | MinorVer;
> +
> +  switch (ProtoVersion) {
> +  case TLS1_VERSION:
> +    //
> +    // TLS 1.0
> +    //
> +    SSL_set_ssl_method (TlsConn->Ssl, TLSv1_method ());
> +    break;
> +  case TLS1_1_VERSION:
> +    //
> +    // TLS 1.1
> +    //
> +    SSL_set_ssl_method (TlsConn->Ssl, TLSv1_1_method ());
> +    break;
> +  case TLS1_2_VERSION:
> +    //
> +    // TLS 1.2
> +    //
> +    SSL_set_ssl_method (TlsConn->Ssl, TLSv1_2_method ());
> +    break;
> +  default:
> +    //
> +    // Unsupported Protocol Version
> +    //
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  return EFI_SUCCESS;;
> +}
> +
> +/**
> +  Set TLS object to work in client or server mode.
> +
> +  This function prepares a TLS object to work in client or server mode.
> +
> +  @param[in]  Tls         Pointer to a TLS object.
> +  @param[in]  IsServer    Work in server mode.
> +
> +  @retval  EFI_SUCCESS           The TLS/SSL work mode was set successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Unsupported TLS/SSL work mode.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetConnectionEnd (
> +  IN     VOID                     *Tls,
> +  IN     BOOLEAN                  IsServer
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if (!IsServer) {
> +    //
> +    // Set TLS to work in Client mode.
> +    //
> +    SSL_set_connect_state (TlsConn->Ssl);
> +  } else {
> +    //
> +    // Set TLS to work in Server mode.
> +    // It is unsupported for UEFI version currently.
> +    //
> +    //SSL_set_accept_state (TlsConn->Ssl);
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Set the ciphers list to be used by the TLS object.
> +
> +  This function sets the ciphers for use by a specified TLS object.
> +
> +  @param[in]  Tls          Pointer to a TLS object.
> +  @param[in]  CipherId     Pointer to a UINT16 cipher Id.
> +  @param[in]  CipherNum    The number of cipher in the list.
> +
> +  @retval  EFI_SUCCESS           The ciphers list was set successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Unsupported TLS cipher in the list.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetCipherList (
> +  IN     VOID                     *Tls,
> +  IN     UINT16                   *CipherId,
> +  IN     UINTN                    CipherNum
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +  UINTN           Index;
> +  CONST CHAR8     *MappingName;
> +  CHAR8           CipherString[500];
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  MappingName = NULL;
> +
> +  memset (CipherString, 0, sizeof (CipherString));
> +
> +  for (Index = 0; Index < CipherNum; Index++) {
> +    //
> +    // Handling OpenSSL / RFC Cipher name mapping.
> +    //
> +    MappingName = TlsGetCipherString (*(CipherId + Index));
> +    if (MappingName == NULL) {
> +      return EFI_UNSUPPORTED;
> +    }
> +
> +    if (Index != 0) {
> +      //
> +      // The ciphers were separated by a colon.
> +      //
> +      AsciiStrCatS (CipherString, sizeof (CipherString), ":");
> +    }
> +
> +    AsciiStrCatS (CipherString, sizeof (CipherString), MappingName);
> +  }
> +
> +  AsciiStrCatS (CipherString, sizeof (CipherString), ":@STRENGTH");
> +
> +  //
> +  // Sets the ciphers for use by the Tls object.
> +  //
> +  if (SSL_set_cipher_list (TlsConn->Ssl, CipherString) <= 0) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Set the compression method for TLS/SSL operations.
> +
> +  This function handles TLS/SSL integrated compression methods.
> +
> +  @param[in]  CompMethod    The compression method ID.
> +
> +  @retval  EFI_SUCCESS        The compression method for the communication
> was
> +                              set successfully.
> +  @retval  EFI_UNSUPPORTED    Unsupported compression method.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetCompressionMethod (
> +  IN     UINT8                    CompMethod
> +  )
> +{
> +  COMP_METHOD  *Cm;
> +  INTN         Ret;
> +
> +  Cm  = NULL;
> +  Ret = 0;
> +
> +  if (CompMethod == 0) {
> +    //
> +    // TLS defines one standard compression method,
> CompressionMethod.null (0),
> +    // which specifies that data exchanged via the record protocol will not be
> compressed.
> +    // So, return EFI_SUCCESS directly (RFC 3749).
> +    //
> +    return EFI_SUCCESS;
> +  } else if (CompMethod == 1) {
> +    Cm = COMP_zlib();
> +  } else {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  //
> +  // Adds the compression method to the list of available
> +  // compression methods.
> +  //
> +  Ret = SSL_COMP_add_compression_method (CompMethod, Cm);
> +  if (Ret != 0) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Set peer certificate verification mode for the TLS connection.
> +
> +  This function sets the verification mode flags for the TLS connection.
> +
> +  @param[in]  Tls           Pointer to the TLS object.
> +  @param[in]  VerifyMode    A set of logically or'ed verification mode flags.
> +
> +**/
> +VOID
> +EFIAPI
> +TlsSetVerify (
> +  IN     VOID                     *Tls,
> +  IN     UINT32                   VerifyMode
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
> +    return;
> +  }
> +
> +  //
> +  // Set peer certificate verification parameters with NULL callback.
> +  //
> +  SSL_set_verify (TlsConn->Ssl, VerifyMode, NULL);
> +}
> +
> +/**
> +  Sets a TLS/SSL session ID to be used during TLS/SSL connect.
> +
> +  This function sets a session ID to be used when the TLS/SSL connection is
> +  to be established.
> +
> +  @param[in]  Tls             Pointer to the TLS object.
> +  @param[in]  SessionId       Session ID data used for session resumption.
> +  @param[in]  SessionIdLen    Length of Session ID in bytes.
> +
> +  @retval  EFI_SUCCESS           Session ID was set successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       No available session for ID setting.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetSessionId (
> +  IN     VOID                     *Tls,
> +  IN     UINT8                    *SessionId,
> +  IN     UINT16                   SessionIdLen
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +  SSL_SESSION     *Session;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  Session = NULL;
> +
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Session = SSL_get_session (TlsConn->Ssl);
> +  if (Session == NULL) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  Session->session_id_length = SessionIdLen;
> +  CopyMem (Session->session_id, SessionId, Session->session_id_length);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Adds the CA to the cert store when requesting Server or Client
> authentication.
> +
> +  This function adds the CA certificate to the list of CAs when requesting
> +  Server or Client authentication for the chosen TLS connection.
> +
> +  @param[in]  Tls         Pointer to the TLS object.
> +  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
> +                          X.509 certificate or PEM-encoded X.509 certificate.
> +  @param[in]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
> +  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be
> allocated.
> +  @retval  EFI_ABORTED             Invalid X.509 certificate.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetCaCertificate (
> +  IN     VOID                     *Tls,
> +  IN     VOID                     *Data,
> +  IN     UINTN                    DataSize
> +  )
> +{
> +  BIO             *BioCert;
> +  X509            *Cert;
> +  X509_STORE      *X509Store;
> +  EFI_STATUS      Status;
> +  TLS_CONNECTION  *TlsConn;
> +  SSL_CTX         *SslCtx;
> +  INTN            Ret;
> +  unsigned long   ErrorCode;
> +
> +  BioCert   = NULL;
> +  Cert      = NULL;
> +  X509Store = NULL;
> +  Status    = EFI_SUCCESS;
> +  TlsConn   = (TLS_CONNECTION *) Tls;
> +  Ret       = 0;
> +
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize
> == 0) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
> +  // Determine whether certificate is from DER encoding, if so, translate it to
> X509 structure.
> +  //
> +  Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize);
> +  if (Cert == NULL) {
> +    //
> +    // Certificate is from PEM encoding.
> +    //
> +    BioCert = BIO_new (BIO_s_mem ());
> +    if (BioCert == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ON_EXIT;
> +    }
> +
> +    if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) {
> +      Status = EFI_ABORTED;
> +      goto ON_EXIT;
> +    }
> +
> +    Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
> +    if (Cert == NULL) {
> +      Status = EFI_ABORTED;
> +      goto ON_EXIT;
> +    }
> +  }
> +
> +  SslCtx    = SSL_get_SSL_CTX (TlsConn->Ssl);
> +  X509Store = SSL_CTX_get_cert_store (SslCtx);
> +  if (X509Store == NULL) {
> +      Status = EFI_ABORTED;
> +      goto ON_EXIT;
> +  }
> +
> +  //
> +  // Add certificate to X509 store
> +  //
> +  Ret = X509_STORE_add_cert (X509Store, Cert);
> +  if (Ret != 1) {
> +    ErrorCode = ERR_peek_last_error ();
> +    //
> +    // Ignore "already in table" errors
> +    //
> +    if (!(ERR_GET_FUNC (ErrorCode) == X509_F_X509_STORE_ADD_CERT &&
> +        ERR_GET_REASON (ErrorCode) ==
> X509_R_CERT_ALREADY_IN_HASH_TABLE)) {
> +      Status = EFI_ABORTED;
> +      goto ON_EXIT;
> +    }
> +  }
> +
> +ON_EXIT:
> +  if (BioCert != NULL) {
> +    BIO_free (BioCert);
> +  }
> +
> +  if (Cert != NULL) {
> +    X509_free (Cert);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Loads the local public certificate into the specified TLS object.
> +
> +  This function loads the X.509 certificate into the specified TLS object
> +  for TLS negotiation.
> +
> +  @param[in]  Tls         Pointer to the TLS object.
> +  @param[in]  Data        Pointer to the data buffer of a DER-encoded binary
> +                          X.509 certificate or PEM-encoded X.509 certificate.
> +  @param[in]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
> +  @retval  EFI_OUT_OF_RESOURCES    Required resources could not be
> allocated.
> +  @retval  EFI_ABORTED             Invalid X.509 certificate.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetHostPublicCert (
> +  IN     VOID                     *Tls,
> +  IN     VOID                     *Data,
> +  IN     UINTN                    DataSize
> +  )
> +{
> +  BIO             *BioCert;
> +  X509            *Cert;
> +  EFI_STATUS      Status;
> +  TLS_CONNECTION  *TlsConn;
> +
> +  BioCert = NULL;
> +  Cert    = NULL;
> +  Status  = EFI_SUCCESS;
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL || Data == NULL || DataSize
> == 0) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // DER-encoded binary X.509 certificate or PEM-encoded X.509 certificate.
> +  // Determine whether certificate is from DER encoding, if so, translate it to
> X509 structure.
> +  //
> +  Cert = d2i_X509 (NULL, (const unsigned char ** )&Data, (long) DataSize);
> +  if (Cert == NULL) {
> +    //
> +    // Certificate is from PEM encoding.
> +    //
> +    BioCert = BIO_new (BIO_s_mem ());
> +    if (BioCert == NULL) {
> +      Status = EFI_OUT_OF_RESOURCES;
> +      goto ON_EXIT;
> +    }
> +
> +    if (BIO_write (BioCert, Data, (UINT32) DataSize) <= 0) {
> +      Status = EFI_ABORTED;
> +      goto ON_EXIT;
> +    }
> +
> +    Cert = PEM_read_bio_X509 (BioCert, NULL, NULL, NULL);
> +    if (Cert == NULL) {
> +      Status = EFI_ABORTED;
> +      goto ON_EXIT;
> +    }
> +  }
> +
> +  if (SSL_use_certificate (TlsConn->Ssl, Cert) != 1) {
> +    Status = EFI_ABORTED;
> +    goto ON_EXIT;
> +  }
> +
> +ON_EXIT:
> +  if (BioCert != NULL) {
> +    BIO_free (BioCert);
> +  }
> +
> +  if (Cert != NULL) {
> +    X509_free (Cert);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Adds the local private key to the specified TLS object.
> +
> +  This function adds the local private key (PEM-encoded RSA or PKCS#8
> private
> +  key) into the specified TLS object for TLS negotiation.
> +
> +  @param[in]  Tls         Pointer to the TLS object.
> +  @param[in]  Data        Pointer to the data buffer of a PEM-encoded RSA
> +                          or PKCS#8 private key.
> +  @param[in]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS     The operation succeeded.
> +  @retval  EFI_UNSUPPORTED This function is not supported.
> +  @retval  EFI_ABORTED     Invalid private key data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetHostPrivateKey (
> +  IN     VOID                     *Tls,
> +  IN     VOID                     *Data,
> +  IN     UINTN                    DataSize
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Adds the CA-supplied certificate revocation list for certificate validation.
> +
> +  This function adds the CA-supplied certificate revocation list data for
> +  certificate validity checking.
> +
> +  @param[in]  Data        Pointer to the data buffer of a DER-encoded CRL data.
> +  @param[in]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS     The operation succeeded.
> +  @retval  EFI_UNSUPPORTED This function is not supported.
> +  @retval  EFI_ABORTED     Invalid CRL data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsSetCertRevocationList (
> +  IN     VOID                     *Data,
> +  IN     UINTN                    DataSize
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Gets the protocol version used by the specified TLS connection.
> +
> +  This function returns the protocol version used by the specified TLS
> +  connection.
> +
> +  @param[in]  Tls    Pointer to the TLS object.
> +
> +  @return  The protocol version of the specified TLS connection.
> +
> +**/
> +UINT16
> +EFIAPI
> +TlsGetVersion (
> +  IN     VOID                     *Tls
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +
> +  ASSERT (TlsConn != NULL);
> +
> +  return (UINT16)(SSL_version (TlsConn->Ssl));
> +}
> +
> +/**
> +  Gets the connection end of the specified TLS connection.
> +
> +  This function returns the connection end (as client or as server) used by
> +  the specified TLS connection.
> +
> +  @param[in]  Tls    Pointer to the TLS object.
> +
> +  @return  The connection end used by the specified TLS connection.
> +
> +**/
> +UINT8
> +EFIAPI
> +TlsGetConnectionEnd (
> +  IN     VOID                     *Tls
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +
> +  ASSERT (TlsConn != NULL);
> +
> +  return (UINT8)SSL_is_server (TlsConn->Ssl);
> +}
> +
> +/**
> +  Gets the cipher suite used by the specified TLS connection.
> +
> +  This function returns current cipher suite used by the specified
> +  TLS connection.
> +
> +  @param[in]      Tls         Pointer to the TLS object.
> +  @param[in,out]  CipherId    The cipher suite used by the TLS object.
> +
> +  @retval  EFI_SUCCESS           The cipher suite was returned successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Unsupported cipher suite.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetCurrentCipher (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT16                   *CipherId
> +  )
> +{
> +  TLS_CONNECTION    *TlsConn;
> +  CONST SSL_CIPHER  *Cipher;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  Cipher  = NULL;
> +
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL || CipherId == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Cipher = SSL_get_current_cipher (TlsConn->Ssl);
> +  if (Cipher == NULL) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  *CipherId = (SSL_CIPHER_get_id (Cipher)) & 0xFFFF;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Gets the compression methods used by the specified TLS connection.
> +
> +  This function returns current integrated compression methods used by
> +  the specified TLS connection.
> +
> +  @param[in]      Tls              Pointer to the TLS object.
> +  @param[in,out]  CompressionId    The current compression method used
> by
> +                                   the TLS object.
> +
> +  @retval  EFI_SUCCESS           The compression method was returned
> successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_ABORTED           Invalid Compression method.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetCurrentCompressionId (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *CompressionId
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Gets the verification mode currently set in the TLS connection.
> +
> +  This function returns the peer verification mode currently set in the
> +  specified TLS connection.
> +
> +  @param[in]  Tls    Pointer to the TLS object.
> +
> +  @return  The verification mode set in the specified TLS connection.
> +
> +**/
> +UINT32
> +EFIAPI
> +TlsGetVerify (
> +  IN     VOID                     *Tls
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +
> +  ASSERT (TlsConn != NULL);
> +
> +  return SSL_get_verify_mode (TlsConn->Ssl);
> +}
> +
> +/**
> +  Gets the session ID used by the specified TLS connection.
> +
> +  This function returns the TLS/SSL session ID currently used by the
> +  specified TLS connection.
> +
> +  @param[in]      Tls             Pointer to the TLS object.
> +  @param[in,out]  SessionId       Buffer to contain the returned session ID.
> +  @param[in,out]  SessionIdLen    The length of Session ID in bytes.
> +
> +  @retval  EFI_SUCCESS           The Session ID was returned successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetSessionId (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *SessionId,
> +  IN OUT UINT16                   *SessionIdLen
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +  SSL_SESSION     *Session;
> +  CONST UINT8     *SslSessionId;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  Session = NULL;
> +
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL || SessionId == NULL ||
> SessionIdLen == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Session = SSL_get_session (TlsConn->Ssl);
> +  if (Session == NULL) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  SslSessionId = SSL_SESSION_get_id (Session, (unsigned int
> *)SessionIdLen);
> +  CopyMem (SessionId, SslSessionId, *SessionIdLen);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Gets the client random data used in the specified TLS connection.
> +
> +  This function returns the TLS/SSL client random data currently used in
> +  the specified TLS connection.
> +
> +  @param[in]      Tls             Pointer to the TLS object.
> +  @param[in,out]  ClientRandom    Buffer to contain the returned client
> +                                  random data (32 bytes).
> +
> +**/
> +VOID
> +EFIAPI
> +TlsGetClientRandom (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *ClientRandom
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL || ClientRandom == NULL) {
> +    return;
> +  }
> +
> +  CopyMem (ClientRandom, TlsConn->Ssl->s3->client_random,
> SSL3_RANDOM_SIZE);
> +}
> +
> +/**
> +  Gets the server random data used in the specified TLS connection.
> +
> +  This function returns the TLS/SSL server random data currently used in
> +  the specified TLS connection.
> +
> +  @param[in]      Tls             Pointer to the TLS object.
> +  @param[in,out]  ServerRandom    Buffer to contain the returned server
> +                                  random data (32 bytes).
> +
> +**/
> +VOID
> +EFIAPI
> +TlsGetServerRandom (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *ServerRandom
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL || ServerRandom == NULL) {
> +    return;
> +  }
> +
> +  CopyMem (ServerRandom, TlsConn->Ssl->s3->server_random,
> SSL3_RANDOM_SIZE);
> +}
> +
> +/**
> +  Gets the master key data used in the specified TLS connection.
> +
> +  This function returns the TLS/SSL master key material currently used in
> +  the specified TLS connection.
> +
> +  @param[in]      Tls            Pointer to the TLS object.
> +  @param[in,out]  KeyMaterial    Buffer to contain the returned key material.
> +
> +  @retval  EFI_SUCCESS           Key material was returned successfully.
> +  @retval  EFI_INVALID_PARAMETER The parameter is invalid.
> +  @retval  EFI_UNSUPPORTED       Invalid TLS/SSL session.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetKeyMaterial (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *KeyMaterial
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +  SSL_SESSION     *Session;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  Session = NULL;
> +
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL || KeyMaterial == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Session = SSL_get_session (TlsConn->Ssl);
> +
> +  if (Session == NULL) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  CopyMem (KeyMaterial, Session->master_key, Session-
> >master_key_length);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Gets the CA Certificate from the cert store.
> +
> +  This function returns the CA certificate for the chosen
> +  TLS connection.
> +
> +  @param[in]      Tls         Pointer to the TLS object.
> +  @param[out]     Data        Pointer to the data buffer to receive the CA
> +                              certificate data sent to the client.
> +  @param[in,out]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_UNSUPPORTED         This function is not supported.
> +  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetCaCertificate (
> +  IN     VOID                     *Tls,
> +  OUT    VOID                     *Data,
> +  IN OUT UINTN                    *DataSize
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Gets the local public Certificate set in the specified TLS object.
> +
> +  This function returns the local public certificate which was currently set
> +  in the specified TLS object.
> +
> +  @param[in]      Tls         Pointer to the TLS object.
> +  @param[out]     Data        Pointer to the data buffer to receive the local
> +                              public certificate.
> +  @param[in,out]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_INVALID_PARAMETER   The parameter is invalid.
> +  @retval  EFI_NOT_FOUND           The certificate is not found.
> +  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetHostPublicCert (
> +  IN     VOID                     *Tls,
> +  OUT    VOID                     *Data,
> +  IN OUT UINTN                    *DataSize
> +  )
> +{
> +  X509            *Cert;
> +  EFI_STATUS      Status;
> +  TLS_CONNECTION  *TlsConn;
> +
> +  Cert    = NULL;
> +  Status  = EFI_SUCCESS;
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL || DataSize == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Cert = SSL_get_certificate(TlsConn->Ssl);
> +  if (Cert == NULL) {
> +    Status = EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Only DER encoding is supported currently.
> +  //
> +  if (*DataSize < (UINTN) i2d_X509 (Cert, NULL)) {
> +    *DataSize = (UINTN) i2d_X509 (Cert, NULL);
> +    return EFI_BUFFER_TOO_SMALL;
> +  }
> +
> +  *DataSize = (UINTN) i2d_X509 (Cert, (unsigned char **) &Data);
> +
> +  return Status;
> +}
> +
> +/**
> +  Gets the local private key set in the specified TLS object.
> +
> +  This function returns the local private key data which was currently set
> +  in the specified TLS object.
> +
> +  @param[in]      Tls         Pointer to the TLS object.
> +  @param[out]     Data        Pointer to the data buffer to receive the local
> +                              private key data.
> +  @param[in,out]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_UNSUPPORTED         This function is not supported.
> +  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetHostPrivateKey (
> +  IN     VOID                     *Tls,
> +  OUT    VOID                     *Data,
> +  IN OUT UINTN                    *DataSize
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Gets the CA-supplied certificate revocation list data set in the specified
> +  TLS object.
> +
> +  This function returns the CA-supplied certificate revocation list data which
> +  was currently set in the specified TLS object.
> +
> +  @param[out]     Data        Pointer to the data buffer to receive the CRL data.
> +  @param[in,out]  DataSize    The size of data buffer in bytes.
> +
> +  @retval  EFI_SUCCESS             The operation succeeded.
> +  @retval  EFI_UNSUPPORTED         This function is not supported.
> +  @retval  EFI_BUFFER_TOO_SMALL    The Data is too small to hold the data.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsGetCertRevocationList (
> +  OUT    VOID                     *Data,
> +  IN OUT UINTN                    *DataSize
> +  )
> +{
> +  return EFI_UNSUPPORTED;
> +}
> diff --git a/CryptoPkg/Library/TlsLib/TlsInit.c
> b/CryptoPkg/Library/TlsLib/TlsInit.c
> new file mode 100644
> index 0000000..6b1fd93
> --- /dev/null
> +++ b/CryptoPkg/Library/TlsLib/TlsInit.c
> @@ -0,0 +1,291 @@
> +/** @file
> +  SSL/TLS Initialization Library Wrapper Implementation over OpenSSL.
> +
> +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 "InternalTlsLib.h"
> +
> +/**
> +  Initializes the OpenSSL library.
> +
> +  This function registers ciphers and digests used directly and indirectly
> +  by SSL/TLS, and initializes the readable error messages.
> +  This function must be called before any other action takes places.
> +
> +**/
> +VOID
> +EFIAPI
> +TlsInitialize (
> +  VOID
> +  )
> +{
> +  //
> +  // Performs initialization of crypto and ssl library, and loads required
> +  // algorithms.
> +  //
> +  SSL_library_init ();
> +
> +  //
> +  // Loads error strings from both crypto and ssl library.
> +  //
> +  SSL_load_error_strings ();
> +
> +  /// OpenSSL_add_all_algorithms();
> +
> +  //
> +  // Initialize the pseudorandom number generator.
> +  //
> +  RandomSeed (NULL, 0);
> +}
> +
> +/**
> +  Free an allocated SSL_CTX object.
> +
> +  @param[in]  TlsCtx    Pointer to the SSL_CTX object to be released.
> +
> +**/
> +VOID
> +EFIAPI
> +TlsCtxFree (
> +  IN   VOID                  *TlsCtx
> +  )
> +{
> +  if (TlsCtx == NULL) {
> +    return;
> +  }
> +
> +  if (TlsCtx != NULL) {
> +    SSL_CTX_free ((SSL_CTX *) (TlsCtx));
> +  }
> +}
> +
> +/**
> +  Creates a new SSL_CTX object as framework to establish TLS/SSL enabled
> +  connections.
> +
> +  @param[in]  MajorVer    Major Version of TLS/SSL Protocol.
> +  @param[in]  MinorVer    Minor Version of TLS/SSL Protocol.
> +
> +  @return  Pointer to an allocated SSL_CTX object.
> +           If the creation failed, TlsCtxNew() returns NULL.
> +
> +**/
> +VOID *
> +EFIAPI
> +TlsCtxNew (
> +  IN     UINT8                    MajorVer,
> +  IN     UINT8                    MinorVer
> +  )
> +{
> +  SSL_CTX  *TlsCtx;
> +  UINT16   ProtoVersion;
> +
> +  ProtoVersion = (MajorVer << 8) | MinorVer;
> +
> +  TlsCtx = SSL_CTX_new (SSLv23_client_method ());
> +  if (TlsCtx == NULL) {
> +    return NULL;
> +  }
> +
> +  //
> +  // Ensure SSLv3 is disabled
> +  //
> +  SSL_CTX_set_options (TlsCtx, SSL_OP_NO_SSLv3);
> +
> +  //
> +  // Treat as minimum accepted versions.  Client can use higher
> +  // TLS version if server supports it
> +  //
> +  switch (ProtoVersion) {
> +  case TLS1_VERSION:
> +    //
> +    // TLS 1.0
> +    //
> +    break;
> +  case TLS1_1_VERSION:
> +    //
> +    // TLS 1.1
> +    //
> +    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1);
> +    break;
> +  case TLS1_2_VERSION:
> +    //
> +    // TLS 1.2
> +    //
> +    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1);
> +    SSL_CTX_set_options (TlsCtx, SSL_OP_NO_TLSv1_1);
> +    break;
> +  default:
> +    //
> +    // Unsupported TLS/SSL Protocol Version.
> +    //
> +    break;
> +  }
> +
> +  return (VOID *) TlsCtx;
> +}
> +
> +/**
> +  Free an allocated TLS object.
> +
> +  This function removes the TLS object pointed to by Tls and frees up the
> +  allocated memory. If Tls is NULL, nothing is done.
> +
> +  @param[in]  Tls    Pointer to the TLS object to be freed.
> +
> +**/
> +VOID
> +EFIAPI
> +TlsFree (
> +  IN     VOID                     *Tls
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  if (TlsConn == NULL) {
> +    return;
> +  }
> +
> +  //
> +  // Free the internal TLS and BIO objects.
> +  //
> +  if (TlsConn->Ssl != NULL) {
> +    SSL_free (TlsConn->Ssl);
> +  }
> +
> +  if (TlsConn->InBio != NULL) {
> +    BIO_free (TlsConn->InBio);
> +  }
> +
> +  if (TlsConn->OutBio != NULL) {
> +    BIO_free (TlsConn->OutBio);
> +  }
> +
> +  OPENSSL_free (Tls);
> +}
> +
> +/**
> +  Create a new TLS object for a connection.
> +
> +  This function creates a new TLS object for a connection. The new object
> +  inherits the setting of the underlying context TlsCtx: connection method,
> +  options, verification setting.
> +
> +  @param[in]  TlsCtx    Pointer to the SSL_CTX object.
> +
> +  @return  Pointer to an allocated SSL object.
> +           If the creation failed, TlsNew() returns NULL.
> +
> +**/
> +VOID *
> +EFIAPI
> +TlsNew (
> +  IN     VOID                     *TlsCtx
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +  SSL_CTX         *SslCtx;
> +  X509_STORE      *X509Store;
> +
> +  TlsConn = NULL;
> +
> +  //
> +  // Allocate one new TLS_CONNECTION object
> +  //
> +  TlsConn = (TLS_CONNECTION *) OPENSSL_malloc (sizeof
> (TLS_CONNECTION));
> +  if (TlsConn == NULL) {
> +    return NULL;
> +  }
> +
> +  TlsConn->Ssl = NULL;
> +
> +  //
> +  // Create a new SSL Object
> +  //
> +  TlsConn->Ssl = SSL_new ((SSL_CTX *) TlsCtx);
> +  if (TlsConn->Ssl == NULL) {
> +    TlsFree ((VOID *) TlsConn);
> +    return NULL;
> +  }
> +
> +  //
> +  // Initialize the created SSL Object
> +  //
> +  SSL_set_info_callback (TlsConn->Ssl, NULL);
> +
> +  TlsConn->InBio = NULL;
> +
> +  //
> +  // Set up Reading BIO for TLS connection
> +  //
> +  TlsConn->InBio = BIO_new (BIO_s_mem ());
> +  if (TlsConn->InBio == NULL) {
> +    TlsFree ((VOID *) TlsConn);
> +    return NULL;
> +  }
> +
> +  //
> +  // Sets the behaviour of memory BIO when it is empty. It will set the
> +  // read retry flag.
> +  //
> +  BIO_set_mem_eof_return (TlsConn->InBio, -1);
> +
> +  TlsConn->OutBio = NULL;
> +
> +  //
> +  // Set up Writing BIO for TLS connection
> +  //
> +  TlsConn->OutBio = BIO_new (BIO_s_mem ());
> +  if (TlsConn->OutBio == NULL) {
> +    TlsFree ((VOID *) TlsConn);
> +    return NULL;
> +  }
> +
> +  //
> +  // Sets the behaviour of memory BIO when it is empty. It will set the
> +  // write retry flag.
> +  //
> +  BIO_set_mem_eof_return (TlsConn->OutBio, -1);
> +
> +  ASSERT (TlsConn->Ssl != NULL && TlsConn->InBio != NULL && TlsConn-
> >OutBio != NULL);
> +
> +  //
> +  // Connects the InBio and OutBio for the read and write operations.
> +  //
> +  SSL_set_bio (TlsConn->Ssl, TlsConn->InBio, TlsConn->OutBio);
> +
> +  //
> +  // Create new X509 store if needed
> +  //
> +  SslCtx    = SSL_get_SSL_CTX (TlsConn->Ssl);
> +  X509Store = SSL_CTX_get_cert_store (SslCtx);
> +  if (X509Store == NULL) {
> +    X509Store = X509_STORE_new ();
> +    if (X509Store == NULL) {
> +      TlsFree ((VOID *) TlsConn);
> +      return NULL;
> +    }
> +    SSL_CTX_set1_verify_cert_store (SslCtx, X509Store);
> +    X509_STORE_free (X509Store);
> +  }
> +
> +  //
> +  // Set X509_STORE flags used in certificate validation
> +  //
> +  X509_STORE_set_flags (
> +    X509Store,
> +    X509_V_FLAG_PARTIAL_CHAIN | X509_V_FLAG_NO_CHECK_TIME
> +    );
> +  return (VOID *) TlsConn;
> +}
> diff --git a/CryptoPkg/Library/TlsLib/TlsLib.inf
> b/CryptoPkg/Library/TlsLib/TlsLib.inf
> new file mode 100644
> index 0000000..2122b3b
> --- /dev/null
> +++ b/CryptoPkg/Library/TlsLib/TlsLib.inf
> @@ -0,0 +1,49 @@
> +## @file
> +#  SSL/TLS Wrapper Library Instance based on OpenSSL.
> +#
> +#  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.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION                    = 0x00010005
> +  BASE_NAME                      = TlsLib
> +  MODULE_UNI_FILE                = TlsLib.uni
> +  FILE_GUID                      = CC729DC5-4E21-0B36-1A00-3A8E1B86A155
> +  MODULE_TYPE                    = DXE_DRIVER
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = TlsLib|DXE_DRIVER DXE_CORE
> UEFI_APPLICATION UEFI_DRIVER
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 IPF ARM AARCH64
> +#
> +
> +[Sources]
> +  InternalTlsLib.h
> +  TlsInit.c
> +  TlsConfig.c
> +  TlsProcess.c
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  CryptoPkg/CryptoPkg.dec
> +
> +[LibraryClasses]
> +  BaseLib
> +  BaseMemoryLib
> +  MemoryAllocationLib
> +  UefiRuntimeServicesTableLib
> +  DebugLib
> +  OpensslLib
> +  IntrinsicLib
> +  PrintLib
> diff --git a/CryptoPkg/Library/TlsLib/TlsLib.uni
> b/CryptoPkg/Library/TlsLib/TlsLib.uni
> new file mode 100644
> index 0000000..9b79287
> --- /dev/null
> +++ b/CryptoPkg/Library/TlsLib/TlsLib.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// SSL/TLS Wrapper Library Instance based on OpenSSL.
> +//
> +// 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.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "SSL/TLS Wrapper
> Library Instance"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This module
> provides SSL/TLS Wrapper Library Instance."
> \ No newline at end of file
> diff --git a/CryptoPkg/Library/TlsLib/TlsProcess.c
> b/CryptoPkg/Library/TlsLib/TlsProcess.c
> new file mode 100644
> index 0000000..52b55d7
> --- /dev/null
> +++ b/CryptoPkg/Library/TlsLib/TlsProcess.c
> @@ -0,0 +1,461 @@
> +/** @file
> +  SSL/TLS Process Library Wrapper Implementation over OpenSSL.
> +  The process includes the TLS handshake and packet I/O.
> +
> +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 "InternalTlsLib.h"
> +
> +#define MAX_BUFFER_SIZE   32768
> +
> +/**
> +  Checks if the TLS handshake was done.
> +
> +  This function will check if the specified TLS handshake was done.
> +
> +  @param[in]  Tls    Pointer to the TLS object for handshake state checking.
> +
> +  @retval  TRUE     The TLS handshake was done.
> +  @retval  FALSE    The TLS handshake was not done.
> +
> +**/
> +BOOLEAN
> +EFIAPI
> +TlsInHandshake (
> +  IN     VOID                     *Tls
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
> +    return FALSE;
> +  }
> +
> +  //
> +  // Return the status which indicates if the TLS handshake was done.
> +  //
> +  return !SSL_is_init_finished (TlsConn->Ssl);
> +}
> +
> +/**
> +  Perform a TLS/SSL handshake.
> +
> +  This function will perform a TLS/SSL handshake.
> +
> +  @param[in]       Tls            Pointer to the TLS object for handshake operation.
> +  @param[in]       BufferIn       Pointer to the most recently received TLS
> Handshake packet.
> +  @param[in]       BufferInSize   Packet size in bytes for the most recently
> received TLS
> +                                  Handshake packet.
> +  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
> +  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On
> input, it is
> +                                  the buffer size provided by the caller. On output, it
> +                                  is the buffer size in fact needed to contain the
> +                                  packet.
> +
> +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  Tls is NULL.
> +                                  BufferIn is NULL but BufferInSize is NOT 0.
> +                                  BufferInSize is 0 but BufferIn is NOT NULL.
> +                                  BufferOutSize is NULL.
> +                                  BufferOut is NULL if *BufferOutSize is not zero.
> +  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the
> response packet.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsDoHandshake (
> +  IN     VOID                     *Tls,
> +  IN     UINT8                    *BufferIn, OPTIONAL
> +  IN     UINTN                    BufferInSize, OPTIONAL
> +     OUT UINT8                    *BufferOut, OPTIONAL
> +  IN OUT UINTN                    *BufferOutSize
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +  UINTN           PendingBufferSize;
> +  INTN            Ret;
> +  unsigned long   ErrorCode;
> +
> +  TlsConn           = (TLS_CONNECTION *) Tls;
> +  PendingBufferSize = 0;
> +  Ret               = 1;
> +
> +  if (TlsConn == NULL || \
> +    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio ==
> NULL || \
> +    BufferOutSize == NULL || \
> +    (BufferIn == NULL && BufferInSize != 0) || \
> +    (BufferIn != NULL && BufferInSize == 0) || \
> +    (BufferOut == NULL && *BufferOutSize != 0)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  if(BufferIn == NULL && BufferInSize == 0) {
> +    //
> +    // If RequestBuffer is NULL and RequestSize is 0, and TLS session
> +    // status is EfiTlsSessionNotStarted, the TLS session will be initiated
> +    // and the response packet needs to be ClientHello.
> +    //
> +    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
> +    if (PendingBufferSize == 0) {
> +      SSL_set_connect_state (TlsConn->Ssl);
> +      Ret = SSL_do_handshake (TlsConn->Ssl);
> +      PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
> +    }
> +  } else {
> +    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
> +    if (PendingBufferSize == 0) {
> +      BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);
> +      Ret = SSL_do_handshake (TlsConn->Ssl);
> +      PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
> +    }
> +  }
> +
> +  if (Ret < 1) {
> +    Ret = SSL_get_error (TlsConn->Ssl, (int) Ret);
> +    if (Ret == SSL_ERROR_SSL ||
> +        Ret == SSL_ERROR_SYSCALL ||
> +        Ret == SSL_ERROR_ZERO_RETURN) {
> +      DEBUG ((
> +        DEBUG_ERROR,
> +        "%a SSL_HANDSHAKE_ERROR State=0x%x SSL_ERROR_%a\n",
> +        __FUNCTION__,
> +        SSL_get_state (TlsConn->Ssl),
> +        Ret == SSL_ERROR_SSL ? "SSL" : Ret == SSL_ERROR_SYSCALL ?
> "SYSCALL" : "ZERO_RETURN"
> +        ));
> +      DEBUG_CODE_BEGIN ();
> +        while (TRUE) {
> +          ErrorCode = ERR_get_error ();
> +          if (ErrorCode == 0) {
> +            break;
> +          }
> +          DEBUG ((
> +            DEBUG_ERROR,
> +            "%a ERROR 0x%x=L%x:F%x:R%x\n",
> +            __FUNCTION__,
> +            ErrorCode,
> +            ERR_GET_LIB (ErrorCode),
> +            ERR_GET_FUNC (ErrorCode),
> +            ERR_GET_REASON (ErrorCode)
> +            ));
> +        }
> +      DEBUG_CODE_END ();
> +      return EFI_PROTOCOL_ERROR;
> +    }
> +  }
> +
> +  if (PendingBufferSize > *BufferOutSize) {
> +    *BufferOutSize = PendingBufferSize;
> +    return EFI_BUFFER_TOO_SMALL;
> +  }
> +
> +  if (PendingBufferSize > 0) {
> +    *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32)
> PendingBufferSize);
> +  } else {
> +    *BufferOutSize = 0;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Hande Alert message recorded in BufferIn. If BufferIn is NULL and
> BufferInSize is zero,
> +  TLS session has errors and the response packet needs to be Alert message
> based on error type.
> +
> +  @param[in]       Tls            Pointer to the TLS object for state checking.
> +  @param[in]       BufferIn       Pointer to the most recently received TLS Alert
> packet.
> +  @param[in]       BufferInSize   Packet size in bytes for the most recently
> received TLS
> +                                  Alert packet.
> +  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.
> +  @param[in, out]  BufferOutSize  Pointer to the buffer size in bytes. On
> input, it is
> +                                  the buffer size provided by the caller. On output, it
> +                                  is the buffer size in fact needed to contain the
> +                                  packet.
> +
> +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  Tls is NULL.
> +                                  BufferIn is NULL but BufferInSize is NOT 0.
> +                                  BufferInSize is 0 but BufferIn is NOT NULL.
> +                                  BufferOutSize is NULL.
> +                                  BufferOut is NULL if *BufferOutSize is not zero.
> +  @retval EFI_ABORTED             An error occurred.
> +  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the
> response packet.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsHandeAlert (
> +  IN     VOID                     *Tls,
> +  IN     UINT8                    *BufferIn, OPTIONAL
> +  IN     UINTN                    BufferInSize, OPTIONAL
> +     OUT UINT8                    *BufferOut, OPTIONAL
> +  IN OUT UINTN                    *BufferOutSize
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +  UINTN           PendingBufferSize;
> +  UINT8           *TempBuffer;
> +  INTN            Ret;
> +
> +  TlsConn           = (TLS_CONNECTION *) Tls;
> +  PendingBufferSize = 0;
> +  TempBuffer        = NULL;
> +  Ret               = 0;
> +
> +  if (TlsConn == NULL || \
> +    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio ==
> NULL || \
> +    BufferOutSize == NULL || \
> +    (BufferIn == NULL && BufferInSize != 0) || \
> +    (BufferIn != NULL && BufferInSize == 0) || \
> +    (BufferOut == NULL && *BufferOutSize != 0)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
> +  if (PendingBufferSize == 0 && BufferIn != NULL && BufferInSize != 0) {
> +    Ret = BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);
> +    if (Ret != (INTN) BufferInSize) {
> +      return EFI_ABORTED;
> +    }
> +
> +    TempBuffer = (UINT8 *) OPENSSL_malloc (MAX_BUFFER_SIZE);
> +
> +    //
> +    // ssl3_send_alert() will be called in ssl3_read_bytes() function.
> +    // TempBuffer is invalid since it's a Alert message, so just ignore it.
> +    //
> +    SSL_read (TlsConn->Ssl, TempBuffer, MAX_BUFFER_SIZE);
> +
> +    OPENSSL_free (TempBuffer);
> +
> +    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
> +  }
> +
> +  if (PendingBufferSize > *BufferOutSize) {
> +    *BufferOutSize = PendingBufferSize;
> +    return EFI_BUFFER_TOO_SMALL;
> +  }
> +
> +  if (PendingBufferSize > 0) {
> +    *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32)
> PendingBufferSize);
> +  } else {
> +    *BufferOutSize = 0;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Build the CloseNotify packet.
> +
> +  @param[in]       Tls            Pointer to the TLS object for state checking.
> +  @param[in, out]  Buffer         Pointer to the buffer to hold the built packet.
> +  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input,
> it is
> +                                  the buffer size provided by the caller. On output, it
> +                                  is the buffer size in fact needed to contain the
> +                                  packet.
> +
> +  @retval EFI_SUCCESS             The required TLS packet is built successfully.
> +  @retval EFI_INVALID_PARAMETER   One or more of the following
> conditions is TRUE:
> +                                  Tls is NULL.
> +                                  BufferSize is NULL.
> +                                  Buffer is NULL if *BufferSize is not zero.
> +  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the
> response packet.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsCloseNotify (
> +  IN     VOID                     *Tls,
> +  IN OUT UINT8                    *Buffer,
> +  IN OUT UINTN                    *BufferSize
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +  UINTN           PendingBufferSize;
> +
> +  TlsConn           = (TLS_CONNECTION *) Tls;
> +  PendingBufferSize = 0;
> +
> +  if (TlsConn == NULL || \
> +    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio ==
> NULL || \
> +    BufferSize == NULL || \
> +    (Buffer == NULL && *BufferSize != 0)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
> +  if (PendingBufferSize == 0) {
> +    //
> +    // ssl3_send_alert() and ssl3_dispatch_alert() function will be called.
> +    //
> +    SSL_shutdown (TlsConn->Ssl);
> +    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);
> +  }
> +
> +  if (PendingBufferSize > *BufferSize) {
> +    *BufferSize = PendingBufferSize;
> +    return EFI_BUFFER_TOO_SMALL;
> +  }
> +
> +  if (PendingBufferSize > 0) {
> +    *BufferSize = BIO_read (TlsConn->OutBio, Buffer, (UINT32)
> PendingBufferSize);
> +  } else {
> +    *BufferSize = 0;
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Attempts to read bytes from one TLS object and places the data in Buffer.
> +
> +  This function will attempt to read BufferSize bytes from the TLS object
> +  and places the data in Buffer.
> +
> +  @param[in]      Tls           Pointer to the TLS object.
> +  @param[in,out]  Buffer        Pointer to the buffer to store the data.
> +  @param[in]      BufferSize    The size of Buffer in bytes.
> +
> +  @retval  >0    The amount of data successfully read from the TLS object.
> +  @retval  <=0   No data was successfully read.
> +
> +**/
> +INTN
> +EFIAPI
> +TlsCtrlTrafficOut (
> +  IN     VOID                     *Tls,
> +  IN OUT VOID                     *Buffer,
> +  IN     UINTN                    BufferSize
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  if (TlsConn == NULL || TlsConn->OutBio == 0) {
> +    return -1;
> +  }
> +
> +  //
> +  // Read and return the amount of data from the BIO.
> +  //
> +  return BIO_read (TlsConn->OutBio, Buffer, (UINT32) BufferSize);
> +}
> +
> +/**
> +  Attempts to write data from the buffer to TLS object.
> +
> +  This function will attempt to write BufferSize bytes data from the Buffer
> +  to the TLS object.
> +
> +  @param[in]  Tls           Pointer to the TLS object.
> +  @param[in]  Buffer        Pointer to the data buffer.
> +  @param[in]  BufferSize    The size of Buffer in bytes.
> +
> +  @retval  >0    The amount of data successfully written to the TLS object.
> +  @retval <=0    No data was successfully written.
> +
> +**/
> +INTN
> +EFIAPI
> +TlsCtrlTrafficIn (
> +  IN     VOID                     *Tls,
> +  IN     VOID                     *Buffer,
> +  IN     UINTN                    BufferSize
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  if (TlsConn == NULL || TlsConn->InBio == 0) {
> +    return -1;
> +  }
> +
> +  //
> +  // Write and return the amount of data to the BIO.
> +  //
> +  return BIO_write (TlsConn->InBio, Buffer, (UINT32) BufferSize);
> +}
> +/**
> +  Attempts to read bytes from the specified TLS connection into the buffer.
> +
> +  This function tries to read BufferSize bytes data from the specified TLS
> +  connection into the Buffer.
> +
> +  @param[in]      Tls           Pointer to the TLS connection for data reading.
> +  @param[in,out]  Buffer        Pointer to the data buffer.
> +  @param[in]      BufferSize    The size of Buffer in bytes.
> +
> +  @retval  >0    The read operation was successful, and return value is the
> +                 number of bytes actually read from the TLS connection.
> +  @retval  <=0   The read operation was not successful.
> +
> +**/
> +INTN
> +EFIAPI
> +TlsRead (
> +  IN     VOID                     *Tls,
> +  IN OUT VOID                     *Buffer,
> +  IN     UINTN                    BufferSize
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
> +    return -1;
> +  }
> +
> +  //
> +  // Read bytes from the specified TLS connection.
> +  //
> +  return SSL_read (TlsConn->Ssl, Buffer, (UINT32) BufferSize);
> +}
> +
> +/**
> +  Attempts to write data to a TLS connection.
> +
> +  This function tries to write BufferSize bytes data from the Buffer into the
> +  specified TLS connection.
> +
> +  @param[in]  Tls           Pointer to the TLS connection for data writing.
> +  @param[in]  Buffer        Pointer to the data buffer.
> +  @param[in]  BufferSize    The size of Buffer in bytes.
> +
> +  @retval  >0    The write operation was successful, and return value is the
> +                 number of bytes actually written to the TLS connection.
> +  @retval <=0    The write operation was not successful.
> +
> +**/
> +INTN
> +EFIAPI
> +TlsWrite (
> +  IN     VOID                     *Tls,
> +  IN     VOID                     *Buffer,
> +  IN     UINTN                    BufferSize
> +  )
> +{
> +  TLS_CONNECTION  *TlsConn;
> +
> +  TlsConn = (TLS_CONNECTION *) Tls;
> +  if (TlsConn == NULL || TlsConn->Ssl == NULL) {
> +    return -1;
> +  }
> +
> +  //
> +  // Write bytes to the specified TLS connection.
> +  //
> +  return SSL_write (TlsConn->Ssl, Buffer, (UINT32) BufferSize);
> +}
> --
> 1.9.5.msysgit.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration
  2016-12-15  2:22   ` Fu, Siyuan
@ 2016-12-22  2:52     ` Ye, Ting
  2016-12-22  3:13       ` Wu, Jiaxin
  0 siblings, 1 reply; 37+ messages in thread
From: Ye, Ting @ 2016-12-22  2:52 UTC (permalink / raw)
  To: Fu, Siyuan, Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Zhang, Lubo, Long, Qin, Thomas Palmer

I agree. Adding new StringToGuid and GuidToString to common library seems a good idea if we don't have existing APIs.  

In GuidToString, the comment indicates that SPrint will NULL terminate the string, so use Size -1 to skip the NULL. However, I see UnicodeSPrint in MdePkg returns the number of Unicode characters in the produced output buffer, not including the Null-terminator.
It looks inconsistent to me. Please check that.

Others are good to me.
Reviewed-by: Ye Ting <ting.ye@intel.com>

Best Regards,
Ting


-----Original Message-----
From: Fu, Siyuan 
Sent: Thursday, December 15, 2016 10:22 AM
To: Wu, Jiaxin <jiaxin.wu@intel.com>; edk2-devel@lists.01.org
Cc: Ye, Ting <ting.ye@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; Long, Qin <qin.long@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>
Subject: RE: [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration

Hi, Jiaxin

PrintLib support "%g" to print a GUID so you don't need to use "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x" in GuidToString(). 
Beside of that, I do see a lot of drivers has similar internal function StringToGuid() or StrToGuid(), do we have a common library interface for this? if not I think it may worth to create one.

Other parts are good with me.
Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>


Best Regards
Siyuan

-----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 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration

This patch provides the UI to support TLS auth configuration.
* EFI_SIGNATURE_LIST format is used for 'TlsCaCertificate'
variable. So, TLS supports multiple certificate configuration.
* The variable attribute is BS with NV, which only target at
preventing runtime phase attack.

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/Include/Guid/TlsAuthConfigHii.h         |   25 +
 NetworkPkg/Include/Guid/TlsAuthentication.h        |   29 +
 NetworkPkg/NetworkPkg.dec                          |    7 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c     |  135 ++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf   |   73 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni   |   21 +
 .../TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni     |   19 +
 .../TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni   |   39 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c    | 1841 ++++++++++++++++++++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h    |  282 +++
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h  |   49 +
 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr   |  152 ++
 12 files changed, 2672 insertions(+)
 create mode 100644 NetworkPkg/Include/Guid/TlsAuthConfigHii.h
 create mode 100644 NetworkPkg/Include/Guid/TlsAuthentication.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
 create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr

diff --git a/NetworkPkg/Include/Guid/TlsAuthConfigHii.h b/NetworkPkg/Include/Guid/TlsAuthConfigHii.h
new file mode 100644
index 0000000..9d21426
--- /dev/null
+++ b/NetworkPkg/Include/Guid/TlsAuthConfigHii.h
@@ -0,0 +1,25 @@
+/** @file
+  GUIDs used as HII FormSet and HII Package list GUID in TlsAuthConfigDxe 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 that 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 __TLS_AUTH_CONFIG_HII_GUID_H__
+#define __TLS_AUTH_CONFIG_HII_GUID_H__
+
+#define TLS_AUTH_CONFIG_GUID \
+  { \
+    0xb0eae4f8, 0x9a04, 0x4c6d, { 0xa7, 0x48, 0x79, 0x3d, 0xaa, 0xf, 0x65, 0xdf } \
+  }
+
+extern EFI_GUID gTlsAuthConfigGuid;
+
+#endif
diff --git a/NetworkPkg/Include/Guid/TlsAuthentication.h b/NetworkPkg/Include/Guid/TlsAuthentication.h
new file mode 100644
index 0000000..2e800dc
--- /dev/null
+++ b/NetworkPkg/Include/Guid/TlsAuthentication.h
@@ -0,0 +1,29 @@
+/** @file
+  This file defines TlsCaCertificate variable.
+  
+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 that 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 __TLS_AUTHENTICATION_H__
+#define __TLS_AUTHENTICATION_H__
+
+// Private variable for CA Certificate configuration
+//
+#define EFI_TLS_CA_CERTIFICATE_GUID \
+  { \
+    0xfd2340D0, 0x3dab, 0x4349, { 0xa6, 0xc7, 0x3b, 0x4f, 0x12, 0xb4, 0x8e, 0xae } \
+  }
+
+#define EFI_TLS_CA_CERTIFICATE_VARIABLE       L"TlsCaCertificate"
+
+extern EFI_GUID gEfiTlsCaCertificateGuid;
+
+#endif
diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec
index 268188a..24d45f4 100644
--- a/NetworkPkg/NetworkPkg.dec
+++ b/NetworkPkg/NetworkPkg.dec
@@ -38,10 +38,17 @@
   gIScsiConfigGuid              = { 0x4b47d616, 0xa8d6, 0x4552, { 0x9d, 0x44, 0xcc, 0xad, 0x2e, 0xf, 0x4c, 0xf9}}
 
   # Include/Guid/HttpBootConfigHii.h
   gHttpBootConfigGuid           = { 0x4d20583a, 0x7765, 0x4e7a, { 0x8a, 0x67, 0xdc, 0xde, 0x74, 0xee, 0x3e, 0xc5 }}
 
+  # Include/Guid/TlsAuthConfigHii.h
+  gTlsAuthConfigGuid            = { 0xb0eae4f8, 0x9a04, 0x4c6d, { 0xa7, 0x48, 0x79, 0x3d, 0xaa, 0xf, 0x65, 0xdf }}
+  
+  # Include/Guid/TlsAuthentication.h
+  gEfiTlsCaCertificateGuid      = { 0xfd2340D0, 0x3dab, 0x4349, { 0xa6, 0xc7, 0x3b, 0x4f, 0x12, 0xb4, 0x8e, 0xae }}
+  
+
 [PcdsFeatureFlag]
   ## Indicates if the IPsec IKEv2 Certificate Authentication feature is enabled or not.<BR><BR>
   #   TRUE  - Certificate Authentication feature is enabled.<BR>
   #   FALSE - Does not support Certificate Authentication.<BR>
   # @Prompt Enable IPsec IKEv2 Certificate Authentication.
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
new file mode 100644
index 0000000..647bc2f
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
@@ -0,0 +1,135 @@
+/** @file
+  The DriverEntryPoint for TlsAuthConfigDxe 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.
+
+**/
+
+#include "TlsAuthConfigImpl.h"
+
+/**
+  Unloads an image.
+
+  @param  ImageHandle           Handle that identifies the image to be unloaded.
+
+  @retval EFI_SUCCESS           The image has been unloaded.
+  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
+
+**/
+EFI_STATUS 
+EFIAPI
+TlsAuthConfigDxeUnload (
+  IN EFI_HANDLE  ImageHandle
+  )
+{
+  EFI_STATUS                     Status;
+  TLS_AUTH_CONFIG_PRIVATE_DATA   *PrivateData;
+
+  Status = gBS->HandleProtocol (
+                  ImageHandle,
+                  &gEfiCallerIdGuid,
+                  (VOID **) &PrivateData
+                  );  
+  if (EFI_ERROR (Status)) {
+    return Status;  
+  }
+  
+  ASSERT (PrivateData->Signature == TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE);
+
+  gBS->UninstallMultipleProtocolInterfaces (
+         &ImageHandle,
+         &gEfiCallerIdGuid,
+         PrivateData,
+         NULL
+         );
+  
+  TlsAuthConfigFormUnload (PrivateData);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  This is the declaration of an EFI image entry point. This entry point is
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
+  both device drivers and bus drivers.
+
+  @param  ImageHandle           The firmware allocated handle for the UEFI image.
+  @param  SystemTable           A pointer to the EFI System Table.
+
+  @retval EFI_SUCCESS           The operation completed successfully.
+  @retval Others                An unexpected error occurred.
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigDxeDriverEntryPoint (
+  IN EFI_HANDLE        ImageHandle,
+  IN EFI_SYSTEM_TABLE  *SystemTable
+  )
+{
+  EFI_STATUS  Status;
+
+  TLS_AUTH_CONFIG_PRIVATE_DATA   *PrivateData;
+
+  PrivateData = NULL;
+  
+  //
+  // If already started, return.
+  //
+  Status = gBS->OpenProtocol (
+                  ImageHandle,
+                  &gEfiCallerIdGuid,
+                  NULL,
+                  ImageHandle,
+                  ImageHandle,
+                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+                  );
+  if (!EFI_ERROR (Status)) {
+    return EFI_ALREADY_STARTED;
+  }
+
+  //
+  // Initialize the private data structure.
+  //
+  PrivateData = AllocateZeroPool (sizeof (TLS_AUTH_CONFIG_PRIVATE_DATA));
+  if (PrivateData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize the HII configuration form.
+  //
+  Status = TlsAuthConfigFormInit (PrivateData);
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+
+  //
+  // Install private GUID.
+  //    
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &ImageHandle,
+                  &gEfiCallerIdGuid,
+                  PrivateData,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_ERROR;
+  }
+  
+  return EFI_SUCCESS;
+
+ON_ERROR:
+  TlsAuthConfigFormUnload (PrivateData);
+  FreePool (PrivateData);
+
+  return Status;
+}
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
new file mode 100644
index 0000000..19f095e
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
@@ -0,0 +1,73 @@
+## @file
+#  Provides the capability to configure Tls Authentication in a setup browser
+#  By this module, user may change the content of TlsCaCertificate.
+#
+# 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.
+#
+##
+
+[Defines]
+  INF_VERSION               = 0x00010005
+  BASE_NAME                 = TlsAuthConfigDxe
+  MODULE_UNI_FILE           = TlsAuthConfigDxe.uni
+  FILE_GUID                 = 7ca1024f-eb17-11e5-9dba-28d2447c4829
+  MODULE_TYPE               = DXE_DRIVER
+  VERSION_STRING            = 1.0
+  ENTRY_POINT               = TlsAuthConfigDxeDriverEntryPoint
+  UNLOAD_IMAGE              = TlsAuthConfigDxeUnload
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+  
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  NetworkPkg/NetworkPkg.dec
+
+[Sources]
+  TlsAuthConfigImpl.c
+  TlsAuthConfigImpl.h
+  TlsAuthConfigNvData.h
+  TlsAuthConfigDxe.c
+  TlsAuthConfigDxeStrings.uni
+  TlsAuthConfigVfr.vfr
+
+[LibraryClasses]
+  BaseLib
+  BaseMemoryLib
+  MemoryAllocationLib
+  UefiLib
+  UefiBootServicesTableLib
+  UefiRuntimeServicesTableLib
+  UefiDriverEntryPoint
+  DebugLib
+  HiiLib
+  DevicePathLib
+  UefiHiiServicesLib
+  FileExplorerLib
+  PrintLib
+  
+[Protocols]
+  gEfiDevicePathProtocolGuid                    ## PRODUCES
+  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
+  gEfiSimpleFileSystemProtocolGuid              ## SOMETIMES_CONSUMES
+
+[Guids]
+  gTlsAuthConfigGuid                            ## PRODUCES  ## GUID
+  gEfiCertX509Guid                              ## CONSUMES  ## GUID  # Indicate the cert type
+  gEfiIfrTianoGuid                              ## CONSUMES  ## HII
+  gEfiTlsCaCertificateGuid                      ## PRODUCES  ## GUID
+
+[Depex]
+  gEfiHiiConfigRoutingProtocolGuid  AND
+  gEfiHiiDatabaseProtocolGuid
+  
+[UserExtensions.TianoCore."ExtraFiles"]
+  TlsAuthConfigDxeExtra.uni
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
new file mode 100644
index 0000000..f99a14f
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
@@ -0,0 +1,21 @@
+// /** @file
+// Provides the capability to configure Tls Authentication in a setup browser
+//
+// By this module, user may change the content of TlsCaCertificate.
+//
+// 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.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Provides the capability to configure Tls Authentication in a setup browser"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "By this module, user may change the content of TlsCaCertificate."
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
new file mode 100644
index 0000000..ee4c49f
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
@@ -0,0 +1,19 @@
+// /** @file
+// TlsAuthConfigDxe Localized Strings and Content
+//
+// 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.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME 
+#language en-US 
+"TLS Auth Config DXE"
+
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
new file mode 100644
index 0000000..a8f7e43
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
@@ -0,0 +1,39 @@
+/** @file
+  String definitions for Tls Authentication Configuration form.
+
+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.
+
+**/
+
+#langdef en-US "English"
+
+#string STR_TLS_AUTH_CONFIG_TITLE                    #language en-US "Tls Auth Configuration"
+#string STR_TLS_AUTH_CONFIG_HELP                     #language en-US "Press <Enter> to select Tls Auth Configuration."
+
+#string STR_TLS_AUTH_CONFIG_SERVER_CA         		 #language en-US "Server CA Configuration"
+#string STR_TLS_AUTH_CONFIG_SERVER_CA_HELP    		 #language en-US "Press <Enter> to configure Server CA."
+#string STR_TLS_AUTH_CONFIG_CLIENT_CERT         	 #language en-US "Client Cert Configuration"
+#string STR_TLS_AUTH_CONFIG_CLIENT_CERT_HELP    	 #language en-US "Client cert configuration is unsupported currently."
+
+#string STR_TLS_AUTH_CONFIG_ENROLL_CERT              #language en-US "Enroll Cert"    
+#string STR_TLS_AUTH_CONFIG_ENROLL_CERT_HELP         #language en-US "Press <Enter> to enroll cert."
+#string STR_TLS_AUTH_CONFIG_DELETE_CERT              #language en-US "Delete Cert"    
+#string STR_TLS_AUTH_CONFIG_DELETE_CERT_HELP         #language en-US "Press <Enter> to delete cert."
+
+#string STR_TLS_AUTH_CONFIG_ADD_CERT_FILE            #language en-US "Enroll Cert Using File"
+
+#string STR_TLS_AUTH_CONFIG_CERT_GUID                #language en-US "Cert GUID"
+#string STR_TLS_AUTH_CONFIG_CERT_GUID_HELP           #language en-US "Input digit character in 11111111-2222-3333-4444-1234567890ab format."
+#string STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT            #language en-US "Commit Changes and Exit"
+#string STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT         #language en-US "Discard Changes and Exit"
+
+#string STR_CERT_TYPE_PCKS_GUID                      #language en-US "GUID for CERT"
+
+#string STR_NULL                                     #language en-US ""
\ No newline at end of file
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
new file mode 100644
index 0000000..1132cac
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
@@ -0,0 +1,1841 @@
+/** @file
+  The Miscellaneous Routines for TlsAuthConfigDxe 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.
+
+**/
+
+#include "TlsAuthConfigImpl.h"
+
+VOID                    *mStartOpCodeHandle = NULL;
+VOID                    *mEndOpCodeHandle   = NULL;
+EFI_IFR_GUID_LABEL      *mStartLabel        = NULL;
+EFI_IFR_GUID_LABEL      *mEndLabel          = NULL;
+
+
+CHAR16                  mTlsAuthConfigStorageName[] = L"TLS_AUTH_CONFIG_IFR_NVDATA";
+
+TLS_AUTH_CONFIG_PRIVATE_DATA      *mTlsAuthPrivateData = NULL;
+
+HII_VENDOR_DEVICE_PATH  mTlsAuthConfigHiiVendorDevicePath = {
+  {
+    {
+      HARDWARE_DEVICE_PATH,
+      HW_VENDOR_DP,
+      {
+        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+      }
+    },
+    TLS_AUTH_CONFIG_GUID
+  },
+  {
+    END_DEVICE_PATH_TYPE,
+    END_ENTIRE_DEVICE_PATH_SUBTYPE,
+    {
+      (UINT8) (END_DEVICE_PATH_LENGTH),
+      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+    }
+  }
+};
+
+//
+// Possible DER-encoded certificate file suffixes, end with NULL pointer.
+//
+CHAR16* mDerPemEncodedSuffix[] = {
+  L".cer",
+  L".der",
+  L".crt",
+  L".pem",
+  NULL
+};
+
+/**
+  This code checks if the FileSuffix is one of the possible DER/PEM-encoded certificate suffix.
+
+  @param[in] FileSuffix            The suffix of the input certificate file
+
+  @retval    TRUE           It's a DER/PEM-encoded certificate.
+  @retval    FALSE          It's NOT a DER/PEM-encoded certificate.
+
+**/
+BOOLEAN
+IsDerPemEncodeCertificate (
+  IN CONST CHAR16         *FileSuffix
+)
+{
+  UINTN     Index;
+  for (Index = 0; mDerPemEncodedSuffix[Index] != NULL; Index++) {
+    if (StrCmp (FileSuffix, mDerPemEncodedSuffix[Index]) == 0) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}
+
+/**
+  Worker function that prints an EFI_GUID into specified Buffer.
+
+  @param[in]     Guid          Pointer to GUID to print.
+  @param[in]     Buffer        Buffer to print Guid into.
+  @param[in]     BufferSize    Size of Buffer.
+  
+  @retval    Number of characters printed.
+
+**/
+UINTN
+GuidToString (
+  IN  EFI_GUID  *Guid,
+  IN  CHAR16    *Buffer,
+  IN  UINTN     BufferSize
+  )
+{
+  UINTN Size;
+
+  Size = UnicodeSPrint (
+            Buffer,
+            BufferSize, 
+            L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+            (UINTN)Guid->Data1,                    
+            (UINTN)Guid->Data2,
+            (UINTN)Guid->Data3,
+            (UINTN)Guid->Data4[0],
+            (UINTN)Guid->Data4[1],
+            (UINTN)Guid->Data4[2],
+            (UINTN)Guid->Data4[3],
+            (UINTN)Guid->Data4[4],
+            (UINTN)Guid->Data4[5],
+            (UINTN)Guid->Data4[6],
+            (UINTN)Guid->Data4[7]
+            );
+
+  //
+  // SPrint will null terminate the string. The -1 skips the null
+  //
+  return Size - 1;
+}
+
+/**
+  Convert a String to Guid Value.
+
+  @param[in]   Str        Specifies the String to be converted.
+  @param[in]   StrLen     Number of Unicode Characters of String (exclusive \0)
+  @param[out]  Guid       Return the result Guid value.
+
+  @retval    EFI_SUCCESS           The operation is finished successfully.
+  @retval    EFI_NOT_FOUND         Invalid string.
+
+**/
+EFI_STATUS
+StringToGuid (
+  IN   CHAR16           *Str, 
+  IN   UINTN            StrLen, 
+  OUT  EFI_GUID         *Guid
+  )
+{
+  CHAR16             *PtrBuffer;
+  CHAR16             *PtrPosition;
+  UINT16             *Buffer;
+  UINTN              Data;
+  UINTN              Index;
+  UINT16             Digits[3];
+
+  Buffer = (CHAR16 *) AllocateZeroPool (sizeof (CHAR16) * (StrLen + 1));
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  StrCpyS (Buffer, (StrLen + 1), Str);
+
+  //
+  // Data1
+  //
+  PtrBuffer       = Buffer;
+  PtrPosition     = PtrBuffer; 
+  while (*PtrBuffer != L'\0') {
+    if (*PtrBuffer == L'-') {
+      break;
+    }
+    PtrBuffer++;
+  }
+  if (*PtrBuffer == L'\0') {
+    FreePool (Buffer);
+    return EFI_NOT_FOUND;
+  }
+
+  *PtrBuffer      = L'\0';
+  Data            = StrHexToUintn (PtrPosition);
+  Guid->Data1     = (UINT32)Data;
+
+  //
+  // Data2
+  //
+  PtrBuffer++;
+  PtrPosition     = PtrBuffer;
+  while (*PtrBuffer != L'\0') {
+    if (*PtrBuffer == L'-') {
+      break;
+    }
+    PtrBuffer++;
+  }
+  if (*PtrBuffer == L'\0') {
+    FreePool (Buffer);
+    return EFI_NOT_FOUND;
+  }
+  *PtrBuffer      = L'\0';
+  Data            = StrHexToUintn (PtrPosition);
+  Guid->Data2     = (UINT16)Data;
+
+  //
+  // Data3
+  //
+  PtrBuffer++;
+  PtrPosition     = PtrBuffer;
+  while (*PtrBuffer != L'\0') {
+    if (*PtrBuffer == L'-') {
+      break;
+    }
+    PtrBuffer++;
+  }
+  if (*PtrBuffer == L'\0') {
+    FreePool (Buffer);
+    return EFI_NOT_FOUND;
+  }
+  *PtrBuffer      = L'\0';
+  Data            = StrHexToUintn (PtrPosition);
+  Guid->Data3     = (UINT16)Data;
+
+  //
+  // Data4[0..1]
+  //
+  for ( Index = 0 ; Index < 2 ; Index++) {
+    PtrBuffer++;
+    if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {
+      FreePool (Buffer);
+      return EFI_NOT_FOUND;
+    }
+    Digits[0]     = *PtrBuffer;
+    PtrBuffer++;
+    Digits[1]     = *PtrBuffer;
+    Digits[2]     = L'\0';
+    Data          = StrHexToUintn (Digits);
+    Guid->Data4[Index] = (UINT8)Data;
+  }
+
+  //
+  // skip the '-'
+  //
+  PtrBuffer++;
+  if ((*PtrBuffer != L'-' ) || ( *PtrBuffer == L'\0')) {
+    return EFI_NOT_FOUND;
+  }
+
+  //
+  // Data4[2..7]
+  //
+  for ( ; Index < 8; Index++) {
+    PtrBuffer++;
+    if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {
+      FreePool (Buffer);
+      return EFI_NOT_FOUND;
+    }
+    Digits[0]     = *PtrBuffer;
+    PtrBuffer++;
+    Digits[1]     = *PtrBuffer;
+    Digits[2]     = L'\0';
+    Data          = StrHexToUintn (Digits);
+    Guid->Data4[Index] = (UINT8)Data;
+  }
+
+  FreePool (Buffer);
+  
+  return EFI_SUCCESS;
+}
+
+
+/**
+  List all cert in specified database by GUID in the page 
+  for user to select and delete as needed.
+
+  @param[in]    PrivateData         Module's private data.
+  @param[in]    VariableName        The variable name of the vendor's signature database.
+  @param[in]    VendorGuid          A unique identifier for the vendor.
+  @param[in]    LabelNumber         Label number to insert opcodes.
+  @param[in]    FormId              Form ID of current page.
+  @param[in]    QuestionIdBase      Base question id of the signature list.
+
+  @retval   EFI_SUCCESS             Success to update the signature list page
+  @retval   EFI_OUT_OF_RESOURCES    Unable to allocate required resources.
+
+**/
+EFI_STATUS
+UpdateDeletePage (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private,
+  IN CHAR16                           *VariableName,
+  IN EFI_GUID                         *VendorGuid,
+  IN UINT16                           LabelNumber,
+  IN EFI_FORM_ID                      FormId,
+  IN EFI_QUESTION_ID                  QuestionIdBase
+  )
+{
+  EFI_STATUS                  Status;
+  UINT32                      Index;
+  UINTN                       CertCount;
+  UINTN                       GuidIndex;
+  VOID                        *StartOpCodeHandle;
+  VOID                        *EndOpCodeHandle;
+  EFI_IFR_GUID_LABEL          *StartLabel;
+  EFI_IFR_GUID_LABEL          *EndLabel;
+  UINTN                       DataSize;
+  UINT8                       *Data;
+  EFI_SIGNATURE_LIST          *CertList;
+  EFI_SIGNATURE_DATA          *Cert;
+  UINT32                      ItemDataSize;
+  CHAR16                      *GuidStr;
+  EFI_STRING_ID               GuidID;
+  EFI_STRING_ID               Help;
+
+  Data     = NULL;
+  CertList = NULL;
+  Cert     = NULL;
+  GuidStr  = NULL;
+  StartOpCodeHandle = NULL;
+  EndOpCodeHandle   = NULL;
+
+  //
+  // Initialize the container for dynamic opcodes.
+  //
+  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (StartOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (EndOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Create Hii Extend Label OpCode.
+  //
+  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                        StartOpCodeHandle,
+                                        &gEfiIfrTianoGuid,
+                                        NULL,
+                                        sizeof (EFI_IFR_GUID_LABEL)
+                                        );
+  StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
+  StartLabel->Number        = LabelNumber;
+
+  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                      EndOpCodeHandle,
+                                      &gEfiIfrTianoGuid,
+                                      NULL,
+                                      sizeof (EFI_IFR_GUID_LABEL)
+                                      );
+  EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
+  EndLabel->Number        = LABEL_END;
+
+  //
+  // Read Variable.
+  //
+  DataSize = 0;
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+    goto ON_EXIT;
+  }
+
+  Data = (UINT8 *) AllocateZeroPool (DataSize);
+  if (Data == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  GuidStr = AllocateZeroPool (100);
+  if (GuidStr == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Enumerate all data.
+  //
+  ItemDataSize = (UINT32) DataSize;
+  CertList = (EFI_SIGNATURE_LIST *) Data;
+  GuidIndex = 0;
+
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
+      Help = STRING_TOKEN (STR_CERT_TYPE_PCKS_GUID);
+    } else {
+      //
+      // The signature type is not supported in current implementation.
+      //
+      ItemDataSize -= CertList->SignatureListSize;
+      CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+      continue;
+    }
+
+    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+    for (Index = 0; Index < CertCount; Index++) {
+      Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList
+                                              + sizeof (EFI_SIGNATURE_LIST)
+                                              + CertList->SignatureHeaderSize
+                                              + Index * CertList->SignatureSize);
+      //
+      // Display GUID and help
+      //
+      GuidToString (&Cert->SignatureOwner, GuidStr, 100);
+      GuidID  = HiiSetString (Private->RegisteredHandle, 0, GuidStr, NULL);
+      HiiCreateCheckBoxOpCode (
+        StartOpCodeHandle,
+        (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),
+        0,
+        0,
+        GuidID,
+        Help,
+        EFI_IFR_FLAG_CALLBACK,
+        0,
+        NULL
+        );
+    }
+
+    ItemDataSize -= CertList->SignatureListSize;
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+  }
+
+ON_EXIT:
+  HiiUpdateForm (
+    Private->RegisteredHandle,
+    &gTlsAuthConfigGuid,
+    FormId,
+    StartOpCodeHandle,
+    EndOpCodeHandle
+    );
+
+  if (StartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (StartOpCodeHandle);
+  }
+
+  if (EndOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (EndOpCodeHandle);
+  }
+
+  if (Data != NULL) {
+    FreePool (Data);
+  }
+
+  if (GuidStr != NULL) {
+    FreePool (GuidStr);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Delete one entry from cert database.
+
+  @param[in]    PrivateData         Module's private data.
+  @param[in]    VariableName        The variable name of the database.
+  @param[in]    VendorGuid          A unique identifier for the vendor.
+  @param[in]    LabelNumber         Label number to insert opcodes.
+  @param[in]    FormId              Form ID of current page.
+  @param[in]    QuestionIdBase      Base question id of the cert list.
+  @param[in]    DeleteIndex         Cert index to delete.
+
+  @retval   EFI_SUCCESS             Delete siganture successfully.
+  @retval   EFI_NOT_FOUND           Can't find the signature item,
+  @retval   EFI_OUT_OF_RESOURCES    Could not allocate needed resources.
+**/
+EFI_STATUS
+DeleteCert (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private,
+  IN CHAR16                           *VariableName,
+  IN EFI_GUID                         *VendorGuid,
+  IN UINT16                           LabelNumber,
+  IN EFI_FORM_ID                      FormId,
+  IN EFI_QUESTION_ID                  QuestionIdBase,
+  IN UINTN                            DeleteIndex
+  )
+{
+  EFI_STATUS                  Status;
+  UINTN                       DataSize;
+  UINT8                       *Data;
+  UINT8                       *OldData;
+  UINT32                      Attr;
+  UINT32                      Index;
+  EFI_SIGNATURE_LIST          *CertList;
+  EFI_SIGNATURE_LIST          *NewCertList;
+  EFI_SIGNATURE_DATA          *Cert;
+  UINTN                       CertCount;
+  UINT32                      Offset;
+  BOOLEAN                     IsItemFound;
+  UINT32                      ItemDataSize;
+  UINTN                       GuidIndex;
+
+  Data            = NULL;
+  OldData         = NULL;
+  CertList        = NULL;
+  Cert            = NULL;
+  Attr            = 0;
+
+  //
+  // Get original signature list data.
+  //
+  DataSize = 0;
+  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL);
+  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
+    goto ON_EXIT;
+  }
+
+  OldData = (UINT8 *) AllocateZeroPool (DataSize);
+  if (OldData == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData);
+  if (EFI_ERROR(Status)) {
+    goto ON_EXIT;
+  }
+
+  //
+  // Allocate space for new variable.
+  //
+  Data = (UINT8*) AllocateZeroPool (DataSize);
+  if (Data == NULL) {
+    Status  =  EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Enumerate all data and erasing the target item.
+  //
+  IsItemFound = FALSE;
+  ItemDataSize = (UINT32) DataSize;
+  CertList = (EFI_SIGNATURE_LIST *) OldData;
+  Offset = 0;
+  GuidIndex = 0;
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
+      //
+      // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list.
+      //
+      CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize));
+      NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);
+      Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize);
+      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++) {
+        if (GuidIndex == DeleteIndex) {
+          //
+          // Find it! Skip it!
+          //
+          NewCertList->SignatureListSize -= CertList->SignatureSize;
+          IsItemFound = TRUE;
+        } else {
+          //
+          // This item doesn't match. Copy it to the Data buffer.
+          //
+          CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);
+          Offset += CertList->SignatureSize;
+        }
+        GuidIndex++;
+        Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize);
+      }
+    } else {
+      //
+      // This List doesn't match. Just copy it to the Data buffer.
+      //
+      CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
+      Offset += CertList->SignatureListSize;
+    }
+
+    ItemDataSize -= CertList->SignatureListSize;
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+  }
+
+  if (!IsItemFound) {
+    //
+    // Doesn't find the signature Item!
+    //
+    Status = EFI_NOT_FOUND;
+    goto ON_EXIT;
+  }
+
+  //
+  // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list.
+  //
+  ItemDataSize = Offset;
+  CertList = (EFI_SIGNATURE_LIST *) Data;
+  Offset = 0;
+  ZeroMem (OldData, ItemDataSize);
+  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) {
+    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize;
+    DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));
+    if (CertCount != 0) {
+      CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize);
+      Offset += CertList->SignatureListSize;
+    }
+    ItemDataSize -= CertList->SignatureListSize;
+    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize);
+  }
+
+  DataSize = Offset;
+
+  Status = gRT->SetVariable(
+                  VariableName,
+                  VendorGuid,
+                  Attr,
+                  DataSize,
+                  OldData
+                  );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+  if (Data != NULL) {
+    FreePool(Data);
+  }
+
+  if (OldData != NULL) {
+    FreePool(OldData);
+  }
+
+  return UpdateDeletePage (
+           Private,
+           VariableName,
+           VendorGuid,
+           LabelNumber,
+           FormId,
+           QuestionIdBase
+           );
+}
+
+
+/**
+  Close an open file handle.
+
+  @param[in] FileHandle           The file handle to close.
+  
+**/
+VOID
+CloseFile (
+  IN EFI_FILE_HANDLE   FileHandle
+  )
+{
+  if (FileHandle != NULL) {
+    FileHandle->Close (FileHandle);  
+  }
+}
+
+/**
+  Read file content into BufferPtr, the size of the allocate buffer 
+  is *FileSize plus AddtionAllocateSize.
+
+  @param[in]       FileHandle            The file to be read.
+  @param[in, out]  BufferPtr             Pointers to the pointer of allocated buffer.
+  @param[out]      FileSize              Size of input file
+  @param[in]       AddtionAllocateSize   Addtion size the buffer need to be allocated. 
+                                         In case the buffer need to contain others besides the file content.
+  
+  @retval   EFI_SUCCESS                  The file was read into the buffer.
+  @retval   EFI_INVALID_PARAMETER        A parameter was invalid.
+  @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.
+  @retval   others                       Unexpected error.
+
+**/
+EFI_STATUS
+ReadFileContent (
+  IN      EFI_FILE_HANDLE           FileHandle,
+  IN OUT  VOID                      **BufferPtr,
+     OUT  UINTN                     *FileSize,
+  IN      UINTN                     AddtionAllocateSize
+  )
+
+{
+  UINTN      BufferSize;
+  UINT64     SourceFileSize;
+  VOID       *Buffer;
+  EFI_STATUS Status;
+
+  if ((FileHandle == NULL) || (FileSize == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Buffer = NULL;
+
+  //
+  // Get the file size
+  //
+  Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+  
+  Status = FileHandle->SetPosition (FileHandle, 0);
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+  BufferSize = (UINTN) SourceFileSize + AddtionAllocateSize;
+  Buffer =  AllocateZeroPool(BufferSize);
+  if (Buffer == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  BufferSize = (UINTN) SourceFileSize;
+  *FileSize  = BufferSize;
+
+  Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
+  if (EFI_ERROR (Status) || BufferSize != *FileSize) {
+    FreePool (Buffer);
+    Buffer = NULL;
+    Status  = EFI_BAD_BUFFER_SIZE;
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+  
+  *BufferPtr = Buffer;
+  return Status;
+}
+
+/**
+  This function will open a file or directory referenced by DevicePath.
+
+  This function opens a file with the open mode according to the file path. The
+  Attributes is valid only for EFI_FILE_MODE_CREATE.
+
+  @param[in, out]  FilePath        On input, the device path to the file.
+                                   On output, the remaining device path.
+  @param[out]      FileHandle      Pointer to the file handle.
+  @param[in]       OpenMode        The mode to open the file with.
+  @param[in]       Attributes      The file's file attributes.
+
+  @retval EFI_SUCCESS              The information was set.
+  @retval EFI_INVALID_PARAMETER    One of the parameters has an invalid value.
+  @retval EFI_UNSUPPORTED          Could not open the file path.
+  @retval EFI_NOT_FOUND            The specified file could not be found on the
+                                   device or the file system could not be found on
+                                   the device.
+  @retval EFI_NO_MEDIA             The device has no medium.
+  @retval EFI_MEDIA_CHANGED        The device has a different medium in it or the
+                                   medium is no longer supported.
+  @retval EFI_DEVICE_ERROR         The device reported an error.
+  @retval EFI_VOLUME_CORRUPTED     The file system structures are corrupted.
+  @retval EFI_WRITE_PROTECTED      The file or medium is write protected.
+  @retval EFI_ACCESS_DENIED        The file was opened read only.
+  @retval EFI_OUT_OF_RESOURCES     Not enough resources were available to open the
+                                   file.
+  @retval EFI_VOLUME_FULL          The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+OpenFileByDevicePath (
+  IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,
+  OUT EFI_FILE_HANDLE                 *FileHandle,
+  IN UINT64                           OpenMode,
+  IN UINT64                           Attributes
+  )
+{
+  EFI_STATUS                      Status;
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
+  EFI_FILE_PROTOCOL               *Handle1;
+  EFI_FILE_PROTOCOL               *Handle2;
+  EFI_HANDLE                      DeviceHandle;
+
+  if ((FilePath == NULL || FileHandle == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  Status = gBS->LocateDevicePath (
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  FilePath,
+                  &DeviceHandle
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = gBS->OpenProtocol(
+                  DeviceHandle,
+                  &gEfiSimpleFileSystemProtocolGuid,
+                  (VOID**)&EfiSimpleFileSystemProtocol,
+                  gImageHandle,
+                  NULL,
+                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
+  if (EFI_ERROR (Status)) {
+    FileHandle = NULL;
+    return Status;
+  }
+
+  //
+  // go down directories one node at a time.
+  //
+  while (!IsDevicePathEnd (*FilePath)) {
+    //
+    // For file system access each node should be a file path component
+    //
+    if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
+        DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
+       ) {
+      FileHandle = NULL;
+      return (EFI_INVALID_PARAMETER);
+    }
+    //
+    // Open this file path node
+    //
+    Handle2  = Handle1;
+    Handle1 = NULL;
+
+    //
+    // Try to test opening an existing file
+    //
+    Status = Handle2->Open (
+                        Handle2,
+                        &Handle1,
+                        ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
+                        OpenMode &~EFI_FILE_MODE_CREATE,
+                        0
+                        );
+
+    //
+    // see if the error was that it needs to be created
+    //
+    if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
+      Status = Handle2->Open (
+                          Handle2,
+                          &Handle1,
+                          ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
+                          OpenMode,
+                          Attributes
+                          );
+    }
+    //
+    // Close the last node
+    //
+    Handle2->Close (Handle2);
+
+    if (EFI_ERROR(Status)) {
+      return (Status);
+    }
+
+    //
+    // Get the next node
+    //
+    *FilePath = NextDevicePathNode (*FilePath);
+  }
+
+  //
+  // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
+  //
+  *FileHandle = (VOID*)Handle1;
+  return EFI_SUCCESS;
+}
+
+/**
+  This function converts an input device structure to a Unicode string.
+
+  @param[in] DevPath                  A pointer to the device path structure.
+
+  @return A new allocated Unicode string that represents the device path.
+
+**/
+CHAR16 *
+EFIAPI
+DevicePathToStr (
+  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
+  )
+{
+  return ConvertDevicePathToText (
+           DevPath,
+           FALSE,
+           TRUE
+           );
+}
+
+
+/**
+  Extract filename from device path. The returned buffer is allocated using AllocateCopyPool.
+  The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL
+  means not enough memory resource.
+
+  @param DevicePath       Device path.
+
+  @retval NULL            Not enough memory resourece for AllocateCopyPool.
+  @retval Other           A new allocated string that represents the file name.
+
+**/
+CHAR16 *
+ExtractFileNameFromDevicePath (
+  IN   EFI_DEVICE_PATH_PROTOCOL *DevicePath
+  )
+{
+  CHAR16          *String;
+  CHAR16          *MatchString;
+  CHAR16          *LastMatch;
+  CHAR16          *FileName;
+  UINTN           Length;
+
+  ASSERT(DevicePath != NULL);
+
+  String = DevicePathToStr(DevicePath);
+  MatchString = String;
+  LastMatch   = String;
+  FileName    = NULL;
+
+  while(MatchString != NULL){
+    LastMatch   = MatchString + 1;
+    MatchString = StrStr(LastMatch,L"\\");
+  }
+
+  Length = StrLen(LastMatch);
+  FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
+  if (FileName != NULL) {
+    *(FileName + Length) = 0;
+  }
+
+  FreePool(String);
+
+  return FileName;
+}
+
+/**
+  Enroll a new X509 certificate into Variable.
+
+  @param[in] PrivateData     The module's private data.
+  @param[in] VariableName    Variable name of CA database.
+
+  @retval   EFI_SUCCESS            New X509 is enrolled successfully.
+  @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
+
+**/
+EFI_STATUS
+EnrollX509toVariable (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA   *Private,
+  IN CHAR16                         *VariableName
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             X509DataSize;
+  VOID                              *X509Data;
+  EFI_SIGNATURE_LIST                *CACert;
+  EFI_SIGNATURE_DATA                *CACertData;
+  VOID                              *Data;
+  UINTN                             DataSize;
+  UINTN                             SigDataSize;
+  UINT32                            Attr;
+
+  X509DataSize  = 0;
+  SigDataSize   = 0;
+  DataSize      = 0;
+  X509Data      = NULL;
+  CACert        = NULL;
+  CACertData    = NULL;
+  Data          = NULL;
+
+  Status = ReadFileContent (
+             Private->FileContext->FHandle,
+             &X509Data,
+             &X509DataSize,
+             0
+             );
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+  ASSERT (X509Data != NULL);
+
+  SigDataSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize;
+
+  Data = AllocateZeroPool (SigDataSize);
+  if (Data == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto ON_EXIT;
+  }
+
+  //
+  // Fill Certificate Database parameters.
+  //
+  CACert = (EFI_SIGNATURE_LIST*) Data;
+  CACert->SignatureListSize   = (UINT32) SigDataSize;
+  CACert->SignatureHeaderSize = 0;
+  CACert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize);
+  CopyGuid (&CACert->SignatureType, &gEfiCertX509Guid);
+
+  CACertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) CACert + sizeof (EFI_SIGNATURE_LIST));
+  CopyGuid (&CACertData->SignatureOwner, Private->CertGuid);
+  CopyMem ((UINT8* ) (CACertData->SignatureData), X509Data, X509DataSize);
+
+  //
+  // Check if signature database entry has been already existed.
+  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
+  // new signature data to original variable
+  //
+  Attr = TLS_AUTH_CONFIG_VAR_BASE_ATTR;
+
+  Status = gRT->GetVariable(
+                  VariableName,
+                  &gEfiTlsCaCertificateGuid,
+                  NULL,
+                  &DataSize,
+                  NULL
+                  );
+  if (Status == EFI_BUFFER_TOO_SMALL) {
+    Attr |= EFI_VARIABLE_APPEND_WRITE;
+  } else if (Status != EFI_NOT_FOUND) {
+    goto ON_EXIT;
+  }
+
+  Status = gRT->SetVariable(
+                  VariableName,
+                  &gEfiTlsCaCertificateGuid,
+                  Attr,
+                  SigDataSize,
+                  Data
+                  );
+  if (EFI_ERROR (Status)) {
+    goto ON_EXIT;
+  }
+
+ON_EXIT:
+
+  CloseFile (Private->FileContext->FHandle);
+  if (Private->FileContext->FileName != NULL) {
+    FreePool(Private->FileContext->FileName);
+    Private->FileContext->FileName = NULL;
+  }
+
+  Private->FileContext->FHandle = NULL;
+
+  if (Private->CertGuid != NULL) {
+    FreePool (Private->CertGuid);
+    Private->CertGuid = NULL;
+  }
+
+  if (Data != NULL) {
+    FreePool (Data);
+  }
+
+  if (X509Data != NULL) {
+    FreePool (X509Data);
+  }
+
+  return Status;
+}
+
+/**
+  Enroll Cert into TlsCaCertificate. The GUID will be Private->CertGuid.
+
+  @param[in] PrivateData     The module's private data.
+  @param[in] VariableName    Variable name of signature database.
+
+  @retval   EFI_SUCCESS            New Cert enrolled successfully.
+  @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
+  @retval   EFI_UNSUPPORTED        The Cert file is unsupported type.
+  @retval   others                 Fail to enroll Cert data.
+
+**/
+EFI_STATUS
+EnrollCertDatabase (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA  *Private,
+  IN CHAR16                        *VariableName
+  )
+{
+  UINT16*      FilePostFix;
+  UINTN        NameLength;
+
+  if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->CertGuid == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Parse the file's postfix.
+  //
+  NameLength = StrLen (Private->FileContext->FileName);
+  if (NameLength <= 4) {
+    return EFI_INVALID_PARAMETER;
+  }
+  FilePostFix = Private->FileContext->FileName + NameLength - 4;
+
+  if (IsDerPemEncodeCertificate (FilePostFix)) {
+    //
+    // Supports DER-encoded X509 certificate.
+    //
+    return EnrollX509toVariable (Private, VariableName);
+  }
+
+  return EFI_UNSUPPORTED;
+}
+
+/**
+  Refresh the global UpdateData structure.
+
+**/
+VOID
+RefreshUpdateData (
+  VOID
+  )
+{
+  //
+  // Free current updated date
+  //
+  if (mStartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mStartOpCodeHandle);
+  }
+
+  //
+  // Create new OpCode Handle
+  //
+  mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                         mStartOpCodeHandle,
+                                         &gEfiIfrTianoGuid,
+                                         NULL,
+                                         sizeof (EFI_IFR_GUID_LABEL)
+                                         );
+  mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+}
+
+/**
+  Clean up the dynamic opcode at label and form specified by both LabelId.
+
+  @param[in] LabelId         It is both the Form ID and Label ID for opcode deletion.
+  @param[in] PrivateData     Module private data.
+
+**/
+VOID
+CleanUpPage (
+  IN UINT16                           LabelId,
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *PrivateData
+  )
+{
+  RefreshUpdateData ();
+
+  //
+  // Remove all op-codes from dynamic page
+  //
+  mStartLabel->Number = LabelId;
+  HiiUpdateForm (
+    PrivateData->RegisteredHandle,
+    &gTlsAuthConfigGuid,
+    LabelId,
+    mStartOpCodeHandle, // Label LabelId
+    mEndOpCodeHandle    // LABEL_END
+    );
+}
+
+/**
+  Update the form base on the selected file.
+
+  @param FilePath   Point to the file path.
+  @param FormId     The form need to display.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+
+**/
+BOOLEAN
+UpdatePage(
+  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
+  IN  EFI_FORM_ID               FormId
+  )
+{
+  CHAR16                *FileName;
+  EFI_STRING_ID         StringToken;
+
+  FileName = NULL;
+
+  if (FilePath != NULL) {
+    FileName = ExtractFileNameFromDevicePath(FilePath);
+  }
+  if (FileName == NULL) {
+    //
+    // FileName = NULL has two case:
+    // 1. FilePath == NULL, not select file.
+    // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource.
+    // In these two case, no need to update the form, and exit the caller function.
+    //
+    return TRUE;
+  }
+  StringToken =  HiiSetString (mTlsAuthPrivateData->RegisteredHandle, 0, FileName, NULL);
+
+  mTlsAuthPrivateData->FileContext->FileName = FileName;
+
+  OpenFileByDevicePath (
+    &FilePath,
+    &mTlsAuthPrivateData->FileContext->FHandle,
+    EFI_FILE_MODE_READ,
+    0
+    );
+  //
+  // Create Subtitle op-code for the display string of the option.
+  //
+  RefreshUpdateData ();
+  mStartLabel->Number = FormId;
+
+  HiiCreateSubTitleOpCode (
+    mStartOpCodeHandle,
+    StringToken,
+    0,
+    0,
+    0
+   );
+
+  HiiUpdateForm (
+    mTlsAuthPrivateData->RegisteredHandle,
+    &gTlsAuthConfigGuid,
+    FormId,
+    mStartOpCodeHandle, /// Label FormId
+    mEndOpCodeHandle    /// LABEL_END
+    );
+
+  return TRUE;
+}
+
+/**
+  Update the form base on the input file path info.
+
+  @param FilePath    Point to the file path.
+
+  @retval TRUE   Exit caller function.
+  @retval FALSE  Not exit caller function.
+**/
+BOOLEAN
+UpdateCAFromFile (
+  IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
+  )
+{
+  return UpdatePage(FilePath, TLS_AUTH_CONFIG_FORMID4_FORM);
+}
+
+/**
+  Unload the configuration form, this includes: delete all the configuration
+  entries, uninstall the form callback protocol, and free the resources used.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is unloaded.
+  @retval Others                  Failed to unload the form.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormUnload (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  )
+{
+  if (Private->DriverHandle != NULL) {
+    //
+    // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
+    //
+    gBS->UninstallMultipleProtocolInterfaces (
+           Private->DriverHandle,
+           &gEfiDevicePathProtocolGuid,
+           &mTlsAuthConfigHiiVendorDevicePath,
+           &gEfiHiiConfigAccessProtocolGuid,
+           &Private->ConfigAccess,
+           NULL
+           );
+    Private->DriverHandle = NULL;
+  }
+
+  if (Private->RegisteredHandle != NULL) {
+    //
+    // Remove HII package list
+    //
+    HiiRemovePackages (Private->RegisteredHandle);
+    Private->RegisteredHandle = NULL;
+  }
+
+  if (Private->CertGuid != NULL) {
+    FreePool (Private->CertGuid);
+  }
+
+  if (Private->FileContext != NULL) {
+    FreePool (Private->FileContext);
+  }
+
+  FreePool (Private);
+
+  if (mStartOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mStartOpCodeHandle);
+  }
+
+  if (mEndOpCodeHandle != NULL) {
+    HiiFreeOpCodeHandle (mEndOpCodeHandle);
+  }
+
+  return EFI_SUCCESS;
+}
+
+
+/**
+  Initialize the configuration form.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is initialized.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormInit (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  )
+{
+  EFI_STATUS                        Status;
+
+  Private->Signature = TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE;
+  
+  Private->ConfigAccess.ExtractConfig = TlsAuthConfigAccessExtractConfig;
+  Private->ConfigAccess.RouteConfig   = TlsAuthConfigAccessRouteConfig;
+  Private->ConfigAccess.Callback      = TlsAuthConfigAccessCallback;
+
+  //
+  // Install Device Path Protocol and Config Access protocol to driver handle.
+  //
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Private->DriverHandle,
+                  &gEfiDevicePathProtocolGuid,
+                  &mTlsAuthConfigHiiVendorDevicePath,
+                  &gEfiHiiConfigAccessProtocolGuid,
+                  &Private->ConfigAccess,
+                  NULL
+                  );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+  
+  //
+  // Publish our HII data.
+  //
+  Private->RegisteredHandle = HiiAddPackages (
+                                &gTlsAuthConfigGuid,
+                                Private->DriverHandle,
+                                TlsAuthConfigDxeStrings,
+                                TlsAuthConfigVfrBin,
+                                NULL
+                                );
+  if (Private->RegisteredHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  Private->FileContext = AllocateZeroPool (sizeof (TLS_AUTH_CONFIG_FILE_CONTEXT));
+  if (Private->FileContext == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  //
+  // Init OpCode Handle and Allocate space for creation of Buffer
+  //
+  mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (mStartOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
+  if (mEndOpCodeHandle == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Error;
+  }
+
+  //
+  // Create Hii Extend Label OpCode as the start opcode
+  //
+  mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                         mStartOpCodeHandle,
+                                         &gEfiIfrTianoGuid,
+                                         NULL,
+                                         sizeof (EFI_IFR_GUID_LABEL)
+                                         );
+  mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+
+  //
+  // Create Hii Extend Label OpCode as the end opcode
+  //
+  mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
+                                       mEndOpCodeHandle,
+                                       &gEfiIfrTianoGuid,
+                                       NULL,
+                                       sizeof (EFI_IFR_GUID_LABEL)
+                                       );
+  mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
+  mEndLabel->Number       = LABEL_END;
+
+  return EFI_SUCCESS;
+  
+Error:
+  TlsAuthConfigFormUnload (Private);
+  return Status;
+}
+
+/**
+   
+  This function allows the caller to request the current
+  configuration for one or more named elements. The resulting
+  string is in <ConfigAltResp> format. Any and all alternative
+  configuration strings shall also be appended to the end of the
+  current configuration string. If they are, they must appear
+  after the current configuration. They must contain the same
+  routing (GUID, NAME, PATH) as the current configuration string.
+  They must have an additional description indicating the type of
+  alternative configuration the string represents,
+  "ALTCFG=<StringToken>". That <StringToken> (when
+  converted from Hex UNICODE to binary) is a reference to a
+  string in the associated string pack.
+
+  @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Request    A null-terminated Unicode string in
+                    <ConfigRequest> format. Note that this
+                    includes the routing information as well as
+                    the configurable name / value pairs. It is
+                    invalid for this string to be in
+                    <MultiConfigRequest> format. 
+                    If a NULL is passed in for the Request field, 
+                    all of the settings being abstracted by this function 
+                    will be returned in the Results field.  In addition, 
+                    if a ConfigHdr is passed in with no request elements, 
+                    all of the settings being abstracted for that particular 
+                    ConfigHdr reference will be returned in the Results Field.
+
+  @param Progress   On return, points to a character in the
+                    Request string. Points to the string's null
+                    terminator if request was successful. Points
+                    to the most recent "&" before the first
+                    failing name / value pair (or the beginning
+                    of the string if the failure is in the first
+                    name / value pair) if the request was not
+                    successful.
+
+  @param Results    A null-terminated Unicode string in
+                    <MultiConfigAltResp> format which has all values
+                    filled in for the names in the Request string.
+                    String to be allocated by the called function.
+
+  @retval EFI_SUCCESS             The Results string is filled with the
+                                  values corresponding to all requested
+                                  names.
+
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+
+  @retval EFI_NOT_FOUND           Routing data doesn't match any
+                                  known driver. Progress set to the
+                                  first character in the routing header.
+                                  Note: There is no requirement that the
+                                  driver validate the routing data. It
+                                  must skip the <ConfigHdr> in order to
+                                  process the names.
+
+  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
+                                  to most recent "&" before the
+                                  error or the beginning of the
+                                  string.
+
+  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
+                                  to the & before the name in
+                                  question.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessExtractConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Request,
+  OUT       EFI_STRING                      *Progress,
+  OUT       EFI_STRING                      *Results
+  )
+{
+  EFI_STATUS                        Status;
+  UINTN                             BufferSize;
+  UINTN                             Size;
+  EFI_STRING                        ConfigRequest;
+  EFI_STRING                        ConfigRequestHdr;
+  TLS_AUTH_CONFIG_PRIVATE_DATA      *Private;
+  BOOLEAN                           AllocatedRequest;
+
+  if (Progress == NULL || Results == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  AllocatedRequest = FALSE;
+  ConfigRequestHdr = NULL;
+  ConfigRequest    = NULL;
+  Size             = 0;
+
+  Private          = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
+
+  BufferSize       = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+  ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
+  
+  *Progress        = Request;
+
+  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+  
+  ConfigRequest = Request;
+  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
+    //
+    // Request is set to NULL or OFFSET is NULL, construct full request string.
+    //
+    // Allocate and fill a buffer large enough to hold the <ConfigHdr> template
+    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator
+    //
+    ConfigRequestHdr = HiiConstructConfigHdr (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, Private->DriverHandle);
+    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
+    ConfigRequest = AllocateZeroPool (Size);
+    ASSERT (ConfigRequest != NULL);
+    AllocatedRequest = TRUE;
+    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize);
+    FreePool (ConfigRequestHdr);
+    ConfigRequestHdr = NULL;
+  }
+
+  Status = gHiiConfigRouting->BlockToConfig (
+                                gHiiConfigRouting,
+                                ConfigRequest,
+                                (UINT8 *) &Private->TlsAuthConfigNvData,
+                                BufferSize,
+                                Results,
+                                Progress
+                                );
+
+  //
+  // Free the allocated config request string.
+  //
+  if (AllocatedRequest) {
+    FreePool (ConfigRequest);
+  }
+
+  //
+  // Set Progress string to the original request string.
+  //
+  if (Request == NULL) {
+    *Progress = NULL;
+  } else if (StrStr (Request, L"OFFSET") == NULL) {
+    *Progress = Request + StrLen (Request);
+  }
+
+  return Status;
+}
+
+/**
+   
+  This function applies changes in a driver's configuration.
+  Input is a Configuration, which has the routing data for this
+  driver followed by name / value configuration pairs. The driver
+  must apply those pairs to its configurable storage. If the
+  driver's configuration is stored in a linear block of data
+  and the driver's name / value pairs are in <BlockConfig>
+  format, it may use the ConfigToBlock helper function (above) to
+  simplify the job.
+
+  @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Configuration  A null-terminated Unicode string in
+                        <ConfigString> format. 
+  
+  @param Progress       A pointer to a string filled in with the
+                        offset of the most recent '&' before the
+                        first failing name / value pair (or the
+                        beginn ing of the string if the failure
+                        is in the first name / value pair) or
+                        the terminating NULL if all was
+                        successful.
+
+  @retval EFI_SUCCESS             The results have been distributed or are
+                                  awaiting distribution.
+  
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+  
+  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
+                                  Results parameter would result
+                                  in this type of error.
+  
+  @retval EFI_NOT_FOUND           Target for the specified routing data
+                                  was not found
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessRouteConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Configuration,
+  OUT       EFI_STRING                      *Progress
+  )
+{
+  EFI_STATUS                       Status;
+  UINTN                            BufferSize;
+  TLS_AUTH_CONFIG_PRIVATE_DATA     *Private;
+
+  if (Progress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+  *Progress = Configuration;
+
+  if (Configuration == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Check routing data in <ConfigHdr>.
+  // Note: there is no name for Name/Value storage, only GUID will be checked
+  //
+  if (!HiiIsConfigHdrMatch (Configuration, &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
+    return EFI_NOT_FOUND;
+  }
+
+  Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
+  
+  BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+  ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
+
+  Status = gHiiConfigRouting->ConfigToBlock (
+                                gHiiConfigRouting,
+                                Configuration,
+                                (UINT8 *) &Private->TlsAuthConfigNvData,
+                                &BufferSize,
+                                Progress
+                                );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  return Status;
+}  
+
+/**
+   
+  This function is called to provide results data to the driver.
+  This data consists of a unique key that is used to identify
+  which data is either being passed back or being asked for.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  QuestionId             A unique value which is sent to the original
+                                 exporting driver so that it can identify the type
+                                 of data to expect. The format of the data tends to 
+                                 vary based on the opcode that generated the callback.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  ActionRequest          On return, points to the action requested by the
+                                 callback function.
+
+  @retval EFI_SUCCESS            The callback successfully handled the action.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
+                                 variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
+                                 callback.
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessCallback (
+  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN     EFI_BROWSER_ACTION                     Action,
+  IN     EFI_QUESTION_ID                        QuestionId,
+  IN     UINT8                                  Type,
+  IN OUT EFI_IFR_TYPE_VALUE                     *Value,
+  OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
+  )
+{
+  EFI_INPUT_KEY                   Key;
+  EFI_STATUS                      Status;
+  TLS_AUTH_CONFIG_PRIVATE_DATA    *Private;
+  UINTN                           BufferSize;
+  TLS_AUTH_CONFIG_IFR_NVDATA      *IfrNvData;
+  UINT16                          LabelId;
+  EFI_DEVICE_PATH_PROTOCOL        *File;
+
+  Status           = EFI_SUCCESS;
+  File             = NULL;
+
+  if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
+    return EFI_INVALID_PARAMETER;
+  }
+  
+  Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
+
+  mTlsAuthPrivateData = Private;
+
+  //
+  // Retrieve uncommitted data from Browser
+  //
+  BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+  IfrNvData = AllocateZeroPool (BufferSize);
+  if (IfrNvData == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  HiiGetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8 *) IfrNvData);
+
+  if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
+      (Action != EFI_BROWSER_ACTION_CHANGING)) {
+    Status = EFI_UNSUPPORTED;
+    goto EXIT;
+  }
+
+  if (Action == EFI_BROWSER_ACTION_CHANGING) {
+    switch (QuestionId) {
+    case KEY_TLS_AUTH_CONFIG_CLIENT_CERT:
+    case KEY_TLS_AUTH_CONFIG_SERVER_CA:
+      //
+      // Clear Cert GUID.
+      //
+      ZeroMem (IfrNvData->CertGuid, sizeof (IfrNvData->CertGuid));
+      if (Private->CertGuid == NULL) {
+        Private->CertGuid = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));
+        if (Private->CertGuid == NULL) {
+          return EFI_OUT_OF_RESOURCES;
+        }
+      }
+      if (QuestionId == KEY_TLS_AUTH_CONFIG_CLIENT_CERT) {
+        LabelId = TLS_AUTH_CONFIG_FORMID3_FORM;
+      } else if (QuestionId == KEY_TLS_AUTH_CONFIG_SERVER_CA) {
+        LabelId = TLS_AUTH_CONFIG_FORMID4_FORM;
+      }
+
+      //
+      // Refresh selected file.
+      //
+      CleanUpPage (LabelId, Private);
+      break;
+    case KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE:
+      ChooseFile( NULL, NULL, (CHOOSE_HANDLER) UpdateCAFromFile, &File);
+      break;
+
+    case KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT:
+      Status = EnrollCertDatabase (Private, EFI_TLS_CA_CERTIFICATE_VARIABLE);
+      if (EFI_ERROR (Status)) {
+        CreatePopUp (
+          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
+          &Key,
+          L"ERROR: Enroll Cert Failure!",
+          NULL
+          );
+      }
+      break;
+
+    case KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT:
+      if (Private->FileContext->FHandle != NULL) {
+        CloseFile (Private->FileContext->FHandle);
+        Private->FileContext->FHandle = NULL;
+        if (Private->FileContext->FileName!= NULL){
+          FreePool(Private->FileContext->FileName);
+          Private->FileContext->FileName = NULL;
+        }
+      }
+
+      if (Private->CertGuid!= NULL) {
+        FreePool (Private->CertGuid);
+        Private->CertGuid = NULL;
+      }
+      break;
+
+    case KEY_TLS_AUTH_CONFIG_DELETE_CERT:
+      UpdateDeletePage (
+        Private,
+        EFI_TLS_CA_CERTIFICATE_VARIABLE,
+        &gEfiTlsCaCertificateGuid,
+        LABEL_CA_DELETE,
+        TLS_AUTH_CONFIG_FORMID5_FORM,
+        OPTION_DEL_CA_ESTION_ID
+        );
+       break;
+      
+    default:
+      if ((QuestionId >= OPTION_DEL_CA_ESTION_ID) &&
+                 (QuestionId < (OPTION_DEL_CA_ESTION_ID + OPTION_CONFIG_RANGE)))  {
+        DeleteCert (
+          Private,
+          EFI_TLS_CA_CERTIFICATE_VARIABLE,
+          &gEfiTlsCaCertificateGuid,
+          LABEL_CA_DELETE,
+          TLS_AUTH_CONFIG_FORMID5_FORM,
+          OPTION_DEL_CA_ESTION_ID,
+          QuestionId - OPTION_DEL_CA_ESTION_ID
+          );
+      }
+      break;
+    }
+  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
+    switch (QuestionId) {
+    case KEY_TLS_AUTH_CONFIG_CERT_GUID:
+      ASSERT (Private->CertGuid != NULL);
+      Status = StringToGuid (
+                 IfrNvData->CertGuid,
+                 StrLen (IfrNvData->CertGuid),
+                 Private->CertGuid
+                 );
+      if (EFI_ERROR (Status)) {
+        break;
+      }
+
+      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
+      break;
+    default:
+      break;
+    }
+  }
+  
+EXIT:
+
+  if (!EFI_ERROR (Status)) {
+    BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
+    HiiSetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName, BufferSize, (UINT8*) IfrNvData, NULL);
+  }
+
+  FreePool (IfrNvData);
+
+  if (File != NULL){
+    FreePool(File);
+    File = NULL;
+  }
+
+  return EFI_SUCCESS;
+
+}
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
new file mode 100644
index 0000000..398f7b6
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
@@ -0,0 +1,282 @@
+/** @file
+  Header file of Miscellaneous Routines for TlsAuthConfigDxe 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 __TLS_AUTH_CONFIG_IMPL_H__
+#define __TLS_AUTH_CONFIG_IMPL_H__
+
+#include <Uefi.h>
+
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/SimpleFileSystem.h>
+
+//
+// Libraries
+//
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HiiLib.h>
+#include <Library/UefiHiiServicesLib.h>
+#include <Library/FileExplorerLib.h>
+#include <Library/PrintLib.h>
+
+#include <Guid/MdeModuleHii.h>
+#include <Guid/ImageAuthentication.h>
+#include <Guid/TlsAuthentication.h>
+
+
+//
+// Include files with function prototypes
+//
+#include "TlsAuthConfigNvData.h"
+
+extern   UINT8       TlsAuthConfigDxeStrings[];
+extern   UINT8       TlsAuthConfigVfrBin[];
+
+#define TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE    SIGNATURE_32 ('T', 'A', 'C', 'D')
+#define TLS_AUTH_CONFIG_PRIVATE_FROM_THIS(a)      CR (a, TLS_AUTH_CONFIG_PRIVATE_DATA, ConfigAccess, TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE)
+
+#define TLS_AUTH_CONFIG_VAR_BASE_ATTR  (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)
+
+typedef struct _TLS_AUTH_CONFIG_PRIVATE_DATA      TLS_AUTH_CONFIG_PRIVATE_DATA;
+typedef struct _TLS_AUTH_CONFIG_FILE_CONTEXT      TLS_AUTH_CONFIG_FILE_CONTEXT;
+
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+  VENDOR_DEVICE_PATH                VendorDevicePath;
+  EFI_DEVICE_PATH_PROTOCOL          End;
+} HII_VENDOR_DEVICE_PATH;
+
+struct _TLS_AUTH_CONFIG_FILE_CONTEXT {
+  EFI_FILE_HANDLE                   FHandle;
+  UINT16                            *FileName;
+};
+
+struct _TLS_AUTH_CONFIG_PRIVATE_DATA {
+  UINTN                             Signature;
+
+  EFI_HANDLE                        DriverHandle;
+  EFI_HII_HANDLE                    RegisteredHandle;
+  EFI_HII_CONFIG_ACCESS_PROTOCOL    ConfigAccess;
+  TLS_AUTH_CONFIG_IFR_NVDATA        TlsAuthConfigNvData;
+
+  TLS_AUTH_CONFIG_FILE_CONTEXT      *FileContext;
+
+  EFI_GUID                          *CertGuid;
+};
+
+/**
+  Unload the configuration form, this includes: delete all the configuration
+  entries, uninstall the form callback protocol, and free the resources used.
+  The form will only be unload completely when both IP4 and IP6 stack are stopped.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is unloaded.
+  @retval Others                  Failed to unload the form.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormUnload (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  );
+
+/**
+  Initialize the configuration form.
+
+  @param[in]  Private             Pointer to the driver private data.
+
+  @retval EFI_SUCCESS             The configuration form is initialized.
+  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
+
+**/
+EFI_STATUS
+TlsAuthConfigFormInit (
+  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
+  );
+
+/**
+   
+  This function allows the caller to request the current
+  configuration for one or more named elements. The resulting
+  string is in <ConfigAltResp> format. Any and all alternative
+  configuration strings shall also be appended to the end of the
+  current configuration string. If they are, they must appear
+  after the current configuration. They must contain the same
+  routing (GUID, NAME, PATH) as the current configuration string.
+  They must have an additional description indicating the type of
+  alternative configuration the string represents,
+  "ALTCFG=<StringToken>". That <StringToken> (when
+  converted from Hex UNICODE to binary) is a reference to a
+  string in the associated string pack.
+
+  @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Request    A null-terminated Unicode string in
+                    <ConfigRequest> format. Note that this
+                    includes the routing information as well as
+                    the configurable name / value pairs. It is
+                    invalid for this string to be in
+                    <MultiConfigRequest> format. 
+                    If a NULL is passed in for the Request field, 
+                    all of the settings being abstracted by this function 
+                    will be returned in the Results field.  In addition, 
+                    if a ConfigHdr is passed in with no request elements, 
+                    all of the settings being abstracted for that particular 
+                    ConfigHdr reference will be returned in the Results Field.
+
+  @param Progress   On return, points to a character in the
+                    Request string. Points to the string's null
+                    terminator if request was successful. Points
+                    to the most recent "&" before the first
+                    failing name / value pair (or the beginning
+                    of the string if the failure is in the first
+                    name / value pair) if the request was not
+                    successful.
+
+  @param Results    A null-terminated Unicode string in
+                    <MultiConfigAltResp> format which has all values
+                    filled in for the names in the Request string.
+                    String to be allocated by the called function.
+
+  @retval EFI_SUCCESS             The Results string is filled with the
+                                  values corresponding to all requested
+                                  names.
+
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+
+  @retval EFI_NOT_FOUND           Routing data doesn't match any
+                                  known driver. Progress set to the
+                                  first character in the routing header.
+                                  Note: There is no requirement that the
+                                  driver validate the routing data. It
+                                  must skip the <ConfigHdr> in order to
+                                  process the names.
+
+  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
+                                  to most recent "&" before the
+                                  error or the beginning of the
+                                  string.
+
+  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
+                                  to the & before the name in
+                                  question.
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessExtractConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Request,
+  OUT       EFI_STRING                      *Progress,
+  OUT       EFI_STRING                      *Results
+  );
+
+/**
+   
+  This function applies changes in a driver's configuration.
+  Input is a Configuration, which has the routing data for this
+  driver followed by name / value configuration pairs. The driver
+  must apply those pairs to its configurable storage. If the
+  driver's configuration is stored in a linear block of data
+  and the driver's name / value pairs are in <BlockConfig>
+  format, it may use the ConfigToBlock helper function (above) to
+  simplify the job.
+
+  @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+
+  @param Configuration  A null-terminated Unicode string in
+                        <ConfigString> format. 
+  
+  @param Progress       A pointer to a string filled in with the
+                        offset of the most recent '&' before the
+                        first failing name / value pair (or the
+                        beginn ing of the string if the failure
+                        is in the first name / value pair) or
+                        the terminating NULL if all was
+                        successful.
+
+  @retval EFI_SUCCESS             The results have been distributed or are
+                                  awaiting distribution.
+  
+  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
+                                  parts of the results that must be
+                                  stored awaiting possible future
+                                  protocols.
+  
+  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
+                                  Results parameter would result
+                                  in this type of error.
+  
+  @retval EFI_NOT_FOUND           Target for the specified routing data
+                                  was not found
+
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessRouteConfig (
+  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
+  IN CONST  EFI_STRING                      Configuration,
+  OUT       EFI_STRING                      *Progress
+  );  
+
+/**
+   
+  This function is called to provide results data to the driver.
+  This data consists of a unique key that is used to identify
+  which data is either being passed back or being asked for.
+
+  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
+  @param  Action                 Specifies the type of action taken by the browser.
+  @param  QuestionId             A unique value which is sent to the original
+                                 exporting driver so that it can identify the type
+                                 of data to expect. The format of the data tends to 
+                                 vary based on the opcode that generated the callback.
+  @param  Type                   The type of value for the question.
+  @param  Value                  A pointer to the data being sent to the original
+                                 exporting driver.
+  @param  ActionRequest          On return, points to the action requested by the
+                                 callback function.
+
+  @retval EFI_SUCCESS            The callback successfully handled the action.
+  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold the
+                                 variable and its data.
+  @retval EFI_DEVICE_ERROR       The variable could not be saved.
+  @retval EFI_UNSUPPORTED        The specified Action is not supported by the
+                                 callback.
+**/
+EFI_STATUS
+EFIAPI
+TlsAuthConfigAccessCallback (
+  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
+  IN     EFI_BROWSER_ACTION                     Action,
+  IN     EFI_QUESTION_ID                        QuestionId,
+  IN     UINT8                                  Type,
+  IN OUT EFI_IFR_TYPE_VALUE                     *Value,
+  OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
+  );
+
+#endif
+
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
new file mode 100644
index 0000000..f453201
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
@@ -0,0 +1,49 @@
+/** @file
+  Header file for NV data structure definition.
+
+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 __TLS_AUTH_CONFIG_NV_DATA_H__
+#define __TLS_AUTH_CONFIG_NV_DATA_H__
+
+#include <Guid/TlsAuthConfigHii.h>
+
+#define TLS_AUTH_CONFIG_GUID_SIZE                 36
+#define TLS_AUTH_CONFIG_GUID_STORAGE_SIZE         37
+
+#define TLS_AUTH_CONFIG_FORMID1_FORM              1
+#define TLS_AUTH_CONFIG_FORMID2_FORM              2
+#define TLS_AUTH_CONFIG_FORMID3_FORM              3
+#define TLS_AUTH_CONFIG_FORMID4_FORM              4
+#define TLS_AUTH_CONFIG_FORMID5_FORM              5
+
+
+#define KEY_TLS_AUTH_CONFIG_SERVER_CA                  0x1000
+#define KEY_TLS_AUTH_CONFIG_CLIENT_CERT                0x1001
+#define KEY_TLS_AUTH_CONFIG_ENROLL_CERT                0x1002
+#define KEY_TLS_AUTH_CONFIG_DELETE_CERT                0x1003
+#define KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE      0x1004
+#define KEY_TLS_AUTH_CONFIG_CERT_GUID                  0x1005
+#define KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT        0x1006
+#define KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT     0x1007
+
+#define OPTION_DEL_CA_ESTION_ID                        0x2000
+#define OPTION_CONFIG_RANGE                            0x1000
+
+#define LABEL_CA_DELETE                                0x1101
+#define LABEL_END                                      0xffff
+
+typedef struct {
+  CHAR16    CertGuid[TLS_AUTH_CONFIG_GUID_STORAGE_SIZE];
+} TLS_AUTH_CONFIG_IFR_NVDATA;
+
+#endif
diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
new file mode 100644
index 0000000..fb130d9
--- /dev/null
+++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
@@ -0,0 +1,152 @@
+/** @file
+  VFR file used by TlsAuthConfigDxe 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.
+
+**/
+
+#include "TlsAuthConfigNvData.h"
+
+formset
+  guid   = TLS_AUTH_CONFIG_GUID,
+  title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_TITLE),
+  help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_HELP),
+
+  varstore TLS_AUTH_CONFIG_IFR_NVDATA,
+    name = TLS_AUTH_CONFIG_IFR_NVDATA,
+    guid = TLS_AUTH_CONFIG_GUID;
+
+  //
+  // ##1 Form1: Main form for Tls Auth configration
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID1_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_TITLE);
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+    
+    //
+    // Display Server CA configration
+    //
+    goto TLS_AUTH_CONFIG_FORMID2_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_SERVER_CA;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    //
+    // Display Client cert configration
+    //
+    grayoutif TRUE; /// Current unsupported.
+    goto TLS_AUTH_CONFIG_FORMID3_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_CLIENT_CERT;
+    endif;
+  endform; 
+
+  //
+  // ##2 Form2: CA configuration
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID2_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA);
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID4_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_ENROLL_CERT;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID5_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT_HELP),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_DELETE_CERT;
+  endform;
+
+  //
+  // ##3 Form3 : Client cert configuration
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID3_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT);
+    
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+  //
+  // TODO...
+  //
+  endform;
+
+  //
+  // ##4 Form4: Enroll cert for CA
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID4_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT);
+    
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID4_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ADD_CERT_FILE),
+         help = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ADD_CERT_FILE),
+         flags = INTERACTIVE,
+         key = KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+    label TLS_AUTH_CONFIG_FORMID4_FORM;
+    label LABEL_END;
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    string  varid   = TLS_AUTH_CONFIG_IFR_NVDATA.CertGuid,
+            prompt  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CERT_GUID),
+            help    = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CERT_GUID_HELP),
+            flags   = INTERACTIVE,
+            key     = KEY_TLS_AUTH_CONFIG_CERT_GUID,
+            minsize = TLS_AUTH_CONFIG_GUID_SIZE,
+            maxsize = TLS_AUTH_CONFIG_GUID_SIZE,
+    endstring;
+
+    subtitle text = STRING_TOKEN(STR_NULL);
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+    goto TLS_AUTH_CONFIG_FORMID1_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT;
+
+    goto TLS_AUTH_CONFIG_FORMID1_FORM,
+         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT),
+         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT),
+         flags  = INTERACTIVE,
+         key    = KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT;
+         
+  endform;
+
+  //
+  // ##5 Form5: Delete cert for CA
+  //
+  form formid = TLS_AUTH_CONFIG_FORMID5_FORM,
+    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT);
+
+    label LABEL_CA_DELETE;
+    label LABEL_END;
+    
+    subtitle text = STRING_TOKEN(STR_NULL);
+
+  endform;
+  
+endformset;
-- 
1.9.5.msysgit.1



^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration
  2016-12-22  2:52     ` Ye, Ting
@ 2016-12-22  3:13       ` Wu, Jiaxin
  0 siblings, 0 replies; 37+ messages in thread
From: Wu, Jiaxin @ 2016-12-22  3:13 UTC (permalink / raw)
  To: Ye, Ting, Fu, Siyuan, edk2-devel@lists.01.org
  Cc: Zhang, Lubo, Long, Qin, Thomas Palmer

Thanks Ting. The standardization is in the plan. Before finished, I will keep the existing APIs.

As the return value of GuidToString, you are right, it should be "Size" instead of "Size-1".  I will correct it before commit the patch.

Thanks,
Jiaxin

> -----Original Message-----
> From: Ye, Ting
> Sent: Thursday, December 22, 2016 10:52 AM
> To: Fu, Siyuan <siyuan.fu@intel.com>; Wu, Jiaxin <jiaxin.wu@intel.com>;
> edk2-devel@lists.01.org
> Cc: Zhang, Lubo <lubo.zhang@intel.com>; Long, Qin <qin.long@intel.com>;
> Thomas Palmer <thomas.palmer@hpe.com>
> Subject: RE: [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to
> support TLS auth configuration
> 
> I agree. Adding new StringToGuid and GuidToString to common library seems
> a good idea if we don't have existing APIs.
> 
> In GuidToString, the comment indicates that SPrint will NULL terminate the
> string, so use Size -1 to skip the NULL. However, I see UnicodeSPrint in
> MdePkg returns the number of Unicode characters in the produced output
> buffer, not including the Null-terminator.
> It looks inconsistent to me. Please check that.
> 
> Others are good to me.
> Reviewed-by: Ye Ting <ting.ye@intel.com>
> 
> Best Regards,
> Ting
> 
> 
> -----Original Message-----
> From: Fu, Siyuan
> Sent: Thursday, December 15, 2016 10:22 AM
> To: Wu, Jiaxin <jiaxin.wu@intel.com>; edk2-devel@lists.01.org
> Cc: Ye, Ting <ting.ye@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>;
> Long, Qin <qin.long@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>
> Subject: RE: [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to
> support TLS auth configuration
> 
> Hi, Jiaxin
> 
> PrintLib support "%g" to print a GUID so you don't need to use "%08x-%04x-
> %04x-%02x%02x-%02x%02x%02x%02x%02x%02x" in GuidToString().
> Beside of that, I do see a lot of drivers has similar internal function
> StringToGuid() or StrToGuid(), do we have a common library interface for this?
> if not I think it may worth to create one.
> 
> Other parts are good with me.
> Reviewed-by: Fu Siyuan <siyuan.fu@intel.com>
> 
> 
> Best Regards
> Siyuan
> 
> -----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 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to
> support TLS auth configuration
> 
> This patch provides the UI to support TLS auth configuration.
> * EFI_SIGNATURE_LIST format is used for 'TlsCaCertificate'
> variable. So, TLS supports multiple certificate configuration.
> * The variable attribute is BS with NV, which only target at
> preventing runtime phase attack.
> 
> 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/Include/Guid/TlsAuthConfigHii.h         |   25 +
>  NetworkPkg/Include/Guid/TlsAuthentication.h        |   29 +
>  NetworkPkg/NetworkPkg.dec                          |    7 +
>  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c     |  135 ++
>  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf   |   73 +
>  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni   |   21 +
>  .../TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni     |   19 +
>  .../TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni   |   39 +
>  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c    | 1841
> ++++++++++++++++++++
>  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h    |  282 +++
>  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h  |   49 +
>  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr   |  152 ++
>  12 files changed, 2672 insertions(+)
>  create mode 100644 NetworkPkg/Include/Guid/TlsAuthConfigHii.h
>  create mode 100644 NetworkPkg/Include/Guid/TlsAuthentication.h
>  create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
>  create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
>  create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
>  create mode 100644
> NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
>  create mode 100644
> NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
>  create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
>  create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
>  create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
>  create mode 100644 NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
> 
> diff --git a/NetworkPkg/Include/Guid/TlsAuthConfigHii.h
> b/NetworkPkg/Include/Guid/TlsAuthConfigHii.h
> new file mode 100644
> index 0000000..9d21426
> --- /dev/null
> +++ b/NetworkPkg/Include/Guid/TlsAuthConfigHii.h
> @@ -0,0 +1,25 @@
> +/** @file
> +  GUIDs used as HII FormSet and HII Package list GUID in TlsAuthConfigDxe
> 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 that 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 __TLS_AUTH_CONFIG_HII_GUID_H__
> +#define __TLS_AUTH_CONFIG_HII_GUID_H__
> +
> +#define TLS_AUTH_CONFIG_GUID \
> +  { \
> +    0xb0eae4f8, 0x9a04, 0x4c6d, { 0xa7, 0x48, 0x79, 0x3d, 0xaa, 0xf, 0x65,
> 0xdf } \
> +  }
> +
> +extern EFI_GUID gTlsAuthConfigGuid;
> +
> +#endif
> diff --git a/NetworkPkg/Include/Guid/TlsAuthentication.h
> b/NetworkPkg/Include/Guid/TlsAuthentication.h
> new file mode 100644
> index 0000000..2e800dc
> --- /dev/null
> +++ b/NetworkPkg/Include/Guid/TlsAuthentication.h
> @@ -0,0 +1,29 @@
> +/** @file
> +  This file defines TlsCaCertificate variable.
> +
> +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 that 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 __TLS_AUTHENTICATION_H__
> +#define __TLS_AUTHENTICATION_H__
> +
> +// Private variable for CA Certificate configuration
> +//
> +#define EFI_TLS_CA_CERTIFICATE_GUID \
> +  { \
> +    0xfd2340D0, 0x3dab, 0x4349, { 0xa6, 0xc7, 0x3b, 0x4f, 0x12, 0xb4, 0x8e,
> 0xae } \
> +  }
> +
> +#define EFI_TLS_CA_CERTIFICATE_VARIABLE       L"TlsCaCertificate"
> +
> +extern EFI_GUID gEfiTlsCaCertificateGuid;
> +
> +#endif
> diff --git a/NetworkPkg/NetworkPkg.dec b/NetworkPkg/NetworkPkg.dec
> index 268188a..24d45f4 100644
> --- a/NetworkPkg/NetworkPkg.dec
> +++ b/NetworkPkg/NetworkPkg.dec
> @@ -38,10 +38,17 @@
>    gIScsiConfigGuid              = { 0x4b47d616, 0xa8d6, 0x4552, { 0x9d, 0x44, 0xcc,
> 0xad, 0x2e, 0xf, 0x4c, 0xf9}}
> 
>    # Include/Guid/HttpBootConfigHii.h
>    gHttpBootConfigGuid           = { 0x4d20583a, 0x7765, 0x4e7a, { 0x8a, 0x67,
> 0xdc, 0xde, 0x74, 0xee, 0x3e, 0xc5 }}
> 
> +  # Include/Guid/TlsAuthConfigHii.h
> +  gTlsAuthConfigGuid            = { 0xb0eae4f8, 0x9a04, 0x4c6d, { 0xa7, 0x48,
> 0x79, 0x3d, 0xaa, 0xf, 0x65, 0xdf }}
> +
> +  # Include/Guid/TlsAuthentication.h
> +  gEfiTlsCaCertificateGuid      = { 0xfd2340D0, 0x3dab, 0x4349, { 0xa6, 0xc7,
> 0x3b, 0x4f, 0x12, 0xb4, 0x8e, 0xae }}
> +
> +
>  [PcdsFeatureFlag]
>    ## Indicates if the IPsec IKEv2 Certificate Authentication feature is enabled
> or not.<BR><BR>
>    #   TRUE  - Certificate Authentication feature is enabled.<BR>
>    #   FALSE - Does not support Certificate Authentication.<BR>
>    # @Prompt Enable IPsec IKEv2 Certificate Authentication.
> diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
> b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
> new file mode 100644
> index 0000000..647bc2f
> --- /dev/null
> +++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.c
> @@ -0,0 +1,135 @@
> +/** @file
> +  The DriverEntryPoint for TlsAuthConfigDxe 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.
> +
> +**/
> +
> +#include "TlsAuthConfigImpl.h"
> +
> +/**
> +  Unloads an image.
> +
> +  @param  ImageHandle           Handle that identifies the image to be
> unloaded.
> +
> +  @retval EFI_SUCCESS           The image has been unloaded.
> +  @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image
> handle.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsAuthConfigDxeUnload (
> +  IN EFI_HANDLE  ImageHandle
> +  )
> +{
> +  EFI_STATUS                     Status;
> +  TLS_AUTH_CONFIG_PRIVATE_DATA   *PrivateData;
> +
> +  Status = gBS->HandleProtocol (
> +                  ImageHandle,
> +                  &gEfiCallerIdGuid,
> +                  (VOID **) &PrivateData
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  ASSERT (PrivateData->Signature ==
> TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE);
> +
> +  gBS->UninstallMultipleProtocolInterfaces (
> +         &ImageHandle,
> +         &gEfiCallerIdGuid,
> +         PrivateData,
> +         NULL
> +         );
> +
> +  TlsAuthConfigFormUnload (PrivateData);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This is the declaration of an EFI image entry point. This entry point is
> +  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
> +  both device drivers and bus drivers.
> +
> +  @param  ImageHandle           The firmware allocated handle for the UEFI
> image.
> +  @param  SystemTable           A pointer to the EFI System Table.
> +
> +  @retval EFI_SUCCESS           The operation completed successfully.
> +  @retval Others                An unexpected error occurred.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsAuthConfigDxeDriverEntryPoint (
> +  IN EFI_HANDLE        ImageHandle,
> +  IN EFI_SYSTEM_TABLE  *SystemTable
> +  )
> +{
> +  EFI_STATUS  Status;
> +
> +  TLS_AUTH_CONFIG_PRIVATE_DATA   *PrivateData;
> +
> +  PrivateData = NULL;
> +
> +  //
> +  // If already started, return.
> +  //
> +  Status = gBS->OpenProtocol (
> +                  ImageHandle,
> +                  &gEfiCallerIdGuid,
> +                  NULL,
> +                  ImageHandle,
> +                  ImageHandle,
> +                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL
> +                  );
> +  if (!EFI_ERROR (Status)) {
> +    return EFI_ALREADY_STARTED;
> +  }
> +
> +  //
> +  // Initialize the private data structure.
> +  //
> +  PrivateData = AllocateZeroPool (sizeof
> (TLS_AUTH_CONFIG_PRIVATE_DATA));
> +  if (PrivateData == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // Initialize the HII configuration form.
> +  //
> +  Status = TlsAuthConfigFormInit (PrivateData);
> +  if (EFI_ERROR (Status)) {
> +    goto ON_ERROR;
> +  }
> +
> +  //
> +  // Install private GUID.
> +  //
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &ImageHandle,
> +                  &gEfiCallerIdGuid,
> +                  PrivateData,
> +                  NULL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto ON_ERROR;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +ON_ERROR:
> +  TlsAuthConfigFormUnload (PrivateData);
> +  FreePool (PrivateData);
> +
> +  return Status;
> +}
> +
> diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
> b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
> new file mode 100644
> index 0000000..19f095e
> --- /dev/null
> +++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
> @@ -0,0 +1,73 @@
> +## @file
> +#  Provides the capability to configure Tls Authentication in a setup browser
> +#  By this module, user may change the content of TlsCaCertificate.
> +#
> +# 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.
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION               = 0x00010005
> +  BASE_NAME                 = TlsAuthConfigDxe
> +  MODULE_UNI_FILE           = TlsAuthConfigDxe.uni
> +  FILE_GUID                 = 7ca1024f-eb17-11e5-9dba-28d2447c4829
> +  MODULE_TYPE               = DXE_DRIVER
> +  VERSION_STRING            = 1.0
> +  ENTRY_POINT               = TlsAuthConfigDxeDriverEntryPoint
> +  UNLOAD_IMAGE              = TlsAuthConfigDxeUnload
> +
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  MdeModulePkg/MdeModulePkg.dec
> +  NetworkPkg/NetworkPkg.dec
> +
> +[Sources]
> +  TlsAuthConfigImpl.c
> +  TlsAuthConfigImpl.h
> +  TlsAuthConfigNvData.h
> +  TlsAuthConfigDxe.c
> +  TlsAuthConfigDxeStrings.uni
> +  TlsAuthConfigVfr.vfr
> +
> +[LibraryClasses]
> +  BaseLib
> +  BaseMemoryLib
> +  MemoryAllocationLib
> +  UefiLib
> +  UefiBootServicesTableLib
> +  UefiRuntimeServicesTableLib
> +  UefiDriverEntryPoint
> +  DebugLib
> +  HiiLib
> +  DevicePathLib
> +  UefiHiiServicesLib
> +  FileExplorerLib
> +  PrintLib
> +
> +[Protocols]
> +  gEfiDevicePathProtocolGuid                    ## PRODUCES
> +  gEfiHiiConfigAccessProtocolGuid               ## PRODUCES
> +  gEfiSimpleFileSystemProtocolGuid              ## SOMETIMES_CONSUMES
> +
> +[Guids]
> +  gTlsAuthConfigGuid                            ## PRODUCES  ## GUID
> +  gEfiCertX509Guid                              ## CONSUMES  ## GUID  # Indicate the
> cert type
> +  gEfiIfrTianoGuid                              ## CONSUMES  ## HII
> +  gEfiTlsCaCertificateGuid                      ## PRODUCES  ## GUID
> +
> +[Depex]
> +  gEfiHiiConfigRoutingProtocolGuid  AND
> +  gEfiHiiDatabaseProtocolGuid
> +
> +[UserExtensions.TianoCore."ExtraFiles"]
> +  TlsAuthConfigDxeExtra.uni
> diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
> b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
> new file mode 100644
> index 0000000..f99a14f
> --- /dev/null
> +++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.uni
> @@ -0,0 +1,21 @@
> +// /** @file
> +// Provides the capability to configure Tls Authentication in a setup browser
> +//
> +// By this module, user may change the content of TlsCaCertificate.
> +//
> +// 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.
> +//
> +// **/
> +
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "Provides the
> capability to configure Tls Authentication in a setup browser"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "By this module,
> user may change the content of TlsCaCertificate."
> +
> diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
> b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
> new file mode 100644
> index 0000000..ee4c49f
> --- /dev/null
> +++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeExtra.uni
> @@ -0,0 +1,19 @@
> +// /** @file
> +// TlsAuthConfigDxe Localized Strings and Content
> +//
> +// 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.
> +//
> +// **/
> +
> +#string STR_PROPERTIES_MODULE_NAME
> +#language en-US
> +"TLS Auth Config DXE"
> +
> +
> diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
> b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
> new file mode 100644
> index 0000000..a8f7e43
> --- /dev/null
> +++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxeStrings.uni
> @@ -0,0 +1,39 @@
> +/** @file
> +  String definitions for Tls Authentication Configuration form.
> +
> +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.
> +
> +**/
> +
> +#langdef en-US "English"
> +
> +#string STR_TLS_AUTH_CONFIG_TITLE                    #language en-US "Tls Auth
> Configuration"
> +#string STR_TLS_AUTH_CONFIG_HELP                     #language en-US "Press
> <Enter> to select Tls Auth Configuration."
> +
> +#string STR_TLS_AUTH_CONFIG_SERVER_CA         		 #language
> en-US "Server CA Configuration"
> +#string STR_TLS_AUTH_CONFIG_SERVER_CA_HELP    		 #language
> en-US "Press <Enter> to configure Server CA."
> +#string STR_TLS_AUTH_CONFIG_CLIENT_CERT         	 #language en-US
> "Client Cert Configuration"
> +#string STR_TLS_AUTH_CONFIG_CLIENT_CERT_HELP    	 #language
> en-US "Client cert configuration is unsupported currently."
> +
> +#string STR_TLS_AUTH_CONFIG_ENROLL_CERT              #language en-US
> "Enroll Cert"
> +#string STR_TLS_AUTH_CONFIG_ENROLL_CERT_HELP         #language en-US
> "Press <Enter> to enroll cert."
> +#string STR_TLS_AUTH_CONFIG_DELETE_CERT              #language en-US
> "Delete Cert"
> +#string STR_TLS_AUTH_CONFIG_DELETE_CERT_HELP         #language en-US
> "Press <Enter> to delete cert."
> +
> +#string STR_TLS_AUTH_CONFIG_ADD_CERT_FILE            #language en-US
> "Enroll Cert Using File"
> +
> +#string STR_TLS_AUTH_CONFIG_CERT_GUID                #language en-US "Cert
> GUID"
> +#string STR_TLS_AUTH_CONFIG_CERT_GUID_HELP           #language en-US
> "Input digit character in 11111111-2222-3333-4444-1234567890ab format."
> +#string STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT            #language en-US
> "Commit Changes and Exit"
> +#string STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT         #language en-
> US "Discard Changes and Exit"
> +
> +#string STR_CERT_TYPE_PCKS_GUID                      #language en-US "GUID for
> CERT"
> +
> +#string STR_NULL                                     #language en-US ""
> \ No newline at end of file
> diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
> b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
> new file mode 100644
> index 0000000..1132cac
> --- /dev/null
> +++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.c
> @@ -0,0 +1,1841 @@
> +/** @file
> +  The Miscellaneous Routines for TlsAuthConfigDxe 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.
> +
> +**/
> +
> +#include "TlsAuthConfigImpl.h"
> +
> +VOID                    *mStartOpCodeHandle = NULL;
> +VOID                    *mEndOpCodeHandle   = NULL;
> +EFI_IFR_GUID_LABEL      *mStartLabel        = NULL;
> +EFI_IFR_GUID_LABEL      *mEndLabel          = NULL;
> +
> +
> +CHAR16                  mTlsAuthConfigStorageName[] =
> L"TLS_AUTH_CONFIG_IFR_NVDATA";
> +
> +TLS_AUTH_CONFIG_PRIVATE_DATA      *mTlsAuthPrivateData = NULL;
> +
> +HII_VENDOR_DEVICE_PATH  mTlsAuthConfigHiiVendorDevicePath = {
> +  {
> +    {
> +      HARDWARE_DEVICE_PATH,
> +      HW_VENDOR_DP,
> +      {
> +        (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
> +        (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
> +      }
> +    },
> +    TLS_AUTH_CONFIG_GUID
> +  },
> +  {
> +    END_DEVICE_PATH_TYPE,
> +    END_ENTIRE_DEVICE_PATH_SUBTYPE,
> +    {
> +      (UINT8) (END_DEVICE_PATH_LENGTH),
> +      (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
> +    }
> +  }
> +};
> +
> +//
> +// Possible DER-encoded certificate file suffixes, end with NULL pointer.
> +//
> +CHAR16* mDerPemEncodedSuffix[] = {
> +  L".cer",
> +  L".der",
> +  L".crt",
> +  L".pem",
> +  NULL
> +};
> +
> +/**
> +  This code checks if the FileSuffix is one of the possible DER/PEM-encoded
> certificate suffix.
> +
> +  @param[in] FileSuffix            The suffix of the input certificate file
> +
> +  @retval    TRUE           It's a DER/PEM-encoded certificate.
> +  @retval    FALSE          It's NOT a DER/PEM-encoded certificate.
> +
> +**/
> +BOOLEAN
> +IsDerPemEncodeCertificate (
> +  IN CONST CHAR16         *FileSuffix
> +)
> +{
> +  UINTN     Index;
> +  for (Index = 0; mDerPemEncodedSuffix[Index] != NULL; Index++) {
> +    if (StrCmp (FileSuffix, mDerPemEncodedSuffix[Index]) == 0) {
> +      return TRUE;
> +    }
> +  }
> +  return FALSE;
> +}
> +
> +/**
> +  Worker function that prints an EFI_GUID into specified Buffer.
> +
> +  @param[in]     Guid          Pointer to GUID to print.
> +  @param[in]     Buffer        Buffer to print Guid into.
> +  @param[in]     BufferSize    Size of Buffer.
> +
> +  @retval    Number of characters printed.
> +
> +**/
> +UINTN
> +GuidToString (
> +  IN  EFI_GUID  *Guid,
> +  IN  CHAR16    *Buffer,
> +  IN  UINTN     BufferSize
> +  )
> +{
> +  UINTN Size;
> +
> +  Size = UnicodeSPrint (
> +            Buffer,
> +            BufferSize,
> +            L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
> +            (UINTN)Guid->Data1,
> +            (UINTN)Guid->Data2,
> +            (UINTN)Guid->Data3,
> +            (UINTN)Guid->Data4[0],
> +            (UINTN)Guid->Data4[1],
> +            (UINTN)Guid->Data4[2],
> +            (UINTN)Guid->Data4[3],
> +            (UINTN)Guid->Data4[4],
> +            (UINTN)Guid->Data4[5],
> +            (UINTN)Guid->Data4[6],
> +            (UINTN)Guid->Data4[7]
> +            );
> +
> +  //
> +  // SPrint will null terminate the string. The -1 skips the null
> +  //
> +  return Size - 1;
> +}
> +
> +/**
> +  Convert a String to Guid Value.
> +
> +  @param[in]   Str        Specifies the String to be converted.
> +  @param[in]   StrLen     Number of Unicode Characters of String (exclusive
> \0)
> +  @param[out]  Guid       Return the result Guid value.
> +
> +  @retval    EFI_SUCCESS           The operation is finished successfully.
> +  @retval    EFI_NOT_FOUND         Invalid string.
> +
> +**/
> +EFI_STATUS
> +StringToGuid (
> +  IN   CHAR16           *Str,
> +  IN   UINTN            StrLen,
> +  OUT  EFI_GUID         *Guid
> +  )
> +{
> +  CHAR16             *PtrBuffer;
> +  CHAR16             *PtrPosition;
> +  UINT16             *Buffer;
> +  UINTN              Data;
> +  UINTN              Index;
> +  UINT16             Digits[3];
> +
> +  Buffer = (CHAR16 *) AllocateZeroPool (sizeof (CHAR16) * (StrLen + 1));
> +  if (Buffer == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  StrCpyS (Buffer, (StrLen + 1), Str);
> +
> +  //
> +  // Data1
> +  //
> +  PtrBuffer       = Buffer;
> +  PtrPosition     = PtrBuffer;
> +  while (*PtrBuffer != L'\0') {
> +    if (*PtrBuffer == L'-') {
> +      break;
> +    }
> +    PtrBuffer++;
> +  }
> +  if (*PtrBuffer == L'\0') {
> +    FreePool (Buffer);
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  *PtrBuffer      = L'\0';
> +  Data            = StrHexToUintn (PtrPosition);
> +  Guid->Data1     = (UINT32)Data;
> +
> +  //
> +  // Data2
> +  //
> +  PtrBuffer++;
> +  PtrPosition     = PtrBuffer;
> +  while (*PtrBuffer != L'\0') {
> +    if (*PtrBuffer == L'-') {
> +      break;
> +    }
> +    PtrBuffer++;
> +  }
> +  if (*PtrBuffer == L'\0') {
> +    FreePool (Buffer);
> +    return EFI_NOT_FOUND;
> +  }
> +  *PtrBuffer      = L'\0';
> +  Data            = StrHexToUintn (PtrPosition);
> +  Guid->Data2     = (UINT16)Data;
> +
> +  //
> +  // Data3
> +  //
> +  PtrBuffer++;
> +  PtrPosition     = PtrBuffer;
> +  while (*PtrBuffer != L'\0') {
> +    if (*PtrBuffer == L'-') {
> +      break;
> +    }
> +    PtrBuffer++;
> +  }
> +  if (*PtrBuffer == L'\0') {
> +    FreePool (Buffer);
> +    return EFI_NOT_FOUND;
> +  }
> +  *PtrBuffer      = L'\0';
> +  Data            = StrHexToUintn (PtrPosition);
> +  Guid->Data3     = (UINT16)Data;
> +
> +  //
> +  // Data4[0..1]
> +  //
> +  for ( Index = 0 ; Index < 2 ; Index++) {
> +    PtrBuffer++;
> +    if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {
> +      FreePool (Buffer);
> +      return EFI_NOT_FOUND;
> +    }
> +    Digits[0]     = *PtrBuffer;
> +    PtrBuffer++;
> +    Digits[1]     = *PtrBuffer;
> +    Digits[2]     = L'\0';
> +    Data          = StrHexToUintn (Digits);
> +    Guid->Data4[Index] = (UINT8)Data;
> +  }
> +
> +  //
> +  // skip the '-'
> +  //
> +  PtrBuffer++;
> +  if ((*PtrBuffer != L'-' ) || ( *PtrBuffer == L'\0')) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  //
> +  // Data4[2..7]
> +  //
> +  for ( ; Index < 8; Index++) {
> +    PtrBuffer++;
> +    if ((*PtrBuffer == L'\0') || ( *(PtrBuffer + 1) == L'\0')) {
> +      FreePool (Buffer);
> +      return EFI_NOT_FOUND;
> +    }
> +    Digits[0]     = *PtrBuffer;
> +    PtrBuffer++;
> +    Digits[1]     = *PtrBuffer;
> +    Digits[2]     = L'\0';
> +    Data          = StrHexToUintn (Digits);
> +    Guid->Data4[Index] = (UINT8)Data;
> +  }
> +
> +  FreePool (Buffer);
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  List all cert in specified database by GUID in the page
> +  for user to select and delete as needed.
> +
> +  @param[in]    PrivateData         Module's private data.
> +  @param[in]    VariableName        The variable name of the vendor's
> signature database.
> +  @param[in]    VendorGuid          A unique identifier for the vendor.
> +  @param[in]    LabelNumber         Label number to insert opcodes.
> +  @param[in]    FormId              Form ID of current page.
> +  @param[in]    QuestionIdBase      Base question id of the signature list.
> +
> +  @retval   EFI_SUCCESS             Success to update the signature list page
> +  @retval   EFI_OUT_OF_RESOURCES    Unable to allocate required resources.
> +
> +**/
> +EFI_STATUS
> +UpdateDeletePage (
> +  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private,
> +  IN CHAR16                           *VariableName,
> +  IN EFI_GUID                         *VendorGuid,
> +  IN UINT16                           LabelNumber,
> +  IN EFI_FORM_ID                      FormId,
> +  IN EFI_QUESTION_ID                  QuestionIdBase
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  UINT32                      Index;
> +  UINTN                       CertCount;
> +  UINTN                       GuidIndex;
> +  VOID                        *StartOpCodeHandle;
> +  VOID                        *EndOpCodeHandle;
> +  EFI_IFR_GUID_LABEL          *StartLabel;
> +  EFI_IFR_GUID_LABEL          *EndLabel;
> +  UINTN                       DataSize;
> +  UINT8                       *Data;
> +  EFI_SIGNATURE_LIST          *CertList;
> +  EFI_SIGNATURE_DATA          *Cert;
> +  UINT32                      ItemDataSize;
> +  CHAR16                      *GuidStr;
> +  EFI_STRING_ID               GuidID;
> +  EFI_STRING_ID               Help;
> +
> +  Data     = NULL;
> +  CertList = NULL;
> +  Cert     = NULL;
> +  GuidStr  = NULL;
> +  StartOpCodeHandle = NULL;
> +  EndOpCodeHandle   = NULL;
> +
> +  //
> +  // Initialize the container for dynamic opcodes.
> +  //
> +  StartOpCodeHandle = HiiAllocateOpCodeHandle ();
> +  if (StartOpCodeHandle == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  }
> +
> +  EndOpCodeHandle = HiiAllocateOpCodeHandle ();
> +  if (EndOpCodeHandle == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  }
> +
> +  //
> +  // Create Hii Extend Label OpCode.
> +  //
> +  StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
> +                                        StartOpCodeHandle,
> +                                        &gEfiIfrTianoGuid,
> +                                        NULL,
> +                                        sizeof (EFI_IFR_GUID_LABEL)
> +                                        );
> +  StartLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
> +  StartLabel->Number        = LabelNumber;
> +
> +  EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
> +                                      EndOpCodeHandle,
> +                                      &gEfiIfrTianoGuid,
> +                                      NULL,
> +                                      sizeof (EFI_IFR_GUID_LABEL)
> +                                      );
> +  EndLabel->ExtendOpCode  = EFI_IFR_EXTEND_OP_LABEL;
> +  EndLabel->Number        = LABEL_END;
> +
> +  //
> +  // Read Variable.
> +  //
> +  DataSize = 0;
> +  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize,
> Data);
> +  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
> +    goto ON_EXIT;
> +  }
> +
> +  Data = (UINT8 *) AllocateZeroPool (DataSize);
> +  if (Data == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  }
> +
> +  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize,
> Data);
> +  if (EFI_ERROR (Status)) {
> +    goto ON_EXIT;
> +  }
> +
> +  GuidStr = AllocateZeroPool (100);
> +  if (GuidStr == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  }
> +
> +  //
> +  // Enumerate all data.
> +  //
> +  ItemDataSize = (UINT32) DataSize;
> +  CertList = (EFI_SIGNATURE_LIST *) Data;
> +  GuidIndex = 0;
> +
> +  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize))
> {
> +
> +    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
> +      Help = STRING_TOKEN (STR_CERT_TYPE_PCKS_GUID);
> +    } else {
> +      //
> +      // The signature type is not supported in current implementation.
> +      //
> +      ItemDataSize -= CertList->SignatureListSize;
> +      CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList-
> >SignatureListSize);
> +      continue;
> +    }
> +
> +    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) -
> CertList->SignatureHeaderSize) / CertList->SignatureSize;
> +    for (Index = 0; Index < CertCount; Index++) {
> +      Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList
> +                                              + sizeof (EFI_SIGNATURE_LIST)
> +                                              + CertList->SignatureHeaderSize
> +                                              + Index * CertList->SignatureSize);
> +      //
> +      // Display GUID and help
> +      //
> +      GuidToString (&Cert->SignatureOwner, GuidStr, 100);
> +      GuidID  = HiiSetString (Private->RegisteredHandle, 0, GuidStr, NULL);
> +      HiiCreateCheckBoxOpCode (
> +        StartOpCodeHandle,
> +        (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++),
> +        0,
> +        0,
> +        GuidID,
> +        Help,
> +        EFI_IFR_FLAG_CALLBACK,
> +        0,
> +        NULL
> +        );
> +    }
> +
> +    ItemDataSize -= CertList->SignatureListSize;
> +    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList-
> >SignatureListSize);
> +  }
> +
> +ON_EXIT:
> +  HiiUpdateForm (
> +    Private->RegisteredHandle,
> +    &gTlsAuthConfigGuid,
> +    FormId,
> +    StartOpCodeHandle,
> +    EndOpCodeHandle
> +    );
> +
> +  if (StartOpCodeHandle != NULL) {
> +    HiiFreeOpCodeHandle (StartOpCodeHandle);
> +  }
> +
> +  if (EndOpCodeHandle != NULL) {
> +    HiiFreeOpCodeHandle (EndOpCodeHandle);
> +  }
> +
> +  if (Data != NULL) {
> +    FreePool (Data);
> +  }
> +
> +  if (GuidStr != NULL) {
> +    FreePool (GuidStr);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Delete one entry from cert database.
> +
> +  @param[in]    PrivateData         Module's private data.
> +  @param[in]    VariableName        The variable name of the database.
> +  @param[in]    VendorGuid          A unique identifier for the vendor.
> +  @param[in]    LabelNumber         Label number to insert opcodes.
> +  @param[in]    FormId              Form ID of current page.
> +  @param[in]    QuestionIdBase      Base question id of the cert list.
> +  @param[in]    DeleteIndex         Cert index to delete.
> +
> +  @retval   EFI_SUCCESS             Delete siganture successfully.
> +  @retval   EFI_NOT_FOUND           Can't find the signature item,
> +  @retval   EFI_OUT_OF_RESOURCES    Could not allocate needed resources.
> +**/
> +EFI_STATUS
> +DeleteCert (
> +  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private,
> +  IN CHAR16                           *VariableName,
> +  IN EFI_GUID                         *VendorGuid,
> +  IN UINT16                           LabelNumber,
> +  IN EFI_FORM_ID                      FormId,
> +  IN EFI_QUESTION_ID                  QuestionIdBase,
> +  IN UINTN                            DeleteIndex
> +  )
> +{
> +  EFI_STATUS                  Status;
> +  UINTN                       DataSize;
> +  UINT8                       *Data;
> +  UINT8                       *OldData;
> +  UINT32                      Attr;
> +  UINT32                      Index;
> +  EFI_SIGNATURE_LIST          *CertList;
> +  EFI_SIGNATURE_LIST          *NewCertList;
> +  EFI_SIGNATURE_DATA          *Cert;
> +  UINTN                       CertCount;
> +  UINT32                      Offset;
> +  BOOLEAN                     IsItemFound;
> +  UINT32                      ItemDataSize;
> +  UINTN                       GuidIndex;
> +
> +  Data            = NULL;
> +  OldData         = NULL;
> +  CertList        = NULL;
> +  Cert            = NULL;
> +  Attr            = 0;
> +
> +  //
> +  // Get original signature list data.
> +  //
> +  DataSize = 0;
> +  Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize,
> NULL);
> +  if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) {
> +    goto ON_EXIT;
> +  }
> +
> +  OldData = (UINT8 *) AllocateZeroPool (DataSize);
> +  if (OldData == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  }
> +
> +  Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize,
> OldData);
> +  if (EFI_ERROR(Status)) {
> +    goto ON_EXIT;
> +  }
> +
> +  //
> +  // Allocate space for new variable.
> +  //
> +  Data = (UINT8*) AllocateZeroPool (DataSize);
> +  if (Data == NULL) {
> +    Status  =  EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  }
> +
> +  //
> +  // Enumerate all data and erasing the target item.
> +  //
> +  IsItemFound = FALSE;
> +  ItemDataSize = (UINT32) DataSize;
> +  CertList = (EFI_SIGNATURE_LIST *) OldData;
> +  Offset = 0;
> +  GuidIndex = 0;
> +  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize))
> {
> +    if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) {
> +      //
> +      // Copy EFI_SIGNATURE_LIST header then calculate the signature count
> in this list.
> +      //
> +      CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) +
> CertList->SignatureHeaderSize));
> +      NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset);
> +      Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList-
> >SignatureHeaderSize);
> +      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++) {
> +        if (GuidIndex == DeleteIndex) {
> +          //
> +          // Find it! Skip it!
> +          //
> +          NewCertList->SignatureListSize -= CertList->SignatureSize;
> +          IsItemFound = TRUE;
> +        } else {
> +          //
> +          // This item doesn't match. Copy it to the Data buffer.
> +          //
> +          CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize);
> +          Offset += CertList->SignatureSize;
> +        }
> +        GuidIndex++;
> +        Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList-
> >SignatureSize);
> +      }
> +    } else {
> +      //
> +      // This List doesn't match. Just copy it to the Data buffer.
> +      //
> +      CopyMem (Data + Offset, (UINT8*)(CertList), CertList-
> >SignatureListSize);
> +      Offset += CertList->SignatureListSize;
> +    }
> +
> +    ItemDataSize -= CertList->SignatureListSize;
> +    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList-
> >SignatureListSize);
> +  }
> +
> +  if (!IsItemFound) {
> +    //
> +    // Doesn't find the signature Item!
> +    //
> +    Status = EFI_NOT_FOUND;
> +    goto ON_EXIT;
> +  }
> +
> +  //
> +  // Delete the EFI_SIGNATURE_LIST header if there is no signature in the
> list.
> +  //
> +  ItemDataSize = Offset;
> +  CertList = (EFI_SIGNATURE_LIST *) Data;
> +  Offset = 0;
> +  ZeroMem (OldData, ItemDataSize);
> +  while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize))
> {
> +    CertCount  = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) -
> CertList->SignatureHeaderSize) / CertList->SignatureSize;
> +    DEBUG ((DEBUG_INFO, "       CertCount = %x\n", CertCount));
> +    if (CertCount != 0) {
> +      CopyMem (OldData + Offset, (UINT8*)(CertList), CertList-
> >SignatureListSize);
> +      Offset += CertList->SignatureListSize;
> +    }
> +    ItemDataSize -= CertList->SignatureListSize;
> +    CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList-
> >SignatureListSize);
> +  }
> +
> +  DataSize = Offset;
> +
> +  Status = gRT->SetVariable(
> +                  VariableName,
> +                  VendorGuid,
> +                  Attr,
> +                  DataSize,
> +                  OldData
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status));
> +    goto ON_EXIT;
> +  }
> +
> +ON_EXIT:
> +  if (Data != NULL) {
> +    FreePool(Data);
> +  }
> +
> +  if (OldData != NULL) {
> +    FreePool(OldData);
> +  }
> +
> +  return UpdateDeletePage (
> +           Private,
> +           VariableName,
> +           VendorGuid,
> +           LabelNumber,
> +           FormId,
> +           QuestionIdBase
> +           );
> +}
> +
> +
> +/**
> +  Close an open file handle.
> +
> +  @param[in] FileHandle           The file handle to close.
> +
> +**/
> +VOID
> +CloseFile (
> +  IN EFI_FILE_HANDLE   FileHandle
> +  )
> +{
> +  if (FileHandle != NULL) {
> +    FileHandle->Close (FileHandle);
> +  }
> +}
> +
> +/**
> +  Read file content into BufferPtr, the size of the allocate buffer
> +  is *FileSize plus AddtionAllocateSize.
> +
> +  @param[in]       FileHandle            The file to be read.
> +  @param[in, out]  BufferPtr             Pointers to the pointer of allocated
> buffer.
> +  @param[out]      FileSize              Size of input file
> +  @param[in]       AddtionAllocateSize   Addtion size the buffer need to be
> allocated.
> +                                         In case the buffer need to contain others besides the
> file content.
> +
> +  @retval   EFI_SUCCESS                  The file was read into the buffer.
> +  @retval   EFI_INVALID_PARAMETER        A parameter was invalid.
> +  @retval   EFI_OUT_OF_RESOURCES         A memory allocation failed.
> +  @retval   others                       Unexpected error.
> +
> +**/
> +EFI_STATUS
> +ReadFileContent (
> +  IN      EFI_FILE_HANDLE           FileHandle,
> +  IN OUT  VOID                      **BufferPtr,
> +     OUT  UINTN                     *FileSize,
> +  IN      UINTN                     AddtionAllocateSize
> +  )
> +
> +{
> +  UINTN      BufferSize;
> +  UINT64     SourceFileSize;
> +  VOID       *Buffer;
> +  EFI_STATUS Status;
> +
> +  if ((FileHandle == NULL) || (FileSize == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Buffer = NULL;
> +
> +  //
> +  // Get the file size
> +  //
> +  Status = FileHandle->SetPosition (FileHandle, (UINT64) -1);
> +  if (EFI_ERROR (Status)) {
> +    goto ON_EXIT;
> +  }
> +
> +  Status = FileHandle->GetPosition (FileHandle, &SourceFileSize);
> +  if (EFI_ERROR (Status)) {
> +    goto ON_EXIT;
> +  }
> +
> +  Status = FileHandle->SetPosition (FileHandle, 0);
> +  if (EFI_ERROR (Status)) {
> +    goto ON_EXIT;
> +  }
> +
> +  BufferSize = (UINTN) SourceFileSize + AddtionAllocateSize;
> +  Buffer =  AllocateZeroPool(BufferSize);
> +  if (Buffer == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  BufferSize = (UINTN) SourceFileSize;
> +  *FileSize  = BufferSize;
> +
> +  Status = FileHandle->Read (FileHandle, &BufferSize, Buffer);
> +  if (EFI_ERROR (Status) || BufferSize != *FileSize) {
> +    FreePool (Buffer);
> +    Buffer = NULL;
> +    Status  = EFI_BAD_BUFFER_SIZE;
> +    goto ON_EXIT;
> +  }
> +
> +ON_EXIT:
> +
> +  *BufferPtr = Buffer;
> +  return Status;
> +}
> +
> +/**
> +  This function will open a file or directory referenced by DevicePath.
> +
> +  This function opens a file with the open mode according to the file path.
> The
> +  Attributes is valid only for EFI_FILE_MODE_CREATE.
> +
> +  @param[in, out]  FilePath        On input, the device path to the file.
> +                                   On output, the remaining device path.
> +  @param[out]      FileHandle      Pointer to the file handle.
> +  @param[in]       OpenMode        The mode to open the file with.
> +  @param[in]       Attributes      The file's file attributes.
> +
> +  @retval EFI_SUCCESS              The information was set.
> +  @retval EFI_INVALID_PARAMETER    One of the parameters has an invalid
> value.
> +  @retval EFI_UNSUPPORTED          Could not open the file path.
> +  @retval EFI_NOT_FOUND            The specified file could not be found on
> the
> +                                   device or the file system could not be found on
> +                                   the device.
> +  @retval EFI_NO_MEDIA             The device has no medium.
> +  @retval EFI_MEDIA_CHANGED        The device has a different medium in it
> or the
> +                                   medium is no longer supported.
> +  @retval EFI_DEVICE_ERROR         The device reported an error.
> +  @retval EFI_VOLUME_CORRUPTED     The file system structures are
> corrupted.
> +  @retval EFI_WRITE_PROTECTED      The file or medium is write protected.
> +  @retval EFI_ACCESS_DENIED        The file was opened read only.
> +  @retval EFI_OUT_OF_RESOURCES     Not enough resources were available
> to open the
> +                                   file.
> +  @retval EFI_VOLUME_FULL          The volume is full.
> +**/
> +EFI_STATUS
> +EFIAPI
> +OpenFileByDevicePath (
> +  IN OUT EFI_DEVICE_PATH_PROTOCOL     **FilePath,
> +  OUT EFI_FILE_HANDLE                 *FileHandle,
> +  IN UINT64                           OpenMode,
> +  IN UINT64                           Attributes
> +  )
> +{
> +  EFI_STATUS                      Status;
> +  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
> +  EFI_FILE_PROTOCOL               *Handle1;
> +  EFI_FILE_PROTOCOL               *Handle2;
> +  EFI_HANDLE                      DeviceHandle;
> +
> +  if ((FilePath == NULL || FileHandle == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Status = gBS->LocateDevicePath (
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  FilePath,
> +                  &DeviceHandle
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = gBS->OpenProtocol(
> +                  DeviceHandle,
> +                  &gEfiSimpleFileSystemProtocolGuid,
> +                  (VOID**)&EfiSimpleFileSystemProtocol,
> +                  gImageHandle,
> +                  NULL,
> +                  EFI_OPEN_PROTOCOL_GET_PROTOCOL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  Status = EfiSimpleFileSystemProtocol-
> >OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
> +  if (EFI_ERROR (Status)) {
> +    FileHandle = NULL;
> +    return Status;
> +  }
> +
> +  //
> +  // go down directories one node at a time.
> +  //
> +  while (!IsDevicePathEnd (*FilePath)) {
> +    //
> +    // For file system access each node should be a file path component
> +    //
> +    if (DevicePathType    (*FilePath) != MEDIA_DEVICE_PATH ||
> +        DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
> +       ) {
> +      FileHandle = NULL;
> +      return (EFI_INVALID_PARAMETER);
> +    }
> +    //
> +    // Open this file path node
> +    //
> +    Handle2  = Handle1;
> +    Handle1 = NULL;
> +
> +    //
> +    // Try to test opening an existing file
> +    //
> +    Status = Handle2->Open (
> +                        Handle2,
> +                        &Handle1,
> +                        ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
> +                        OpenMode &~EFI_FILE_MODE_CREATE,
> +                        0
> +                        );
> +
> +    //
> +    // see if the error was that it needs to be created
> +    //
> +    if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode
> &~EFI_FILE_MODE_CREATE))) {
> +      Status = Handle2->Open (
> +                          Handle2,
> +                          &Handle1,
> +                          ((FILEPATH_DEVICE_PATH*)*FilePath)->PathName,
> +                          OpenMode,
> +                          Attributes
> +                          );
> +    }
> +    //
> +    // Close the last node
> +    //
> +    Handle2->Close (Handle2);
> +
> +    if (EFI_ERROR(Status)) {
> +      return (Status);
> +    }
> +
> +    //
> +    // Get the next node
> +    //
> +    *FilePath = NextDevicePathNode (*FilePath);
> +  }
> +
> +  //
> +  // This is a weak spot since if the undefined SHELL_FILE_HANDLE format
> changes this must change also!
> +  //
> +  *FileHandle = (VOID*)Handle1;
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  This function converts an input device structure to a Unicode string.
> +
> +  @param[in] DevPath                  A pointer to the device path structure.
> +
> +  @return A new allocated Unicode string that represents the device path.
> +
> +**/
> +CHAR16 *
> +EFIAPI
> +DevicePathToStr (
> +  IN EFI_DEVICE_PATH_PROTOCOL     *DevPath
> +  )
> +{
> +  return ConvertDevicePathToText (
> +           DevPath,
> +           FALSE,
> +           TRUE
> +           );
> +}
> +
> +
> +/**
> +  Extract filename from device path. The returned buffer is allocated using
> AllocateCopyPool.
> +  The caller is responsible for freeing the allocated buffer using FreePool(). If
> return NULL
> +  means not enough memory resource.
> +
> +  @param DevicePath       Device path.
> +
> +  @retval NULL            Not enough memory resourece for AllocateCopyPool.
> +  @retval Other           A new allocated string that represents the file name.
> +
> +**/
> +CHAR16 *
> +ExtractFileNameFromDevicePath (
> +  IN   EFI_DEVICE_PATH_PROTOCOL *DevicePath
> +  )
> +{
> +  CHAR16          *String;
> +  CHAR16          *MatchString;
> +  CHAR16          *LastMatch;
> +  CHAR16          *FileName;
> +  UINTN           Length;
> +
> +  ASSERT(DevicePath != NULL);
> +
> +  String = DevicePathToStr(DevicePath);
> +  MatchString = String;
> +  LastMatch   = String;
> +  FileName    = NULL;
> +
> +  while(MatchString != NULL){
> +    LastMatch   = MatchString + 1;
> +    MatchString = StrStr(LastMatch,L"\\");
> +  }
> +
> +  Length = StrLen(LastMatch);
> +  FileName = AllocateCopyPool ((Length + 1) * sizeof(CHAR16), LastMatch);
> +  if (FileName != NULL) {
> +    *(FileName + Length) = 0;
> +  }
> +
> +  FreePool(String);
> +
> +  return FileName;
> +}
> +
> +/**
> +  Enroll a new X509 certificate into Variable.
> +
> +  @param[in] PrivateData     The module's private data.
> +  @param[in] VariableName    Variable name of CA database.
> +
> +  @retval   EFI_SUCCESS            New X509 is enrolled successfully.
> +  @retval   EFI_OUT_OF_RESOURCES   Could not allocate needed resources.
> +
> +**/
> +EFI_STATUS
> +EnrollX509toVariable (
> +  IN TLS_AUTH_CONFIG_PRIVATE_DATA   *Private,
> +  IN CHAR16                         *VariableName
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  UINTN                             X509DataSize;
> +  VOID                              *X509Data;
> +  EFI_SIGNATURE_LIST                *CACert;
> +  EFI_SIGNATURE_DATA                *CACertData;
> +  VOID                              *Data;
> +  UINTN                             DataSize;
> +  UINTN                             SigDataSize;
> +  UINT32                            Attr;
> +
> +  X509DataSize  = 0;
> +  SigDataSize   = 0;
> +  DataSize      = 0;
> +  X509Data      = NULL;
> +  CACert        = NULL;
> +  CACertData    = NULL;
> +  Data          = NULL;
> +
> +  Status = ReadFileContent (
> +             Private->FileContext->FHandle,
> +             &X509Data,
> +             &X509DataSize,
> +             0
> +             );
> +  if (EFI_ERROR (Status)) {
> +    goto ON_EXIT;
> +  }
> +  ASSERT (X509Data != NULL);
> +
> +  SigDataSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA)
> - 1 + X509DataSize;
> +
> +  Data = AllocateZeroPool (SigDataSize);
> +  if (Data == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto ON_EXIT;
> +  }
> +
> +  //
> +  // Fill Certificate Database parameters.
> +  //
> +  CACert = (EFI_SIGNATURE_LIST*) Data;
> +  CACert->SignatureListSize   = (UINT32) SigDataSize;
> +  CACert->SignatureHeaderSize = 0;
> +  CACert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 +
> X509DataSize);
> +  CopyGuid (&CACert->SignatureType, &gEfiCertX509Guid);
> +
> +  CACertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) CACert + sizeof
> (EFI_SIGNATURE_LIST));
> +  CopyGuid (&CACertData->SignatureOwner, Private->CertGuid);
> +  CopyMem ((UINT8* ) (CACertData->SignatureData), X509Data,
> X509DataSize);
> +
> +  //
> +  // Check if signature database entry has been already existed.
> +  // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the
> +  // new signature data to original variable
> +  //
> +  Attr = TLS_AUTH_CONFIG_VAR_BASE_ATTR;
> +
> +  Status = gRT->GetVariable(
> +                  VariableName,
> +                  &gEfiTlsCaCertificateGuid,
> +                  NULL,
> +                  &DataSize,
> +                  NULL
> +                  );
> +  if (Status == EFI_BUFFER_TOO_SMALL) {
> +    Attr |= EFI_VARIABLE_APPEND_WRITE;
> +  } else if (Status != EFI_NOT_FOUND) {
> +    goto ON_EXIT;
> +  }
> +
> +  Status = gRT->SetVariable(
> +                  VariableName,
> +                  &gEfiTlsCaCertificateGuid,
> +                  Attr,
> +                  SigDataSize,
> +                  Data
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    goto ON_EXIT;
> +  }
> +
> +ON_EXIT:
> +
> +  CloseFile (Private->FileContext->FHandle);
> +  if (Private->FileContext->FileName != NULL) {
> +    FreePool(Private->FileContext->FileName);
> +    Private->FileContext->FileName = NULL;
> +  }
> +
> +  Private->FileContext->FHandle = NULL;
> +
> +  if (Private->CertGuid != NULL) {
> +    FreePool (Private->CertGuid);
> +    Private->CertGuid = NULL;
> +  }
> +
> +  if (Data != NULL) {
> +    FreePool (Data);
> +  }
> +
> +  if (X509Data != NULL) {
> +    FreePool (X509Data);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +  Enroll Cert into TlsCaCertificate. The GUID will be Private->CertGuid.
> +
> +  @param[in] PrivateData     The module's private data.
> +  @param[in] VariableName    Variable name of signature database.
> +
> +  @retval   EFI_SUCCESS            New Cert enrolled successfully.
> +  @retval   EFI_INVALID_PARAMETER  The parameter is invalid.
> +  @retval   EFI_UNSUPPORTED        The Cert file is unsupported type.
> +  @retval   others                 Fail to enroll Cert data.
> +
> +**/
> +EFI_STATUS
> +EnrollCertDatabase (
> +  IN TLS_AUTH_CONFIG_PRIVATE_DATA  *Private,
> +  IN CHAR16                        *VariableName
> +  )
> +{
> +  UINT16*      FilePostFix;
> +  UINTN        NameLength;
> +
> +  if ((Private->FileContext->FileName == NULL) || (Private->FileContext-
> >FHandle == NULL) || (Private->CertGuid == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Parse the file's postfix.
> +  //
> +  NameLength = StrLen (Private->FileContext->FileName);
> +  if (NameLength <= 4) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  FilePostFix = Private->FileContext->FileName + NameLength - 4;
> +
> +  if (IsDerPemEncodeCertificate (FilePostFix)) {
> +    //
> +    // Supports DER-encoded X509 certificate.
> +    //
> +    return EnrollX509toVariable (Private, VariableName);
> +  }
> +
> +  return EFI_UNSUPPORTED;
> +}
> +
> +/**
> +  Refresh the global UpdateData structure.
> +
> +**/
> +VOID
> +RefreshUpdateData (
> +  VOID
> +  )
> +{
> +  //
> +  // Free current updated date
> +  //
> +  if (mStartOpCodeHandle != NULL) {
> +    HiiFreeOpCodeHandle (mStartOpCodeHandle);
> +  }
> +
> +  //
> +  // Create new OpCode Handle
> +  //
> +  mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
> +
> +  //
> +  // Create Hii Extend Label OpCode as the start opcode
> +  //
> +  mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
> +                                         mStartOpCodeHandle,
> +                                         &gEfiIfrTianoGuid,
> +                                         NULL,
> +                                         sizeof (EFI_IFR_GUID_LABEL)
> +                                         );
> +  mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
> +}
> +
> +/**
> +  Clean up the dynamic opcode at label and form specified by both LabelId.
> +
> +  @param[in] LabelId         It is both the Form ID and Label ID for opcode
> deletion.
> +  @param[in] PrivateData     Module private data.
> +
> +**/
> +VOID
> +CleanUpPage (
> +  IN UINT16                           LabelId,
> +  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *PrivateData
> +  )
> +{
> +  RefreshUpdateData ();
> +
> +  //
> +  // Remove all op-codes from dynamic page
> +  //
> +  mStartLabel->Number = LabelId;
> +  HiiUpdateForm (
> +    PrivateData->RegisteredHandle,
> +    &gTlsAuthConfigGuid,
> +    LabelId,
> +    mStartOpCodeHandle, // Label LabelId
> +    mEndOpCodeHandle    // LABEL_END
> +    );
> +}
> +
> +/**
> +  Update the form base on the selected file.
> +
> +  @param FilePath   Point to the file path.
> +  @param FormId     The form need to display.
> +
> +  @retval TRUE   Exit caller function.
> +  @retval FALSE  Not exit caller function.
> +
> +**/
> +BOOLEAN
> +UpdatePage(
> +  IN  EFI_DEVICE_PATH_PROTOCOL  *FilePath,
> +  IN  EFI_FORM_ID               FormId
> +  )
> +{
> +  CHAR16                *FileName;
> +  EFI_STRING_ID         StringToken;
> +
> +  FileName = NULL;
> +
> +  if (FilePath != NULL) {
> +    FileName = ExtractFileNameFromDevicePath(FilePath);
> +  }
> +  if (FileName == NULL) {
> +    //
> +    // FileName = NULL has two case:
> +    // 1. FilePath == NULL, not select file.
> +    // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL
> not enough memory resource.
> +    // In these two case, no need to update the form, and exit the caller
> function.
> +    //
> +    return TRUE;
> +  }
> +  StringToken =  HiiSetString (mTlsAuthPrivateData->RegisteredHandle, 0,
> FileName, NULL);
> +
> +  mTlsAuthPrivateData->FileContext->FileName = FileName;
> +
> +  OpenFileByDevicePath (
> +    &FilePath,
> +    &mTlsAuthPrivateData->FileContext->FHandle,
> +    EFI_FILE_MODE_READ,
> +    0
> +    );
> +  //
> +  // Create Subtitle op-code for the display string of the option.
> +  //
> +  RefreshUpdateData ();
> +  mStartLabel->Number = FormId;
> +
> +  HiiCreateSubTitleOpCode (
> +    mStartOpCodeHandle,
> +    StringToken,
> +    0,
> +    0,
> +    0
> +   );
> +
> +  HiiUpdateForm (
> +    mTlsAuthPrivateData->RegisteredHandle,
> +    &gTlsAuthConfigGuid,
> +    FormId,
> +    mStartOpCodeHandle, /// Label FormId
> +    mEndOpCodeHandle    /// LABEL_END
> +    );
> +
> +  return TRUE;
> +}
> +
> +/**
> +  Update the form base on the input file path info.
> +
> +  @param FilePath    Point to the file path.
> +
> +  @retval TRUE   Exit caller function.
> +  @retval FALSE  Not exit caller function.
> +**/
> +BOOLEAN
> +UpdateCAFromFile (
> +  IN EFI_DEVICE_PATH_PROTOCOL    *FilePath
> +  )
> +{
> +  return UpdatePage(FilePath, TLS_AUTH_CONFIG_FORMID4_FORM);
> +}
> +
> +/**
> +  Unload the configuration form, this includes: delete all the configuration
> +  entries, uninstall the form callback protocol, and free the resources used.
> +
> +  @param[in]  Private             Pointer to the driver private data.
> +
> +  @retval EFI_SUCCESS             The configuration form is unloaded.
> +  @retval Others                  Failed to unload the form.
> +
> +**/
> +EFI_STATUS
> +TlsAuthConfigFormUnload (
> +  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
> +  )
> +{
> +  if (Private->DriverHandle != NULL) {
> +    //
> +    // Uninstall EFI_HII_CONFIG_ACCESS_PROTOCOL
> +    //
> +    gBS->UninstallMultipleProtocolInterfaces (
> +           Private->DriverHandle,
> +           &gEfiDevicePathProtocolGuid,
> +           &mTlsAuthConfigHiiVendorDevicePath,
> +           &gEfiHiiConfigAccessProtocolGuid,
> +           &Private->ConfigAccess,
> +           NULL
> +           );
> +    Private->DriverHandle = NULL;
> +  }
> +
> +  if (Private->RegisteredHandle != NULL) {
> +    //
> +    // Remove HII package list
> +    //
> +    HiiRemovePackages (Private->RegisteredHandle);
> +    Private->RegisteredHandle = NULL;
> +  }
> +
> +  if (Private->CertGuid != NULL) {
> +    FreePool (Private->CertGuid);
> +  }
> +
> +  if (Private->FileContext != NULL) {
> +    FreePool (Private->FileContext);
> +  }
> +
> +  FreePool (Private);
> +
> +  if (mStartOpCodeHandle != NULL) {
> +    HiiFreeOpCodeHandle (mStartOpCodeHandle);
> +  }
> +
> +  if (mEndOpCodeHandle != NULL) {
> +    HiiFreeOpCodeHandle (mEndOpCodeHandle);
> +  }
> +
> +  return EFI_SUCCESS;
> +}
> +
> +
> +/**
> +  Initialize the configuration form.
> +
> +  @param[in]  Private             Pointer to the driver private data.
> +
> +  @retval EFI_SUCCESS             The configuration form is initialized.
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
> +
> +**/
> +EFI_STATUS
> +TlsAuthConfigFormInit (
> +  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
> +  )
> +{
> +  EFI_STATUS                        Status;
> +
> +  Private->Signature = TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE;
> +
> +  Private->ConfigAccess.ExtractConfig = TlsAuthConfigAccessExtractConfig;
> +  Private->ConfigAccess.RouteConfig   = TlsAuthConfigAccessRouteConfig;
> +  Private->ConfigAccess.Callback      = TlsAuthConfigAccessCallback;
> +
> +  //
> +  // Install Device Path Protocol and Config Access protocol to driver handle.
> +  //
> +  Status = gBS->InstallMultipleProtocolInterfaces (
> +                  &Private->DriverHandle,
> +                  &gEfiDevicePathProtocolGuid,
> +                  &mTlsAuthConfigHiiVendorDevicePath,
> +                  &gEfiHiiConfigAccessProtocolGuid,
> +                  &Private->ConfigAccess,
> +                  NULL
> +                  );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // Publish our HII data.
> +  //
> +  Private->RegisteredHandle = HiiAddPackages (
> +                                &gTlsAuthConfigGuid,
> +                                Private->DriverHandle,
> +                                TlsAuthConfigDxeStrings,
> +                                TlsAuthConfigVfrBin,
> +                                NULL
> +                                );
> +  if (Private->RegisteredHandle == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Error;
> +  }
> +
> +  Private->FileContext = AllocateZeroPool (sizeof
> (TLS_AUTH_CONFIG_FILE_CONTEXT));
> +  if (Private->FileContext == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Error;
> +  }
> +
> +  //
> +  // Init OpCode Handle and Allocate space for creation of Buffer
> +  //
> +  mStartOpCodeHandle = HiiAllocateOpCodeHandle ();
> +  if (mStartOpCodeHandle == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Error;
> +  }
> +
> +  mEndOpCodeHandle = HiiAllocateOpCodeHandle ();
> +  if (mEndOpCodeHandle == NULL) {
> +    Status = EFI_OUT_OF_RESOURCES;
> +    goto Error;
> +  }
> +
> +  //
> +  // Create Hii Extend Label OpCode as the start opcode
> +  //
> +  mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
> +                                         mStartOpCodeHandle,
> +                                         &gEfiIfrTianoGuid,
> +                                         NULL,
> +                                         sizeof (EFI_IFR_GUID_LABEL)
> +                                         );
> +  mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
> +
> +  //
> +  // Create Hii Extend Label OpCode as the end opcode
> +  //
> +  mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode (
> +                                       mEndOpCodeHandle,
> +                                       &gEfiIfrTianoGuid,
> +                                       NULL,
> +                                       sizeof (EFI_IFR_GUID_LABEL)
> +                                       );
> +  mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL;
> +  mEndLabel->Number       = LABEL_END;
> +
> +  return EFI_SUCCESS;
> +
> +Error:
> +  TlsAuthConfigFormUnload (Private);
> +  return Status;
> +}
> +
> +/**
> +
> +  This function allows the caller to request the current
> +  configuration for one or more named elements. The resulting
> +  string is in <ConfigAltResp> format. Any and all alternative
> +  configuration strings shall also be appended to the end of the
> +  current configuration string. If they are, they must appear
> +  after the current configuration. They must contain the same
> +  routing (GUID, NAME, PATH) as the current configuration string.
> +  They must have an additional description indicating the type of
> +  alternative configuration the string represents,
> +  "ALTCFG=<StringToken>". That <StringToken> (when
> +  converted from Hex UNICODE to binary) is a reference to a
> +  string in the associated string pack.
> +
> +  @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +
> +  @param Request    A null-terminated Unicode string in
> +                    <ConfigRequest> format. Note that this
> +                    includes the routing information as well as
> +                    the configurable name / value pairs. It is
> +                    invalid for this string to be in
> +                    <MultiConfigRequest> format.
> +                    If a NULL is passed in for the Request field,
> +                    all of the settings being abstracted by this function
> +                    will be returned in the Results field.  In addition,
> +                    if a ConfigHdr is passed in with no request elements,
> +                    all of the settings being abstracted for that particular
> +                    ConfigHdr reference will be returned in the Results Field.
> +
> +  @param Progress   On return, points to a character in the
> +                    Request string. Points to the string's null
> +                    terminator if request was successful. Points
> +                    to the most recent "&" before the first
> +                    failing name / value pair (or the beginning
> +                    of the string if the failure is in the first
> +                    name / value pair) if the request was not
> +                    successful.
> +
> +  @param Results    A null-terminated Unicode string in
> +                    <MultiConfigAltResp> format which has all values
> +                    filled in for the names in the Request string.
> +                    String to be allocated by the called function.
> +
> +  @retval EFI_SUCCESS             The Results string is filled with the
> +                                  values corresponding to all requested
> +                                  names.
> +
> +  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
> +                                  parts of the results that must be
> +                                  stored awaiting possible future
> +                                  protocols.
> +
> +  @retval EFI_NOT_FOUND           Routing data doesn't match any
> +                                  known driver. Progress set to the
> +                                  first character in the routing header.
> +                                  Note: There is no requirement that the
> +                                  driver validate the routing data. It
> +                                  must skip the <ConfigHdr> in order to
> +                                  process the names.
> +
> +  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
> +                                  to most recent "&" before the
> +                                  error or the beginning of the
> +                                  string.
> +
> +  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
> +                                  to the & before the name in
> +                                  question.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsAuthConfigAccessExtractConfig (
> +  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
> +  IN CONST  EFI_STRING                      Request,
> +  OUT       EFI_STRING                      *Progress,
> +  OUT       EFI_STRING                      *Results
> +  )
> +{
> +  EFI_STATUS                        Status;
> +  UINTN                             BufferSize;
> +  UINTN                             Size;
> +  EFI_STRING                        ConfigRequest;
> +  EFI_STRING                        ConfigRequestHdr;
> +  TLS_AUTH_CONFIG_PRIVATE_DATA      *Private;
> +  BOOLEAN                           AllocatedRequest;
> +
> +  if (Progress == NULL || Results == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  AllocatedRequest = FALSE;
> +  ConfigRequestHdr = NULL;
> +  ConfigRequest    = NULL;
> +  Size             = 0;
> +
> +  Private          = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
> +
> +  BufferSize       = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
> +  ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
> +
> +  *Progress        = Request;
> +
> +  if ((Request != NULL) && !HiiIsConfigHdrMatch (Request,
> &gTlsAuthConfigGuid, mTlsAuthConfigStorageName)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  ConfigRequest = Request;
> +  if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) {
> +    //
> +    // Request is set to NULL or OFFSET is NULL, construct full request string.
> +    //
> +    // Allocate and fill a buffer large enough to hold the <ConfigHdr>
> template
> +    // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW"
> followed by a Null-terminator
> +    //
> +    ConfigRequestHdr = HiiConstructConfigHdr (&gTlsAuthConfigGuid,
> mTlsAuthConfigStorageName, Private->DriverHandle);
> +    Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16);
> +    ConfigRequest = AllocateZeroPool (Size);
> +    ASSERT (ConfigRequest != NULL);
> +    AllocatedRequest = TRUE;
> +    UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX",
> ConfigRequestHdr, (UINT64)BufferSize);
> +    FreePool (ConfigRequestHdr);
> +    ConfigRequestHdr = NULL;
> +  }
> +
> +  Status = gHiiConfigRouting->BlockToConfig (
> +                                gHiiConfigRouting,
> +                                ConfigRequest,
> +                                (UINT8 *) &Private->TlsAuthConfigNvData,
> +                                BufferSize,
> +                                Results,
> +                                Progress
> +                                );
> +
> +  //
> +  // Free the allocated config request string.
> +  //
> +  if (AllocatedRequest) {
> +    FreePool (ConfigRequest);
> +  }
> +
> +  //
> +  // Set Progress string to the original request string.
> +  //
> +  if (Request == NULL) {
> +    *Progress = NULL;
> +  } else if (StrStr (Request, L"OFFSET") == NULL) {
> +    *Progress = Request + StrLen (Request);
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  This function applies changes in a driver's configuration.
> +  Input is a Configuration, which has the routing data for this
> +  driver followed by name / value configuration pairs. The driver
> +  must apply those pairs to its configurable storage. If the
> +  driver's configuration is stored in a linear block of data
> +  and the driver's name / value pairs are in <BlockConfig>
> +  format, it may use the ConfigToBlock helper function (above) to
> +  simplify the job.
> +
> +  @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +
> +  @param Configuration  A null-terminated Unicode string in
> +                        <ConfigString> format.
> +
> +  @param Progress       A pointer to a string filled in with the
> +                        offset of the most recent '&' before the
> +                        first failing name / value pair (or the
> +                        beginn ing of the string if the failure
> +                        is in the first name / value pair) or
> +                        the terminating NULL if all was
> +                        successful.
> +
> +  @retval EFI_SUCCESS             The results have been distributed or are
> +                                  awaiting distribution.
> +
> +  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
> +                                  parts of the results that must be
> +                                  stored awaiting possible future
> +                                  protocols.
> +
> +  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
> +                                  Results parameter would result
> +                                  in this type of error.
> +
> +  @retval EFI_NOT_FOUND           Target for the specified routing data
> +                                  was not found
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsAuthConfigAccessRouteConfig (
> +  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
> +  IN CONST  EFI_STRING                      Configuration,
> +  OUT       EFI_STRING                      *Progress
> +  )
> +{
> +  EFI_STATUS                       Status;
> +  UINTN                            BufferSize;
> +  TLS_AUTH_CONFIG_PRIVATE_DATA     *Private;
> +
> +  if (Progress == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +  *Progress = Configuration;
> +
> +  if (Configuration == NULL) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  //
> +  // Check routing data in <ConfigHdr>.
> +  // Note: there is no name for Name/Value storage, only GUID will be
> checked
> +  //
> +  if (!HiiIsConfigHdrMatch (Configuration, &gTlsAuthConfigGuid,
> mTlsAuthConfigStorageName)) {
> +    return EFI_NOT_FOUND;
> +  }
> +
> +  Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
> +
> +  BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
> +  ZeroMem (&Private->TlsAuthConfigNvData, BufferSize);
> +
> +  Status = gHiiConfigRouting->ConfigToBlock (
> +                                gHiiConfigRouting,
> +                                Configuration,
> +                                (UINT8 *) &Private->TlsAuthConfigNvData,
> +                                &BufferSize,
> +                                Progress
> +                                );
> +  if (EFI_ERROR (Status)) {
> +    return Status;
> +  }
> +
> +  return Status;
> +}
> +
> +/**
> +
> +  This function is called to provide results data to the driver.
> +  This data consists of a unique key that is used to identify
> +  which data is either being passed back or being asked for.
> +
> +  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Action                 Specifies the type of action taken by the browser.
> +  @param  QuestionId             A unique value which is sent to the original
> +                                 exporting driver so that it can identify the type
> +                                 of data to expect. The format of the data tends to
> +                                 vary based on the opcode that generated the callback.
> +  @param  Type                   The type of value for the question.
> +  @param  Value                  A pointer to the data being sent to the original
> +                                 exporting driver.
> +  @param  ActionRequest          On return, points to the action requested by
> the
> +                                 callback function.
> +
> +  @retval EFI_SUCCESS            The callback successfully handled the action.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold
> the
> +                                 variable and its data.
> +  @retval EFI_DEVICE_ERROR       The variable could not be saved.
> +  @retval EFI_UNSUPPORTED        The specified Action is not supported by
> the
> +                                 callback.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsAuthConfigAccessCallback (
> +  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
> +  IN     EFI_BROWSER_ACTION                     Action,
> +  IN     EFI_QUESTION_ID                        QuestionId,
> +  IN     UINT8                                  Type,
> +  IN OUT EFI_IFR_TYPE_VALUE                     *Value,
> +  OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
> +  )
> +{
> +  EFI_INPUT_KEY                   Key;
> +  EFI_STATUS                      Status;
> +  TLS_AUTH_CONFIG_PRIVATE_DATA    *Private;
> +  UINTN                           BufferSize;
> +  TLS_AUTH_CONFIG_IFR_NVDATA      *IfrNvData;
> +  UINT16                          LabelId;
> +  EFI_DEVICE_PATH_PROTOCOL        *File;
> +
> +  Status           = EFI_SUCCESS;
> +  File             = NULL;
> +
> +  if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) {
> +    return EFI_INVALID_PARAMETER;
> +  }
> +
> +  Private = TLS_AUTH_CONFIG_PRIVATE_FROM_THIS (This);
> +
> +  mTlsAuthPrivateData = Private;
> +
> +  //
> +  // Retrieve uncommitted data from Browser
> +  //
> +  BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
> +  IfrNvData = AllocateZeroPool (BufferSize);
> +  if (IfrNvData == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  HiiGetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName,
> BufferSize, (UINT8 *) IfrNvData);
> +
> +  if ((Action != EFI_BROWSER_ACTION_CHANGED) &&
> +      (Action != EFI_BROWSER_ACTION_CHANGING)) {
> +    Status = EFI_UNSUPPORTED;
> +    goto EXIT;
> +  }
> +
> +  if (Action == EFI_BROWSER_ACTION_CHANGING) {
> +    switch (QuestionId) {
> +    case KEY_TLS_AUTH_CONFIG_CLIENT_CERT:
> +    case KEY_TLS_AUTH_CONFIG_SERVER_CA:
> +      //
> +      // Clear Cert GUID.
> +      //
> +      ZeroMem (IfrNvData->CertGuid, sizeof (IfrNvData->CertGuid));
> +      if (Private->CertGuid == NULL) {
> +        Private->CertGuid = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID));
> +        if (Private->CertGuid == NULL) {
> +          return EFI_OUT_OF_RESOURCES;
> +        }
> +      }
> +      if (QuestionId == KEY_TLS_AUTH_CONFIG_CLIENT_CERT) {
> +        LabelId = TLS_AUTH_CONFIG_FORMID3_FORM;
> +      } else if (QuestionId == KEY_TLS_AUTH_CONFIG_SERVER_CA) {
> +        LabelId = TLS_AUTH_CONFIG_FORMID4_FORM;
> +      }
> +
> +      //
> +      // Refresh selected file.
> +      //
> +      CleanUpPage (LabelId, Private);
> +      break;
> +    case KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE:
> +      ChooseFile( NULL, NULL, (CHOOSE_HANDLER) UpdateCAFromFile, &File);
> +      break;
> +
> +    case KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT:
> +      Status = EnrollCertDatabase (Private,
> EFI_TLS_CA_CERTIFICATE_VARIABLE);
> +      if (EFI_ERROR (Status)) {
> +        CreatePopUp (
> +          EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE,
> +          &Key,
> +          L"ERROR: Enroll Cert Failure!",
> +          NULL
> +          );
> +      }
> +      break;
> +
> +    case KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT:
> +      if (Private->FileContext->FHandle != NULL) {
> +        CloseFile (Private->FileContext->FHandle);
> +        Private->FileContext->FHandle = NULL;
> +        if (Private->FileContext->FileName!= NULL){
> +          FreePool(Private->FileContext->FileName);
> +          Private->FileContext->FileName = NULL;
> +        }
> +      }
> +
> +      if (Private->CertGuid!= NULL) {
> +        FreePool (Private->CertGuid);
> +        Private->CertGuid = NULL;
> +      }
> +      break;
> +
> +    case KEY_TLS_AUTH_CONFIG_DELETE_CERT:
> +      UpdateDeletePage (
> +        Private,
> +        EFI_TLS_CA_CERTIFICATE_VARIABLE,
> +        &gEfiTlsCaCertificateGuid,
> +        LABEL_CA_DELETE,
> +        TLS_AUTH_CONFIG_FORMID5_FORM,
> +        OPTION_DEL_CA_ESTION_ID
> +        );
> +       break;
> +
> +    default:
> +      if ((QuestionId >= OPTION_DEL_CA_ESTION_ID) &&
> +                 (QuestionId < (OPTION_DEL_CA_ESTION_ID +
> OPTION_CONFIG_RANGE)))  {
> +        DeleteCert (
> +          Private,
> +          EFI_TLS_CA_CERTIFICATE_VARIABLE,
> +          &gEfiTlsCaCertificateGuid,
> +          LABEL_CA_DELETE,
> +          TLS_AUTH_CONFIG_FORMID5_FORM,
> +          OPTION_DEL_CA_ESTION_ID,
> +          QuestionId - OPTION_DEL_CA_ESTION_ID
> +          );
> +      }
> +      break;
> +    }
> +  } else if (Action == EFI_BROWSER_ACTION_CHANGED) {
> +    switch (QuestionId) {
> +    case KEY_TLS_AUTH_CONFIG_CERT_GUID:
> +      ASSERT (Private->CertGuid != NULL);
> +      Status = StringToGuid (
> +                 IfrNvData->CertGuid,
> +                 StrLen (IfrNvData->CertGuid),
> +                 Private->CertGuid
> +                 );
> +      if (EFI_ERROR (Status)) {
> +        break;
> +      }
> +
> +      *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY;
> +      break;
> +    default:
> +      break;
> +    }
> +  }
> +
> +EXIT:
> +
> +  if (!EFI_ERROR (Status)) {
> +    BufferSize = sizeof (TLS_AUTH_CONFIG_IFR_NVDATA);
> +    HiiSetBrowserData (&gTlsAuthConfigGuid, mTlsAuthConfigStorageName,
> BufferSize, (UINT8*) IfrNvData, NULL);
> +  }
> +
> +  FreePool (IfrNvData);
> +
> +  if (File != NULL){
> +    FreePool(File);
> +    File = NULL;
> +  }
> +
> +  return EFI_SUCCESS;
> +
> +}
> diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
> b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
> new file mode 100644
> index 0000000..398f7b6
> --- /dev/null
> +++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigImpl.h
> @@ -0,0 +1,282 @@
> +/** @file
> +  Header file of Miscellaneous Routines for TlsAuthConfigDxe 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 __TLS_AUTH_CONFIG_IMPL_H__
> +#define __TLS_AUTH_CONFIG_IMPL_H__
> +
> +#include <Uefi.h>
> +
> +#include <Protocol/HiiConfigAccess.h>
> +#include <Protocol/SimpleFileSystem.h>
> +
> +//
> +// Libraries
> +//
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiRuntimeServicesTableLib.h>
> +#include <Library/MemoryAllocationLib.h>
> +#include <Library/BaseMemoryLib.h>
> +#include <Library/BaseLib.h>
> +#include <Library/UefiLib.h>
> +#include <Library/DebugLib.h>
> +#include <Library/DevicePathLib.h>
> +#include <Library/HiiLib.h>
> +#include <Library/UefiHiiServicesLib.h>
> +#include <Library/FileExplorerLib.h>
> +#include <Library/PrintLib.h>
> +
> +#include <Guid/MdeModuleHii.h>
> +#include <Guid/ImageAuthentication.h>
> +#include <Guid/TlsAuthentication.h>
> +
> +
> +//
> +// Include files with function prototypes
> +//
> +#include "TlsAuthConfigNvData.h"
> +
> +extern   UINT8       TlsAuthConfigDxeStrings[];
> +extern   UINT8       TlsAuthConfigVfrBin[];
> +
> +#define TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE    SIGNATURE_32
> ('T', 'A', 'C', 'D')
> +#define TLS_AUTH_CONFIG_PRIVATE_FROM_THIS(a)      CR (a,
> TLS_AUTH_CONFIG_PRIVATE_DATA, ConfigAccess,
> TLS_AUTH_CONFIG_PRIVATE_DATA_SIGNATURE)
> +
> +#define TLS_AUTH_CONFIG_VAR_BASE_ATTR
> (EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS)
> +
> +typedef struct _TLS_AUTH_CONFIG_PRIVATE_DATA
> TLS_AUTH_CONFIG_PRIVATE_DATA;
> +typedef struct _TLS_AUTH_CONFIG_FILE_CONTEXT
> TLS_AUTH_CONFIG_FILE_CONTEXT;
> +
> +///
> +/// HII specific Vendor Device Path definition.
> +///
> +typedef struct {
> +  VENDOR_DEVICE_PATH                VendorDevicePath;
> +  EFI_DEVICE_PATH_PROTOCOL          End;
> +} HII_VENDOR_DEVICE_PATH;
> +
> +struct _TLS_AUTH_CONFIG_FILE_CONTEXT {
> +  EFI_FILE_HANDLE                   FHandle;
> +  UINT16                            *FileName;
> +};
> +
> +struct _TLS_AUTH_CONFIG_PRIVATE_DATA {
> +  UINTN                             Signature;
> +
> +  EFI_HANDLE                        DriverHandle;
> +  EFI_HII_HANDLE                    RegisteredHandle;
> +  EFI_HII_CONFIG_ACCESS_PROTOCOL    ConfigAccess;
> +  TLS_AUTH_CONFIG_IFR_NVDATA        TlsAuthConfigNvData;
> +
> +  TLS_AUTH_CONFIG_FILE_CONTEXT      *FileContext;
> +
> +  EFI_GUID                          *CertGuid;
> +};
> +
> +/**
> +  Unload the configuration form, this includes: delete all the configuration
> +  entries, uninstall the form callback protocol, and free the resources used.
> +  The form will only be unload completely when both IP4 and IP6 stack are
> stopped.
> +
> +  @param[in]  Private             Pointer to the driver private data.
> +
> +  @retval EFI_SUCCESS             The configuration form is unloaded.
> +  @retval Others                  Failed to unload the form.
> +
> +**/
> +EFI_STATUS
> +TlsAuthConfigFormUnload (
> +  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
> +  );
> +
> +/**
> +  Initialize the configuration form.
> +
> +  @param[in]  Private             Pointer to the driver private data.
> +
> +  @retval EFI_SUCCESS             The configuration form is initialized.
> +  @retval EFI_OUT_OF_RESOURCES    Failed to allocate memory.
> +
> +**/
> +EFI_STATUS
> +TlsAuthConfigFormInit (
> +  IN TLS_AUTH_CONFIG_PRIVATE_DATA     *Private
> +  );
> +
> +/**
> +
> +  This function allows the caller to request the current
> +  configuration for one or more named elements. The resulting
> +  string is in <ConfigAltResp> format. Any and all alternative
> +  configuration strings shall also be appended to the end of the
> +  current configuration string. If they are, they must appear
> +  after the current configuration. They must contain the same
> +  routing (GUID, NAME, PATH) as the current configuration string.
> +  They must have an additional description indicating the type of
> +  alternative configuration the string represents,
> +  "ALTCFG=<StringToken>". That <StringToken> (when
> +  converted from Hex UNICODE to binary) is a reference to a
> +  string in the associated string pack.
> +
> +  @param This       Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +
> +  @param Request    A null-terminated Unicode string in
> +                    <ConfigRequest> format. Note that this
> +                    includes the routing information as well as
> +                    the configurable name / value pairs. It is
> +                    invalid for this string to be in
> +                    <MultiConfigRequest> format.
> +                    If a NULL is passed in for the Request field,
> +                    all of the settings being abstracted by this function
> +                    will be returned in the Results field.  In addition,
> +                    if a ConfigHdr is passed in with no request elements,
> +                    all of the settings being abstracted for that particular
> +                    ConfigHdr reference will be returned in the Results Field.
> +
> +  @param Progress   On return, points to a character in the
> +                    Request string. Points to the string's null
> +                    terminator if request was successful. Points
> +                    to the most recent "&" before the first
> +                    failing name / value pair (or the beginning
> +                    of the string if the failure is in the first
> +                    name / value pair) if the request was not
> +                    successful.
> +
> +  @param Results    A null-terminated Unicode string in
> +                    <MultiConfigAltResp> format which has all values
> +                    filled in for the names in the Request string.
> +                    String to be allocated by the called function.
> +
> +  @retval EFI_SUCCESS             The Results string is filled with the
> +                                  values corresponding to all requested
> +                                  names.
> +
> +  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
> +                                  parts of the results that must be
> +                                  stored awaiting possible future
> +                                  protocols.
> +
> +  @retval EFI_NOT_FOUND           Routing data doesn't match any
> +                                  known driver. Progress set to the
> +                                  first character in the routing header.
> +                                  Note: There is no requirement that the
> +                                  driver validate the routing data. It
> +                                  must skip the <ConfigHdr> in order to
> +                                  process the names.
> +
> +  @retval EFI_INVALID_PARAMETER   Illegal syntax. Progress set
> +                                  to most recent "&" before the
> +                                  error or the beginning of the
> +                                  string.
> +
> +  @retval EFI_INVALID_PARAMETER   Unknown name. Progress points
> +                                  to the & before the name in
> +                                  question.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsAuthConfigAccessExtractConfig (
> +  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
> +  IN CONST  EFI_STRING                      Request,
> +  OUT       EFI_STRING                      *Progress,
> +  OUT       EFI_STRING                      *Results
> +  );
> +
> +/**
> +
> +  This function applies changes in a driver's configuration.
> +  Input is a Configuration, which has the routing data for this
> +  driver followed by name / value configuration pairs. The driver
> +  must apply those pairs to its configurable storage. If the
> +  driver's configuration is stored in a linear block of data
> +  and the driver's name / value pairs are in <BlockConfig>
> +  format, it may use the ConfigToBlock helper function (above) to
> +  simplify the job.
> +
> +  @param This           Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +
> +  @param Configuration  A null-terminated Unicode string in
> +                        <ConfigString> format.
> +
> +  @param Progress       A pointer to a string filled in with the
> +                        offset of the most recent '&' before the
> +                        first failing name / value pair (or the
> +                        beginn ing of the string if the failure
> +                        is in the first name / value pair) or
> +                        the terminating NULL if all was
> +                        successful.
> +
> +  @retval EFI_SUCCESS             The results have been distributed or are
> +                                  awaiting distribution.
> +
> +  @retval EFI_OUT_OF_RESOURCES    Not enough memory to store the
> +                                  parts of the results that must be
> +                                  stored awaiting possible future
> +                                  protocols.
> +
> +  @retval EFI_INVALID_PARAMETERS  Passing in a NULL for the
> +                                  Results parameter would result
> +                                  in this type of error.
> +
> +  @retval EFI_NOT_FOUND           Target for the specified routing data
> +                                  was not found
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsAuthConfigAccessRouteConfig (
> +  IN CONST  EFI_HII_CONFIG_ACCESS_PROTOCOL  *This,
> +  IN CONST  EFI_STRING                      Configuration,
> +  OUT       EFI_STRING                      *Progress
> +  );
> +
> +/**
> +
> +  This function is called to provide results data to the driver.
> +  This data consists of a unique key that is used to identify
> +  which data is either being passed back or being asked for.
> +
> +  @param  This                   Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL.
> +  @param  Action                 Specifies the type of action taken by the browser.
> +  @param  QuestionId             A unique value which is sent to the original
> +                                 exporting driver so that it can identify the type
> +                                 of data to expect. The format of the data tends to
> +                                 vary based on the opcode that generated the callback.
> +  @param  Type                   The type of value for the question.
> +  @param  Value                  A pointer to the data being sent to the original
> +                                 exporting driver.
> +  @param  ActionRequest          On return, points to the action requested by
> the
> +                                 callback function.
> +
> +  @retval EFI_SUCCESS            The callback successfully handled the action.
> +  @retval EFI_OUT_OF_RESOURCES   Not enough storage is available to hold
> the
> +                                 variable and its data.
> +  @retval EFI_DEVICE_ERROR       The variable could not be saved.
> +  @retval EFI_UNSUPPORTED        The specified Action is not supported by
> the
> +                                 callback.
> +**/
> +EFI_STATUS
> +EFIAPI
> +TlsAuthConfigAccessCallback (
> +  IN     CONST EFI_HII_CONFIG_ACCESS_PROTOCOL   *This,
> +  IN     EFI_BROWSER_ACTION                     Action,
> +  IN     EFI_QUESTION_ID                        QuestionId,
> +  IN     UINT8                                  Type,
> +  IN OUT EFI_IFR_TYPE_VALUE                     *Value,
> +  OUT    EFI_BROWSER_ACTION_REQUEST             *ActionRequest
> +  );
> +
> +#endif
> +
> diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
> b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
> new file mode 100644
> index 0000000..f453201
> --- /dev/null
> +++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigNvData.h
> @@ -0,0 +1,49 @@
> +/** @file
> +  Header file for NV data structure definition.
> +
> +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 __TLS_AUTH_CONFIG_NV_DATA_H__
> +#define __TLS_AUTH_CONFIG_NV_DATA_H__
> +
> +#include <Guid/TlsAuthConfigHii.h>
> +
> +#define TLS_AUTH_CONFIG_GUID_SIZE                 36
> +#define TLS_AUTH_CONFIG_GUID_STORAGE_SIZE         37
> +
> +#define TLS_AUTH_CONFIG_FORMID1_FORM              1
> +#define TLS_AUTH_CONFIG_FORMID2_FORM              2
> +#define TLS_AUTH_CONFIG_FORMID3_FORM              3
> +#define TLS_AUTH_CONFIG_FORMID4_FORM              4
> +#define TLS_AUTH_CONFIG_FORMID5_FORM              5
> +
> +
> +#define KEY_TLS_AUTH_CONFIG_SERVER_CA                  0x1000
> +#define KEY_TLS_AUTH_CONFIG_CLIENT_CERT                0x1001
> +#define KEY_TLS_AUTH_CONFIG_ENROLL_CERT                0x1002
> +#define KEY_TLS_AUTH_CONFIG_DELETE_CERT                0x1003
> +#define KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE      0x1004
> +#define KEY_TLS_AUTH_CONFIG_CERT_GUID                  0x1005
> +#define KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT        0x1006
> +#define KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT     0x1007
> +
> +#define OPTION_DEL_CA_ESTION_ID                        0x2000
> +#define OPTION_CONFIG_RANGE                            0x1000
> +
> +#define LABEL_CA_DELETE                                0x1101
> +#define LABEL_END                                      0xffff
> +
> +typedef struct {
> +  CHAR16    CertGuid[TLS_AUTH_CONFIG_GUID_STORAGE_SIZE];
> +} TLS_AUTH_CONFIG_IFR_NVDATA;
> +
> +#endif
> diff --git a/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
> b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
> new file mode 100644
> index 0000000..fb130d9
> --- /dev/null
> +++ b/NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigVfr.vfr
> @@ -0,0 +1,152 @@
> +/** @file
> +  VFR file used by TlsAuthConfigDxe 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.
> +
> +**/
> +
> +#include "TlsAuthConfigNvData.h"
> +
> +formset
> +  guid   = TLS_AUTH_CONFIG_GUID,
> +  title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_TITLE),
> +  help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_HELP),
> +
> +  varstore TLS_AUTH_CONFIG_IFR_NVDATA,
> +    name = TLS_AUTH_CONFIG_IFR_NVDATA,
> +    guid = TLS_AUTH_CONFIG_GUID;
> +
> +  //
> +  // ##1 Form1: Main form for Tls Auth configration
> +  //
> +  form formid = TLS_AUTH_CONFIG_FORMID1_FORM,
> +    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_TITLE);
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    //
> +    // Display Server CA configration
> +    //
> +    goto TLS_AUTH_CONFIG_FORMID2_FORM,
> +         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA),
> +         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA_HELP),
> +         flags  = INTERACTIVE,
> +         key    = KEY_TLS_AUTH_CONFIG_SERVER_CA;
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    //
> +    // Display Client cert configration
> +    //
> +    grayoutif TRUE; /// Current unsupported.
> +    goto TLS_AUTH_CONFIG_FORMID3_FORM,
> +         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT),
> +         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT_HELP),
> +         flags  = INTERACTIVE,
> +         key    = KEY_TLS_AUTH_CONFIG_CLIENT_CERT;
> +    endif;
> +  endform;
> +
> +  //
> +  // ##2 Form2: CA configuration
> +  //
> +  form formid = TLS_AUTH_CONFIG_FORMID2_FORM,
> +    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SERVER_CA);
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    goto TLS_AUTH_CONFIG_FORMID4_FORM,
> +         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT),
> +         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT_HELP),
> +         flags  = INTERACTIVE,
> +         key    = KEY_TLS_AUTH_CONFIG_ENROLL_CERT;
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    goto TLS_AUTH_CONFIG_FORMID5_FORM,
> +         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT),
> +         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT_HELP),
> +         flags  = INTERACTIVE,
> +         key    = KEY_TLS_AUTH_CONFIG_DELETE_CERT;
> +  endform;
> +
> +  //
> +  // ##3 Form3 : Client cert configuration
> +  //
> +  form formid = TLS_AUTH_CONFIG_FORMID3_FORM,
> +    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CLIENT_CERT);
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +  //
> +  // TODO...
> +  //
> +  endform;
> +
> +  //
> +  // ##4 Form4: Enroll cert for CA
> +  //
> +  form formid = TLS_AUTH_CONFIG_FORMID4_FORM,
> +    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ENROLL_CERT);
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    goto TLS_AUTH_CONFIG_FORMID4_FORM,
> +         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ADD_CERT_FILE),
> +         help = STRING_TOKEN(STR_TLS_AUTH_CONFIG_ADD_CERT_FILE),
> +         flags = INTERACTIVE,
> +         key = KEY_TLS_AUTH_CONFIG_ENROLL_CERT_FROM_FILE;
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +    label TLS_AUTH_CONFIG_FORMID4_FORM;
> +    label LABEL_END;
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    string  varid   = TLS_AUTH_CONFIG_IFR_NVDATA.CertGuid,
> +            prompt  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CERT_GUID),
> +            help    = STRING_TOKEN(STR_TLS_AUTH_CONFIG_CERT_GUID_HELP),
> +            flags   = INTERACTIVE,
> +            key     = KEY_TLS_AUTH_CONFIG_CERT_GUID,
> +            minsize = TLS_AUTH_CONFIG_GUID_SIZE,
> +            maxsize = TLS_AUTH_CONFIG_GUID_SIZE,
> +    endstring;
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +    goto TLS_AUTH_CONFIG_FORMID1_FORM,
> +         prompt = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT),
> +         help   = STRING_TOKEN(STR_TLS_AUTH_CONFIG_SAVE_AND_EXIT),
> +         flags  = INTERACTIVE,
> +         key    = KEY_TLS_AUTH_CONFIG_VALUE_SAVE_AND_EXIT;
> +
> +    goto TLS_AUTH_CONFIG_FORMID1_FORM,
> +         prompt =
> STRING_TOKEN(STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT),
> +         help   =
> STRING_TOKEN(STR_TLS_AUTH_CONFIG_NO_SAVE_AND_EXIT),
> +         flags  = INTERACTIVE,
> +         key    = KEY_TLS_AUTH_CONFIG_VALUE_NO_SAVE_AND_EXIT;
> +
> +  endform;
> +
> +  //
> +  // ##5 Form5: Delete cert for CA
> +  //
> +  form formid = TLS_AUTH_CONFIG_FORMID5_FORM,
> +    title  = STRING_TOKEN(STR_TLS_AUTH_CONFIG_DELETE_CERT);
> +
> +    label LABEL_CA_DELETE;
> +    label LABEL_END;
> +
> +    subtitle text = STRING_TOKEN(STR_NULL);
> +
> +  endform;
> +
> +endformset;
> --
> 1.9.5.msysgit.1


^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6
  2016-12-14  7:34 ` [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6 Jiaxin Wu
  2016-12-15  2:39   ` Fu, Siyuan
@ 2016-12-22  7:33   ` Ye, Ting
  2016-12-22  8:30     ` Wu, Jiaxin
  1 sibling, 1 reply; 37+ messages in thread
From: Ye, Ting @ 2016-12-22  7:33 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Fu, Siyuan, Zhang, Lubo, Long, Qin, Thomas Palmer

Hi Jiaxin,

Some comments included below.

1. In TlsConfigCertificate, HttpInstance->TlsConfigData.CACert is not used and local variable "CACert" is not freed after calling TlsConfiguration->SetData.
2. In TlsConfigureSession, several gotos are useless. Suggest to replace with return status directly.
3.  This two parts will be ==> These

Others are good to me.

Reviewed-by: Ye Ting <ting.ye@intel.com>

Best Regards,
Ye Ting



-----Original Message-----
From: Wu, Jiaxin 
Sent: Wednesday, December 14, 2016 3:34 PM
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


^ permalink raw reply related	[flat|nested] 37+ messages in thread

* Re: [Patch 08/10] NetworkPkg/NetworkPkg.dsc: Enable TlsDxe and TlsAuthConfigDxe module
  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
  1 sibling, 0 replies; 37+ messages in thread
From: Ye, Ting @ 2016-12-22  7:37 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Fu, Siyuan, Zhang, Lubo, Long, Qin, Thomas Palmer

Reviewed-by: Ye Ting <ting.ye@intel.com> 

-----Original Message-----
From: Wu, Jiaxin 
Sent: Wednesday, December 14, 2016 3:34 PM
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 08/10] NetworkPkg/NetworkPkg.dsc: Enable TlsDxe and TlsAuthConfigDxe module

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/NetworkPkg.dsc | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/NetworkPkg/NetworkPkg.dsc b/NetworkPkg/NetworkPkg.dsc index 1ef353e..3d881e9 100644
--- a/NetworkPkg/NetworkPkg.dsc
+++ b/NetworkPkg/NetworkPkg.dsc
@@ -53,12 +53,14 @@
   TcpIoLib|MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf
   HttpLib|MdeModulePkg/Library/DxeHttpLib/DxeHttpLib.inf
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
   OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
   IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+  TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf
   DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf  
   FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+  
+ FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.i
+ nf
   SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
 
 [LibraryClasses.common.UEFI_DRIVER]
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
@@ -111,10 +113,12 @@
   NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf
   NetworkPkg/DnsDxe/DnsDxe.inf
   NetworkPkg/HttpDxe/HttpDxe.inf
   NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf
   NetworkPkg/HttpBootDxe/HttpBootDxe.inf
+  NetworkPkg/TlsDxe/TlsDxe.inf
+  NetworkPkg/TlsAuthConfigDxe/TlsAuthConfigDxe.inf
 
   NetworkPkg/Application/IfConfig6/IfConfig6.inf
   NetworkPkg/Application/IpsecConfig/IpSecConfig.inf
   NetworkPkg/Application/VConfig/VConfig.inf
 
--
1.9.5.msysgit.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 09/10] Nt32Pkg/Nt32Pkg.dsc: Remove the flag for OpensslLib and BaseCryptLib
  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
  2 siblings, 0 replies; 37+ messages in thread
From: Ye, Ting @ 2016-12-22  7:39 UTC (permalink / raw)
  To: Wu, Jiaxin, edk2-devel@lists.01.org
  Cc: Long, Qin, Ni, Ruiyu, Fu, Siyuan, Zhang, Lubo, Thomas Palmer

Reviewed-by: Ye Ting <ting.ye@intel.com> 

-----Original Message-----
From: Wu, Jiaxin 
Sent: Wednesday, December 14, 2016 3:34 PM
To: edk2-devel@lists.01.org
Cc: Long, Qin <qin.long@intel.com>; Ni, Ruiyu <ruiyu.ni@intel.com>; Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>; Wu, Jiaxin <jiaxin.wu@intel.com>
Subject: [Patch 09/10] Nt32Pkg/Nt32Pkg.dsc: Remove the flag for OpensslLib and BaseCryptLib

This patch is used to remove the 'SECURE_BOOT_ENABLE' flag for OpensslLib and BaseCryptLib modules.

Cc: Long Qin <qin.long@intel.com>
Cc: Ni Ruiyu <ruiyu.ni@intel.com>
Cc: Ye Ting <ting.ye@intel.com>
Cc: Fu Siyuan <siyuan.fu@intel.com>
Cc: Zhang Lubo <lubo.zhang@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>
---
 Nt32Pkg/Nt32Pkg.dsc | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/Nt32Pkg/Nt32Pkg.dsc b/Nt32Pkg/Nt32Pkg.dsc index 4458c02..79ab2f7 100644
--- a/Nt32Pkg/Nt32Pkg.dsc
+++ b/Nt32Pkg/Nt32Pkg.dsc
@@ -131,15 +131,15 @@
   DebugPrintErrorLevelLib|MdeModulePkg/Library/DxeDebugPrintErrorLevelLib/DxeDebugPrintErrorLevelLib.inf
   PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
   DebugAgentLib|MdeModulePkg/Library/DebugAgentLibNull/DebugAgentLibNull.inf
   CpuExceptionHandlerLib|MdeModulePkg/Library/CpuExceptionHandlerLibNull/CpuExceptionHandlerLibNull.inf
   LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf
+  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
+  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
   
 !if $(SECURE_BOOT_ENABLE) == TRUE
   PlatformSecureLib|Nt32Pkg/Library/PlatformSecureLib/PlatformSecureLib.inf
-  IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf
-  OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
   TpmMeasurementLib|SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.inf
   AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf
 !else
   TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf
   AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf
@@ -173,13 +173,11 @@
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
 
 [LibraryClasses.common.PEIM]
   PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
   OemHookStatusCodeLib|Nt32Pkg/Library/PeiNt32OemHookStatusCodeLib/PeiNt32OemHookStatusCodeLib.inf
-!if $(SECURE_BOOT_ENABLE) == TRUE  
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
-!endif
 
 [LibraryClasses.common]
   #
   # DXE phase common
   #
@@ -190,13 +188,11 @@
   ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf
   OemHookStatusCodeLib|Nt32Pkg/Library/DxeNt32OemHookStatusCodeLib/DxeNt32OemHookStatusCodeLib.inf
   PeCoffExtraActionLib|Nt32Pkg/Library/DxeNt32PeCoffExtraActionLib/DxeNt32PeCoffExtraActionLib.inf
   ExtractGuidedSectionLib|MdePkg/Library/DxeExtractGuidedSectionLib/DxeExtractGuidedSectionLib.inf
   WinNtLib|Nt32Pkg/Library/DxeWinNtLib/DxeWinNtLib.inf
-!if $(SECURE_BOOT_ENABLE) == TRUE
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
-!endif
 
 [LibraryClasses.common.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
   MemoryAllocationLib|MdeModulePkg/Library/DxeCoreMemoryAllocationLib/DxeCoreMemoryAllocationLib.inf
   PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
@@ -213,13 +209,11 @@
   
 [LibraryClasses.common.DXE_RUNTIME_DRIVER]
   #
   # Runtime
   #
-!if $(SECURE_BOOT_ENABLE) == TRUE
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
-!endif
 
 ################################################################################
 #
 # Pcd Section - list of all EDK II PCD Entries defined by this Platform  #
--
1.9.5.msysgit.1



^ permalink raw reply	[flat|nested] 37+ messages in thread

* Re: [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6
  2016-12-22  7:33   ` Ye, Ting
@ 2016-12-22  8:30     ` Wu, Jiaxin
  0 siblings, 0 replies; 37+ messages in thread
From: Wu, Jiaxin @ 2016-12-22  8:30 UTC (permalink / raw)
  To: Ye, Ting, edk2-devel@lists.01.org
  Cc: Fu, Siyuan, Zhang, Lubo, Long, Qin, Thomas Palmer

Hi Ting,
 
Thanks. I will correct/refine the implementation according your comments.

Thanks,
Jiaxin

> -----Original Message-----
> From: Ye, Ting
> Sent: Thursday, December 22, 2016 3:34 PM
> To: Wu, Jiaxin <jiaxin.wu@intel.com>; edk2-devel@lists.01.org
> Cc: Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>;
> Long, Qin <qin.long@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>
> Subject: RE: [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4
> and IPv6
> 
> Hi Jiaxin,
> 
> Some comments included below.
> 
> 1. In TlsConfigCertificate, HttpInstance->TlsConfigData.CACert is not used
> and local variable "CACert" is not freed after calling TlsConfiguration-
> >SetData.
> 2. In TlsConfigureSession, several gotos are useless. Suggest to replace with
> return status directly.
> 3.  This two parts will be ==> These
> 
> Others are good to me.
> 
> Reviewed-by: Ye Ting <ting.ye@intel.com>
> 
> Best Regards,
> Ye Ting
> 
> 
> 
> -----Original Message-----
> From: Wu, Jiaxin
> Sent: Wednesday, December 14, 2016 3:34 PM
> 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


^ permalink raw reply	[flat|nested] 37+ messages in thread

end of thread, other threads:[~2016-12-22  8:30 UTC | newest]

Thread overview: 37+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-12-14  7:34 [Patch 00/10] Sync staging/HTTPS-TLS feature into edk2 master Jiaxin Wu
2016-12-14  7:34 ` [Patch 01/10] MdePkg: Add TLS related protocol definition Jiaxin Wu
2016-12-14  8:36   ` Long, Qin
2016-12-14  8:39     ` Wu, Jiaxin
2016-12-15  8:34       ` Ye, Ting
2016-12-14  8:43   ` Fu, Siyuan
2016-12-14  7:34 ` [Patch 02/10] MdePkg: Add a header to standardize TLS definitions Jiaxin Wu
2016-12-14  8:42   ` Long, Qin
2016-12-14  8:43   ` Fu, Siyuan
2016-12-15  8:35   ` Ye, Ting
2016-12-14  7:34 ` [Patch 03/10] CryptoPkg: Enable ssl build in OpensslLib directly Jiaxin Wu
2016-12-15  8:37   ` Ye, Ting
2016-12-14  7:34 ` [Patch 04/10] CryptoPkg: Add new TlsLib library Jiaxin Wu
2016-12-16  2:10   ` Ye, Ting
2016-12-16  2:51     ` Wu, Jiaxin
2016-12-14  7:34 ` [Patch 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL Jiaxin Wu
2016-12-14  8:41   ` Fu, Siyuan
2016-12-15  7:24     ` Wu, Jiaxin
2016-12-14  7:34 ` [Patch 06/10] NetworkPkg/TlsAuthConfigDxe: Provide the UI to support TLS auth configuration Jiaxin Wu
2016-12-15  2:22   ` Fu, Siyuan
2016-12-22  2:52     ` Ye, Ting
2016-12-22  3:13       ` Wu, Jiaxin
2016-12-14  7:34 ` [Patch 07/10] NetworkPkg/HttpDxe: HTTPS support over IPv4 and IPv6 Jiaxin Wu
2016-12-15  2:39   ` Fu, Siyuan
2016-12-15  7:14     ` Wu, Jiaxin
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox