]> git.proxmox.com Git - mirror_edk2.git/blobdiff - CryptoPkg/Library/TlsLib/TlsProcess.c
CryptoPkg: Convert files to CRLF line ending
[mirror_edk2.git] / CryptoPkg / Library / TlsLib / TlsProcess.c
index 8532dab97a31ced1a671a423724e5d16656ecf2a..38baac0e8b3f483cce8d1b01edd86e291585bd5f 100644 (file)
-/** @file
-  SSL/TLS Process Library Wrapper Implementation over OpenSSL.
-  The process includes the TLS handshake and packet I/O.
-
-Copyright (c) 2016 - 2017, 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.
-  @retval EFI_ABORTED             Something wrong during handshake.
-
-**/
-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;
-  UINTN           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_ABORTED;
-    }
-  }
-
-  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;
-}
-
-/**
-  Handle 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
-TlsHandleAlert (
-  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);
-}
+/** @file\r
+  SSL/TLS Process Library Wrapper Implementation over OpenSSL.\r
+  The process includes the TLS handshake and packet I/O.\r
+\r
+Copyright (c) 2016 - 2017, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\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 "InternalTlsLib.h"\r
+\r
+#define MAX_BUFFER_SIZE   32768\r
+\r
+/**\r
+  Checks if the TLS handshake was done.\r
+\r
+  This function will check if the specified TLS handshake was done.\r
+\r
+  @param[in]  Tls    Pointer to the TLS object for handshake state checking.\r
+\r
+  @retval  TRUE     The TLS handshake was done.\r
+  @retval  FALSE    The TLS handshake was not done.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+TlsInHandshake (\r
+  IN     VOID                     *Tls\r
+  )\r
+{\r
+  TLS_CONNECTION  *TlsConn;\r
+\r
+  TlsConn = (TLS_CONNECTION *) Tls;\r
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Return the status which indicates if the TLS handshake was done.\r
+  //\r
+  return !SSL_is_init_finished (TlsConn->Ssl);\r
+}\r
+\r
+/**\r
+  Perform a TLS/SSL handshake.\r
+\r
+  This function will perform a TLS/SSL handshake.\r
+\r
+  @param[in]       Tls            Pointer to the TLS object for handshake operation.\r
+  @param[in]       BufferIn       Pointer to the most recently received TLS Handshake packet.\r
+  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS\r
+                                  Handshake packet.\r
+  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.\r
+  @param[in, out]  BufferOutSize  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
+                                  Tls is NULL.\r
+                                  BufferIn is NULL but BufferInSize is NOT 0.\r
+                                  BufferInSize is 0 but BufferIn is NOT NULL.\r
+                                  BufferOutSize is NULL.\r
+                                  BufferOut is NULL if *BufferOutSize is not zero.\r
+  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.\r
+  @retval EFI_ABORTED             Something wrong during handshake.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsDoHandshake (\r
+  IN     VOID                     *Tls,\r
+  IN     UINT8                    *BufferIn, OPTIONAL\r
+  IN     UINTN                    BufferInSize, OPTIONAL\r
+     OUT UINT8                    *BufferOut, OPTIONAL\r
+  IN OUT UINTN                    *BufferOutSize\r
+  )\r
+{\r
+  TLS_CONNECTION  *TlsConn;\r
+  UINTN           PendingBufferSize;\r
+  INTN            Ret;\r
+  UINTN           ErrorCode;\r
+\r
+  TlsConn           = (TLS_CONNECTION *) Tls;\r
+  PendingBufferSize = 0;\r
+  Ret               = 1;\r
+\r
+  if (TlsConn == NULL || \\r
+    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \\r
+    BufferOutSize == NULL || \\r
+    (BufferIn == NULL && BufferInSize != 0) || \\r
+    (BufferIn != NULL && BufferInSize == 0) || \\r
+    (BufferOut == NULL && *BufferOutSize != 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  if(BufferIn == NULL && BufferInSize == 0) {\r
+    //\r
+    // If RequestBuffer is NULL and RequestSize is 0, and TLS session\r
+    // status is EfiTlsSessionNotStarted, the TLS session will be initiated\r
+    // and the response packet needs to be ClientHello.\r
+    //\r
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
+    if (PendingBufferSize == 0) {\r
+      SSL_set_connect_state (TlsConn->Ssl);\r
+      Ret = SSL_do_handshake (TlsConn->Ssl);\r
+      PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
+    }\r
+  } else {\r
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
+    if (PendingBufferSize == 0) {\r
+      BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);\r
+      Ret = SSL_do_handshake (TlsConn->Ssl);\r
+      PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
+    }\r
+  }\r
+\r
+  if (Ret < 1) {\r
+    Ret = SSL_get_error (TlsConn->Ssl, (int) Ret);\r
+    if (Ret == SSL_ERROR_SSL ||\r
+        Ret == SSL_ERROR_SYSCALL ||\r
+        Ret == SSL_ERROR_ZERO_RETURN) {\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "%a SSL_HANDSHAKE_ERROR State=0x%x SSL_ERROR_%a\n",\r
+        __FUNCTION__,\r
+        SSL_get_state (TlsConn->Ssl),\r
+        Ret == SSL_ERROR_SSL ? "SSL" : Ret == SSL_ERROR_SYSCALL ? "SYSCALL" : "ZERO_RETURN"\r
+        ));\r
+      DEBUG_CODE_BEGIN ();\r
+        while (TRUE) {\r
+          ErrorCode = ERR_get_error ();\r
+          if (ErrorCode == 0) {\r
+            break;\r
+          }\r
+          DEBUG ((\r
+            DEBUG_ERROR,\r
+            "%a ERROR 0x%x=L%x:F%x:R%x\n",\r
+            __FUNCTION__,\r
+            ErrorCode,\r
+            ERR_GET_LIB (ErrorCode),\r
+            ERR_GET_FUNC (ErrorCode),\r
+            ERR_GET_REASON (ErrorCode)\r
+            ));\r
+        }\r
+      DEBUG_CODE_END ();\r
+      return EFI_ABORTED;\r
+    }\r
+  }\r
+\r
+  if (PendingBufferSize > *BufferOutSize) {\r
+    *BufferOutSize = PendingBufferSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  if (PendingBufferSize > 0) {\r
+    *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize);\r
+  } else {\r
+    *BufferOutSize = 0;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Handle Alert message recorded in BufferIn. If BufferIn is NULL and BufferInSize is zero,\r
+  TLS session has errors and the response packet needs to be Alert message based on error type.\r
+\r
+  @param[in]       Tls            Pointer to the TLS object for state checking.\r
+  @param[in]       BufferIn       Pointer to the most recently received TLS Alert packet.\r
+  @param[in]       BufferInSize   Packet size in bytes for the most recently received TLS\r
+                                  Alert packet.\r
+  @param[out]      BufferOut      Pointer to the buffer to hold the built packet.\r
+  @param[in, out]  BufferOutSize  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
+                                  Tls is NULL.\r
+                                  BufferIn is NULL but BufferInSize is NOT 0.\r
+                                  BufferInSize is 0 but BufferIn is NOT NULL.\r
+                                  BufferOutSize is NULL.\r
+                                  BufferOut is NULL if *BufferOutSize is not zero.\r
+  @retval EFI_ABORTED             An error occurred.\r
+  @retval EFI_BUFFER_TOO_SMALL    BufferOutSize is too small to hold the response packet.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsHandleAlert (\r
+  IN     VOID                     *Tls,\r
+  IN     UINT8                    *BufferIn, OPTIONAL\r
+  IN     UINTN                    BufferInSize, OPTIONAL\r
+     OUT UINT8                    *BufferOut, OPTIONAL\r
+  IN OUT UINTN                    *BufferOutSize\r
+  )\r
+{\r
+  TLS_CONNECTION  *TlsConn;\r
+  UINTN           PendingBufferSize;\r
+  UINT8           *TempBuffer;\r
+  INTN            Ret;\r
+\r
+  TlsConn           = (TLS_CONNECTION *) Tls;\r
+  PendingBufferSize = 0;\r
+  TempBuffer        = NULL;\r
+  Ret               = 0;\r
+\r
+  if (TlsConn == NULL || \\r
+    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \\r
+    BufferOutSize == NULL || \\r
+    (BufferIn == NULL && BufferInSize != 0) || \\r
+    (BufferIn != NULL && BufferInSize == 0) || \\r
+    (BufferOut == NULL && *BufferOutSize != 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
+  if (PendingBufferSize == 0 && BufferIn != NULL && BufferInSize != 0) {\r
+    Ret = BIO_write (TlsConn->InBio, BufferIn, (UINT32) BufferInSize);\r
+    if (Ret != (INTN) BufferInSize) {\r
+      return EFI_ABORTED;\r
+    }\r
+\r
+    TempBuffer = (UINT8 *) OPENSSL_malloc (MAX_BUFFER_SIZE);\r
+\r
+    //\r
+    // ssl3_send_alert() will be called in ssl3_read_bytes() function.\r
+    // TempBuffer is invalid since it's a Alert message, so just ignore it.\r
+    //\r
+    SSL_read (TlsConn->Ssl, TempBuffer, MAX_BUFFER_SIZE);\r
+\r
+    OPENSSL_free (TempBuffer);\r
+\r
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
+  }\r
+\r
+  if (PendingBufferSize > *BufferOutSize) {\r
+    *BufferOutSize = PendingBufferSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  if (PendingBufferSize > 0) {\r
+    *BufferOutSize = BIO_read (TlsConn->OutBio, BufferOut, (UINT32) PendingBufferSize);\r
+  } else {\r
+    *BufferOutSize = 0;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Build the CloseNotify packet.\r
+\r
+  @param[in]       Tls            Pointer to the TLS object for state checking.\r
+  @param[in, 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
+                                  Tls is 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
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TlsCloseNotify (\r
+  IN     VOID                     *Tls,\r
+  IN OUT UINT8                    *Buffer,\r
+  IN OUT UINTN                    *BufferSize\r
+  )\r
+{\r
+  TLS_CONNECTION  *TlsConn;\r
+  UINTN           PendingBufferSize;\r
+\r
+  TlsConn           = (TLS_CONNECTION *) Tls;\r
+  PendingBufferSize = 0;\r
+\r
+  if (TlsConn == NULL || \\r
+    TlsConn->Ssl == NULL || TlsConn->InBio == NULL || TlsConn->OutBio == NULL || \\r
+    BufferSize == NULL || \\r
+    (Buffer == NULL && *BufferSize != 0)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
+  if (PendingBufferSize == 0) {\r
+    //\r
+    // ssl3_send_alert() and ssl3_dispatch_alert() function will be called.\r
+    //\r
+    SSL_shutdown (TlsConn->Ssl);\r
+    PendingBufferSize = (UINTN) BIO_ctrl_pending (TlsConn->OutBio);\r
+  }\r
+\r
+  if (PendingBufferSize > *BufferSize) {\r
+    *BufferSize = PendingBufferSize;\r
+    return EFI_BUFFER_TOO_SMALL;\r
+  }\r
+\r
+  if (PendingBufferSize > 0) {\r
+    *BufferSize = BIO_read (TlsConn->OutBio, Buffer, (UINT32) PendingBufferSize);\r
+  } else {\r
+    *BufferSize = 0;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+  Attempts to read bytes from one TLS object and places the data in Buffer.\r
+\r
+  This function will attempt to read BufferSize bytes from the TLS object\r
+  and places the data in Buffer.\r
+\r
+  @param[in]      Tls           Pointer to the TLS object.\r
+  @param[in,out]  Buffer        Pointer to the buffer to store the data.\r
+  @param[in]      BufferSize    The size of Buffer in bytes.\r
+\r
+  @retval  >0    The amount of data successfully read from the TLS object.\r
+  @retval  <=0   No data was successfully read.\r
+\r
+**/\r
+INTN\r
+EFIAPI\r
+TlsCtrlTrafficOut (\r
+  IN     VOID                     *Tls,\r
+  IN OUT VOID                     *Buffer,\r
+  IN     UINTN                    BufferSize\r
+  )\r
+{\r
+  TLS_CONNECTION  *TlsConn;\r
+\r
+  TlsConn = (TLS_CONNECTION *) Tls;\r
+  if (TlsConn == NULL || TlsConn->OutBio == 0) {\r
+    return -1;\r
+  }\r
+\r
+  //\r
+  // Read and return the amount of data from the BIO.\r
+  //\r
+  return BIO_read (TlsConn->OutBio, Buffer, (UINT32) BufferSize);\r
+}\r
+\r
+/**\r
+  Attempts to write data from the buffer to TLS object.\r
+\r
+  This function will attempt to write BufferSize bytes data from the Buffer\r
+  to the TLS object.\r
+\r
+  @param[in]  Tls           Pointer to the TLS object.\r
+  @param[in]  Buffer        Pointer to the data buffer.\r
+  @param[in]  BufferSize    The size of Buffer in bytes.\r
+\r
+  @retval  >0    The amount of data successfully written to the TLS object.\r
+  @retval <=0    No data was successfully written.\r
+\r
+**/\r
+INTN\r
+EFIAPI\r
+TlsCtrlTrafficIn (\r
+  IN     VOID                     *Tls,\r
+  IN     VOID                     *Buffer,\r
+  IN     UINTN                    BufferSize\r
+  )\r
+{\r
+  TLS_CONNECTION  *TlsConn;\r
+\r
+  TlsConn = (TLS_CONNECTION *) Tls;\r
+  if (TlsConn == NULL || TlsConn->InBio == 0) {\r
+    return -1;\r
+  }\r
+\r
+  //\r
+  // Write and return the amount of data to the BIO.\r
+  //\r
+  return BIO_write (TlsConn->InBio, Buffer, (UINT32) BufferSize);\r
+}\r
+/**\r
+  Attempts to read bytes from the specified TLS connection into the buffer.\r
+\r
+  This function tries to read BufferSize bytes data from the specified TLS\r
+  connection into the Buffer.\r
+\r
+  @param[in]      Tls           Pointer to the TLS connection for data reading.\r
+  @param[in,out]  Buffer        Pointer to the data buffer.\r
+  @param[in]      BufferSize    The size of Buffer in bytes.\r
+\r
+  @retval  >0    The read operation was successful, and return value is the\r
+                 number of bytes actually read from the TLS connection.\r
+  @retval  <=0   The read operation was not successful.\r
+\r
+**/\r
+INTN\r
+EFIAPI\r
+TlsRead (\r
+  IN     VOID                     *Tls,\r
+  IN OUT VOID                     *Buffer,\r
+  IN     UINTN                    BufferSize\r
+  )\r
+{\r
+  TLS_CONNECTION  *TlsConn;\r
+\r
+  TlsConn = (TLS_CONNECTION *) Tls;\r
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {\r
+    return -1;\r
+  }\r
+\r
+  //\r
+  // Read bytes from the specified TLS connection.\r
+  //\r
+  return SSL_read (TlsConn->Ssl, Buffer, (UINT32) BufferSize);\r
+}\r
+\r
+/**\r
+  Attempts to write data to a TLS connection.\r
+\r
+  This function tries to write BufferSize bytes data from the Buffer into the\r
+  specified TLS connection.\r
+\r
+  @param[in]  Tls           Pointer to the TLS connection for data writing.\r
+  @param[in]  Buffer        Pointer to the data buffer.\r
+  @param[in]  BufferSize    The size of Buffer in bytes.\r
+\r
+  @retval  >0    The write operation was successful, and return value is the\r
+                 number of bytes actually written to the TLS connection.\r
+  @retval <=0    The write operation was not successful.\r
+\r
+**/\r
+INTN\r
+EFIAPI\r
+TlsWrite (\r
+  IN     VOID                     *Tls,\r
+  IN     VOID                     *Buffer,\r
+  IN     UINTN                    BufferSize\r
+  )\r
+{\r
+  TLS_CONNECTION  *TlsConn;\r
+\r
+  TlsConn = (TLS_CONNECTION *) Tls;\r
+  if (TlsConn == NULL || TlsConn->Ssl == NULL) {\r
+    return -1;\r
+  }\r
+\r
+  //\r
+  // Write bytes to the specified TLS connection.\r
+  //\r
+  return SSL_write (TlsConn->Ssl, Buffer, (UINT32) BufferSize);\r
+}\r
+\r