mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-12-17 15:18:06 +01:00
639 lines
22 KiB
C
639 lines
22 KiB
C
|
/** @file
|
||
|
Implementation of EFI TLS Protocol Interfaces.
|
||
|
|
||
|
Copyright (c) 2016 - 2017, 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;
|
||
|
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:
|
||
|
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 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;
|
||
|
}
|
||
|
|