https://bugzilla.tianocore.org/show_bug.cgi?id=1373 Replace BSD 2-Clause License with BSD+Patent License. This change is based on the following emails: https://lists.01.org/pipermail/edk2-devel/2019-February/036260.html https://lists.01.org/pipermail/edk2-devel/2018-October/030385.html RFCs with detailed process for the license change: V3: https://lists.01.org/pipermail/edk2-devel/2019-March/038116.html V2: https://lists.01.org/pipermail/edk2-devel/2019-March/037669.html V1: https://lists.01.org/pipermail/edk2-devel/2019-March/037500.html Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com> Reviewed-by: Siyuan Fu <siyuan.fu@intel.com>
		
			
				
	
	
		
			350 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			350 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 ((EFI_D_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 ((EFI_D_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;
 | |
| }
 | |
| 
 |