From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 781AB81EB4 for ; Thu, 15 Dec 2016 22:16:26 -0800 (PST) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga101.fm.intel.com with ESMTP; 15 Dec 2016 22:16:25 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.33,356,1477983600"; d="scan'208";a="1082533516" Received: from fmsmsx104.amr.corp.intel.com ([10.18.124.202]) by fmsmga001.fm.intel.com with ESMTP; 15 Dec 2016 22:16:25 -0800 Received: from fmsmsx122.amr.corp.intel.com (10.18.125.37) by fmsmsx104.amr.corp.intel.com (10.18.124.202) with Microsoft SMTP Server (TLS) id 14.3.248.2; Thu, 15 Dec 2016 22:16:25 -0800 Received: from shsmsx152.ccr.corp.intel.com (10.239.6.52) by fmsmsx122.amr.corp.intel.com (10.18.125.37) with Microsoft SMTP Server (TLS) id 14.3.248.2; Thu, 15 Dec 2016 22:16:24 -0800 Received: from shsmsx103.ccr.corp.intel.com ([169.254.4.11]) by SHSMSX152.ccr.corp.intel.com ([169.254.6.235]) with mapi id 14.03.0248.002; Fri, 16 Dec 2016 14:16:22 +0800 From: "Ye, Ting" To: "Wu, Jiaxin" , "edk2-devel@lists.01.org" CC: "Fu, Siyuan" , "Zhang, Lubo" , "Long, Qin" , Thomas Palmer Thread-Topic: [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL Thread-Index: AQHSVqP/H6iNX+5DOkuRV3bGglP8t6EJ4pkw Date: Fri, 16 Dec 2016 06:16:22 +0000 Message-ID: References: <1481786530-153704-1-git-send-email-jiaxin.wu@intel.com> In-Reply-To: <1481786530-153704-1-git-send-email-jiaxin.wu@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 16 Dec 2016 06:16:26 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Jiaxin, Some comments included as below. 1. In TlsCreateService Line 325: ASSERT checks after assignment in line 323. Should put ASSE= RT earlier.=20 'Status' looks useless. 2. TlsDriver.h I think the macros ' TLS_INSTANCE_FROM_PROTOCOL_THIS' and ' TLS_INSTAN= CE_FROM_CONFIGURATION_THIS' are hard to read. Maybe we could remove the '_T= HIS' postfix?=20 Please define appropriate names. 3. TlsImpl.c I think it's better to update TlsEcryptPacket to TlsEncryptPacket And also update "continue the other messages encryption\decryption." To= "continue to encrypt/decrypt other messages." " The caller will take responsible to..." to " The caller will be responsi= ble to... " "Received packet may have multiply TLS record message." To " Received pack= et may have multiple TLS record messages." Also update Multiply to multiple in other places. "Copy all TLS plain record header and payload to ProcessBuffer". Proces= sBuffer looks a local variable but not exist. May update to BufferIn? Pleas= e double check. Others are good to me. Reviewed-by: Ye Ting =20 Thanks, Ting -----Original Message----- From: Wu, Jiaxin=20 Sent: Thursday, December 15, 2016 3:22 PM To: edk2-devel@lists.01.org Cc: Ye, Ting ; Fu, Siyuan ; Zhang, = Lubo ; Long, Qin ; Thomas Palmer = ; Wu, Jiaxin Subject: [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation o= ver OpenSSL v2: * Refine the TlsEcryptPacket/TlsDecryptPacket function according the community feedback. This patch is the implementation of EFI TLS Service Binding Protocol, EFI TLS Protocol and EFI TLS Configuration Protocol Interfaces. Cc: Ye Ting Cc: Fu Siyuan Cc: Zhang Lubo Cc: Long Qin Cc: Thomas Palmer Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Wu Jiaxin --- NetworkPkg/TlsDxe/TlsConfigProtocol.c | 152 ++++++++ NetworkPkg/TlsDxe/TlsDriver.c | 498 +++++++++++++++++++++++++++ NetworkPkg/TlsDxe/TlsDriver.h | 237 +++++++++++++ NetworkPkg/TlsDxe/TlsDxe.inf | 65 ++++ NetworkPkg/TlsDxe/TlsDxe.uni | 25 ++ NetworkPkg/TlsDxe/TlsDxeExtra.uni | 18 + NetworkPkg/TlsDxe/TlsImpl.c | 326 ++++++++++++++++++ NetworkPkg/TlsDxe/TlsImpl.h | 315 +++++++++++++++++ NetworkPkg/TlsDxe/TlsProtocol.c | 632 ++++++++++++++++++++++++++++++= ++++ 9 files changed, 2268 insertions(+) create mode 100644 NetworkPkg/TlsDxe/TlsConfigProtocol.c create mode 100644 NetworkPkg/TlsDxe/TlsDriver.c create mode 100644 NetworkPkg/TlsDxe/TlsDriver.h create mode 100644 NetworkPkg/TlsDxe/TlsDxe.inf create mode 100644 NetworkPkg/TlsDxe/TlsDxe.uni create mode 100644 NetworkPkg/TlsDxe/TlsDxeExtra.uni create mode 100644 NetworkPkg/TlsDxe/TlsImpl.c create mode 100644 NetworkPkg/TlsDxe/TlsImpl.h create mode 100644 NetworkPkg/TlsDxe/TlsProtocol.c diff --git a/NetworkPkg/TlsDxe/TlsConfigProtocol.c b/NetworkPkg/TlsDxe/TlsC= onfigProtocol.c new file mode 100644 index 0000000..2ec79c9 --- /dev/null +++ b/NetworkPkg/TlsDxe/TlsConfigProtocol.c @@ -0,0 +1,152 @@ +/** @file + Implementation of EFI TLS Configuration Protocol Interfaces. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include "TlsImpl.h" + +EFI_TLS_CONFIGURATION_PROTOCOL mTlsConfigurationProtocol =3D { + TlsConfigurationSetData, + TlsConfigurationGetData +}; + +/** + Set TLS configuration data. + + The SetData() function sets TLS configuration to non-volatile storage or= volatile + storage. + + @param[in] This Pointer to the EFI_TLS_CONFIGURATION_PRO= TOCOL instance. + @param[in] DataType Configuration data type. + @param[in] Data Pointer to configuration data. + @param[in] DataSize Total size of configuration data. + + @retval EFI_SUCCESS The TLS configuration data is set succes= sfully. + @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_OUT_OF_RESOURCES Required system resources could not be a= llocated. + +**/ +EFI_STATUS +EFIAPI +TlsConfigurationSetData ( + IN EFI_TLS_CONFIGURATION_PROTOCOL *This, + IN EFI_TLS_CONFIG_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ) +{ + EFI_STATUS Status; + TLS_INSTANCE *Instance; + EFI_TPL OldTpl; + + Status =3D EFI_SUCCESS; + + if (This =3D=3D NULL || Data =3D=3D NULL || DataSize =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + Instance =3D TLS_INSTANCE_FROM_CONFIGURATION_THIS (This); + + switch (DataType) { + case EfiTlsConfigDataTypeCACertificate: + Status =3D TlsSetCaCertificate (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPublicCert: + Status =3D TlsSetHostPublicCert (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPrivateKey: + Status =3D TlsSetHostPrivateKey (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeCertRevocationList: + Status =3D TlsSetCertRevocationList (Data, DataSize); + break; + default: + Status =3D EFI_UNSUPPORTED; + } + + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Get TLS configuration data. + + The GetData() function gets TLS configuration. + + @param[in] This Pointer to the EFI_TLS_CONFIGURATION_PRO= TOCOL instance. + @param[in] DataType Configuration data type. + @param[in, out] Data Pointer to configuration data. + @param[in, out] DataSize Total size of configuration data. On inp= ut, it means + the size of Data buffer. On output, it m= eans the size + of copied Data buffer if EFI_SUCCESS, an= d means the + size of desired Data buffer if EFI_BUFFE= R_TOO_SMALL. + + @retval EFI_SUCCESS The TLS configuration data is got succes= sfully. + @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 configuration data is not found. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data= . +**/ +EFI_STATUS +EFIAPI +TlsConfigurationGetData ( + IN EFI_TLS_CONFIGURATION_PROTOCOL *This, + IN EFI_TLS_CONFIG_DATA_TYPE DataType, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataSize + ) +{ + EFI_STATUS Status; + TLS_INSTANCE *Instance; + + EFI_TPL OldTpl; + + Status =3D EFI_SUCCESS; + + if (This =3D=3D NULL || DataSize =3D=3D NULL || (Data =3D=3D NULL && *Da= taSize !=3D 0)) { + return EFI_INVALID_PARAMETER; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + Instance =3D TLS_INSTANCE_FROM_CONFIGURATION_THIS (This); + + switch (DataType) { + case EfiTlsConfigDataTypeCACertificate: + Status =3D TlsGetCaCertificate (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPublicCert: + Status =3D TlsGetHostPublicCert (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPrivateKey: + Status =3D TlsGetHostPrivateKey (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeCertRevocationList: + Status =3D TlsGetCertRevocationList (Data, DataSize); + break; + default: + Status =3D EFI_UNSUPPORTED; + } + + gBS->RestoreTPL (OldTpl); + return Status; +} diff --git a/NetworkPkg/TlsDxe/TlsDriver.c b/NetworkPkg/TlsDxe/TlsDriver.c new file mode 100644 index 0000000..0a75c39 --- /dev/null +++ b/NetworkPkg/TlsDxe/TlsDriver.c @@ -0,0 +1,498 @@ +/** @file + The Driver Binding and Service Binding Protocol for TlsDxe driver. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include "TlsImpl.h" + +EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding =3D { + TlsServiceBindingCreateChild, + TlsServiceBindingDestroyChild +}; + +/** + Release all the resources used by the TLS instance. + + @param[in] Instance The TLS instance data. + +**/ +VOID +TlsCleanInstance ( + IN TLS_INSTANCE *Instance + ) +{ + if (Instance !=3D NULL) { + if (Instance->TlsConn !=3D NULL) { + TlsFree (Instance->TlsConn); + } + + FreePool (Instance); + } +} + +/** + Create the TLS instance and initialize it. + + @param[in] Service The pointer to the TLS service. + @param[out] Instance The pointer to the TLS instance. + + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. + @retval EFI_SUCCESS The TLS instance is created. + +**/ +EFI_STATUS +TlsCreateInstance ( + IN TLS_SERVICE *Service, + OUT TLS_INSTANCE **Instance + ) +{ + TLS_INSTANCE *TlsInstance; + + *Instance =3D NULL; + + TlsInstance =3D AllocateZeroPool (sizeof (TLS_INSTANCE)); + if (TlsInstance =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TlsInstance->Signature =3D TLS_INSTANCE_SIGNATURE; + InitializeListHead (&TlsInstance->Link); + TlsInstance->InDestroy =3D FALSE; + TlsInstance->Service =3D Service; + + CopyMem (&TlsInstance->Tls, &mTlsProtocol, sizeof (TlsInstance->Tls)); + CopyMem (&TlsInstance->TlsConfig, &mTlsConfigurationProtocol, sizeof (Tl= sInstance->TlsConfig)); + + TlsInstance->TlsSessionState =3D EfiTlsSessionNotStarted; + + *Instance =3D TlsInstance; + + return EFI_SUCCESS; +} + +/** + Release all the resources used by the TLS service binding instance. + + @param[in] Service The TLS service data. + +**/ +VOID +TlsCleanService ( + IN TLS_SERVICE *Service + ) +{ + if (Service !=3D NULL) { + if (Service->TlsCtx !=3D NULL) { + TlsCtxFree (Service->TlsCtx); + } + + FreePool (Service); + } +} + +/** + Create then initialize a TLS service. + + @param[in] Image ImageHandle of the TLS driver + @param[out] Service The service for TLS driver + + @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the= service. + @retval EFI_SUCCESS The service is created for the driver. + +**/ +EFI_STATUS +TlsCreateService ( + IN EFI_HANDLE Image, + OUT TLS_SERVICE **Service + ) +{ + EFI_STATUS Status; + TLS_SERVICE *TlsService; + + Status =3D EFI_SUCCESS; + *Service =3D NULL; + + ASSERT (Service !=3D NULL); + + // + // Allocate a TLS Service Data + // + TlsService =3D AllocateZeroPool (sizeof (TLS_SERVICE)); + if (TlsService =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Initialize TLS Service Data + // + TlsService->Signature =3D TLS_SERVICE_SIGNATURE; + CopyMem (&TlsService->ServiceBinding, &mTlsServiceBinding, sizeof (TlsSe= rvice->ServiceBinding)); + TlsService->TlsChildrenNum =3D 0; + InitializeListHead (&TlsService->TlsChildrenList); + TlsService->ImageHandle =3D Image; + + *Service =3D TlsService; + + return Status; +} + +/** + Unloads an image. + + @param[in] ImageHandle Handle that identifies the image to be= unloaded. + + @retval EFI_SUCCESS The image has been unloaded. + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. + +**/ +EFI_STATUS +EFIAPI +TlsUnload ( + IN EFI_HANDLE ImageHandle + ) +{ + EFI_STATUS Status; + UINTN HandleNum; + EFI_HANDLE *HandleBuffer; + UINT32 Index; + EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; + TLS_SERVICE *TlsService; + + HandleBuffer =3D NULL; + ServiceBinding =3D NULL; + TlsService =3D NULL; + + // + // Locate all the handles with Tls service binding protocol. + // + Status =3D gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiTlsServiceBindingProtocolGuid, + NULL, + &HandleNum, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index =3D 0; Index < HandleNum; Index++) { + // + // Firstly, find ServiceBinding interface + // + Status =3D gBS->OpenProtocol ( + HandleBuffer[Index], + &gEfiTlsServiceBindingProtocolGuid, + (VOID **) &ServiceBinding, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + TlsService =3D TLS_SERVICE_FROM_THIS (ServiceBinding); + + // + // Then, uninstall ServiceBinding interface + // + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + HandleBuffer[Index], + &gEfiTlsServiceBindingProtocolGuid, ServiceBinding, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + TlsCleanService (TlsService); + } + + if (HandleBuffer !=3D NULL) { + FreePool (HandleBuffer); + } + + return EFI_SUCCESS; +} + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers includ= ing + both device drivers and bus drivers. + + @param ImageHandle The firmware allocated handle for the UEFI= image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +EFIAPI +TlsDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + TLS_SERVICE *TlsService; + + // + // Create TLS Service + // + Status =3D TlsCreateService (ImageHandle, &TlsService); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (TlsService !=3D NULL); + + // + // Initializes the OpenSSL library. + // + TlsInitialize (); + + // + // Create a new SSL_CTX object as framework to establish TLS/SSL enabled + // connections. TLS 1.0 is used as the default version. + // + TlsService->TlsCtx =3D TlsCtxNew (TLS10_PROTOCOL_VERSION_MAJOR, TLS10_PR= OTOCOL_VERSION_MINOR); + if (TlsService->TlsCtx =3D=3D NULL) { + FreePool (TlsService); + return EFI_ABORTED; + } + + // + // Install the TlsServiceBinding Protocol onto Handle + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &TlsService->Handle, + &gEfiTlsServiceBindingProtocolGuid, + &TlsService->ServiceBinding, + NULL + ); + if (EFI_ERROR (Status)) { + goto ON_CLEAN_SERVICE; + } + + return Status; + +ON_CLEAN_SERVICE: + TlsCleanService (TlsService); + + return Status; +} + +/** + Creates a child handle and installs a protocol. + + The CreateChild() function installs a protocol on ChildHandle. + If ChildHandle is a pointer to NULL, then a new handle is created and re= turned in ChildHandle. + If ChildHandle is not a pointer to NULL, then the protocol installs on t= he existing ChildHandle. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL insta= nce. + @param[in] ChildHandle Pointer to the handle of the child to create. If = it is NULL, + then a new handle is created. If it is a pointer = to an existing UEFI handle, + then the protocol is added to the existing UEFI h= andle. + + @retval EFI_SUCCES The protocol was added to ChildHandle. + @retval EFI_INVALID_PARAMETER ChildHandle is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available t= o create + the child. + @retval other The child handle was not created. + +**/ +EFI_STATUS +EFIAPI +TlsServiceBindingCreateChild ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE *ChildHandle + ) +{ + TLS_SERVICE *TlsService; + TLS_INSTANCE *TlsInstance; + EFI_STATUS Status; + EFI_TPL OldTpl; + + if ((This =3D=3D NULL) || (ChildHandle =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + TlsService =3D TLS_SERVICE_FROM_THIS (This); + + Status =3D TlsCreateInstance (TlsService, &TlsInstance); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (TlsInstance !=3D NULL); + + // + // Create a new TLS connection object. + // + TlsInstance->TlsConn =3D TlsNew (TlsService->TlsCtx); + if (TlsInstance->TlsConn =3D=3D NULL) { + Status =3D EFI_ABORTED; + goto ON_ERROR; + } + + // + // Set default ConnectionEnd to EfiTlsClient + // + Status =3D TlsSetConnectionEnd (TlsInstance->TlsConn, EfiTlsClient); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // Install TLS protocol and configuration protocol onto ChildHandle + // + Status =3D gBS->InstallMultipleProtocolInterfaces ( + ChildHandle, + &gEfiTlsProtocolGuid, + &TlsInstance->Tls, + &gEfiTlsConfigurationProtocolGuid, + &TlsInstance->TlsConfig, + NULL + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + TlsInstance->ChildHandle =3D *ChildHandle; + + // + // Add it to the TLS service's child list. + // + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + InsertTailList (&TlsService->TlsChildrenList, &TlsInstance->Link); + TlsService->TlsChildrenNum++; + + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; + +ON_ERROR: + TlsCleanInstance (TlsInstance); + return Status; +} + +/** + Destroys a child handle with a protocol installed on it. + + The DestroyChild() function does the opposite of CreateChild(). It remov= es a protocol + that was installed by CreateChild() from ChildHandle. If the removed pro= tocol is the + last protocol on ChildHandle, then ChildHandle is destroyed. + + @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance= . + @param ChildHandle Handle of the child to destroy. + + @retval EFI_SUCCES The protocol was removed from ChildHandle. + @retval EFI_UNSUPPORTED ChildHandle does not support the protocol = that is being removed. + @retval EFI_INVALID_PARAMETER Child handle is NULL. + @retval EFI_ACCESS_DENIED The protocol could not be removed from the= ChildHandle + because its services are being used. + @retval other The child handle was not destroyed. + +**/ +EFI_STATUS +EFIAPI +TlsServiceBindingDestroyChild ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE ChildHandle + ) +{ + TLS_SERVICE *TlsService; + TLS_INSTANCE *TlsInstance; + + EFI_TLS_PROTOCOL *Tls; + EFI_TLS_CONFIGURATION_PROTOCOL *TlsConfig; + EFI_STATUS Status; + EFI_TPL OldTpl; + + if ((This =3D=3D NULL) || (ChildHandle =3D=3D NULL)) { + return EFI_INVALID_PARAMETER; + } + + TlsService =3D TLS_SERVICE_FROM_THIS (This); + + // + // Find TLS protocol interface installed in ChildHandle + // + Status =3D gBS->OpenProtocol ( + ChildHandle, + &gEfiTlsProtocolGuid, + (VOID **) &Tls, + TlsService->ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Find TLS configuration protocol interface installed in ChildHandle + // + Status =3D gBS->OpenProtocol ( + ChildHandle, + &gEfiTlsConfigurationProtocolGuid, + (VOID **) &TlsConfig, + TlsService->ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + TlsInstance =3D TLS_INSTANCE_FROM_PROTOCOL_THIS (Tls); + + if (TlsInstance->Service !=3D TlsService) { + return EFI_INVALID_PARAMETER; + } + + if (TlsInstance->InDestroy) { + return EFI_SUCCESS; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + TlsInstance->InDestroy =3D TRUE; + + // + // Uninstall the TLS protocol and TLS Configuration Protocol interface i= nstalled in ChildHandle. + // + Status =3D gBS->UninstallMultipleProtocolInterfaces ( + ChildHandle, + &gEfiTlsProtocolGuid, + Tls, + &gEfiTlsConfigurationProtocolGuid, + TlsConfig, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + RemoveEntryList (&TlsInstance->Link); + TlsService->TlsChildrenNum--; + + gBS->RestoreTPL (OldTpl); + + TlsCleanInstance (TlsInstance); + + return EFI_SUCCESS; +} diff --git a/NetworkPkg/TlsDxe/TlsDriver.h b/NetworkPkg/TlsDxe/TlsDriver.h new file mode 100644 index 0000000..c3c30a8 --- /dev/null +++ b/NetworkPkg/TlsDxe/TlsDriver.h @@ -0,0 +1,237 @@ +/** @file + Header file of the Driver Binding and Service Binding Protocol for TlsDx= e driver. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#ifndef __EFI_TLS_DRIVER_H__ +#define __EFI_TLS_DRIVER_H__ + +#include + +// +// Driver Protocols +// +#include + +// +// Driver Version +// +#define TLS_VERSION 0x00000000 + +#define TLS_SERVICE_SIGNATURE SIGNATURE_32 ('T', 'L', 'S', 'S') + +#define TLS_INSTANCE_SIGNATURE SIGNATURE_32 ('T', 'L', 'S', 'I') + +/// +/// TLS Service Data +/// +typedef struct _TLS_SERVICE TLS_SERVICE; + +/// +/// TLS Instance Data +/// +typedef struct _TLS_INSTANCE TLS_INSTANCE; + + +struct _TLS_SERVICE { + UINT32 Signature; + EFI_SERVICE_BINDING_PROTOCOL ServiceBinding; + + UINT16 TlsChildrenNum; + LIST_ENTRY TlsChildrenList; + + // + // Handle to install TlsServiceBinding protocol. + // + EFI_HANDLE Handle; + EFI_HANDLE ImageHandle; + + // + // Main SSL Context object which is created by a server or client once p= er program + // life-time and which holds mainly default values for the SSL object wh= ich are later + // created for the connections. + // + VOID *TlsCtx; +}; + +struct _TLS_INSTANCE { + UINT32 Signature; + LIST_ENTRY Link; + + BOOLEAN InDestroy; + + TLS_SERVICE *Service; + EFI_HANDLE ChildHandle; + + EFI_TLS_PROTOCOL Tls; + EFI_TLS_CONFIGURATION_PROTOCOL TlsConfig; + + EFI_TLS_SESSION_STATE TlsSessionState; + + // + // Main SSL Connection which is created by a server or a client + // per established connection. + // + VOID *TlsConn; +}; + + +#define TLS_SERVICE_FROM_THIS(a) \ + CR (a, TLS_SERVICE, ServiceBinding, TLS_SERVICE_SIGNATURE) + +#define TLS_INSTANCE_FROM_PROTOCOL_THIS(a) \ + CR (a, TLS_INSTANCE, Tls, TLS_INSTANCE_SIGNATURE) + +#define TLS_INSTANCE_FROM_CONFIGURATION_THIS(a) \ + CR (a, TLS_INSTANCE, TlsConfig, TLS_INSTANCE_SIGNATURE) + + +/** + Release all the resources used by the TLS instance. + + @param[in] Instance The TLS instance data. + +**/ +VOID +TlsCleanInstance ( + IN TLS_INSTANCE *Instance + ); + +/** + Create the TLS instance and initialize it. + + @param[in] Service The pointer to the TLS service. + @param[out] Instance The pointer to the TLS instance. + + @retval EFI_OUT_OF_RESOURCES Failed to allocate resources. + @retval EFI_SUCCESS The TLS instance is created. + +**/ +EFI_STATUS +TlsCreateInstance ( + IN TLS_SERVICE *Service, + OUT TLS_INSTANCE **Instance + ); + +/** + Release all the resources used by the TLS service binding instance. + + @param[in] Service The TLS service data. + +**/ +VOID +TlsCleanService ( + IN TLS_SERVICE *Service + ); + +/** + Create then initialize a TLS service. + + @param[in] Image ImageHandle of the TLS driver + @param[out] Service The service for TLS driver + + @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the= service. + @retval EFI_SUCCESS The service is created for the driver. + +**/ +EFI_STATUS +TlsCreateService ( + IN EFI_HANDLE Image, + OUT TLS_SERVICE **Service + ); + +/** + Unloads an image. + + @param[in] ImageHandle Handle that identifies the image to be unl= oaded. + + @retval EFI_SUCCESS The image has been unloaded. + @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle. + +**/ +EFI_STATUS +EFIAPI +TlsUnload ( + IN EFI_HANDLE ImageHandle + ); + +/** + This is the declaration of an EFI image entry point. This entry point is + the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers includ= ing + both device drivers and bus drivers. + + @param ImageHandle The firmware allocated handle for the UEFI= image. + @param SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The operation completed successfully. + @retval Others An unexpected error occurred. +**/ +EFI_STATUS +EFIAPI +TlsDriverEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ); + +/** + Creates a child handle and installs a protocol. + + The CreateChild() function installs a protocol on ChildHandle. + If ChildHandle is a pointer to NULL, then a new handle is created and re= turned in ChildHandle. + If ChildHandle is not a pointer to NULL, then the protocol installs on t= he existing ChildHandle. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL insta= nce. + @param[in] ChildHandle Pointer to the handle of the child to create. If = it is NULL, + then a new handle is created. If it is a pointer = to an existing UEFI handle, + then the protocol is added to the existing UEFI h= andle. + + @retval EFI_SUCCES The protocol was added to ChildHandle. + @retval EFI_INVALID_PARAMETER ChildHandle is NULL. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available t= o create + the child. + @retval other The child handle was not created. + +**/ +EFI_STATUS +EFIAPI +TlsServiceBindingCreateChild ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE *ChildHandle + ); + +/** + Destroys a child handle with a protocol installed on it. + + The DestroyChild() function does the opposite of CreateChild(). It remov= es a protocol + that was installed by CreateChild() from ChildHandle. If the removed pro= tocol is the + last protocol on ChildHandle, then ChildHandle is destroyed. + + @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance= . + @param ChildHandle Handle of the child to destroy. + + @retval EFI_SUCCES The protocol was removed from ChildHandle. + @retval EFI_UNSUPPORTED ChildHandle does not support the protocol = that is being removed. + @retval EFI_INVALID_PARAMETER Child handle is NULL. + @retval EFI_ACCESS_DENIED The protocol could not be removed from the= ChildHandle + because its services are being used. + @retval other The child handle was not destroyed. + +**/ +EFI_STATUS +EFIAPI +TlsServiceBindingDestroyChild ( + IN EFI_SERVICE_BINDING_PROTOCOL *This, + IN EFI_HANDLE ChildHandle + ); + +#endif diff --git a/NetworkPkg/TlsDxe/TlsDxe.inf b/NetworkPkg/TlsDxe/TlsDxe.inf new file mode 100644 index 0000000..dba3257 --- /dev/null +++ b/NetworkPkg/TlsDxe/TlsDxe.inf @@ -0,0 +1,65 @@ +## @file +# This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol= and +# EFI TLS Configuration Protocol. +# +# This module produces EFI TLS (Transport Layer Security) Protocol and EF= I TLS +# Service Binding Protocol, to provide TLS services. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.
+# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the B= SD License +# which accompanies this distribution. The full text of the license may b= e 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 IM= PLIED. +# +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D TlsDxe + FILE_GUID =3D 3aceb0c0-3c72-11e4-9a56-74d435052646 + MODULE_TYPE =3D UEFI_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D TlsDriverEntryPoint + UNLOAD_IMAGE =3D TlsUnload + MODULE_UNI_FILE =3D TlsDxe.uni + +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + CryptoPkg/CryptoPkg.dec + +[Sources] + TlsDriver.h + TlsDriver.c + TlsProtocol.c + TlsConfigProtocol.c + TlsImpl.h + TlsImpl.c + +[LibraryClasses] + UefiDriverEntryPoint + UefiBootServicesTableLib + MemoryAllocationLib + BaseMemoryLib + BaseLib + UefiLib + DebugLib + NetLib + BaseCryptLib + TlsLib + +[Protocols] + gEfiTlsServiceBindingProtocolGuid ## PRODUCES + gEfiTlsProtocolGuid ## PRODUCES + gEfiTlsConfigurationProtocolGuid ## PRODUCES + +[UserExtensions.TianoCore."ExtraFiles"] + TlsDxeExtra.uni diff --git a/NetworkPkg/TlsDxe/TlsDxe.uni b/NetworkPkg/TlsDxe/TlsDxe.uni new file mode 100644 index 0000000..98c41ca --- /dev/null +++ b/NetworkPkg/TlsDxe/TlsDxe.uni @@ -0,0 +1,25 @@ +// /** @file +// This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol= and +// EFI TLS Configuration Protocol. +// +// This module produces EFI TLS (Transport Layer Security) Protocol, EFI T= LS +// Service Binding Protocol, and EFI TLS Configuration Protocol to provide= TLS +// services. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the B= SD 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 IM= PLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "UEFI TLS service" + +#string STR_MODULE_DESCRIPTION #language en-US "This module produ= ces EFI TLS Protocol, EFI TLS Service Binding Protocol and EFI TLS Configur= ation Protocol to provide EFI TLS services." + diff --git a/NetworkPkg/TlsDxe/TlsDxeExtra.uni b/NetworkPkg/TlsDxe/TlsDxeEx= tra.uni new file mode 100644 index 0000000..a38582a --- /dev/null +++ b/NetworkPkg/TlsDxe/TlsDxeExtra.uni @@ -0,0 +1,18 @@ +// /** @file +// TlsDxe Localized Strings and Content +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the B= SD License +// which accompanies this distribution. The full text of the license may b= e 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 IM= PLIED. +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"EFI TLS DXE Driver" diff --git a/NetworkPkg/TlsDxe/TlsImpl.c b/NetworkPkg/TlsDxe/TlsImpl.c new file mode 100644 index 0000000..9b7bf7d --- /dev/null +++ b/NetworkPkg/TlsDxe/TlsImpl.c @@ -0,0 +1,326 @@ +/** @file + The Miscellaneous Routines for TlsDxe driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+ +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 IMPLI= ED. + +**/ + +#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 TL= S 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 +TlsEcryptPacket ( + 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; + INTN Ret; + =20 + Status =3D EFI_SUCCESS; + BytesCopied =3D 0; + BufferInSize =3D 0; + BufferIn =3D NULL; + BufferInPtr =3D NULL; + RecordHeaderIn =3D NULL; + TempRecordHeader =3D NULL; + BufferOutSize =3D 0; + BufferOut =3D NULL; + Ret =3D 0; + + // + // Calculate the size according to the fragment table. + // + for (Index =3D 0; Index < *FragmentCount; Index++) { + BufferInSize +=3D (*FragmentTable)[Index].FragmentLength; + } + + // + // Allocate buffer for processing data. + // + BufferIn =3D AllocateZeroPool (BufferInSize); + if (BufferIn =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + // + // Copy all TLS plain record header and payload into ProcessBuffer. + // + for (Index =3D 0; Index < *FragmentCount; Index++) { + CopyMem ( + (BufferIn + BytesCopied), + (*FragmentTable)[Index].FragmentBuffer, + (*FragmentTable)[Index].FragmentLength + ); + BytesCopied +=3D (*FragmentTable)[Index].FragmentLength; + } + + BufferOut =3D AllocateZeroPool (MAX_BUFFER_SIZE); + if (BufferOut =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + // + // Parsing buffer. + // + BufferInPtr =3D BufferIn; + TempRecordHeader =3D (TLS_RECORD_HEADER *) BufferOut; + while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { + RecordHeaderIn =3D (TLS_RECORD_HEADER *) BufferInPtr; + =20 + if (RecordHeaderIn->ContentType !=3D TLS_CONTENT_TYPE_APPLICATION_DATA= ) { + Status =3D EFI_INVALID_PARAMETER; + goto ERROR; + } + =20 + ThisPlainMessageSize =3D RecordHeaderIn->Length; + + TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), ThisPl= ainMessageSize); + =20 + Ret =3D TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordH= eader), MAX_BUFFER_SIZE - BufferOutSize); + + if (Ret > 0) { + ThisMessageSize =3D (UINT16) Ret; + } else { + // + // No data was successfully encrypted, continue the other messages e= ncryption. + // + DEBUG ((EFI_D_WARN, "TlsEcryptPacket: No data read from TLS object.\= n")); + =20 + ThisMessageSize =3D 0; + } + + BufferOutSize +=3D ThisMessageSize; + + BufferInPtr +=3D RECORD_HEADER_LEN + ThisPlainMessageSize; + TempRecordHeader +=3D ThisMessageSize; + } + + FreePool (BufferIn); + BufferIn =3D NULL; + + // + // The caller will take responsible to handle the original fragment tabl= e. + // + *FragmentTable =3D AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA)); + if (*FragmentTable =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + (*FragmentTable)[0].FragmentBuffer =3D BufferOut; + (*FragmentTable)[0].FragmentLength =3D BufferOutSize; + *FragmentCount =3D 1; + + return Status; + +ERROR: + =20 + if (BufferIn !=3D NULL) { + FreePool (BufferIn); + BufferIn =3D NULL; + } + + if (BufferOut !=3D NULL) { + FreePool (BufferOut); + BufferOut =3D NULL; + } + =20 + 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 TL= S 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; + INTN Ret; + + Status =3D EFI_SUCCESS; + BytesCopied =3D 0; + BufferIn =3D NULL; + BufferInSize =3D 0; + BufferInPtr =3D NULL; + RecordHeaderIn =3D NULL; + TempRecordHeader =3D NULL; + BufferOut =3D NULL; + BufferOutSize =3D 0; + Ret =3D 0; + + // + // Calculate the size according to the fragment table. + // + for (Index =3D 0; Index < *FragmentCount; Index++) { + BufferInSize +=3D (*FragmentTable)[Index].FragmentLength; + } + + // + // Allocate buffer for processing data + // + BufferIn =3D AllocateZeroPool (BufferInSize); + if (BufferIn =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + // + // Copy all TLS plain record header and payload to ProcessBuffer + // + for (Index =3D 0; Index < *FragmentCount; Index++) { + CopyMem ( + (BufferIn + BytesCopied), + (*FragmentTable)[Index].FragmentBuffer, + (*FragmentTable)[Index].FragmentLength + ); + BytesCopied +=3D (*FragmentTable)[Index].FragmentLength; + } + + BufferOut =3D AllocateZeroPool (MAX_BUFFER_SIZE); + if (BufferOut =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + // + // Parsing buffer. Received packet may have multiply TLS record message. + // + BufferInPtr =3D BufferIn; + TempRecordHeader =3D (TLS_RECORD_HEADER *) BufferOut; + while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { + RecordHeaderIn =3D (TLS_RECORD_HEADER *) BufferInPtr; + + if (RecordHeaderIn->ContentType !=3D TLS_CONTENT_TYPE_APPLICATION_DATA= ) { + Status =3D EFI_INVALID_PARAMETER; + goto ERROR; + } + =20 + ThisCipherMessageSize =3D NTOHS (RecordHeaderIn->Length); + + Ret =3D TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeade= rIn), RECORD_HEADER_LEN + ThisCipherMessageSize); + if (Ret !=3D RECORD_HEADER_LEN + ThisCipherMessageSize) { + TlsInstance->TlsSessionState =3D EfiTlsSessionError; + Status =3D EFI_ABORTED; + goto ERROR; + } + + Ret =3D 0; + Ret =3D TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1= ), MAX_BUFFER_SIZE - BufferOutSize); + + if (Ret > 0) { + ThisPlainMessageSize =3D (UINT16) Ret; + } else { + // + // No data was successfully decrypted, continue the other messages d= ecryption. + // + DEBUG ((EFI_D_WARN, "TlsDecryptPacket: No data read from TLS object.= \n")); + =20 + ThisPlainMessageSize =3D 0; + } + + CopyMem (TempRecordHeader, RecordHeaderIn, RECORD_HEADER_LEN); + TempRecordHeader->Length =3D ThisPlainMessageSize; + BufferOutSize +=3D RECORD_HEADER_LEN + ThisPlainMessageSize; + + BufferInPtr +=3D RECORD_HEADER_LEN + ThisCipherMessageSize; + TempRecordHeader +=3D RECORD_HEADER_LEN + ThisPlainMessageSize; + } + + FreePool (BufferIn); + BufferIn =3D NULL; + + // + // The caller will take responsible to handle the original fragment tabl= e + // + *FragmentTable =3D AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA)); + if (*FragmentTable =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + (*FragmentTable)[0].FragmentBuffer =3D BufferOut; + (*FragmentTable)[0].FragmentLength =3D BufferOutSize; + *FragmentCount =3D 1; + + return Status; + +ERROR: + =20 + if (BufferIn !=3D NULL) { + FreePool (BufferIn); + BufferIn =3D NULL; + } + + if (BufferOut !=3D NULL) { + FreePool (BufferOut); + BufferOut =3D NULL; + } + =20 + return Status; =20 +} diff --git a/NetworkPkg/TlsDxe/TlsImpl.h b/NetworkPkg/TlsDxe/TlsImpl.h new file mode 100644 index 0000000..b0615cb --- /dev/null +++ b/NetworkPkg/TlsDxe/TlsImpl.h @@ -0,0 +1,315 @@ +/** @file + Header file of Miscellaneous Routines for TlsDxe driver. + +Copyright (c) 2016, Intel Corporation. All rights reserved.
+ +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 IMPLI= ED. + +**/ + +#ifndef __EFI_TLS_IMPL_H__ +#define __EFI_TLS_IMPL_H__ + +// +// Libraries +// +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// +// Consumed Protocols +// +#include +#include + +#include + +#include "TlsDriver.h" + +// +// Protocol instances +// +extern EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding; +extern EFI_TLS_PROTOCOL mTlsProtocol; +extern EFI_TLS_CONFIGURATION_PROTOCOL mTlsConfigurationProtocol; + +#define RECORD_HEADER_LEN 5 /// ContentType(1) + Version(2) + Length(2) + +#define MAX_BUFFER_SIZE 32768 + +/** + 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 TL= S 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 +TlsEcryptPacket ( + IN TLS_INSTANCE *TlsInstance, + IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable, + IN UINT32 *FragmentCount + ); + +/** + 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 TL= S 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 + ); + +/** + Set TLS session data. + + The SetSessionData() function set data for a new TLS session. All sessio= n 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 a= llocated. +**/ +EFI_STATUS +EFIAPI +TlsSetSessionData ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + 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 m= eans the size + of copied Data buffer if EFI_SUCCESS, an= d means the + size of desired Data buffer if EFI_BUFFE= R_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 ses= sion 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 + ); + +/** + Build response packet according to TLS state machine. This function is o= nly valid for + alert, handshake and change_cipher_spec content type. + + The BuildResponsePacket() function builds TLS response packet in respons= e to the TLS + request packet specified by RequestBuffer and RequestSize. If RequestBuf= fer 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 Re= questBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosin= g, the TLS + session will be closed and response packet needs to be CloseNotify. If R= equestBuffer 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 bas= ed on error + type. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance= . + @param[in] RequestBuffer Pointer to the most recently received TL= S 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 recent= ly received TLS + packet. 0 is only valid when RequestBuff= er 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 con= tain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built success= fully. + @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 NO= T NULL. + BufferSize is NULL. + Buffer is NULL if *BufferSize is not zer= o. + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the resp= onse packet. + @retval EFI_NOT_READY Current TLS session state is NOT ready t= o 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 + ); + +/** + Decrypt or encrypt TLS packet during session. This function is only vali= d after + session connected and for application_data content type. + + The ProcessPacket () function process each inbound or outbound TLS APP p= acket. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance= . + @param[in, out] FragmentTable Pointer to a list of fragment. The calle= r will take + responsible to handle the original Fragm= entTable 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; o= n output these + fragments contain the TLS header and cip= her text TLS + APP payload. If CryptMode is EfiTlsDecry= pt, on input + these fragments contain the TLS header a= nd cipher text + TLS APP payload; on output these fragmen= ts contain the + TLS header and plain text TLS APP payloa= d. + @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. T= he caller need + call BuildResponsePacket() to generate E= rror Alert + message and send it out. + @retval EFI_OUT_OF_RESOURCES No enough resource to finish the operati= on. +**/ +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 + ); + +/** + Set TLS configuration data. + + The SetData() function sets TLS configuration to non-volatile storage or= volatile + storage. + + @param[in] This Pointer to the EFI_TLS_CONFIGURATION_PRO= TOCOL instance. + @param[in] DataType Configuration data type. + @param[in] Data Pointer to configuration data. + @param[in] DataSize Total size of configuration data. + + @retval EFI_SUCCESS The TLS configuration data is set succes= sfully. + @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_OUT_OF_RESOURCES Required system resources could not be a= llocated. +**/ +EFI_STATUS +EFIAPI +TlsConfigurationSetData ( + IN EFI_TLS_CONFIGURATION_PROTOCOL *This, + IN EFI_TLS_CONFIG_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Get TLS configuration data. + + The GetData() function gets TLS configuration. + + @param[in] This Pointer to the EFI_TLS_CONFIGURATION_PRO= TOCOL instance. + @param[in] DataType Configuration data type. + @param[in, out] Data Pointer to configuration data. + @param[in, out] DataSize Total size of configuration data. On inp= ut, it means + the size of Data buffer. On output, it m= eans the size + of copied Data buffer if EFI_SUCCESS, an= d means the + size of desired Data buffer if EFI_BUFFE= R_TOO_SMALL. + + @retval EFI_SUCCESS The TLS configuration data is got succes= sfully. + @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 configuration data is not found. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data= . +**/ +EFI_STATUS +EFIAPI +TlsConfigurationGetData ( + IN EFI_TLS_CONFIGURATION_PROTOCOL *This, + IN EFI_TLS_CONFIG_DATA_TYPE DataType, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataSize + ); + +#endif diff --git a/NetworkPkg/TlsDxe/TlsProtocol.c b/NetworkPkg/TlsDxe/TlsProtoco= l.c new file mode 100644 index 0000000..bc617e1 --- /dev/null +++ b/NetworkPkg/TlsDxe/TlsProtocol.c @@ -0,0 +1,632 @@ +/** @file + Implementation of EFI TLS Protocol Interfaces. + + Copyright (c) 2016, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include "TlsImpl.h" + +EFI_TLS_PROTOCOL mTlsProtocol =3D { + TlsSetSessionData, + TlsGetSessionData, + TlsBuildResponsePacket, + TlsProcessPacket +}; + +/** + Set TLS session data. + + The SetSessionData() function set data for a new TLS session. All sessio= n 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 a= llocated. +**/ +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 =3D EFI_SUCCESS; + CipherId =3D NULL; + + if (This =3D=3D NULL || Data =3D=3D NULL || DataSize =3D=3D 0) { + return EFI_INVALID_PARAMETER; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + Instance =3D TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if (DataType !=3D EfiTlsSessionState && Instance->TlsSessionState !=3D = EfiTlsSessionNotStarted){ + Status =3D EFI_NOT_READY; + goto ON_EXIT; + } + + switch (DataType) { + // + // Session Configuration + // + case EfiTlsVersion: + if (DataSize !=3D sizeof (EFI_TLS_VERSION)) { + Status =3D EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status =3D TlsSetVersion (Instance->TlsConn, ((EFI_TLS_VERSION *) Data= )->Major, ((EFI_TLS_VERSION *) Data)->Minor); + break; + case EfiTlsConnectionEnd: + if (DataSize !=3D sizeof (EFI_TLS_CONNECTION_END)) { + Status =3D EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status =3D TlsSetConnectionEnd (Instance->TlsConn, *((EFI_TLS_CONNECTI= ON_END *) Data)); + break; + case EfiTlsCipherList: + CipherId =3D AllocatePool (DataSize); + if (CipherId =3D=3D NULL) { + Status =3D EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + for (Index =3D 0; Index < DataSize / sizeof (EFI_TLS_CIPHER); Index++)= { + *(CipherId +Index) =3D HTONS (*(((UINT16 *) Data) + Index)); + } + + Status =3D TlsSetCipherList (Instance->TlsConn, CipherId, DataSize / s= izeof (EFI_TLS_CIPHER)); + + FreePool (CipherId); + break; + case EfiTlsCompressionMethod: + // + // TLS seems only define one CompressionMethod.null, which specifies t= hat data exchanged via the + // record protocol will not be compressed. + // More information from OpenSSL: http://www.openssl.org/docs/manmaste= r/ssl/SSL_COMP_add_compression_method.html + // The TLS RFC does however not specify compression methods or their c= orresponding identifiers, + // so there is currently no compatible way to integrate compression wi= th unknown peers. + // It is therefore currently not recommended to integrate compression = into applications. + // Applications for non-public use may agree on certain compression me= thods. + // Using different compression methods with the same identifier will l= ead to connection failure. + // + for (Index =3D 0; Index < DataSize / sizeof (EFI_TLS_COMPRESSION); Ind= ex++) { + Status =3D TlsSetCompressionMethod (*((UINT8 *) Data + Index)); + if (EFI_ERROR (Status)) { + break; + } + } + + break; + case EfiTlsExtensionData: + Status =3D EFI_UNSUPPORTED; + goto ON_EXIT; + case EfiTlsVerifyMethod: + if (DataSize !=3D sizeof (EFI_TLS_VERIFY)) { + Status =3D EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + TlsSetVerify (Instance->TlsConn, *((UINT32 *) Data)); + break; + case EfiTlsSessionID: + if (DataSize !=3D sizeof (EFI_TLS_SESSION_ID)) { + Status =3D EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status =3D TlsSetSessionId ( + Instance->TlsConn, + ((EFI_TLS_SESSION_ID *) Data)->Data, + ((EFI_TLS_SESSION_ID *) Data)->Length + ); + break; + case EfiTlsSessionState: + if (DataSize !=3D sizeof (EFI_TLS_SESSION_STATE)) { + Status =3D EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Instance->TlsSessionState =3D *(EFI_TLS_SESSION_STATE *) Data; + break; + // + // Session information + // + case EfiTlsClientRandom: + Status =3D EFI_ACCESS_DENIED; + break; + case EfiTlsServerRandom: + Status =3D EFI_ACCESS_DENIED; + break; + case EfiTlsKeyMaterial: + Status =3D EFI_ACCESS_DENIED; + break; + // + // Unsupported type. + // + default: + Status =3D 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 m= eans the size + of copied Data buffer if EFI_SUCCESS, an= d means the + size of desired Data buffer if EFI_BUFFE= R_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 ses= sion 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 =3D EFI_SUCCESS; + + if (This =3D=3D NULL || DataSize =3D=3D NULL || (Data =3D=3D NULL && *Da= taSize !=3D 0)) { + return EFI_INVALID_PARAMETER; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + Instance =3D TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if (Instance->TlsSessionState =3D=3D EfiTlsSessionNotStarted && + (DataType =3D=3D EfiTlsSessionID || DataType =3D=3D EfiTlsClientRandom= || + DataType =3D=3D EfiTlsServerRandom || DataType =3D=3D EfiTlsKeyMateria= l)) { + Status =3D EFI_NOT_READY; + goto ON_EXIT; + } + + switch (DataType) { + case EfiTlsVersion: + if (*DataSize < sizeof (EFI_TLS_VERSION)) { + *DataSize =3D sizeof (EFI_TLS_VERSION); + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize =3D sizeof (EFI_TLS_VERSION); + *((UINT16 *) Data) =3D HTONS (TlsGetVersion (Instance->TlsConn)); + break; + case EfiTlsConnectionEnd: + if (*DataSize < sizeof (EFI_TLS_CONNECTION_END)) { + *DataSize =3D sizeof (EFI_TLS_CONNECTION_END); + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize =3D sizeof (EFI_TLS_CONNECTION_END); + *((UINT8 *) Data) =3D TlsGetConnectionEnd (Instance->TlsConn); + break; + case EfiTlsCipherList: + // + // Get the current session cipher suite. + // + if (*DataSize < sizeof (EFI_TLS_CIPHER)) { + *DataSize =3D sizeof (EFI_TLS_CIPHER); + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize =3D sizeof(EFI_TLS_CIPHER); + Status =3D TlsGetCurrentCipher (Instance->TlsConn, (UINT16 *) Data); + *((UINT16 *) Data) =3D HTONS (*((UINT16 *) Data)); + break; + case EfiTlsCompressionMethod: + // + // Get the current session compression method. + // + if (*DataSize < sizeof (EFI_TLS_COMPRESSION)) { + *DataSize =3D sizeof (EFI_TLS_COMPRESSION); + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize =3D sizeof (EFI_TLS_COMPRESSION); + Status =3D TlsGetCurrentCompressionId (Instance->TlsConn, (UINT8 *) Da= ta); + break; + case EfiTlsExtensionData: + Status =3D EFI_UNSUPPORTED; + goto ON_EXIT; + case EfiTlsVerifyMethod: + if (*DataSize < sizeof (EFI_TLS_VERIFY)) { + *DataSize =3D sizeof (EFI_TLS_VERIFY); + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize =3D sizeof (EFI_TLS_VERIFY); + *((UINT32 *) Data) =3D TlsGetVerify (Instance->TlsConn); + break; + case EfiTlsSessionID: + if (*DataSize < sizeof (EFI_TLS_SESSION_ID)) { + *DataSize =3D sizeof (EFI_TLS_SESSION_ID); + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize =3D sizeof (EFI_TLS_SESSION_ID); + Status =3D 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 =3D sizeof (EFI_TLS_SESSION_STATE); + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize =3D sizeof (EFI_TLS_SESSION_STATE); + CopyMem (Data, &Instance->TlsSessionState, *DataSize); + break; + case EfiTlsClientRandom: + if (*DataSize < sizeof (EFI_TLS_RANDOM)) { + *DataSize =3D sizeof (EFI_TLS_RANDOM); + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize =3D sizeof (EFI_TLS_RANDOM); + TlsGetClientRandom (Instance->TlsConn, (UINT8 *) Data); + break; + case EfiTlsServerRandom: + if (*DataSize < sizeof (EFI_TLS_RANDOM)) { + *DataSize =3D sizeof (EFI_TLS_RANDOM); + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize =3D sizeof (EFI_TLS_RANDOM); + TlsGetServerRandom (Instance->TlsConn, (UINT8 *) Data); + break; + case EfiTlsKeyMaterial: + if (*DataSize < sizeof (EFI_TLS_MASTER_SECRET)) { + *DataSize =3D sizeof (EFI_TLS_MASTER_SECRET); + Status =3D EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize =3D sizeof (EFI_TLS_MASTER_SECRET); + Status =3D TlsGetKeyMaterial (Instance->TlsConn, (UINT8 *) Data); + break; + // + // Unsupported type. + // + default: + Status =3D EFI_UNSUPPORTED; + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Build response packet according to TLS state machine. This function is o= nly valid for + alert, handshake and change_cipher_spec content type. + + The BuildResponsePacket() function builds TLS response packet in respons= e to the TLS + request packet specified by RequestBuffer and RequestSize. If RequestBuf= fer 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 Re= questBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosin= g, the TLS + session will be closed and response packet needs to be CloseNotify. If R= equestBuffer 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 bas= ed on error + type. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance= . + @param[in] RequestBuffer Pointer to the most recently received TL= S 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 recent= ly received TLS + packet. 0 is only valid when RequestBuff= er 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 con= tain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built success= fully. + @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 NO= T NULL. + BufferSize is NULL. + Buffer is NULL if *BufferSize is not zer= o. + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the resp= onse packet. + @retval EFI_NOT_READY Current TLS session state is NOT ready t= o 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 =3D EFI_SUCCESS; + + if ((This =3D=3D NULL) || (BufferSize =3D=3D NULL) || + (RequestBuffer =3D=3D NULL && RequestSize !=3D 0) || + (RequestBuffer !=3D NULL && RequestSize =3D=3D 0) || + (Buffer =3D=3D NULL && *BufferSize !=3D0)) { + return EFI_INVALID_PARAMETER; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + Instance =3D TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if(RequestBuffer =3D=3D NULL && RequestSize =3D=3D 0) { + switch (Instance->TlsSessionState) { + case EfiTlsSessionNotStarted: + // + // ClientHello. + // + Status =3D TlsDoHandshake ( + Instance->TlsConn, + NULL, + 0, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + // + // *BufferSize should not be zero when ClientHello. + // + if (*BufferSize =3D=3D 0) { + Status =3D EFI_ABORTED; + goto ON_EXIT; + } + + Instance->TlsSessionState =3D EfiTlsSessionHandShaking; + + break; + case EfiTlsSessionClosing: + // + // TLS session will be closed and response packet needs to be CloseN= otify. + // + Status =3D TlsCloseNotify ( + Instance->TlsConn, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + // + // *BufferSize should not be zero when build CloseNotify message. + // + if (*BufferSize =3D=3D 0) { + Status =3D 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 =3D TlsHandeAlert ( + 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 =3D EFI_NOT_READY; + } + } else { + // + // 1. Received packet may have multiply TLS record messages. + // 2. One TLS record message may have multiply handshake protocol. + // 3. Some errors may be happened in handshake. + // TlsDoHandshake() can handle all of those cases. + // + if (TlsInHandshake (Instance->TlsConn)) { + Status =3D TlsDoHandshake ( + Instance->TlsConn, + RequestBuffer, + RequestSize, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + if (!TlsInHandshake (Instance->TlsConn)) { + Instance->TlsSessionState =3D EfiTlsSessionDataTransferring; + } + } else { + // + // Must be alert message, Decrypt it and build the ResponsePacket. + // + ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType =3D=3D TL= S_CONTENT_TYPE_ALERT); + + Status =3D TlsHandeAlert ( + Instance->TlsConn, + RequestBuffer, + RequestSize, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + if (Status !=3D EFI_BUFFER_TOO_SMALL) { + Instance->TlsSessionState =3D EfiTlsSessionError; + } + + goto ON_EXIT; + } + } + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Decrypt or encrypt TLS packet during session. This function is only vali= d after + session connected and for application_data content type. + + The ProcessPacket () function process each inbound or outbound TLS APP p= acket. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance= . + @param[in, out] FragmentTable Pointer to a list of fragment. The calle= r will take + responsible to handle the original Fragm= entTable 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; o= n output these + fragments contain the TLS header and cip= her text TLS + APP payload. If CryptMode is EfiTlsDecry= pt, on input + these fragments contain the TLS header a= nd cipher text + TLS APP payload; on output these fragmen= ts contain the + TLS header and plain text TLS APP payloa= d. + @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. T= he caller need + call BuildResponsePacket() to generate E= rror Alert + message and send it out. + @retval EFI_OUT_OF_RESOURCES No enough resource to finish the operati= on. +**/ +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 =3D EFI_SUCCESS; + + if (This =3D=3D NULL || FragmentTable =3D=3D NULL || FragmentCount =3D= =3D NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + + Instance =3D TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if (Instance->TlsSessionState !=3D EfiTlsSessionDataTransferring) { + Status =3D EFI_NOT_READY; + goto ON_EXIT; + } + + // + // Packet sent or received may have multiply TLS record message(Applicat= ion data type). + // So,on input these fragments contain the TLS header and TLS APP payloa= d; + // on output these fragments also contain the TLS header and TLS APP pay= load. + // + switch (CryptMode) { + case EfiTlsEncrypt: + Status =3D TlsEcryptPacket (Instance, FragmentTable, FragmentCount); + break; + case EfiTlsDecrypt: + Status =3D TlsDecryptPacket (Instance, FragmentTable, FragmentCount); + break; + default: + return EFI_INVALID_PARAMETER; + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} --=20 1.9.5.msysgit.1