/** @file | |
Implementation of EFI TLS Protocol Interfaces. | |
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#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. | |
DataSize is invalid for DataType. | |
@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; | |
CONST EFI_TLS_CIPHER *TlsCipherList; | |
UINTN CipherCount; | |
CONST EFI_TLS_VERIFY_HOST *TlsVerifyHost; | |
EFI_TLS_VERIFY VerifyMethod; | |
UINTN VerifyMethodSize; | |
UINTN Index; | |
EFI_TPL OldTpl; | |
Status = EFI_SUCCESS; | |
CipherId = NULL; | |
VerifyMethodSize = sizeof (EFI_TLS_VERIFY); | |
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: | |
if (DataSize % sizeof (EFI_TLS_CIPHER) != 0) { | |
Status = EFI_INVALID_PARAMETER; | |
goto ON_EXIT; | |
} | |
CipherId = AllocatePool (DataSize); | |
if (CipherId == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto ON_EXIT; | |
} | |
TlsCipherList = (CONST EFI_TLS_CIPHER *)Data; | |
CipherCount = DataSize / sizeof (EFI_TLS_CIPHER); | |
for (Index = 0; Index < CipherCount; Index++) { | |
CipherId[Index] = ((TlsCipherList[Index].Data1 << 8) | | |
TlsCipherList[Index].Data2); | |
} | |
Status = TlsSetCipherList (Instance->TlsConn, CipherId, CipherCount); | |
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 EfiTlsVerifyHost: | |
if (DataSize != sizeof (EFI_TLS_VERIFY_HOST)) { | |
Status = EFI_INVALID_PARAMETER; | |
goto ON_EXIT; | |
} | |
TlsVerifyHost = (CONST EFI_TLS_VERIFY_HOST *)Data; | |
if (((TlsVerifyHost->Flags & EFI_TLS_VERIFY_FLAG_ALWAYS_CHECK_SUBJECT) != 0) && | |
((TlsVerifyHost->Flags & EFI_TLS_VERIFY_FLAG_NEVER_CHECK_SUBJECT) != 0)) | |
{ | |
Status = EFI_INVALID_PARAMETER; | |
goto ON_EXIT; | |
} | |
if (((TlsVerifyHost->Flags & EFI_TLS_VERIFY_FLAG_NO_WILDCARDS) != 0) && | |
(((TlsVerifyHost->Flags & EFI_TLS_VERIFY_FLAG_NO_PARTIAL_WILDCARDS) != 0) || | |
((TlsVerifyHost->Flags & EFI_TLS_VERIFY_FLAG_MULTI_LABEL_WILDCARDS) != 0))) | |
{ | |
Status = EFI_INVALID_PARAMETER; | |
goto ON_EXIT; | |
} | |
Status = This->GetSessionData (This, EfiTlsVerifyMethod, &VerifyMethod, &VerifyMethodSize); | |
if (EFI_ERROR (Status)) { | |
goto ON_EXIT; | |
} | |
if ((VerifyMethod & EFI_TLS_VERIFY_PEER) == 0) { | |
Status = EFI_INVALID_PARAMETER; | |
goto ON_EXIT; | |
} | |
Status = TlsSetVerifyHost (Instance->TlsConn, TlsVerifyHost->Flags, TlsVerifyHost->HostName); | |
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; | |
} |