mirror of
https://github.com/CloverHackyColor/CloverBootloader.git
synced 2024-11-14 10:05:43 +01:00
351 lines
11 KiB
C
351 lines
11 KiB
C
/** @file
|
|
The Miscellaneous Routines for TlsDxe driver.
|
|
|
|
Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>
|
|
|
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
|
|
**/
|
|
|
|
#include "TlsImpl.h"
|
|
|
|
/**
|
|
Encrypt the message listed in fragment.
|
|
|
|
@param[in] TlsInstance The pointer to the TLS instance.
|
|
@param[in, out] FragmentTable Pointer to a list of fragment.
|
|
On input these fragments contain the TLS header and
|
|
plain text TLS payload;
|
|
On output these fragments contain the TLS header and
|
|
cipher text TLS payload.
|
|
@param[in] FragmentCount Number of fragment.
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
|
|
@retval EFI_ABORTED TLS session state is incorrect.
|
|
@retval Others Other errors as indicated.
|
|
**/
|
|
EFI_STATUS
|
|
TlsEncryptPacket (
|
|
IN TLS_INSTANCE *TlsInstance,
|
|
IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
|
|
IN UINT32 *FragmentCount
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
UINT32 BytesCopied;
|
|
UINT32 BufferInSize;
|
|
UINT8 *BufferIn;
|
|
UINT8 *BufferInPtr;
|
|
TLS_RECORD_HEADER *RecordHeaderIn;
|
|
UINT16 ThisPlainMessageSize;
|
|
TLS_RECORD_HEADER *TempRecordHeader;
|
|
UINT16 ThisMessageSize;
|
|
UINT32 BufferOutSize;
|
|
UINT8 *BufferOut;
|
|
UINT32 RecordCount;
|
|
INTN Ret;
|
|
|
|
Status = EFI_SUCCESS;
|
|
BytesCopied = 0;
|
|
BufferInSize = 0;
|
|
BufferIn = NULL;
|
|
BufferInPtr = NULL;
|
|
RecordHeaderIn = NULL;
|
|
TempRecordHeader = NULL;
|
|
BufferOutSize = 0;
|
|
BufferOut = NULL;
|
|
RecordCount = 0;
|
|
Ret = 0;
|
|
|
|
//
|
|
// Calculate the size according to the fragment table.
|
|
//
|
|
for (Index = 0; Index < *FragmentCount; Index++) {
|
|
BufferInSize += (*FragmentTable)[Index].FragmentLength;
|
|
}
|
|
|
|
//
|
|
// Allocate buffer for processing data.
|
|
//
|
|
BufferIn = AllocateZeroPool (BufferInSize);
|
|
if (BufferIn == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ERROR;
|
|
}
|
|
|
|
//
|
|
// Copy all TLS plain record header and payload into BufferIn.
|
|
//
|
|
for (Index = 0; Index < *FragmentCount; Index++) {
|
|
CopyMem (
|
|
(BufferIn + BytesCopied),
|
|
(*FragmentTable)[Index].FragmentBuffer,
|
|
(*FragmentTable)[Index].FragmentLength
|
|
);
|
|
BytesCopied += (*FragmentTable)[Index].FragmentLength;
|
|
}
|
|
|
|
//
|
|
// Count TLS record number.
|
|
//
|
|
BufferInPtr = BufferIn;
|
|
while ((UINTN)BufferInPtr < (UINTN)BufferIn + BufferInSize) {
|
|
RecordHeaderIn = (TLS_RECORD_HEADER *)BufferInPtr;
|
|
if ((RecordHeaderIn->ContentType != TlsContentTypeApplicationData) || (RecordHeaderIn->Length > TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH)) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto ERROR;
|
|
}
|
|
|
|
BufferInPtr += TLS_RECORD_HEADER_LENGTH + RecordHeaderIn->Length;
|
|
RecordCount++;
|
|
}
|
|
|
|
//
|
|
// Allocate enough buffer to hold TLS Ciphertext.
|
|
//
|
|
BufferOut = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH));
|
|
if (BufferOut == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ERROR;
|
|
}
|
|
|
|
//
|
|
// Parsing buffer. Received packet may have multiple TLS record messages.
|
|
//
|
|
BufferInPtr = BufferIn;
|
|
TempRecordHeader = (TLS_RECORD_HEADER *)BufferOut;
|
|
while ((UINTN)BufferInPtr < (UINTN)BufferIn + BufferInSize) {
|
|
RecordHeaderIn = (TLS_RECORD_HEADER *)BufferInPtr;
|
|
|
|
ThisPlainMessageSize = RecordHeaderIn->Length;
|
|
|
|
TlsWrite (TlsInstance->TlsConn, (UINT8 *)(RecordHeaderIn + 1), ThisPlainMessageSize);
|
|
|
|
Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader), TLS_RECORD_HEADER_LENGTH + TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH);
|
|
|
|
if (Ret > 0) {
|
|
ThisMessageSize = (UINT16)Ret;
|
|
} else {
|
|
//
|
|
// No data was successfully encrypted, continue to encrypt other messages.
|
|
//
|
|
DEBUG ((DEBUG_WARN, "TlsEncryptPacket: No data read from TLS object.\n"));
|
|
|
|
ThisMessageSize = 0;
|
|
}
|
|
|
|
BufferOutSize += ThisMessageSize;
|
|
|
|
BufferInPtr += TLS_RECORD_HEADER_LENGTH + ThisPlainMessageSize;
|
|
TempRecordHeader = (TLS_RECORD_HEADER *)((UINT8 *)TempRecordHeader + ThisMessageSize);
|
|
}
|
|
|
|
FreePool (BufferIn);
|
|
BufferIn = NULL;
|
|
|
|
//
|
|
// The caller will be responsible to handle the original fragment table.
|
|
//
|
|
*FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
|
|
if (*FragmentTable == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ERROR;
|
|
}
|
|
|
|
(*FragmentTable)[0].FragmentBuffer = BufferOut;
|
|
(*FragmentTable)[0].FragmentLength = BufferOutSize;
|
|
*FragmentCount = 1;
|
|
|
|
return Status;
|
|
|
|
ERROR:
|
|
|
|
if (BufferIn != NULL) {
|
|
FreePool (BufferIn);
|
|
BufferIn = NULL;
|
|
}
|
|
|
|
if (BufferOut != NULL) {
|
|
FreePool (BufferOut);
|
|
BufferOut = NULL;
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Decrypt the message listed in fragment.
|
|
|
|
@param[in] TlsInstance The pointer to the TLS instance.
|
|
@param[in, out] FragmentTable Pointer to a list of fragment.
|
|
On input these fragments contain the TLS header and
|
|
cipher text TLS payload;
|
|
On output these fragments contain the TLS header and
|
|
plain text TLS payload.
|
|
@param[in] FragmentCount Number of fragment.
|
|
|
|
@retval EFI_SUCCESS The operation completed successfully.
|
|
@retval EFI_OUT_OF_RESOURCES Can't allocate memory resources.
|
|
@retval EFI_ABORTED TLS session state is incorrect.
|
|
@retval Others Other errors as indicated.
|
|
**/
|
|
EFI_STATUS
|
|
TlsDecryptPacket (
|
|
IN TLS_INSTANCE *TlsInstance,
|
|
IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable,
|
|
IN UINT32 *FragmentCount
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
UINT32 BytesCopied;
|
|
UINT8 *BufferIn;
|
|
UINT32 BufferInSize;
|
|
UINT8 *BufferInPtr;
|
|
TLS_RECORD_HEADER *RecordHeaderIn;
|
|
UINT16 ThisCipherMessageSize;
|
|
TLS_RECORD_HEADER *TempRecordHeader;
|
|
UINT16 ThisPlainMessageSize;
|
|
UINT8 *BufferOut;
|
|
UINT32 BufferOutSize;
|
|
UINT32 RecordCount;
|
|
INTN Ret;
|
|
|
|
Status = EFI_SUCCESS;
|
|
BytesCopied = 0;
|
|
BufferIn = NULL;
|
|
BufferInSize = 0;
|
|
BufferInPtr = NULL;
|
|
RecordHeaderIn = NULL;
|
|
TempRecordHeader = NULL;
|
|
BufferOut = NULL;
|
|
BufferOutSize = 0;
|
|
RecordCount = 0;
|
|
Ret = 0;
|
|
|
|
//
|
|
// Calculate the size according to the fragment table.
|
|
//
|
|
for (Index = 0; Index < *FragmentCount; Index++) {
|
|
BufferInSize += (*FragmentTable)[Index].FragmentLength;
|
|
}
|
|
|
|
//
|
|
// Allocate buffer for processing data
|
|
//
|
|
BufferIn = AllocateZeroPool (BufferInSize);
|
|
if (BufferIn == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ERROR;
|
|
}
|
|
|
|
//
|
|
// Copy all TLS plain record header and payload to BufferIn
|
|
//
|
|
for (Index = 0; Index < *FragmentCount; Index++) {
|
|
CopyMem (
|
|
(BufferIn + BytesCopied),
|
|
(*FragmentTable)[Index].FragmentBuffer,
|
|
(*FragmentTable)[Index].FragmentLength
|
|
);
|
|
BytesCopied += (*FragmentTable)[Index].FragmentLength;
|
|
}
|
|
|
|
//
|
|
// Count TLS record number.
|
|
//
|
|
BufferInPtr = BufferIn;
|
|
while ((UINTN)BufferInPtr < (UINTN)BufferIn + BufferInSize) {
|
|
RecordHeaderIn = (TLS_RECORD_HEADER *)BufferInPtr;
|
|
if ((RecordHeaderIn->ContentType != TlsContentTypeApplicationData) || (NTOHS (RecordHeaderIn->Length) > TLS_CIPHERTEXT_RECORD_MAX_PAYLOAD_LENGTH)) {
|
|
Status = EFI_INVALID_PARAMETER;
|
|
goto ERROR;
|
|
}
|
|
|
|
BufferInPtr += TLS_RECORD_HEADER_LENGTH + NTOHS (RecordHeaderIn->Length);
|
|
RecordCount++;
|
|
}
|
|
|
|
//
|
|
// Allocate enough buffer to hold TLS Plaintext.
|
|
//
|
|
BufferOut = AllocateZeroPool (RecordCount * (TLS_RECORD_HEADER_LENGTH + TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH));
|
|
if (BufferOut == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ERROR;
|
|
}
|
|
|
|
//
|
|
// Parsing buffer. Received packet may have multiple TLS record messages.
|
|
//
|
|
BufferInPtr = BufferIn;
|
|
TempRecordHeader = (TLS_RECORD_HEADER *)BufferOut;
|
|
while ((UINTN)BufferInPtr < (UINTN)BufferIn + BufferInSize) {
|
|
RecordHeaderIn = (TLS_RECORD_HEADER *)BufferInPtr;
|
|
|
|
ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length);
|
|
|
|
Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *)(RecordHeaderIn), TLS_RECORD_HEADER_LENGTH + ThisCipherMessageSize);
|
|
if (Ret != TLS_RECORD_HEADER_LENGTH + ThisCipherMessageSize) {
|
|
TlsInstance->TlsSessionState = EfiTlsSessionError;
|
|
Status = EFI_ABORTED;
|
|
goto ERROR;
|
|
}
|
|
|
|
Ret = 0;
|
|
Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader + 1), TLS_PLAINTEXT_RECORD_MAX_PAYLOAD_LENGTH);
|
|
|
|
if (Ret > 0) {
|
|
ThisPlainMessageSize = (UINT16)Ret;
|
|
} else {
|
|
//
|
|
// No data was successfully decrypted, continue to decrypt other messages.
|
|
//
|
|
DEBUG ((DEBUG_WARN, "TlsDecryptPacket: No data read from TLS object.\n"));
|
|
|
|
ThisPlainMessageSize = 0;
|
|
}
|
|
|
|
CopyMem (TempRecordHeader, RecordHeaderIn, TLS_RECORD_HEADER_LENGTH);
|
|
TempRecordHeader->Length = ThisPlainMessageSize;
|
|
BufferOutSize += TLS_RECORD_HEADER_LENGTH + ThisPlainMessageSize;
|
|
|
|
BufferInPtr += TLS_RECORD_HEADER_LENGTH + ThisCipherMessageSize;
|
|
TempRecordHeader = (TLS_RECORD_HEADER *)((UINT8 *)TempRecordHeader + TLS_RECORD_HEADER_LENGTH + ThisPlainMessageSize);
|
|
}
|
|
|
|
FreePool (BufferIn);
|
|
BufferIn = NULL;
|
|
|
|
//
|
|
// The caller will be responsible to handle the original fragment table
|
|
//
|
|
*FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA));
|
|
if (*FragmentTable == NULL) {
|
|
Status = EFI_OUT_OF_RESOURCES;
|
|
goto ERROR;
|
|
}
|
|
|
|
(*FragmentTable)[0].FragmentBuffer = BufferOut;
|
|
(*FragmentTable)[0].FragmentLength = BufferOutSize;
|
|
*FragmentCount = 1;
|
|
|
|
return Status;
|
|
|
|
ERROR:
|
|
|
|
if (BufferIn != NULL) {
|
|
FreePool (BufferIn);
|
|
BufferIn = NULL;
|
|
}
|
|
|
|
if (BufferOut != NULL) {
|
|
FreePool (BufferOut);
|
|
BufferOut = NULL;
|
|
}
|
|
|
|
return Status;
|
|
}
|