]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/TlsDxe/TlsProtocol.c
NetworkPkg/TlsDxe: verify DataSize for EfiTlsCipherList
[mirror_edk2.git] / NetworkPkg / TlsDxe / TlsProtocol.c
index ee1c496239b10410289482ab36b1f9f813611182..a5f95a09834516e9ca7f90e0726216c3f22c2f25 100644 (file)
-/** @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);
-
-  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);
-
-  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);
-
-  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 = TlsHandleAlert (
-                 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 multiple TLS record messages.
-    // 2. One TLS record message may have multiple 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 = TlsHandleAlert (
-                 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);
-
-  if (Instance->TlsSessionState != EfiTlsSessionDataTransferring) {
-    Status = EFI_NOT_READY;
-    goto ON_EXIT;
-  }
-
-  //
-  // Packet sent or received may have multiple TLS record messages (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 = TlsEncryptPacket (Instance, FragmentTable, FragmentCount);
-    break;
-  case EfiTlsDecrypt:
-    Status = TlsDecryptPacket (Instance, FragmentTable, FragmentCount);
-    break;
-  default:
-    return EFI_INVALID_PARAMETER;
-  }
-
-ON_EXIT:
-  gBS->RestoreTPL (OldTpl);
-  return Status;
-}
+/** @file\r
+  Implementation of EFI TLS Protocol Interfaces.\r
+\r
+  Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
+\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include "TlsImpl.h"\r
+\r
+EFI_TLS_PROTOCOL  mTlsProtocol = {\r
+  TlsSetSessionData,\r
+  TlsGetSessionData,\r
+  TlsBuildResponsePacket,\r
+  TlsProcessPacket\r
+};\r
+\r
+/**\r
+  Set TLS session data.\r
+\r
+  The SetSessionData() function set data for a new TLS session. All session data should\r
+  be set before BuildResponsePacket() invoked.\r
+\r
+  @param[in]  This                Pointer to the EFI_TLS_PROTOCOL instance.\r
+  @param[in]  DataType            TLS session data type.\r
+  @param[in]  Data                Pointer to session data.\r
+  @param[in]  DataSize            Total size of session data.\r
+\r
+  @retval EFI_SUCCESS             The TLS session data is set successfully.\r
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:\r
+                                  This is NULL.\r
+                                  Data is NULL.\r
+                                  DataSize is 0.\r
+                                  DataSize is invalid for DataType.\r
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.\r
+  @retval EFI_ACCESS_DENIED       If the DataType is one of below:\r
+                                  EfiTlsClientRandom\r
+                                  EfiTlsServerRandom\r
+                                  EfiTlsKeyMaterial\r
+  @retval EFI_NOT_READY           Current TLS session state is NOT\r
+                                  EfiTlsSessionStateNotStarted.\r
+  @retval EFI_OUT_OF_RESOURCES    Required system resources could not be allocated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsSetSessionData (\r
+  IN     EFI_TLS_PROTOCOL              *This,\r
+  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,\r
+  IN     VOID                          *Data,\r
+  IN     UINTN                         DataSize\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TLS_INSTANCE              *Instance;\r
+  UINT16                    *CipherId;\r
+  UINTN                     CipherCount;\r
+  UINTN                     Index;\r
+\r
+  EFI_TPL                   OldTpl;\r
+\r
+  Status = EFI_SUCCESS;\r
+  CipherId = NULL;\r
+\r
+  if (This == NULL || Data == NULL || DataSize == 0) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+  Instance = TLS_INSTANCE_FROM_PROTOCOL (This);\r
+\r
+  if (DataType != EfiTlsSessionState  && Instance->TlsSessionState != EfiTlsSessionNotStarted){\r
+    Status = EFI_NOT_READY;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  switch (DataType) {\r
+  //\r
+  // Session Configuration\r
+  //\r
+  case EfiTlsVersion:\r
+    if (DataSize != sizeof (EFI_TLS_VERSION)) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    Status = TlsSetVersion (Instance->TlsConn, ((EFI_TLS_VERSION *) Data)->Major, ((EFI_TLS_VERSION *) Data)->Minor);\r
+    break;\r
+  case EfiTlsConnectionEnd:\r
+    if (DataSize != sizeof (EFI_TLS_CONNECTION_END)) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    Status = TlsSetConnectionEnd (Instance->TlsConn, *((EFI_TLS_CONNECTION_END *) Data));\r
+    break;\r
+  case EfiTlsCipherList:\r
+    if (DataSize % sizeof (EFI_TLS_CIPHER) != 0) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    CipherId = AllocatePool (DataSize);\r
+    if (CipherId == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    CipherCount = DataSize / sizeof (EFI_TLS_CIPHER);\r
+    for (Index = 0; Index < CipherCount; Index++) {\r
+      *(CipherId +Index) = HTONS (*(((UINT16 *) Data) + Index));\r
+    }\r
+\r
+    Status = TlsSetCipherList (Instance->TlsConn, CipherId, CipherCount);\r
+\r
+    FreePool (CipherId);\r
+    break;\r
+  case EfiTlsCompressionMethod:\r
+    //\r
+    // TLS seems only define one CompressionMethod.null, which specifies that data exchanged via the\r
+    // record protocol will not be compressed.\r
+    // More information from OpenSSL: http://www.openssl.org/docs/manmaster/ssl/SSL_COMP_add_compression_method.html\r
+    // The TLS RFC does however not specify compression methods or their corresponding identifiers,\r
+    // so there is currently no compatible way to integrate compression with unknown peers.\r
+    // It is therefore currently not recommended to integrate compression into applications.\r
+    // Applications for non-public use may agree on certain compression methods.\r
+    // Using different compression methods with the same identifier will lead to connection failure.\r
+    //\r
+    for (Index = 0; Index < DataSize / sizeof (EFI_TLS_COMPRESSION); Index++) {\r
+      Status = TlsSetCompressionMethod (*((UINT8 *) Data + Index));\r
+      if (EFI_ERROR (Status)) {\r
+        break;\r
+      }\r
+    }\r
+\r
+    break;\r
+  case EfiTlsExtensionData:\r
+    Status = EFI_UNSUPPORTED;\r
+    goto ON_EXIT;\r
+  case EfiTlsVerifyMethod:\r
+    if (DataSize != sizeof (EFI_TLS_VERIFY)) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    TlsSetVerify (Instance->TlsConn, *((UINT32 *) Data));\r
+    break;\r
+  case EfiTlsSessionID:\r
+    if (DataSize != sizeof (EFI_TLS_SESSION_ID)) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    Status = TlsSetSessionId (\r
+               Instance->TlsConn,\r
+               ((EFI_TLS_SESSION_ID *) Data)->Data,\r
+               ((EFI_TLS_SESSION_ID *) Data)->Length\r
+               );\r
+    break;\r
+  case EfiTlsSessionState:\r
+    if (DataSize != sizeof (EFI_TLS_SESSION_STATE)) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto ON_EXIT;\r
+    }\r
+\r
+    Instance->TlsSessionState = *(EFI_TLS_SESSION_STATE *) Data;\r
+    break;\r
+  //\r
+  // Session information\r
+  //\r
+  case EfiTlsClientRandom:\r
+    Status = EFI_ACCESS_DENIED;\r
+    break;\r
+  case EfiTlsServerRandom:\r
+    Status = EFI_ACCESS_DENIED;\r
+    break;\r
+  case EfiTlsKeyMaterial:\r
+    Status = EFI_ACCESS_DENIED;\r
+    break;\r
+  //\r
+  // Unsupported type.\r
+  //\r
+  default:\r
+    Status = EFI_UNSUPPORTED;\r
+  }\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get TLS session data.\r
+\r
+  The GetSessionData() function return the TLS session information.\r
+\r
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.\r
+  @param[in]       DataType       TLS session data type.\r
+  @param[in, out]  Data           Pointer to session data.\r
+  @param[in, out]  DataSize       Total size of session data. On input, it means\r
+                                  the size of Data buffer. On output, it means the size\r
+                                  of copied Data buffer if EFI_SUCCESS, and means the\r
+                                  size of desired Data buffer if EFI_BUFFER_TOO_SMALL.\r
+\r
+  @retval EFI_SUCCESS             The TLS session data is got successfully.\r
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:\r
+                                  This is NULL.\r
+                                  DataSize is NULL.\r
+                                  Data is NULL if *DataSize is not zero.\r
+  @retval EFI_UNSUPPORTED         The DataType is unsupported.\r
+  @retval EFI_NOT_FOUND           The TLS session data is not found.\r
+  @retval EFI_NOT_READY           The DataType is not ready in current session state.\r
+  @retval EFI_BUFFER_TOO_SMALL    The buffer is too small to hold the data.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsGetSessionData (\r
+  IN     EFI_TLS_PROTOCOL              *This,\r
+  IN     EFI_TLS_SESSION_DATA_TYPE     DataType,\r
+  IN OUT VOID                          *Data,  OPTIONAL\r
+  IN OUT UINTN                         *DataSize\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TLS_INSTANCE              *Instance;\r
+\r
+  EFI_TPL                   OldTpl;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+  Instance = TLS_INSTANCE_FROM_PROTOCOL (This);\r
+\r
+  if (Instance->TlsSessionState == EfiTlsSessionNotStarted &&\r
+    (DataType == EfiTlsSessionID || DataType == EfiTlsClientRandom ||\r
+    DataType == EfiTlsServerRandom || DataType == EfiTlsKeyMaterial)) {\r
+    Status = EFI_NOT_READY;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  switch (DataType) {\r
+  case EfiTlsVersion:\r
+    if (*DataSize < sizeof (EFI_TLS_VERSION)) {\r
+      *DataSize = sizeof (EFI_TLS_VERSION);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto ON_EXIT;\r
+    }\r
+    *DataSize = sizeof (EFI_TLS_VERSION);\r
+    *((UINT16 *) Data) = HTONS (TlsGetVersion (Instance->TlsConn));\r
+    break;\r
+  case EfiTlsConnectionEnd:\r
+    if (*DataSize < sizeof (EFI_TLS_CONNECTION_END)) {\r
+      *DataSize = sizeof (EFI_TLS_CONNECTION_END);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto ON_EXIT;\r
+    }\r
+    *DataSize = sizeof (EFI_TLS_CONNECTION_END);\r
+    *((UINT8 *) Data) = TlsGetConnectionEnd (Instance->TlsConn);\r
+    break;\r
+  case EfiTlsCipherList:\r
+    //\r
+    // Get the current session cipher suite.\r
+    //\r
+    if (*DataSize < sizeof (EFI_TLS_CIPHER)) {\r
+      *DataSize = sizeof (EFI_TLS_CIPHER);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto ON_EXIT;\r
+    }\r
+    *DataSize = sizeof(EFI_TLS_CIPHER);\r
+    Status = TlsGetCurrentCipher (Instance->TlsConn, (UINT16 *) Data);\r
+    *((UINT16 *) Data) = HTONS (*((UINT16 *) Data));\r
+    break;\r
+  case EfiTlsCompressionMethod:\r
+    //\r
+    // Get the current session compression method.\r
+    //\r
+    if (*DataSize < sizeof (EFI_TLS_COMPRESSION)) {\r
+      *DataSize = sizeof (EFI_TLS_COMPRESSION);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto ON_EXIT;\r
+    }\r
+    *DataSize = sizeof (EFI_TLS_COMPRESSION);\r
+    Status = TlsGetCurrentCompressionId (Instance->TlsConn, (UINT8 *) Data);\r
+    break;\r
+  case EfiTlsExtensionData:\r
+    Status = EFI_UNSUPPORTED;\r
+    goto ON_EXIT;\r
+  case EfiTlsVerifyMethod:\r
+    if (*DataSize < sizeof (EFI_TLS_VERIFY)) {\r
+      *DataSize = sizeof (EFI_TLS_VERIFY);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto ON_EXIT;\r
+    }\r
+    *DataSize = sizeof (EFI_TLS_VERIFY);\r
+    *((UINT32 *) Data) = TlsGetVerify (Instance->TlsConn);\r
+    break;\r
+  case EfiTlsSessionID:\r
+    if (*DataSize < sizeof (EFI_TLS_SESSION_ID)) {\r
+      *DataSize = sizeof (EFI_TLS_SESSION_ID);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto ON_EXIT;\r
+    }\r
+    *DataSize = sizeof (EFI_TLS_SESSION_ID);\r
+    Status = TlsGetSessionId (\r
+               Instance->TlsConn,\r
+               ((EFI_TLS_SESSION_ID *) Data)->Data,\r
+               &(((EFI_TLS_SESSION_ID *) Data)->Length)\r
+               );\r
+    break;\r
+  case EfiTlsSessionState:\r
+    if (*DataSize < sizeof (EFI_TLS_SESSION_STATE)) {\r
+      *DataSize = sizeof (EFI_TLS_SESSION_STATE);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto ON_EXIT;\r
+    }\r
+    *DataSize = sizeof (EFI_TLS_SESSION_STATE);\r
+    CopyMem (Data, &Instance->TlsSessionState, *DataSize);\r
+    break;\r
+  case EfiTlsClientRandom:\r
+    if (*DataSize < sizeof (EFI_TLS_RANDOM)) {\r
+      *DataSize = sizeof (EFI_TLS_RANDOM);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto ON_EXIT;\r
+    }\r
+    *DataSize = sizeof (EFI_TLS_RANDOM);\r
+    TlsGetClientRandom (Instance->TlsConn, (UINT8 *) Data);\r
+    break;\r
+  case EfiTlsServerRandom:\r
+    if (*DataSize < sizeof (EFI_TLS_RANDOM)) {\r
+      *DataSize = sizeof (EFI_TLS_RANDOM);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto ON_EXIT;\r
+    }\r
+    *DataSize = sizeof (EFI_TLS_RANDOM);\r
+    TlsGetServerRandom (Instance->TlsConn, (UINT8 *) Data);\r
+    break;\r
+  case EfiTlsKeyMaterial:\r
+    if (*DataSize < sizeof (EFI_TLS_MASTER_SECRET)) {\r
+      *DataSize = sizeof (EFI_TLS_MASTER_SECRET);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto ON_EXIT;\r
+    }\r
+    *DataSize = sizeof (EFI_TLS_MASTER_SECRET);\r
+    Status = TlsGetKeyMaterial (Instance->TlsConn, (UINT8 *) Data);\r
+    break;\r
+  //\r
+  // Unsupported type.\r
+  //\r
+  default:\r
+    Status = EFI_UNSUPPORTED;\r
+  }\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Build response packet according to TLS state machine. This function is only valid for\r
+  alert, handshake and change_cipher_spec content type.\r
+\r
+  The BuildResponsePacket() function builds TLS response packet in response to the TLS\r
+  request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and\r
+  RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session\r
+  will be initiated and the response packet needs to be ClientHello. If RequestBuffer is\r
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS\r
+  session will be closed and response packet needs to be CloseNotify. If RequestBuffer is\r
+  NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS\r
+  session has errors and the response packet needs to be Alert message based on error\r
+  type.\r
+\r
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.\r
+  @param[in]       RequestBuffer  Pointer to the most recently received TLS packet. NULL\r
+                                  means TLS need initiate the TLS session and response\r
+                                  packet need to be ClientHello.\r
+  @param[in]       RequestSize    Packet size in bytes for the most recently received TLS\r
+                                  packet. 0 is only valid when RequestBuffer is NULL.\r
+  @param[out]      Buffer         Pointer to the buffer to hold the built packet.\r
+  @param[in, out]  BufferSize     Pointer to the buffer size in bytes. On input, it is\r
+                                  the buffer size provided by the caller. On output, it\r
+                                  is the buffer size in fact needed to contain the\r
+                                  packet.\r
+\r
+  @retval EFI_SUCCESS             The required TLS packet is built successfully.\r
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:\r
+                                  This is NULL.\r
+                                  RequestBuffer is NULL but RequestSize is NOT 0.\r
+                                  RequestSize is 0 but RequestBuffer is NOT NULL.\r
+                                  BufferSize is NULL.\r
+                                  Buffer is NULL if *BufferSize is not zero.\r
+  @retval EFI_BUFFER_TOO_SMALL    BufferSize is too small to hold the response packet.\r
+  @retval EFI_NOT_READY           Current TLS session state is NOT ready to build\r
+                                  ResponsePacket.\r
+  @retval EFI_ABORTED             Something wrong build response packet.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsBuildResponsePacket (\r
+  IN     EFI_TLS_PROTOCOL              *This,\r
+  IN     UINT8                         *RequestBuffer, OPTIONAL\r
+  IN     UINTN                         RequestSize, OPTIONAL\r
+     OUT UINT8                         *Buffer, OPTIONAL\r
+  IN OUT UINTN                         *BufferSize\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TLS_INSTANCE              *Instance;\r
+  EFI_TPL                   OldTpl;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  if ((This == NULL) || (BufferSize == NULL) ||\r
+      (RequestBuffer == NULL && RequestSize != 0) ||\r
+      (RequestBuffer != NULL && RequestSize == 0) ||\r
+      (Buffer == NULL && *BufferSize !=0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+  Instance = TLS_INSTANCE_FROM_PROTOCOL (This);\r
+\r
+  if(RequestBuffer == NULL && RequestSize == 0) {\r
+    switch (Instance->TlsSessionState) {\r
+    case EfiTlsSessionNotStarted:\r
+      //\r
+      // ClientHello.\r
+      //\r
+      Status = TlsDoHandshake (\r
+                 Instance->TlsConn,\r
+                 NULL,\r
+                 0,\r
+                 Buffer,\r
+                 BufferSize\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      //\r
+      // *BufferSize should not be zero when ClientHello.\r
+      //\r
+      if (*BufferSize == 0) {\r
+        Status = EFI_ABORTED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      Instance->TlsSessionState = EfiTlsSessionHandShaking;\r
+\r
+      break;\r
+    case EfiTlsSessionClosing:\r
+      //\r
+      // TLS session will be closed and response packet needs to be CloseNotify.\r
+      //\r
+      Status = TlsCloseNotify (\r
+                 Instance->TlsConn,\r
+                 Buffer,\r
+                 BufferSize\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      //\r
+      // *BufferSize should not be zero when build CloseNotify message.\r
+      //\r
+      if (*BufferSize == 0) {\r
+        Status = EFI_ABORTED;\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      break;\r
+    case EfiTlsSessionError:\r
+      //\r
+      // TLS session has errors and the response packet needs to be Alert\r
+      // message based on error type.\r
+      //\r
+      Status = TlsHandleAlert (\r
+                 Instance->TlsConn,\r
+                 NULL,\r
+                 0,\r
+                 Buffer,\r
+                 BufferSize\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      break;\r
+    default:\r
+      //\r
+      // Current TLS session state is NOT ready to build ResponsePacket.\r
+      //\r
+      Status = EFI_NOT_READY;\r
+    }\r
+  } else {\r
+    //\r
+    // 1. Received packet may have multiple TLS record messages.\r
+    // 2. One TLS record message may have multiple handshake protocol.\r
+    // 3. Some errors may be happened in handshake.\r
+    // TlsDoHandshake() can handle all of those cases.\r
+    //\r
+    if (TlsInHandshake (Instance->TlsConn)) {\r
+      Status = TlsDoHandshake (\r
+                 Instance->TlsConn,\r
+                 RequestBuffer,\r
+                 RequestSize,\r
+                 Buffer,\r
+                 BufferSize\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        goto ON_EXIT;\r
+      }\r
+\r
+      if (!TlsInHandshake (Instance->TlsConn)) {\r
+        Instance->TlsSessionState = EfiTlsSessionDataTransferring;\r
+      }\r
+    } else {\r
+      //\r
+      // Must be alert message, Decrypt it and build the ResponsePacket.\r
+      //\r
+      ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType == TlsContentTypeAlert);\r
+\r
+      Status = TlsHandleAlert (\r
+                 Instance->TlsConn,\r
+                 RequestBuffer,\r
+                 RequestSize,\r
+                 Buffer,\r
+                 BufferSize\r
+                 );\r
+      if (EFI_ERROR (Status)) {\r
+        if (Status != EFI_BUFFER_TOO_SMALL) {\r
+          Instance->TlsSessionState = EfiTlsSessionError;\r
+        }\r
+\r
+        goto ON_EXIT;\r
+      }\r
+    }\r
+  }\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Decrypt or encrypt TLS packet during session. This function is only valid after\r
+  session connected and for application_data content type.\r
+\r
+  The ProcessPacket () function process each inbound or outbound TLS APP packet.\r
+\r
+  @param[in]       This           Pointer to the EFI_TLS_PROTOCOL instance.\r
+  @param[in, out]  FragmentTable  Pointer to a list of fragment. The caller will take\r
+                                  responsible to handle the original FragmentTable while\r
+                                  it may be reallocated in TLS driver. If CryptMode is\r
+                                  EfiTlsEncrypt, on input these fragments contain the TLS\r
+                                  header and plain text TLS APP payload; on output these\r
+                                  fragments contain the TLS header and cipher text TLS\r
+                                  APP payload. If CryptMode is EfiTlsDecrypt, on input\r
+                                  these fragments contain the TLS header and cipher text\r
+                                  TLS APP payload; on output these fragments contain the\r
+                                  TLS header and plain text TLS APP payload.\r
+  @param[in]       FragmentCount  Number of fragment.\r
+  @param[in]       CryptMode      Crypt mode.\r
+\r
+  @retval EFI_SUCCESS             The operation completed successfully.\r
+  @retval EFI_INVALID_PARAMETER   One or more of the following conditions is TRUE:\r
+                                  This is NULL.\r
+                                  FragmentTable is NULL.\r
+                                  FragmentCount is NULL.\r
+                                  CryptoMode is invalid.\r
+  @retval EFI_NOT_READY           Current TLS session state is NOT\r
+                                  EfiTlsSessionDataTransferring.\r
+  @retval EFI_ABORTED             Something wrong decryption the message. TLS session\r
+                                  status will become EfiTlsSessionError. The caller need\r
+                                  call BuildResponsePacket() to generate Error Alert\r
+                                  message and send it out.\r
+  @retval EFI_OUT_OF_RESOURCES    No enough resource to finish the operation.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsProcessPacket (\r
+  IN     EFI_TLS_PROTOCOL              *This,\r
+  IN OUT EFI_TLS_FRAGMENT_DATA         **FragmentTable,\r
+  IN     UINT32                        *FragmentCount,\r
+  IN     EFI_TLS_CRYPT_MODE            CryptMode\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+  TLS_INSTANCE              *Instance;\r
+\r
+  EFI_TPL                   OldTpl;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  if (This == NULL || FragmentTable == NULL || FragmentCount == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+  Instance = TLS_INSTANCE_FROM_PROTOCOL (This);\r
+\r
+  if (Instance->TlsSessionState != EfiTlsSessionDataTransferring) {\r
+    Status = EFI_NOT_READY;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  //\r
+  // Packet sent or received may have multiple TLS record messages (Application data type).\r
+  // So,on input these fragments contain the TLS header and TLS APP payload;\r
+  // on output these fragments also contain the TLS header and TLS APP payload.\r
+  //\r
+  switch (CryptMode) {\r
+  case EfiTlsEncrypt:\r
+    Status = TlsEncryptPacket (Instance, FragmentTable, FragmentCount);\r
+    break;\r
+  case EfiTlsDecrypt:\r
+    Status = TlsDecryptPacket (Instance, FragmentTable, FragmentCount);\r
+    break;\r
+  default:\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+ON_EXIT:\r
+  gBS->RestoreTPL (OldTpl);\r
+  return Status;\r
+}\r
+\r