-/** @file
- Implementation of EFI TLS Protocol Interfaces.
-
- Copyright (c) 2016 - 2017, 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 == TlsContentTypeAlert);
-
- 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
+ SPDX-License-Identifier: BSD-2-Clause-Patent\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
+ CONST EFI_TLS_CIPHER *TlsCipherList;\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
+ TlsCipherList = (CONST EFI_TLS_CIPHER *) Data;\r
+ CipherCount = DataSize / sizeof (EFI_TLS_CIPHER);\r
+ for (Index = 0; Index < CipherCount; Index++) {\r
+ CipherId[Index] = ((TlsCipherList[Index].Data1 << 8) |\r
+ TlsCipherList[Index].Data2);\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