-/** @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