* [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL @ 2016-12-15 7:22 Jiaxin Wu 2016-12-16 6:16 ` Ye, Ting 0 siblings, 1 reply; 3+ messages in thread From: Jiaxin Wu @ 2016-12-15 7:22 UTC (permalink / raw) To: edk2-devel Cc: Ye Ting, Fu Siyuan, Zhang Lubo, Long Qin, Thomas Palmer, Wu Jiaxin 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 <ting.ye@intel.com> Cc: Fu Siyuan <siyuan.fu@intel.com> Cc: Zhang Lubo <lubo.zhang@intel.com> Cc: Long Qin <qin.long@intel.com> Cc: Thomas Palmer <thomas.palmer@hpe.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com> --- 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/TlsConfigProtocol.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.<BR> + + 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 IMPLIED. + +**/ + +#include "TlsImpl.h" + +EFI_TLS_CONFIGURATION_PROTOCOL mTlsConfigurationProtocol = { + 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_PROTOCOL 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 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_OUT_OF_RESOURCES Required system resources could not be allocated. + +**/ +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 = EFI_SUCCESS; + + if (This == NULL || Data == NULL || DataSize == 0) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This); + + switch (DataType) { + case EfiTlsConfigDataTypeCACertificate: + Status = TlsSetCaCertificate (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPublicCert: + Status = TlsSetHostPublicCert (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPrivateKey: + Status = TlsSetHostPrivateKey (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeCertRevocationList: + Status = TlsSetCertRevocationList (Data, DataSize); + break; + default: + Status = 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_PROTOCOL 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 input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The TLS configuration 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 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 = EFI_SUCCESS; + + if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This); + + switch (DataType) { + case EfiTlsConfigDataTypeCACertificate: + Status = TlsGetCaCertificate (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPublicCert: + Status = TlsGetHostPublicCert (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPrivateKey: + Status = TlsGetHostPrivateKey (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeCertRevocationList: + Status = TlsGetCertRevocationList (Data, DataSize); + break; + default: + Status = 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.<BR> + + 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 IMPLIED. + +**/ + +#include "TlsImpl.h" + +EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding = { + 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 != NULL) { + if (Instance->TlsConn != 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 = NULL; + + TlsInstance = AllocateZeroPool (sizeof (TLS_INSTANCE)); + if (TlsInstance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TlsInstance->Signature = TLS_INSTANCE_SIGNATURE; + InitializeListHead (&TlsInstance->Link); + TlsInstance->InDestroy = FALSE; + TlsInstance->Service = Service; + + CopyMem (&TlsInstance->Tls, &mTlsProtocol, sizeof (TlsInstance->Tls)); + CopyMem (&TlsInstance->TlsConfig, &mTlsConfigurationProtocol, sizeof (TlsInstance->TlsConfig)); + + TlsInstance->TlsSessionState = EfiTlsSessionNotStarted; + + *Instance = 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 != NULL) { + if (Service->TlsCtx != 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 = EFI_SUCCESS; + *Service = NULL; + + ASSERT (Service != NULL); + + // + // Allocate a TLS Service Data + // + TlsService = AllocateZeroPool (sizeof (TLS_SERVICE)); + if (TlsService == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Initialize TLS Service Data + // + TlsService->Signature = TLS_SERVICE_SIGNATURE; + CopyMem (&TlsService->ServiceBinding, &mTlsServiceBinding, sizeof (TlsService->ServiceBinding)); + TlsService->TlsChildrenNum = 0; + InitializeListHead (&TlsService->TlsChildrenList); + TlsService->ImageHandle = Image; + + *Service = 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 = NULL; + ServiceBinding = NULL; + TlsService = NULL; + + // + // Locate all the handles with Tls service binding protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiTlsServiceBindingProtocolGuid, + NULL, + &HandleNum, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleNum; Index++) { + // + // Firstly, find ServiceBinding interface + // + Status = gBS->OpenProtocol ( + HandleBuffer[Index], + &gEfiTlsServiceBindingProtocolGuid, + (VOID **) &ServiceBinding, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + TlsService = TLS_SERVICE_FROM_THIS (ServiceBinding); + + // + // Then, uninstall ServiceBinding interface + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + HandleBuffer[Index], + &gEfiTlsServiceBindingProtocolGuid, ServiceBinding, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + TlsCleanService (TlsService); + } + + if (HandleBuffer != 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 including + 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 = TlsCreateService (ImageHandle, &TlsService); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (TlsService != 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 = TlsCtxNew (TLS10_PROTOCOL_VERSION_MAJOR, TLS10_PROTOCOL_VERSION_MINOR); + if (TlsService->TlsCtx == NULL) { + FreePool (TlsService); + return EFI_ABORTED; + } + + // + // Install the TlsServiceBinding Protocol onto Handle + // + Status = 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 returned in ChildHandle. + If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. + @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 handle. + + @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 to 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 == NULL) || (ChildHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + TlsService = TLS_SERVICE_FROM_THIS (This); + + Status = TlsCreateInstance (TlsService, &TlsInstance); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (TlsInstance != NULL); + + // + // Create a new TLS connection object. + // + TlsInstance->TlsConn = TlsNew (TlsService->TlsCtx); + if (TlsInstance->TlsConn == NULL) { + Status = EFI_ABORTED; + goto ON_ERROR; + } + + // + // Set default ConnectionEnd to EfiTlsClient + // + Status = TlsSetConnectionEnd (TlsInstance->TlsConn, EfiTlsClient); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // Install TLS protocol and configuration protocol onto ChildHandle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + ChildHandle, + &gEfiTlsProtocolGuid, + &TlsInstance->Tls, + &gEfiTlsConfigurationProtocolGuid, + &TlsInstance->TlsConfig, + NULL + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + TlsInstance->ChildHandle = *ChildHandle; + + // + // Add it to the TLS service's child list. + // + OldTpl = 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 removes a protocol + that was installed by CreateChild() from ChildHandle. If the removed protocol 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 == NULL) || (ChildHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + TlsService = TLS_SERVICE_FROM_THIS (This); + + // + // Find TLS protocol interface installed in ChildHandle + // + Status = 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 = gBS->OpenProtocol ( + ChildHandle, + &gEfiTlsConfigurationProtocolGuid, + (VOID **) &TlsConfig, + TlsService->ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + TlsInstance = TLS_INSTANCE_FROM_PROTOCOL_THIS (Tls); + + if (TlsInstance->Service != TlsService) { + return EFI_INVALID_PARAMETER; + } + + if (TlsInstance->InDestroy) { + return EFI_SUCCESS; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + TlsInstance->InDestroy = TRUE; + + // + // Uninstall the TLS protocol and TLS Configuration Protocol interface installed in ChildHandle. + // + Status = 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 TlsDxe driver. + + Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> + + 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 IMPLIED. + +**/ + +#ifndef __EFI_TLS_DRIVER_H__ +#define __EFI_TLS_DRIVER_H__ + +#include <Uefi.h> + +// +// Driver Protocols +// +#include <Protocol/ServiceBinding.h> + +// +// 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 per program + // life-time and which holds mainly default values for the SSL object which 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 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 + ); + +/** + 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 including + 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 returned in ChildHandle. + If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. + @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 handle. + + @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 to 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 removes a protocol + that was installed by CreateChild() from ChildHandle. If the removed protocol 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 EFI TLS +# Service Binding Protocol, to provide TLS services. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +# +# 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 IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TlsDxe + FILE_GUID = 3aceb0c0-3c72-11e4-9a56-74d435052646 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = TlsDriverEntryPoint + UNLOAD_IMAGE = TlsUnload + MODULE_UNI_FILE = TlsDxe.uni + +# +# VALID_ARCHITECTURES = 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 TLS +// Service Binding Protocol, and EFI TLS Configuration Protocol to provide TLS +// services. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +// +// 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 IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "UEFI TLS service" + +#string STR_MODULE_DESCRIPTION #language en-US "This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and EFI TLS Configuration Protocol to provide EFI TLS services." + diff --git a/NetworkPkg/TlsDxe/TlsDxeExtra.uni b/NetworkPkg/TlsDxe/TlsDxeExtra.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.<BR> +// +// 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 IMPLIED. +// +// **/ + +#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.<BR> + +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 IMPLIED. + +**/ + +#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 +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; + + Status = EFI_SUCCESS; + BytesCopied = 0; + BufferInSize = 0; + BufferIn = NULL; + BufferInPtr = NULL; + RecordHeaderIn = NULL; + TempRecordHeader = NULL; + BufferOutSize = 0; + BufferOut = NULL; + 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 ProcessBuffer. + // + for (Index = 0; Index < *FragmentCount; Index++) { + CopyMem ( + (BufferIn + BytesCopied), + (*FragmentTable)[Index].FragmentBuffer, + (*FragmentTable)[Index].FragmentLength + ); + BytesCopied += (*FragmentTable)[Index].FragmentLength; + } + + BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE); + if (BufferOut == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + // + // Parsing buffer. + // + BufferInPtr = BufferIn; + TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut; + while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { + RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr; + + if (RecordHeaderIn->ContentType != TLS_CONTENT_TYPE_APPLICATION_DATA) { + Status = EFI_INVALID_PARAMETER; + goto ERROR; + } + + ThisPlainMessageSize = RecordHeaderIn->Length; + + TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), ThisPlainMessageSize); + + Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader), MAX_BUFFER_SIZE - BufferOutSize); + + if (Ret > 0) { + ThisMessageSize = (UINT16) Ret; + } else { + // + // No data was successfully encrypted, continue the other messages encryption. + // + DEBUG ((EFI_D_WARN, "TlsEcryptPacket: No data read from TLS object.\n")); + + ThisMessageSize = 0; + } + + BufferOutSize += ThisMessageSize; + + BufferInPtr += RECORD_HEADER_LEN + ThisPlainMessageSize; + TempRecordHeader += ThisMessageSize; + } + + FreePool (BufferIn); + BufferIn = NULL; + + // + // The caller will take 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; + INTN Ret; + + Status = EFI_SUCCESS; + BytesCopied = 0; + BufferIn = NULL; + BufferInSize = 0; + BufferInPtr = NULL; + RecordHeaderIn = NULL; + TempRecordHeader = NULL; + BufferOut = NULL; + BufferOutSize = 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 ProcessBuffer + // + for (Index = 0; Index < *FragmentCount; Index++) { + CopyMem ( + (BufferIn + BytesCopied), + (*FragmentTable)[Index].FragmentBuffer, + (*FragmentTable)[Index].FragmentLength + ); + BytesCopied += (*FragmentTable)[Index].FragmentLength; + } + + BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE); + if (BufferOut == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + // + // Parsing buffer. Received packet may have multiply TLS record message. + // + BufferInPtr = BufferIn; + TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut; + while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { + RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr; + + if (RecordHeaderIn->ContentType != TLS_CONTENT_TYPE_APPLICATION_DATA) { + Status = EFI_INVALID_PARAMETER; + goto ERROR; + } + + ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length); + + Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn), RECORD_HEADER_LEN + ThisCipherMessageSize); + if (Ret != RECORD_HEADER_LEN + ThisCipherMessageSize) { + TlsInstance->TlsSessionState = EfiTlsSessionError; + Status = EFI_ABORTED; + goto ERROR; + } + + Ret = 0; + Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1), MAX_BUFFER_SIZE - BufferOutSize); + + if (Ret > 0) { + ThisPlainMessageSize = (UINT16) Ret; + } else { + // + // No data was successfully decrypted, continue the other messages decryption. + // + DEBUG ((EFI_D_WARN, "TlsDecryptPacket: No data read from TLS object.\n")); + + ThisPlainMessageSize = 0; + } + + CopyMem (TempRecordHeader, RecordHeaderIn, RECORD_HEADER_LEN); + TempRecordHeader->Length = ThisPlainMessageSize; + BufferOutSize += RECORD_HEADER_LEN + ThisPlainMessageSize; + + BufferInPtr += RECORD_HEADER_LEN + ThisCipherMessageSize; + TempRecordHeader += RECORD_HEADER_LEN + ThisPlainMessageSize; + } + + FreePool (BufferIn); + BufferIn = NULL; + + // + // The caller will take 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; +} 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.<BR> + +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 IMPLIED. + +**/ + +#ifndef __EFI_TLS_IMPL_H__ +#define __EFI_TLS_IMPL_H__ + +// +// Libraries +// +#include <Library/UefiBootServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/BaseLib.h> +#include <Library/UefiLib.h> +#include <Library/DebugLib.h> +#include <Library/NetLib.h> +#include <Library/BaseCryptLib.h> +#include <Library/TlsLib.h> + +// +// Consumed Protocols +// +#include <Protocol/Tls.h> +#include <Protocol/TlsConfig.h> + +#include <IndustryStandard/Tls1.h> + +#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 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 +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 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 + ); + +/** + Set TLS session data. + + The SetSessionData() function set data for a new TLS session. All session data should + be set before BuildResponsePacket() invoked. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] DataType TLS session data type. + @param[in] Data Pointer to session data. + @param[in] DataSize Total size of session data. + + @retval EFI_SUCCESS The TLS session data is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + DataSize is 0. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_ACCESS_DENIED If the DataType is one of below: + EfiTlsClientRandom + EfiTlsServerRandom + EfiTlsKeyMaterial + @retval EFI_NOT_READY Current TLS session state is NOT + EfiTlsSessionStateNotStarted. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +EFI_STATUS +EFIAPI +TlsSetSessionData ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Get TLS session data. + + The GetSessionData() function return the TLS session information. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] DataType TLS session data type. + @param[in, out] Data Pointer to session data. + @param[in, out] DataSize Total size of session data. On input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The TLS session data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + DataSize is NULL. + Data is NULL if *DataSize is not zero. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The TLS session data is not found. + @retval EFI_NOT_READY The DataType is not ready in current session state. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data. +**/ +EFI_STATUS +EFIAPI +TlsGetSessionData ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataSize + ); + +/** + Build response packet according to TLS state machine. This function is only valid for + alert, handshake and change_cipher_spec content type. + + The BuildResponsePacket() function builds TLS response packet in response to the TLS + request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and + RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session + will be initiated and the response packet needs to be ClientHello. If RequestBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS + session will be closed and response packet needs to be CloseNotify. If RequestBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS + session has errors and the response packet needs to be Alert message based on error + type. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] RequestBuffer Pointer to the most recently received TLS packet. NULL + means TLS need initiate the TLS session and response + packet need to be ClientHello. + @param[in] RequestSize Packet size in bytes for the most recently received TLS + packet. 0 is only valid when RequestBuffer is NULL. + @param[out] Buffer Pointer to the buffer to hold the built packet. + @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + RequestBuffer is NULL but RequestSize is NOT 0. + RequestSize is 0 but RequestBuffer is NOT NULL. + BufferSize is NULL. + Buffer is NULL if *BufferSize is not zero. + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet. + @retval EFI_NOT_READY Current TLS session state is NOT ready to build + ResponsePacket. + @retval EFI_ABORTED Something wrong build response packet. +**/ +EFI_STATUS +EFIAPI +TlsBuildResponsePacket ( + IN EFI_TLS_PROTOCOL *This, + IN UINT8 *RequestBuffer, OPTIONAL + IN UINTN RequestSize, OPTIONAL + OUT UINT8 *Buffer, OPTIONAL + IN OUT UINTN *BufferSize + ); + +/** + Decrypt or encrypt TLS packet during session. This function is only valid after + session connected and for application_data content type. + + The ProcessPacket () function process each inbound or outbound TLS APP packet. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in, out] FragmentTable Pointer to a list of fragment. The caller will take + responsible to handle the original FragmentTable while + it may be reallocated in TLS driver. If CryptMode is + EfiTlsEncrypt, on input these fragments contain the TLS + header and plain text TLS APP payload; on output these + fragments contain the TLS header and cipher text TLS + APP payload. If CryptMode is EfiTlsDecrypt, on input + these fragments contain the TLS header and cipher text + TLS APP payload; on output these fragments contain the + TLS header and plain text TLS APP payload. + @param[in] FragmentCount Number of fragment. + @param[in] CryptMode Crypt mode. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + FragmentTable is NULL. + FragmentCount is NULL. + CryptoMode is invalid. + @retval EFI_NOT_READY Current TLS session state is NOT + EfiTlsSessionDataTransferring. + @retval EFI_ABORTED Something wrong decryption the message. TLS session + status will become EfiTlsSessionError. The caller need + call BuildResponsePacket() to generate Error Alert + message and send it out. + @retval EFI_OUT_OF_RESOURCES No enough resource to finish the operation. +**/ +EFI_STATUS +EFIAPI +TlsProcessPacket ( + IN EFI_TLS_PROTOCOL *This, + IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable, + IN UINT32 *FragmentCount, + IN EFI_TLS_CRYPT_MODE CryptMode + ); + +/** + 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_PROTOCOL 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 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_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +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_PROTOCOL 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 input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The TLS configuration 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 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/TlsProtocol.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.<BR> + + 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 IMPLIED. + +**/ + +#include "TlsImpl.h" + +EFI_TLS_PROTOCOL mTlsProtocol = { + TlsSetSessionData, + TlsGetSessionData, + TlsBuildResponsePacket, + TlsProcessPacket +}; + +/** + Set TLS session data. + + The SetSessionData() function set data for a new TLS session. All session data should + be set before BuildResponsePacket() invoked. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] DataType TLS session data type. + @param[in] Data Pointer to session data. + @param[in] DataSize Total size of session data. + + @retval EFI_SUCCESS The TLS session data is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + DataSize is 0. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_ACCESS_DENIED If the DataType is one of below: + EfiTlsClientRandom + EfiTlsServerRandom + EfiTlsKeyMaterial + @retval EFI_NOT_READY Current TLS session state is NOT + EfiTlsSessionStateNotStarted. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +EFI_STATUS +EFIAPI +TlsSetSessionData ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ) +{ + EFI_STATUS Status; + TLS_INSTANCE *Instance; + UINT16 *CipherId; + UINTN Index; + + EFI_TPL OldTpl; + + Status = EFI_SUCCESS; + CipherId = NULL; + + if (This == NULL || Data == NULL || DataSize == 0) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if (DataType != EfiTlsSessionState && Instance->TlsSessionState != EfiTlsSessionNotStarted){ + Status = EFI_NOT_READY; + goto ON_EXIT; + } + + switch (DataType) { + // + // Session Configuration + // + case EfiTlsVersion: + if (DataSize != sizeof (EFI_TLS_VERSION)) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status = TlsSetVersion (Instance->TlsConn, ((EFI_TLS_VERSION *) Data)->Major, ((EFI_TLS_VERSION *) Data)->Minor); + break; + case EfiTlsConnectionEnd: + if (DataSize != sizeof (EFI_TLS_CONNECTION_END)) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status = TlsSetConnectionEnd (Instance->TlsConn, *((EFI_TLS_CONNECTION_END *) Data)); + break; + case EfiTlsCipherList: + CipherId = AllocatePool (DataSize); + if (CipherId == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + for (Index = 0; Index < DataSize / sizeof (EFI_TLS_CIPHER); Index++) { + *(CipherId +Index) = HTONS (*(((UINT16 *) Data) + Index)); + } + + Status = TlsSetCipherList (Instance->TlsConn, CipherId, DataSize / sizeof (EFI_TLS_CIPHER)); + + FreePool (CipherId); + break; + case EfiTlsCompressionMethod: + // + // TLS seems only define one CompressionMethod.null, which specifies that data exchanged via the + // record protocol will not be compressed. + // More information from OpenSSL: http://www.openssl.org/docs/manmaster/ssl/SSL_COMP_add_compression_method.html + // The TLS RFC does however not specify compression methods or their corresponding identifiers, + // so there is currently no compatible way to integrate compression with unknown peers. + // It is therefore currently not recommended to integrate compression into applications. + // Applications for non-public use may agree on certain compression methods. + // Using different compression methods with the same identifier will lead to connection failure. + // + for (Index = 0; Index < DataSize / sizeof (EFI_TLS_COMPRESSION); Index++) { + Status = TlsSetCompressionMethod (*((UINT8 *) Data + Index)); + if (EFI_ERROR (Status)) { + break; + } + } + + break; + case EfiTlsExtensionData: + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + case EfiTlsVerifyMethod: + if (DataSize != sizeof (EFI_TLS_VERIFY)) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + TlsSetVerify (Instance->TlsConn, *((UINT32 *) Data)); + break; + case EfiTlsSessionID: + if (DataSize != sizeof (EFI_TLS_SESSION_ID)) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status = TlsSetSessionId ( + Instance->TlsConn, + ((EFI_TLS_SESSION_ID *) Data)->Data, + ((EFI_TLS_SESSION_ID *) Data)->Length + ); + break; + case EfiTlsSessionState: + if (DataSize != sizeof (EFI_TLS_SESSION_STATE)) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Instance->TlsSessionState = *(EFI_TLS_SESSION_STATE *) Data; + break; + // + // Session information + // + case EfiTlsClientRandom: + Status = EFI_ACCESS_DENIED; + break; + case EfiTlsServerRandom: + Status = EFI_ACCESS_DENIED; + break; + case EfiTlsKeyMaterial: + Status = EFI_ACCESS_DENIED; + break; + // + // Unsupported type. + // + default: + Status = EFI_UNSUPPORTED; + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Get TLS session data. + + The GetSessionData() function return the TLS session information. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] DataType TLS session data type. + @param[in, out] Data Pointer to session data. + @param[in, out] DataSize Total size of session data. On input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The TLS session data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + DataSize is NULL. + Data is NULL if *DataSize is not zero. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The TLS session data is not found. + @retval EFI_NOT_READY The DataType is not ready in current session state. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data. +**/ +EFI_STATUS +EFIAPI +TlsGetSessionData ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataSize + ) +{ + EFI_STATUS Status; + TLS_INSTANCE *Instance; + + EFI_TPL OldTpl; + + Status = EFI_SUCCESS; + + if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if (Instance->TlsSessionState == EfiTlsSessionNotStarted && + (DataType == EfiTlsSessionID || DataType == EfiTlsClientRandom || + DataType == EfiTlsServerRandom || DataType == EfiTlsKeyMaterial)) { + Status = EFI_NOT_READY; + goto ON_EXIT; + } + + switch (DataType) { + case EfiTlsVersion: + if (*DataSize < sizeof (EFI_TLS_VERSION)) { + *DataSize = sizeof (EFI_TLS_VERSION); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_VERSION); + *((UINT16 *) Data) = HTONS (TlsGetVersion (Instance->TlsConn)); + break; + case EfiTlsConnectionEnd: + if (*DataSize < sizeof (EFI_TLS_CONNECTION_END)) { + *DataSize = sizeof (EFI_TLS_CONNECTION_END); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_CONNECTION_END); + *((UINT8 *) Data) = TlsGetConnectionEnd (Instance->TlsConn); + break; + case EfiTlsCipherList: + // + // Get the current session cipher suite. + // + if (*DataSize < sizeof (EFI_TLS_CIPHER)) { + *DataSize = sizeof (EFI_TLS_CIPHER); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof(EFI_TLS_CIPHER); + Status = TlsGetCurrentCipher (Instance->TlsConn, (UINT16 *) Data); + *((UINT16 *) Data) = HTONS (*((UINT16 *) Data)); + break; + case EfiTlsCompressionMethod: + // + // Get the current session compression method. + // + if (*DataSize < sizeof (EFI_TLS_COMPRESSION)) { + *DataSize = sizeof (EFI_TLS_COMPRESSION); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_COMPRESSION); + Status = TlsGetCurrentCompressionId (Instance->TlsConn, (UINT8 *) Data); + break; + case EfiTlsExtensionData: + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + case EfiTlsVerifyMethod: + if (*DataSize < sizeof (EFI_TLS_VERIFY)) { + *DataSize = sizeof (EFI_TLS_VERIFY); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_VERIFY); + *((UINT32 *) Data) = TlsGetVerify (Instance->TlsConn); + break; + case EfiTlsSessionID: + if (*DataSize < sizeof (EFI_TLS_SESSION_ID)) { + *DataSize = sizeof (EFI_TLS_SESSION_ID); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_SESSION_ID); + Status = TlsGetSessionId ( + Instance->TlsConn, + ((EFI_TLS_SESSION_ID *) Data)->Data, + &(((EFI_TLS_SESSION_ID *) Data)->Length) + ); + break; + case EfiTlsSessionState: + if (*DataSize < sizeof (EFI_TLS_SESSION_STATE)) { + *DataSize = sizeof (EFI_TLS_SESSION_STATE); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_SESSION_STATE); + CopyMem (Data, &Instance->TlsSessionState, *DataSize); + break; + case EfiTlsClientRandom: + if (*DataSize < sizeof (EFI_TLS_RANDOM)) { + *DataSize = sizeof (EFI_TLS_RANDOM); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_RANDOM); + TlsGetClientRandom (Instance->TlsConn, (UINT8 *) Data); + break; + case EfiTlsServerRandom: + if (*DataSize < sizeof (EFI_TLS_RANDOM)) { + *DataSize = sizeof (EFI_TLS_RANDOM); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_RANDOM); + TlsGetServerRandom (Instance->TlsConn, (UINT8 *) Data); + break; + case EfiTlsKeyMaterial: + if (*DataSize < sizeof (EFI_TLS_MASTER_SECRET)) { + *DataSize = sizeof (EFI_TLS_MASTER_SECRET); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_MASTER_SECRET); + Status = TlsGetKeyMaterial (Instance->TlsConn, (UINT8 *) Data); + break; + // + // Unsupported type. + // + default: + Status = EFI_UNSUPPORTED; + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Build response packet according to TLS state machine. This function is only valid for + alert, handshake and change_cipher_spec content type. + + The BuildResponsePacket() function builds TLS response packet in response to the TLS + request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and + RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session + will be initiated and the response packet needs to be ClientHello. If RequestBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS + session will be closed and response packet needs to be CloseNotify. If RequestBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS + session has errors and the response packet needs to be Alert message based on error + type. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] RequestBuffer Pointer to the most recently received TLS packet. NULL + means TLS need initiate the TLS session and response + packet need to be ClientHello. + @param[in] RequestSize Packet size in bytes for the most recently received TLS + packet. 0 is only valid when RequestBuffer is NULL. + @param[out] Buffer Pointer to the buffer to hold the built packet. + @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + RequestBuffer is NULL but RequestSize is NOT 0. + RequestSize is 0 but RequestBuffer is NOT NULL. + BufferSize is NULL. + Buffer is NULL if *BufferSize is not zero. + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet. + @retval EFI_NOT_READY Current TLS session state is NOT ready to build + ResponsePacket. + @retval EFI_ABORTED Something wrong build response packet. +**/ +EFI_STATUS +EFIAPI +TlsBuildResponsePacket ( + IN EFI_TLS_PROTOCOL *This, + IN UINT8 *RequestBuffer, OPTIONAL + IN UINTN RequestSize, OPTIONAL + OUT UINT8 *Buffer, OPTIONAL + IN OUT UINTN *BufferSize + ) +{ + EFI_STATUS Status; + TLS_INSTANCE *Instance; + EFI_TPL OldTpl; + + Status = EFI_SUCCESS; + + if ((This == NULL) || (BufferSize == NULL) || + (RequestBuffer == NULL && RequestSize != 0) || + (RequestBuffer != NULL && RequestSize == 0) || + (Buffer == NULL && *BufferSize !=0)) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if(RequestBuffer == NULL && RequestSize == 0) { + switch (Instance->TlsSessionState) { + case EfiTlsSessionNotStarted: + // + // ClientHello. + // + Status = TlsDoHandshake ( + Instance->TlsConn, + NULL, + 0, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + // + // *BufferSize should not be zero when ClientHello. + // + if (*BufferSize == 0) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + + Instance->TlsSessionState = EfiTlsSessionHandShaking; + + break; + case EfiTlsSessionClosing: + // + // TLS session will be closed and response packet needs to be CloseNotify. + // + Status = TlsCloseNotify ( + Instance->TlsConn, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + // + // *BufferSize should not be zero when build CloseNotify message. + // + if (*BufferSize == 0) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + + break; + case EfiTlsSessionError: + // + // TLS session has errors and the response packet needs to be Alert + // message based on error type. + // + Status = 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 = 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 = TlsDoHandshake ( + Instance->TlsConn, + RequestBuffer, + RequestSize, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + if (!TlsInHandshake (Instance->TlsConn)) { + Instance->TlsSessionState = EfiTlsSessionDataTransferring; + } + } else { + // + // Must be alert message, Decrypt it and build the ResponsePacket. + // + ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType == TLS_CONTENT_TYPE_ALERT); + + Status = TlsHandeAlert ( + Instance->TlsConn, + RequestBuffer, + RequestSize, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + if (Status != EFI_BUFFER_TOO_SMALL) { + Instance->TlsSessionState = EfiTlsSessionError; + } + + goto ON_EXIT; + } + } + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Decrypt or encrypt TLS packet during session. This function is only valid after + session connected and for application_data content type. + + The ProcessPacket () function process each inbound or outbound TLS APP packet. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in, out] FragmentTable Pointer to a list of fragment. The caller will take + responsible to handle the original FragmentTable while + it may be reallocated in TLS driver. If CryptMode is + EfiTlsEncrypt, on input these fragments contain the TLS + header and plain text TLS APP payload; on output these + fragments contain the TLS header and cipher text TLS + APP payload. If CryptMode is EfiTlsDecrypt, on input + these fragments contain the TLS header and cipher text + TLS APP payload; on output these fragments contain the + TLS header and plain text TLS APP payload. + @param[in] FragmentCount Number of fragment. + @param[in] CryptMode Crypt mode. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + FragmentTable is NULL. + FragmentCount is NULL. + CryptoMode is invalid. + @retval EFI_NOT_READY Current TLS session state is NOT + EfiTlsSessionDataTransferring. + @retval EFI_ABORTED Something wrong decryption the message. TLS session + status will become EfiTlsSessionError. The caller need + call BuildResponsePacket() to generate Error Alert + message and send it out. + @retval EFI_OUT_OF_RESOURCES No enough resource to finish the operation. +**/ +EFI_STATUS +EFIAPI +TlsProcessPacket ( + IN EFI_TLS_PROTOCOL *This, + IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable, + IN UINT32 *FragmentCount, + IN EFI_TLS_CRYPT_MODE CryptMode + ) +{ + EFI_STATUS Status; + TLS_INSTANCE *Instance; + + EFI_TPL OldTpl; + + Status = EFI_SUCCESS; + + if (This == NULL || FragmentTable == NULL || FragmentCount == NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if (Instance->TlsSessionState != EfiTlsSessionDataTransferring) { + Status = EFI_NOT_READY; + goto ON_EXIT; + } + + // + // Packet sent or received may have multiply TLS record message(Application data type). + // So,on input these fragments contain the TLS header and TLS APP payload; + // on output these fragments also contain the TLS header and TLS APP payload. + // + switch (CryptMode) { + case EfiTlsEncrypt: + Status = TlsEcryptPacket (Instance, FragmentTable, FragmentCount); + break; + case EfiTlsDecrypt: + Status = TlsDecryptPacket (Instance, FragmentTable, FragmentCount); + break; + default: + return EFI_INVALID_PARAMETER; + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} -- 1.9.5.msysgit.1 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL 2016-12-15 7:22 [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL Jiaxin Wu @ 2016-12-16 6:16 ` Ye, Ting 2016-12-16 7:30 ` Wu, Jiaxin 0 siblings, 1 reply; 3+ messages in thread From: Ye, Ting @ 2016-12-16 6:16 UTC (permalink / raw) To: Wu, Jiaxin, edk2-devel@lists.01.org Cc: Fu, Siyuan, Zhang, Lubo, Long, Qin, Thomas Palmer Hi Jiaxin, Some comments included as below. 1. In TlsCreateService Line 325: ASSERT checks after assignment in line 323. Should put ASSERT earlier. 'Status' looks useless. 2. TlsDriver.h I think the macros ' TLS_INSTANCE_FROM_PROTOCOL_THIS' and ' TLS_INSTANCE_FROM_CONFIGURATION_THIS' are hard to read. Maybe we could remove the '_THIS' postfix? 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 responsible to... " "Received packet may have multiply TLS record message." To " Received packet may have multiple TLS record messages." Also update Multiply to multiple in other places. "Copy all TLS plain record header and payload to ProcessBuffer". ProcessBuffer looks a local variable but not exist. May update to BufferIn? Please double check. Others are good to me. Reviewed-by: Ye Ting <ting.ye@intel.com> Thanks, Ting -----Original Message----- From: Wu, Jiaxin Sent: Thursday, December 15, 2016 3:22 PM To: edk2-devel@lists.01.org Cc: Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; Long, Qin <qin.long@intel.com>; Thomas Palmer <thomas.palmer@hpe.com>; Wu, Jiaxin <jiaxin.wu@intel.com> Subject: [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over 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 <ting.ye@intel.com> Cc: Fu Siyuan <siyuan.fu@intel.com> Cc: Zhang Lubo <lubo.zhang@intel.com> Cc: Long Qin <qin.long@intel.com> Cc: Thomas Palmer <thomas.palmer@hpe.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com> --- 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/TlsConfigProtocol.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.<BR> + + 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 IMPLIED. + +**/ + +#include "TlsImpl.h" + +EFI_TLS_CONFIGURATION_PROTOCOL mTlsConfigurationProtocol = { + 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_PROTOCOL 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 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_OUT_OF_RESOURCES Required system resources could not be allocated. + +**/ +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 = EFI_SUCCESS; + + if (This == NULL || Data == NULL || DataSize == 0) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This); + + switch (DataType) { + case EfiTlsConfigDataTypeCACertificate: + Status = TlsSetCaCertificate (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPublicCert: + Status = TlsSetHostPublicCert (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPrivateKey: + Status = TlsSetHostPrivateKey (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeCertRevocationList: + Status = TlsSetCertRevocationList (Data, DataSize); + break; + default: + Status = 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_PROTOCOL 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 input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The TLS configuration 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 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 = EFI_SUCCESS; + + if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This); + + switch (DataType) { + case EfiTlsConfigDataTypeCACertificate: + Status = TlsGetCaCertificate (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPublicCert: + Status = TlsGetHostPublicCert (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeHostPrivateKey: + Status = TlsGetHostPrivateKey (Instance->TlsConn, Data, DataSize); + break; + case EfiTlsConfigDataTypeCertRevocationList: + Status = TlsGetCertRevocationList (Data, DataSize); + break; + default: + Status = 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.<BR> + + 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 IMPLIED. + +**/ + +#include "TlsImpl.h" + +EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding = { + 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 != NULL) { + if (Instance->TlsConn != 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 = NULL; + + TlsInstance = AllocateZeroPool (sizeof (TLS_INSTANCE)); + if (TlsInstance == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + TlsInstance->Signature = TLS_INSTANCE_SIGNATURE; + InitializeListHead (&TlsInstance->Link); + TlsInstance->InDestroy = FALSE; + TlsInstance->Service = Service; + + CopyMem (&TlsInstance->Tls, &mTlsProtocol, sizeof (TlsInstance->Tls)); + CopyMem (&TlsInstance->TlsConfig, &mTlsConfigurationProtocol, sizeof (TlsInstance->TlsConfig)); + + TlsInstance->TlsSessionState = EfiTlsSessionNotStarted; + + *Instance = 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 != NULL) { + if (Service->TlsCtx != 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 = EFI_SUCCESS; + *Service = NULL; + + ASSERT (Service != NULL); + + // + // Allocate a TLS Service Data + // + TlsService = AllocateZeroPool (sizeof (TLS_SERVICE)); + if (TlsService == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Initialize TLS Service Data + // + TlsService->Signature = TLS_SERVICE_SIGNATURE; + CopyMem (&TlsService->ServiceBinding, &mTlsServiceBinding, sizeof (TlsService->ServiceBinding)); + TlsService->TlsChildrenNum = 0; + InitializeListHead (&TlsService->TlsChildrenList); + TlsService->ImageHandle = Image; + + *Service = 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 = NULL; + ServiceBinding = NULL; + TlsService = NULL; + + // + // Locate all the handles with Tls service binding protocol. + // + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiTlsServiceBindingProtocolGuid, + NULL, + &HandleNum, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + for (Index = 0; Index < HandleNum; Index++) { + // + // Firstly, find ServiceBinding interface + // + Status = gBS->OpenProtocol ( + HandleBuffer[Index], + &gEfiTlsServiceBindingProtocolGuid, + (VOID **) &ServiceBinding, + ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + TlsService = TLS_SERVICE_FROM_THIS (ServiceBinding); + + // + // Then, uninstall ServiceBinding interface + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + HandleBuffer[Index], + &gEfiTlsServiceBindingProtocolGuid, ServiceBinding, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + TlsCleanService (TlsService); + } + + if (HandleBuffer != 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 including + 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 = TlsCreateService (ImageHandle, &TlsService); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (TlsService != 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 = TlsCtxNew (TLS10_PROTOCOL_VERSION_MAJOR, TLS10_PROTOCOL_VERSION_MINOR); + if (TlsService->TlsCtx == NULL) { + FreePool (TlsService); + return EFI_ABORTED; + } + + // + // Install the TlsServiceBinding Protocol onto Handle + // + Status = 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 returned in ChildHandle. + If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. + @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 handle. + + @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 to 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 == NULL) || (ChildHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + TlsService = TLS_SERVICE_FROM_THIS (This); + + Status = TlsCreateInstance (TlsService, &TlsInstance); + if (EFI_ERROR (Status)) { + return Status; + } + + ASSERT (TlsInstance != NULL); + + // + // Create a new TLS connection object. + // + TlsInstance->TlsConn = TlsNew (TlsService->TlsCtx); + if (TlsInstance->TlsConn == NULL) { + Status = EFI_ABORTED; + goto ON_ERROR; + } + + // + // Set default ConnectionEnd to EfiTlsClient + // + Status = TlsSetConnectionEnd (TlsInstance->TlsConn, EfiTlsClient); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + // + // Install TLS protocol and configuration protocol onto ChildHandle + // + Status = gBS->InstallMultipleProtocolInterfaces ( + ChildHandle, + &gEfiTlsProtocolGuid, + &TlsInstance->Tls, + &gEfiTlsConfigurationProtocolGuid, + &TlsInstance->TlsConfig, + NULL + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + + TlsInstance->ChildHandle = *ChildHandle; + + // + // Add it to the TLS service's child list. + // + OldTpl = 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 removes a protocol + that was installed by CreateChild() from ChildHandle. If the removed protocol 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 == NULL) || (ChildHandle == NULL)) { + return EFI_INVALID_PARAMETER; + } + + TlsService = TLS_SERVICE_FROM_THIS (This); + + // + // Find TLS protocol interface installed in ChildHandle + // + Status = 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 = gBS->OpenProtocol ( + ChildHandle, + &gEfiTlsConfigurationProtocolGuid, + (VOID **) &TlsConfig, + TlsService->ImageHandle, + NULL, + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + TlsInstance = TLS_INSTANCE_FROM_PROTOCOL_THIS (Tls); + + if (TlsInstance->Service != TlsService) { + return EFI_INVALID_PARAMETER; + } + + if (TlsInstance->InDestroy) { + return EFI_SUCCESS; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + TlsInstance->InDestroy = TRUE; + + // + // Uninstall the TLS protocol and TLS Configuration Protocol interface installed in ChildHandle. + // + Status = 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 TlsDxe driver. + + Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> + + 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 IMPLIED. + +**/ + +#ifndef __EFI_TLS_DRIVER_H__ +#define __EFI_TLS_DRIVER_H__ + +#include <Uefi.h> + +// +// Driver Protocols +// +#include <Protocol/ServiceBinding.h> + +// +// 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 per program + // life-time and which holds mainly default values for the SSL object which 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 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 + ); + +/** + 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 including + 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 returned in ChildHandle. + If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle. + + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance. + @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 handle. + + @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 to 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 removes a protocol + that was installed by CreateChild() from ChildHandle. If the removed protocol 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 EFI TLS +# Service Binding Protocol, to provide TLS services. +# +# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +# +# 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 IMPLIED. +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = TlsDxe + FILE_GUID = 3aceb0c0-3c72-11e4-9a56-74d435052646 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = TlsDriverEntryPoint + UNLOAD_IMAGE = TlsUnload + MODULE_UNI_FILE = TlsDxe.uni + +# +# VALID_ARCHITECTURES = 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 TLS +// Service Binding Protocol, and EFI TLS Configuration Protocol to provide TLS +// services. +// +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> +// +// 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 IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "UEFI TLS service" + +#string STR_MODULE_DESCRIPTION #language en-US "This module produces EFI TLS Protocol, EFI TLS Service Binding Protocol and EFI TLS Configuration Protocol to provide EFI TLS services." + diff --git a/NetworkPkg/TlsDxe/TlsDxeExtra.uni b/NetworkPkg/TlsDxe/TlsDxeExtra.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.<BR> +// +// 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 IMPLIED. +// +// **/ + +#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.<BR> + +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 IMPLIED. + +**/ + +#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 +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; + + Status = EFI_SUCCESS; + BytesCopied = 0; + BufferInSize = 0; + BufferIn = NULL; + BufferInPtr = NULL; + RecordHeaderIn = NULL; + TempRecordHeader = NULL; + BufferOutSize = 0; + BufferOut = NULL; + 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 ProcessBuffer. + // + for (Index = 0; Index < *FragmentCount; Index++) { + CopyMem ( + (BufferIn + BytesCopied), + (*FragmentTable)[Index].FragmentBuffer, + (*FragmentTable)[Index].FragmentLength + ); + BytesCopied += (*FragmentTable)[Index].FragmentLength; + } + + BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE); + if (BufferOut == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + // + // Parsing buffer. + // + BufferInPtr = BufferIn; + TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut; + while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { + RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr; + + if (RecordHeaderIn->ContentType != TLS_CONTENT_TYPE_APPLICATION_DATA) { + Status = EFI_INVALID_PARAMETER; + goto ERROR; + } + + ThisPlainMessageSize = RecordHeaderIn->Length; + + TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), ThisPlainMessageSize); + + Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 *)(TempRecordHeader), MAX_BUFFER_SIZE - BufferOutSize); + + if (Ret > 0) { + ThisMessageSize = (UINT16) Ret; + } else { + // + // No data was successfully encrypted, continue the other messages encryption. + // + DEBUG ((EFI_D_WARN, "TlsEcryptPacket: No data read from TLS object.\n")); + + ThisMessageSize = 0; + } + + BufferOutSize += ThisMessageSize; + + BufferInPtr += RECORD_HEADER_LEN + ThisPlainMessageSize; + TempRecordHeader += ThisMessageSize; + } + + FreePool (BufferIn); + BufferIn = NULL; + + // + // The caller will take 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; + INTN Ret; + + Status = EFI_SUCCESS; + BytesCopied = 0; + BufferIn = NULL; + BufferInSize = 0; + BufferInPtr = NULL; + RecordHeaderIn = NULL; + TempRecordHeader = NULL; + BufferOut = NULL; + BufferOutSize = 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 ProcessBuffer + // + for (Index = 0; Index < *FragmentCount; Index++) { + CopyMem ( + (BufferIn + BytesCopied), + (*FragmentTable)[Index].FragmentBuffer, + (*FragmentTable)[Index].FragmentLength + ); + BytesCopied += (*FragmentTable)[Index].FragmentLength; + } + + BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE); + if (BufferOut == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ERROR; + } + + // + // Parsing buffer. Received packet may have multiply TLS record message. + // + BufferInPtr = BufferIn; + TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut; + while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { + RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr; + + if (RecordHeaderIn->ContentType != TLS_CONTENT_TYPE_APPLICATION_DATA) { + Status = EFI_INVALID_PARAMETER; + goto ERROR; + } + + ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length); + + Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn), RECORD_HEADER_LEN + ThisCipherMessageSize); + if (Ret != RECORD_HEADER_LEN + ThisCipherMessageSize) { + TlsInstance->TlsSessionState = EfiTlsSessionError; + Status = EFI_ABORTED; + goto ERROR; + } + + Ret = 0; + Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1), MAX_BUFFER_SIZE - BufferOutSize); + + if (Ret > 0) { + ThisPlainMessageSize = (UINT16) Ret; + } else { + // + // No data was successfully decrypted, continue the other messages decryption. + // + DEBUG ((EFI_D_WARN, "TlsDecryptPacket: No data read from TLS object.\n")); + + ThisPlainMessageSize = 0; + } + + CopyMem (TempRecordHeader, RecordHeaderIn, RECORD_HEADER_LEN); + TempRecordHeader->Length = ThisPlainMessageSize; + BufferOutSize += RECORD_HEADER_LEN + ThisPlainMessageSize; + + BufferInPtr += RECORD_HEADER_LEN + ThisCipherMessageSize; + TempRecordHeader += RECORD_HEADER_LEN + ThisPlainMessageSize; + } + + FreePool (BufferIn); + BufferIn = NULL; + + // + // The caller will take 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; +} 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.<BR> + +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 IMPLIED. + +**/ + +#ifndef __EFI_TLS_IMPL_H__ +#define __EFI_TLS_IMPL_H__ + +// +// Libraries +// +#include <Library/UefiBootServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/BaseLib.h> +#include <Library/UefiLib.h> +#include <Library/DebugLib.h> +#include <Library/NetLib.h> +#include <Library/BaseCryptLib.h> +#include <Library/TlsLib.h> + +// +// Consumed Protocols +// +#include <Protocol/Tls.h> +#include <Protocol/TlsConfig.h> + +#include <IndustryStandard/Tls1.h> + +#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 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 +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 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 + ); + +/** + Set TLS session data. + + The SetSessionData() function set data for a new TLS session. All session data should + be set before BuildResponsePacket() invoked. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] DataType TLS session data type. + @param[in] Data Pointer to session data. + @param[in] DataSize Total size of session data. + + @retval EFI_SUCCESS The TLS session data is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + DataSize is 0. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_ACCESS_DENIED If the DataType is one of below: + EfiTlsClientRandom + EfiTlsServerRandom + EfiTlsKeyMaterial + @retval EFI_NOT_READY Current TLS session state is NOT + EfiTlsSessionStateNotStarted. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +EFI_STATUS +EFIAPI +TlsSetSessionData ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ); + +/** + Get TLS session data. + + The GetSessionData() function return the TLS session information. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] DataType TLS session data type. + @param[in, out] Data Pointer to session data. + @param[in, out] DataSize Total size of session data. On input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The TLS session data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + DataSize is NULL. + Data is NULL if *DataSize is not zero. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The TLS session data is not found. + @retval EFI_NOT_READY The DataType is not ready in current session state. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data. +**/ +EFI_STATUS +EFIAPI +TlsGetSessionData ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataSize + ); + +/** + Build response packet according to TLS state machine. This function is only valid for + alert, handshake and change_cipher_spec content type. + + The BuildResponsePacket() function builds TLS response packet in response to the TLS + request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and + RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session + will be initiated and the response packet needs to be ClientHello. If RequestBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS + session will be closed and response packet needs to be CloseNotify. If RequestBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS + session has errors and the response packet needs to be Alert message based on error + type. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] RequestBuffer Pointer to the most recently received TLS packet. NULL + means TLS need initiate the TLS session and response + packet need to be ClientHello. + @param[in] RequestSize Packet size in bytes for the most recently received TLS + packet. 0 is only valid when RequestBuffer is NULL. + @param[out] Buffer Pointer to the buffer to hold the built packet. + @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + RequestBuffer is NULL but RequestSize is NOT 0. + RequestSize is 0 but RequestBuffer is NOT NULL. + BufferSize is NULL. + Buffer is NULL if *BufferSize is not zero. + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet. + @retval EFI_NOT_READY Current TLS session state is NOT ready to build + ResponsePacket. + @retval EFI_ABORTED Something wrong build response packet. +**/ +EFI_STATUS +EFIAPI +TlsBuildResponsePacket ( + IN EFI_TLS_PROTOCOL *This, + IN UINT8 *RequestBuffer, OPTIONAL + IN UINTN RequestSize, OPTIONAL + OUT UINT8 *Buffer, OPTIONAL + IN OUT UINTN *BufferSize + ); + +/** + Decrypt or encrypt TLS packet during session. This function is only valid after + session connected and for application_data content type. + + The ProcessPacket () function process each inbound or outbound TLS APP packet. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in, out] FragmentTable Pointer to a list of fragment. The caller will take + responsible to handle the original FragmentTable while + it may be reallocated in TLS driver. If CryptMode is + EfiTlsEncrypt, on input these fragments contain the TLS + header and plain text TLS APP payload; on output these + fragments contain the TLS header and cipher text TLS + APP payload. If CryptMode is EfiTlsDecrypt, on input + these fragments contain the TLS header and cipher text + TLS APP payload; on output these fragments contain the + TLS header and plain text TLS APP payload. + @param[in] FragmentCount Number of fragment. + @param[in] CryptMode Crypt mode. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + FragmentTable is NULL. + FragmentCount is NULL. + CryptoMode is invalid. + @retval EFI_NOT_READY Current TLS session state is NOT + EfiTlsSessionDataTransferring. + @retval EFI_ABORTED Something wrong decryption the message. TLS session + status will become EfiTlsSessionError. The caller need + call BuildResponsePacket() to generate Error Alert + message and send it out. + @retval EFI_OUT_OF_RESOURCES No enough resource to finish the operation. +**/ +EFI_STATUS +EFIAPI +TlsProcessPacket ( + IN EFI_TLS_PROTOCOL *This, + IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable, + IN UINT32 *FragmentCount, + IN EFI_TLS_CRYPT_MODE CryptMode + ); + +/** + 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_PROTOCOL 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 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_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +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_PROTOCOL 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 input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The TLS configuration 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 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/TlsProtocol.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.<BR> + + 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 IMPLIED. + +**/ + +#include "TlsImpl.h" + +EFI_TLS_PROTOCOL mTlsProtocol = { + TlsSetSessionData, + TlsGetSessionData, + TlsBuildResponsePacket, + TlsProcessPacket +}; + +/** + Set TLS session data. + + The SetSessionData() function set data for a new TLS session. All session data should + be set before BuildResponsePacket() invoked. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] DataType TLS session data type. + @param[in] Data Pointer to session data. + @param[in] DataSize Total size of session data. + + @retval EFI_SUCCESS The TLS session data is set successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + Data is NULL. + DataSize is 0. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_ACCESS_DENIED If the DataType is one of below: + EfiTlsClientRandom + EfiTlsServerRandom + EfiTlsKeyMaterial + @retval EFI_NOT_READY Current TLS session state is NOT + EfiTlsSessionStateNotStarted. + @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated. +**/ +EFI_STATUS +EFIAPI +TlsSetSessionData ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN VOID *Data, + IN UINTN DataSize + ) +{ + EFI_STATUS Status; + TLS_INSTANCE *Instance; + UINT16 *CipherId; + UINTN Index; + + EFI_TPL OldTpl; + + Status = EFI_SUCCESS; + CipherId = NULL; + + if (This == NULL || Data == NULL || DataSize == 0) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if (DataType != EfiTlsSessionState && Instance->TlsSessionState != EfiTlsSessionNotStarted){ + Status = EFI_NOT_READY; + goto ON_EXIT; + } + + switch (DataType) { + // + // Session Configuration + // + case EfiTlsVersion: + if (DataSize != sizeof (EFI_TLS_VERSION)) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status = TlsSetVersion (Instance->TlsConn, ((EFI_TLS_VERSION *) Data)->Major, ((EFI_TLS_VERSION *) Data)->Minor); + break; + case EfiTlsConnectionEnd: + if (DataSize != sizeof (EFI_TLS_CONNECTION_END)) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status = TlsSetConnectionEnd (Instance->TlsConn, *((EFI_TLS_CONNECTION_END *) Data)); + break; + case EfiTlsCipherList: + CipherId = AllocatePool (DataSize); + if (CipherId == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + for (Index = 0; Index < DataSize / sizeof (EFI_TLS_CIPHER); Index++) { + *(CipherId +Index) = HTONS (*(((UINT16 *) Data) + Index)); + } + + Status = TlsSetCipherList (Instance->TlsConn, CipherId, DataSize / sizeof (EFI_TLS_CIPHER)); + + FreePool (CipherId); + break; + case EfiTlsCompressionMethod: + // + // TLS seems only define one CompressionMethod.null, which specifies that data exchanged via the + // record protocol will not be compressed. + // More information from OpenSSL: http://www.openssl.org/docs/manmaster/ssl/SSL_COMP_add_compression_method.html + // The TLS RFC does however not specify compression methods or their corresponding identifiers, + // so there is currently no compatible way to integrate compression with unknown peers. + // It is therefore currently not recommended to integrate compression into applications. + // Applications for non-public use may agree on certain compression methods. + // Using different compression methods with the same identifier will lead to connection failure. + // + for (Index = 0; Index < DataSize / sizeof (EFI_TLS_COMPRESSION); Index++) { + Status = TlsSetCompressionMethod (*((UINT8 *) Data + Index)); + if (EFI_ERROR (Status)) { + break; + } + } + + break; + case EfiTlsExtensionData: + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + case EfiTlsVerifyMethod: + if (DataSize != sizeof (EFI_TLS_VERIFY)) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + TlsSetVerify (Instance->TlsConn, *((UINT32 *) Data)); + break; + case EfiTlsSessionID: + if (DataSize != sizeof (EFI_TLS_SESSION_ID)) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Status = TlsSetSessionId ( + Instance->TlsConn, + ((EFI_TLS_SESSION_ID *) Data)->Data, + ((EFI_TLS_SESSION_ID *) Data)->Length + ); + break; + case EfiTlsSessionState: + if (DataSize != sizeof (EFI_TLS_SESSION_STATE)) { + Status = EFI_INVALID_PARAMETER; + goto ON_EXIT; + } + + Instance->TlsSessionState = *(EFI_TLS_SESSION_STATE *) Data; + break; + // + // Session information + // + case EfiTlsClientRandom: + Status = EFI_ACCESS_DENIED; + break; + case EfiTlsServerRandom: + Status = EFI_ACCESS_DENIED; + break; + case EfiTlsKeyMaterial: + Status = EFI_ACCESS_DENIED; + break; + // + // Unsupported type. + // + default: + Status = EFI_UNSUPPORTED; + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Get TLS session data. + + The GetSessionData() function return the TLS session information. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] DataType TLS session data type. + @param[in, out] Data Pointer to session data. + @param[in, out] DataSize Total size of session data. On input, it means + the size of Data buffer. On output, it means the size + of copied Data buffer if EFI_SUCCESS, and means the + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. + + @retval EFI_SUCCESS The TLS session data is got successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + DataSize is NULL. + Data is NULL if *DataSize is not zero. + @retval EFI_UNSUPPORTED The DataType is unsupported. + @retval EFI_NOT_FOUND The TLS session data is not found. + @retval EFI_NOT_READY The DataType is not ready in current session state. + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data. +**/ +EFI_STATUS +EFIAPI +TlsGetSessionData ( + IN EFI_TLS_PROTOCOL *This, + IN EFI_TLS_SESSION_DATA_TYPE DataType, + IN OUT VOID *Data, OPTIONAL + IN OUT UINTN *DataSize + ) +{ + EFI_STATUS Status; + TLS_INSTANCE *Instance; + + EFI_TPL OldTpl; + + Status = EFI_SUCCESS; + + if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if (Instance->TlsSessionState == EfiTlsSessionNotStarted && + (DataType == EfiTlsSessionID || DataType == EfiTlsClientRandom || + DataType == EfiTlsServerRandom || DataType == EfiTlsKeyMaterial)) { + Status = EFI_NOT_READY; + goto ON_EXIT; + } + + switch (DataType) { + case EfiTlsVersion: + if (*DataSize < sizeof (EFI_TLS_VERSION)) { + *DataSize = sizeof (EFI_TLS_VERSION); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_VERSION); + *((UINT16 *) Data) = HTONS (TlsGetVersion (Instance->TlsConn)); + break; + case EfiTlsConnectionEnd: + if (*DataSize < sizeof (EFI_TLS_CONNECTION_END)) { + *DataSize = sizeof (EFI_TLS_CONNECTION_END); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_CONNECTION_END); + *((UINT8 *) Data) = TlsGetConnectionEnd (Instance->TlsConn); + break; + case EfiTlsCipherList: + // + // Get the current session cipher suite. + // + if (*DataSize < sizeof (EFI_TLS_CIPHER)) { + *DataSize = sizeof (EFI_TLS_CIPHER); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof(EFI_TLS_CIPHER); + Status = TlsGetCurrentCipher (Instance->TlsConn, (UINT16 *) Data); + *((UINT16 *) Data) = HTONS (*((UINT16 *) Data)); + break; + case EfiTlsCompressionMethod: + // + // Get the current session compression method. + // + if (*DataSize < sizeof (EFI_TLS_COMPRESSION)) { + *DataSize = sizeof (EFI_TLS_COMPRESSION); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_COMPRESSION); + Status = TlsGetCurrentCompressionId (Instance->TlsConn, (UINT8 *) Data); + break; + case EfiTlsExtensionData: + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + case EfiTlsVerifyMethod: + if (*DataSize < sizeof (EFI_TLS_VERIFY)) { + *DataSize = sizeof (EFI_TLS_VERIFY); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_VERIFY); + *((UINT32 *) Data) = TlsGetVerify (Instance->TlsConn); + break; + case EfiTlsSessionID: + if (*DataSize < sizeof (EFI_TLS_SESSION_ID)) { + *DataSize = sizeof (EFI_TLS_SESSION_ID); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_SESSION_ID); + Status = TlsGetSessionId ( + Instance->TlsConn, + ((EFI_TLS_SESSION_ID *) Data)->Data, + &(((EFI_TLS_SESSION_ID *) Data)->Length) + ); + break; + case EfiTlsSessionState: + if (*DataSize < sizeof (EFI_TLS_SESSION_STATE)) { + *DataSize = sizeof (EFI_TLS_SESSION_STATE); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_SESSION_STATE); + CopyMem (Data, &Instance->TlsSessionState, *DataSize); + break; + case EfiTlsClientRandom: + if (*DataSize < sizeof (EFI_TLS_RANDOM)) { + *DataSize = sizeof (EFI_TLS_RANDOM); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_RANDOM); + TlsGetClientRandom (Instance->TlsConn, (UINT8 *) Data); + break; + case EfiTlsServerRandom: + if (*DataSize < sizeof (EFI_TLS_RANDOM)) { + *DataSize = sizeof (EFI_TLS_RANDOM); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_RANDOM); + TlsGetServerRandom (Instance->TlsConn, (UINT8 *) Data); + break; + case EfiTlsKeyMaterial: + if (*DataSize < sizeof (EFI_TLS_MASTER_SECRET)) { + *DataSize = sizeof (EFI_TLS_MASTER_SECRET); + Status = EFI_BUFFER_TOO_SMALL; + goto ON_EXIT; + } + *DataSize = sizeof (EFI_TLS_MASTER_SECRET); + Status = TlsGetKeyMaterial (Instance->TlsConn, (UINT8 *) Data); + break; + // + // Unsupported type. + // + default: + Status = EFI_UNSUPPORTED; + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Build response packet according to TLS state machine. This function is only valid for + alert, handshake and change_cipher_spec content type. + + The BuildResponsePacket() function builds TLS response packet in response to the TLS + request packet specified by RequestBuffer and RequestSize. If RequestBuffer is NULL and + RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS session + will be initiated and the response packet needs to be ClientHello. If RequestBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, the TLS + session will be closed and response packet needs to be CloseNotify. If RequestBuffer is + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the TLS + session has errors and the response packet needs to be Alert message based on error + type. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in] RequestBuffer Pointer to the most recently received TLS packet. NULL + means TLS need initiate the TLS session and response + packet need to be ClientHello. + @param[in] RequestSize Packet size in bytes for the most recently received TLS + packet. 0 is only valid when RequestBuffer is NULL. + @param[out] Buffer Pointer to the buffer to hold the built packet. + @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, it is + the buffer size provided by the caller. On output, it + is the buffer size in fact needed to contain the + packet. + + @retval EFI_SUCCESS The required TLS packet is built successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + RequestBuffer is NULL but RequestSize is NOT 0. + RequestSize is 0 but RequestBuffer is NOT NULL. + BufferSize is NULL. + Buffer is NULL if *BufferSize is not zero. + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the response packet. + @retval EFI_NOT_READY Current TLS session state is NOT ready to build + ResponsePacket. + @retval EFI_ABORTED Something wrong build response packet. +**/ +EFI_STATUS +EFIAPI +TlsBuildResponsePacket ( + IN EFI_TLS_PROTOCOL *This, + IN UINT8 *RequestBuffer, OPTIONAL + IN UINTN RequestSize, OPTIONAL + OUT UINT8 *Buffer, OPTIONAL + IN OUT UINTN *BufferSize + ) +{ + EFI_STATUS Status; + TLS_INSTANCE *Instance; + EFI_TPL OldTpl; + + Status = EFI_SUCCESS; + + if ((This == NULL) || (BufferSize == NULL) || + (RequestBuffer == NULL && RequestSize != 0) || + (RequestBuffer != NULL && RequestSize == 0) || + (Buffer == NULL && *BufferSize !=0)) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if(RequestBuffer == NULL && RequestSize == 0) { + switch (Instance->TlsSessionState) { + case EfiTlsSessionNotStarted: + // + // ClientHello. + // + Status = TlsDoHandshake ( + Instance->TlsConn, + NULL, + 0, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + // + // *BufferSize should not be zero when ClientHello. + // + if (*BufferSize == 0) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + + Instance->TlsSessionState = EfiTlsSessionHandShaking; + + break; + case EfiTlsSessionClosing: + // + // TLS session will be closed and response packet needs to be CloseNotify. + // + Status = TlsCloseNotify ( + Instance->TlsConn, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + // + // *BufferSize should not be zero when build CloseNotify message. + // + if (*BufferSize == 0) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + + break; + case EfiTlsSessionError: + // + // TLS session has errors and the response packet needs to be Alert + // message based on error type. + // + Status = 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 = 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 = TlsDoHandshake ( + Instance->TlsConn, + RequestBuffer, + RequestSize, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + if (!TlsInHandshake (Instance->TlsConn)) { + Instance->TlsSessionState = EfiTlsSessionDataTransferring; + } + } else { + // + // Must be alert message, Decrypt it and build the ResponsePacket. + // + ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType == TLS_CONTENT_TYPE_ALERT); + + Status = TlsHandeAlert ( + Instance->TlsConn, + RequestBuffer, + RequestSize, + Buffer, + BufferSize + ); + if (EFI_ERROR (Status)) { + if (Status != EFI_BUFFER_TOO_SMALL) { + Instance->TlsSessionState = EfiTlsSessionError; + } + + goto ON_EXIT; + } + } + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} + +/** + Decrypt or encrypt TLS packet during session. This function is only valid after + session connected and for application_data content type. + + The ProcessPacket () function process each inbound or outbound TLS APP packet. + + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. + @param[in, out] FragmentTable Pointer to a list of fragment. The caller will take + responsible to handle the original FragmentTable while + it may be reallocated in TLS driver. If CryptMode is + EfiTlsEncrypt, on input these fragments contain the TLS + header and plain text TLS APP payload; on output these + fragments contain the TLS header and cipher text TLS + APP payload. If CryptMode is EfiTlsDecrypt, on input + these fragments contain the TLS header and cipher text + TLS APP payload; on output these fragments contain the + TLS header and plain text TLS APP payload. + @param[in] FragmentCount Number of fragment. + @param[in] CryptMode Crypt mode. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE: + This is NULL. + FragmentTable is NULL. + FragmentCount is NULL. + CryptoMode is invalid. + @retval EFI_NOT_READY Current TLS session state is NOT + EfiTlsSessionDataTransferring. + @retval EFI_ABORTED Something wrong decryption the message. TLS session + status will become EfiTlsSessionError. The caller need + call BuildResponsePacket() to generate Error Alert + message and send it out. + @retval EFI_OUT_OF_RESOURCES No enough resource to finish the operation. +**/ +EFI_STATUS +EFIAPI +TlsProcessPacket ( + IN EFI_TLS_PROTOCOL *This, + IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable, + IN UINT32 *FragmentCount, + IN EFI_TLS_CRYPT_MODE CryptMode + ) +{ + EFI_STATUS Status; + TLS_INSTANCE *Instance; + + EFI_TPL OldTpl; + + Status = EFI_SUCCESS; + + if (This == NULL || FragmentTable == NULL || FragmentCount == NULL) { + return EFI_INVALID_PARAMETER; + } + + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); + + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); + + if (Instance->TlsSessionState != EfiTlsSessionDataTransferring) { + Status = EFI_NOT_READY; + goto ON_EXIT; + } + + // + // Packet sent or received may have multiply TLS record message(Application data type). + // So,on input these fragments contain the TLS header and TLS APP payload; + // on output these fragments also contain the TLS header and TLS APP payload. + // + switch (CryptMode) { + case EfiTlsEncrypt: + Status = TlsEcryptPacket (Instance, FragmentTable, FragmentCount); + break; + case EfiTlsDecrypt: + Status = TlsDecryptPacket (Instance, FragmentTable, FragmentCount); + break; + default: + return EFI_INVALID_PARAMETER; + } + +ON_EXIT: + gBS->RestoreTPL (OldTpl); + return Status; +} -- 1.9.5.msysgit.1 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL 2016-12-16 6:16 ` Ye, Ting @ 2016-12-16 7:30 ` Wu, Jiaxin 0 siblings, 0 replies; 3+ messages in thread From: Wu, Jiaxin @ 2016-12-16 7:30 UTC (permalink / raw) To: Ye, Ting, edk2-devel@lists.01.org Cc: Fu, Siyuan, Zhang, Lubo, Long, Qin, Thomas Palmer Thanks Ting, I have updated the patch according your comments. [PATCH v2 04/10] CryptoPkg: Add new TlsLib library [PATCH v3 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL Best Regards! Jiaxin > -----Original Message----- > From: Ye, Ting > Sent: Friday, December 16, 2016 2:16 PM > To: Wu, Jiaxin <jiaxin.wu@intel.com>; edk2-devel@lists.01.org > Cc: Fu, Siyuan <siyuan.fu@intel.com>; Zhang, Lubo <lubo.zhang@intel.com>; > Long, Qin <qin.long@intel.com>; Thomas Palmer <thomas.palmer@hpe.com> > Subject: RE: [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver > implementation over OpenSSL > > Hi Jiaxin, > > Some comments included as below. > > 1. In TlsCreateService > Line 325: ASSERT checks after assignment in line 323. Should put ASSERT > earlier. > 'Status' looks useless. > > 2. TlsDriver.h > I think the macros ' TLS_INSTANCE_FROM_PROTOCOL_THIS' and ' > TLS_INSTANCE_FROM_CONFIGURATION_THIS' are hard to read. Maybe we > could remove the '_THIS' postfix? > 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 > responsible to... " > "Received packet may have multiply TLS record message." To " > Received packet may have multiple TLS record messages." > Also update Multiply to multiple in other places. > > "Copy all TLS plain record header and payload to ProcessBuffer". > ProcessBuffer looks a local variable but not exist. May update to BufferIn? > Please double check. > > Others are good to me. > > Reviewed-by: Ye Ting <ting.ye@intel.com> > > Thanks, > Ting > > -----Original Message----- > From: Wu, Jiaxin > Sent: Thursday, December 15, 2016 3:22 PM > To: edk2-devel@lists.01.org > Cc: Ye, Ting <ting.ye@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>; Zhang, > Lubo <lubo.zhang@intel.com>; Long, Qin <qin.long@intel.com>; Thomas > Palmer <thomas.palmer@hpe.com>; Wu, Jiaxin <jiaxin.wu@intel.com> > Subject: [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation > over 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 <ting.ye@intel.com> > Cc: Fu Siyuan <siyuan.fu@intel.com> > Cc: Zhang Lubo <lubo.zhang@intel.com> > Cc: Long Qin <qin.long@intel.com> > Cc: Thomas Palmer <thomas.palmer@hpe.com> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Wu Jiaxin <jiaxin.wu@intel.com> > --- > 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/TlsConfigProtocol.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.<BR> > + > + 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 IMPLIED. > + > +**/ > + > +#include "TlsImpl.h" > + > +EFI_TLS_CONFIGURATION_PROTOCOL mTlsConfigurationProtocol = { > + 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_PROTOCOL 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 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_OUT_OF_RESOURCES Required system resources could not > be allocated. > + > +**/ > +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 = EFI_SUCCESS; > + > + if (This == NULL || Data == NULL || DataSize == 0) { > + return EFI_INVALID_PARAMETER; > + } > + > + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); > + > + Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This); > + > + switch (DataType) { > + case EfiTlsConfigDataTypeCACertificate: > + Status = TlsSetCaCertificate (Instance->TlsConn, Data, DataSize); > + break; > + case EfiTlsConfigDataTypeHostPublicCert: > + Status = TlsSetHostPublicCert (Instance->TlsConn, Data, DataSize); > + break; > + case EfiTlsConfigDataTypeHostPrivateKey: > + Status = TlsSetHostPrivateKey (Instance->TlsConn, Data, DataSize); > + break; > + case EfiTlsConfigDataTypeCertRevocationList: > + Status = TlsSetCertRevocationList (Data, DataSize); > + break; > + default: > + Status = 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_PROTOCOL 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 input, it > means > + the size of Data buffer. On output, it means the size > + of copied Data buffer if EFI_SUCCESS, and means the > + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. > + > + @retval EFI_SUCCESS The TLS configuration 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 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 = EFI_SUCCESS; > + > + if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) > { > + return EFI_INVALID_PARAMETER; > + } > + > + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); > + > + Instance = TLS_INSTANCE_FROM_CONFIGURATION_THIS (This); > + > + switch (DataType) { > + case EfiTlsConfigDataTypeCACertificate: > + Status = TlsGetCaCertificate (Instance->TlsConn, Data, DataSize); > + break; > + case EfiTlsConfigDataTypeHostPublicCert: > + Status = TlsGetHostPublicCert (Instance->TlsConn, Data, DataSize); > + break; > + case EfiTlsConfigDataTypeHostPrivateKey: > + Status = TlsGetHostPrivateKey (Instance->TlsConn, Data, DataSize); > + break; > + case EfiTlsConfigDataTypeCertRevocationList: > + Status = TlsGetCertRevocationList (Data, DataSize); > + break; > + default: > + Status = 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.<BR> > + > + 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 IMPLIED. > + > +**/ > + > +#include "TlsImpl.h" > + > +EFI_SERVICE_BINDING_PROTOCOL mTlsServiceBinding = { > + 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 != NULL) { > + if (Instance->TlsConn != 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 = NULL; > + > + TlsInstance = AllocateZeroPool (sizeof (TLS_INSTANCE)); > + if (TlsInstance == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + TlsInstance->Signature = TLS_INSTANCE_SIGNATURE; > + InitializeListHead (&TlsInstance->Link); > + TlsInstance->InDestroy = FALSE; > + TlsInstance->Service = Service; > + > + CopyMem (&TlsInstance->Tls, &mTlsProtocol, sizeof (TlsInstance->Tls)); > + CopyMem (&TlsInstance->TlsConfig, &mTlsConfigurationProtocol, sizeof > (TlsInstance->TlsConfig)); > + > + TlsInstance->TlsSessionState = EfiTlsSessionNotStarted; > + > + *Instance = 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 != NULL) { > + if (Service->TlsCtx != 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 = EFI_SUCCESS; > + *Service = NULL; > + > + ASSERT (Service != NULL); > + > + // > + // Allocate a TLS Service Data > + // > + TlsService = AllocateZeroPool (sizeof (TLS_SERVICE)); > + if (TlsService == NULL) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Initialize TLS Service Data > + // > + TlsService->Signature = TLS_SERVICE_SIGNATURE; > + CopyMem (&TlsService->ServiceBinding, &mTlsServiceBinding, sizeof > (TlsService->ServiceBinding)); > + TlsService->TlsChildrenNum = 0; > + InitializeListHead (&TlsService->TlsChildrenList); > + TlsService->ImageHandle = Image; > + > + *Service = 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 = NULL; > + ServiceBinding = NULL; > + TlsService = NULL; > + > + // > + // Locate all the handles with Tls service binding protocol. > + // > + Status = gBS->LocateHandleBuffer ( > + ByProtocol, > + &gEfiTlsServiceBindingProtocolGuid, > + NULL, > + &HandleNum, > + &HandleBuffer > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + for (Index = 0; Index < HandleNum; Index++) { > + // > + // Firstly, find ServiceBinding interface > + // > + Status = gBS->OpenProtocol ( > + HandleBuffer[Index], > + &gEfiTlsServiceBindingProtocolGuid, > + (VOID **) &ServiceBinding, > + ImageHandle, > + NULL, > + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + TlsService = TLS_SERVICE_FROM_THIS (ServiceBinding); > + > + // > + // Then, uninstall ServiceBinding interface > + // > + Status = gBS->UninstallMultipleProtocolInterfaces ( > + HandleBuffer[Index], > + &gEfiTlsServiceBindingProtocolGuid, ServiceBinding, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + TlsCleanService (TlsService); > + } > + > + if (HandleBuffer != 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 including > + 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 = TlsCreateService (ImageHandle, &TlsService); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ASSERT (TlsService != 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 = TlsCtxNew (TLS10_PROTOCOL_VERSION_MAJOR, > TLS10_PROTOCOL_VERSION_MINOR); > + if (TlsService->TlsCtx == NULL) { > + FreePool (TlsService); > + return EFI_ABORTED; > + } > + > + // > + // Install the TlsServiceBinding Protocol onto Handle > + // > + Status = 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 > returned in ChildHandle. > + If ChildHandle is not a pointer to NULL, then the protocol installs on the > existing ChildHandle. > + > + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL > instance. > + @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 handle. > + > + @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 to 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 == NULL) || (ChildHandle == NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + TlsService = TLS_SERVICE_FROM_THIS (This); > + > + Status = TlsCreateInstance (TlsService, &TlsInstance); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + ASSERT (TlsInstance != NULL); > + > + // > + // Create a new TLS connection object. > + // > + TlsInstance->TlsConn = TlsNew (TlsService->TlsCtx); > + if (TlsInstance->TlsConn == NULL) { > + Status = EFI_ABORTED; > + goto ON_ERROR; > + } > + > + // > + // Set default ConnectionEnd to EfiTlsClient > + // > + Status = TlsSetConnectionEnd (TlsInstance->TlsConn, EfiTlsClient); > + if (EFI_ERROR (Status)) { > + goto ON_ERROR; > + } > + > + // > + // Install TLS protocol and configuration protocol onto ChildHandle > + // > + Status = gBS->InstallMultipleProtocolInterfaces ( > + ChildHandle, > + &gEfiTlsProtocolGuid, > + &TlsInstance->Tls, > + &gEfiTlsConfigurationProtocolGuid, > + &TlsInstance->TlsConfig, > + NULL > + ); > + if (EFI_ERROR (Status)) { > + goto ON_ERROR; > + } > + > + TlsInstance->ChildHandle = *ChildHandle; > + > + // > + // Add it to the TLS service's child list. > + // > + OldTpl = 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 removes > a protocol > + that was installed by CreateChild() from ChildHandle. If the removed > protocol 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 == NULL) || (ChildHandle == NULL)) { > + return EFI_INVALID_PARAMETER; > + } > + > + TlsService = TLS_SERVICE_FROM_THIS (This); > + > + // > + // Find TLS protocol interface installed in ChildHandle > + // > + Status = 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 = gBS->OpenProtocol ( > + ChildHandle, > + &gEfiTlsConfigurationProtocolGuid, > + (VOID **) &TlsConfig, > + TlsService->ImageHandle, > + NULL, > + EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL > + ); > + if (EFI_ERROR (Status)) { > + return Status; > + } > + > + TlsInstance = TLS_INSTANCE_FROM_PROTOCOL_THIS (Tls); > + > + if (TlsInstance->Service != TlsService) { > + return EFI_INVALID_PARAMETER; > + } > + > + if (TlsInstance->InDestroy) { > + return EFI_SUCCESS; > + } > + > + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); > + > + TlsInstance->InDestroy = TRUE; > + > + // > + // Uninstall the TLS protocol and TLS Configuration Protocol interface > installed in ChildHandle. > + // > + Status = 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 TlsDxe > driver. > + > + Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> > + > + 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 IMPLIED. > + > +**/ > + > +#ifndef __EFI_TLS_DRIVER_H__ > +#define __EFI_TLS_DRIVER_H__ > + > +#include <Uefi.h> > + > +// > +// Driver Protocols > +// > +#include <Protocol/ServiceBinding.h> > + > +// > +// 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 per > program > + // life-time and which holds mainly default values for the SSL object which > 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 > 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 > + ); > + > +/** > + 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 including > + 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 > returned in ChildHandle. > + If ChildHandle is not a pointer to NULL, then the protocol installs on the > existing ChildHandle. > + > + @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL > instance. > + @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 handle. > + > + @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 to 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 removes > a protocol > + that was installed by CreateChild() from ChildHandle. If the removed > protocol 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 EFI > TLS > +# Service Binding Protocol, to provide TLS services. > +# > +# Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> > +# > +# 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 IMPLIED. > +# > +# > +## > + > +[Defines] > + INF_VERSION = 0x00010005 > + BASE_NAME = TlsDxe > + FILE_GUID = 3aceb0c0-3c72-11e4-9a56-74d435052646 > + MODULE_TYPE = UEFI_DRIVER > + VERSION_STRING = 1.0 > + ENTRY_POINT = TlsDriverEntryPoint > + UNLOAD_IMAGE = TlsUnload > + MODULE_UNI_FILE = TlsDxe.uni > + > +# > +# VALID_ARCHITECTURES = 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 TLS > +// Service Binding Protocol, and EFI TLS Configuration Protocol to provide > TLS > +// services. > +// > +// Copyright (c) 2016, Intel Corporation. All rights reserved.<BR> > +// > +// 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 IMPLIED. > +// > +// **/ > + > + > +#string STR_MODULE_ABSTRACT #language en-US "UEFI TLS service" > + > +#string STR_MODULE_DESCRIPTION #language en-US "This module > produces EFI TLS Protocol, EFI TLS Service Binding Protocol and EFI TLS > Configuration Protocol to provide EFI TLS services." > + > diff --git a/NetworkPkg/TlsDxe/TlsDxeExtra.uni > b/NetworkPkg/TlsDxe/TlsDxeExtra.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.<BR> > +// > +// 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 IMPLIED. > +// > +// **/ > + > +#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.<BR> > + > +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 IMPLIED. > + > +**/ > + > +#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 > +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; > + > + Status = EFI_SUCCESS; > + BytesCopied = 0; > + BufferInSize = 0; > + BufferIn = NULL; > + BufferInPtr = NULL; > + RecordHeaderIn = NULL; > + TempRecordHeader = NULL; > + BufferOutSize = 0; > + BufferOut = NULL; > + 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 ProcessBuffer. > + // > + for (Index = 0; Index < *FragmentCount; Index++) { > + CopyMem ( > + (BufferIn + BytesCopied), > + (*FragmentTable)[Index].FragmentBuffer, > + (*FragmentTable)[Index].FragmentLength > + ); > + BytesCopied += (*FragmentTable)[Index].FragmentLength; > + } > + > + BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE); > + if (BufferOut == NULL) { > + Status = EFI_OUT_OF_RESOURCES; > + goto ERROR; > + } > + > + // > + // Parsing buffer. > + // > + BufferInPtr = BufferIn; > + TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut; > + while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { > + RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr; > + > + if (RecordHeaderIn->ContentType != > TLS_CONTENT_TYPE_APPLICATION_DATA) { > + Status = EFI_INVALID_PARAMETER; > + goto ERROR; > + } > + > + ThisPlainMessageSize = RecordHeaderIn->Length; > + > + TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), > ThisPlainMessageSize); > + > + Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 > *)(TempRecordHeader), MAX_BUFFER_SIZE - BufferOutSize); > + > + if (Ret > 0) { > + ThisMessageSize = (UINT16) Ret; > + } else { > + // > + // No data was successfully encrypted, continue the other messages > encryption. > + // > + DEBUG ((EFI_D_WARN, "TlsEcryptPacket: No data read from TLS > object.\n")); > + > + ThisMessageSize = 0; > + } > + > + BufferOutSize += ThisMessageSize; > + > + BufferInPtr += RECORD_HEADER_LEN + ThisPlainMessageSize; > + TempRecordHeader += ThisMessageSize; > + } > + > + FreePool (BufferIn); > + BufferIn = NULL; > + > + // > + // The caller will take 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; > + INTN Ret; > + > + Status = EFI_SUCCESS; > + BytesCopied = 0; > + BufferIn = NULL; > + BufferInSize = 0; > + BufferInPtr = NULL; > + RecordHeaderIn = NULL; > + TempRecordHeader = NULL; > + BufferOut = NULL; > + BufferOutSize = 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 ProcessBuffer > + // > + for (Index = 0; Index < *FragmentCount; Index++) { > + CopyMem ( > + (BufferIn + BytesCopied), > + (*FragmentTable)[Index].FragmentBuffer, > + (*FragmentTable)[Index].FragmentLength > + ); > + BytesCopied += (*FragmentTable)[Index].FragmentLength; > + } > + > + BufferOut = AllocateZeroPool (MAX_BUFFER_SIZE); > + if (BufferOut == NULL) { > + Status = EFI_OUT_OF_RESOURCES; > + goto ERROR; > + } > + > + // > + // Parsing buffer. Received packet may have multiply TLS record message. > + // > + BufferInPtr = BufferIn; > + TempRecordHeader = (TLS_RECORD_HEADER *) BufferOut; > + while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { > + RecordHeaderIn = (TLS_RECORD_HEADER *) BufferInPtr; > + > + if (RecordHeaderIn->ContentType != > TLS_CONTENT_TYPE_APPLICATION_DATA) { > + Status = EFI_INVALID_PARAMETER; > + goto ERROR; > + } > + > + ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length); > + > + Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn), > RECORD_HEADER_LEN + ThisCipherMessageSize); > + if (Ret != RECORD_HEADER_LEN + ThisCipherMessageSize) { > + TlsInstance->TlsSessionState = EfiTlsSessionError; > + Status = EFI_ABORTED; > + goto ERROR; > + } > + > + Ret = 0; > + Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1), > MAX_BUFFER_SIZE - BufferOutSize); > + > + if (Ret > 0) { > + ThisPlainMessageSize = (UINT16) Ret; > + } else { > + // > + // No data was successfully decrypted, continue the other messages > decryption. > + // > + DEBUG ((EFI_D_WARN, "TlsDecryptPacket: No data read from TLS > object.\n")); > + > + ThisPlainMessageSize = 0; > + } > + > + CopyMem (TempRecordHeader, RecordHeaderIn, > RECORD_HEADER_LEN); > + TempRecordHeader->Length = ThisPlainMessageSize; > + BufferOutSize += RECORD_HEADER_LEN + ThisPlainMessageSize; > + > + BufferInPtr += RECORD_HEADER_LEN + ThisCipherMessageSize; > + TempRecordHeader += RECORD_HEADER_LEN + ThisPlainMessageSize; > + } > + > + FreePool (BufferIn); > + BufferIn = NULL; > + > + // > + // The caller will take 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; > +} > 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.<BR> > + > +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 IMPLIED. > + > +**/ > + > +#ifndef __EFI_TLS_IMPL_H__ > +#define __EFI_TLS_IMPL_H__ > + > +// > +// Libraries > +// > +#include <Library/UefiBootServicesTableLib.h> > +#include <Library/MemoryAllocationLib.h> > +#include <Library/BaseMemoryLib.h> > +#include <Library/BaseLib.h> > +#include <Library/UefiLib.h> > +#include <Library/DebugLib.h> > +#include <Library/NetLib.h> > +#include <Library/BaseCryptLib.h> > +#include <Library/TlsLib.h> > + > +// > +// Consumed Protocols > +// > +#include <Protocol/Tls.h> > +#include <Protocol/TlsConfig.h> > + > +#include <IndustryStandard/Tls1.h> > + > +#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 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 > +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 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 > + ); > + > +/** > + Set TLS session data. > + > + The SetSessionData() function set data for a new TLS session. All session > data should > + be set before BuildResponsePacket() invoked. > + > + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. > + @param[in] DataType TLS session data type. > + @param[in] Data Pointer to session data. > + @param[in] DataSize Total size of session data. > + > + @retval EFI_SUCCESS The TLS session data is set successfully. > + @retval EFI_INVALID_PARAMETER One or more of the following > conditions is TRUE: > + This is NULL. > + Data is NULL. > + DataSize is 0. > + @retval EFI_UNSUPPORTED The DataType is unsupported. > + @retval EFI_ACCESS_DENIED If the DataType is one of below: > + EfiTlsClientRandom > + EfiTlsServerRandom > + EfiTlsKeyMaterial > + @retval EFI_NOT_READY Current TLS session state is NOT > + EfiTlsSessionStateNotStarted. > + @retval EFI_OUT_OF_RESOURCES Required system resources could not > be allocated. > +**/ > +EFI_STATUS > +EFIAPI > +TlsSetSessionData ( > + IN EFI_TLS_PROTOCOL *This, > + IN EFI_TLS_SESSION_DATA_TYPE DataType, > + IN VOID *Data, > + IN UINTN DataSize > + ); > + > +/** > + Get TLS session data. > + > + The GetSessionData() function return the TLS session information. > + > + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. > + @param[in] DataType TLS session data type. > + @param[in, out] Data Pointer to session data. > + @param[in, out] DataSize Total size of session data. On input, it means > + the size of Data buffer. On output, it means the size > + of copied Data buffer if EFI_SUCCESS, and means the > + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. > + > + @retval EFI_SUCCESS The TLS session data is got successfully. > + @retval EFI_INVALID_PARAMETER One or more of the following > conditions is TRUE: > + This is NULL. > + DataSize is NULL. > + Data is NULL if *DataSize is not zero. > + @retval EFI_UNSUPPORTED The DataType is unsupported. > + @retval EFI_NOT_FOUND The TLS session data is not found. > + @retval EFI_NOT_READY The DataType is not ready in current session > state. > + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data. > +**/ > +EFI_STATUS > +EFIAPI > +TlsGetSessionData ( > + IN EFI_TLS_PROTOCOL *This, > + IN EFI_TLS_SESSION_DATA_TYPE DataType, > + IN OUT VOID *Data, OPTIONAL > + IN OUT UINTN *DataSize > + ); > + > +/** > + Build response packet according to TLS state machine. This function is only > valid for > + alert, handshake and change_cipher_spec content type. > + > + The BuildResponsePacket() function builds TLS response packet in > response to the TLS > + request packet specified by RequestBuffer and RequestSize. If > RequestBuffer is NULL and > + RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS > session > + will be initiated and the response packet needs to be ClientHello. If > RequestBuffer is > + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, > the TLS > + session will be closed and response packet needs to be CloseNotify. If > RequestBuffer is > + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the > TLS > + session has errors and the response packet needs to be Alert message > based on error > + type. > + > + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. > + @param[in] RequestBuffer Pointer to the most recently received TLS > packet. NULL > + means TLS need initiate the TLS session and response > + packet need to be ClientHello. > + @param[in] RequestSize Packet size in bytes for the most recently > received TLS > + packet. 0 is only valid when RequestBuffer is NULL. > + @param[out] Buffer Pointer to the buffer to hold the built packet. > + @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, > it is > + the buffer size provided by the caller. On output, it > + is the buffer size in fact needed to contain the > + packet. > + > + @retval EFI_SUCCESS The required TLS packet is built successfully. > + @retval EFI_INVALID_PARAMETER One or more of the following > conditions is TRUE: > + This is NULL. > + RequestBuffer is NULL but RequestSize is NOT 0. > + RequestSize is 0 but RequestBuffer is NOT NULL. > + BufferSize is NULL. > + Buffer is NULL if *BufferSize is not zero. > + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the > response packet. > + @retval EFI_NOT_READY Current TLS session state is NOT ready to > build > + ResponsePacket. > + @retval EFI_ABORTED Something wrong build response packet. > +**/ > +EFI_STATUS > +EFIAPI > +TlsBuildResponsePacket ( > + IN EFI_TLS_PROTOCOL *This, > + IN UINT8 *RequestBuffer, OPTIONAL > + IN UINTN RequestSize, OPTIONAL > + OUT UINT8 *Buffer, OPTIONAL > + IN OUT UINTN *BufferSize > + ); > + > +/** > + Decrypt or encrypt TLS packet during session. This function is only valid > after > + session connected and for application_data content type. > + > + The ProcessPacket () function process each inbound or outbound TLS APP > packet. > + > + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. > + @param[in, out] FragmentTable Pointer to a list of fragment. The caller > will take > + responsible to handle the original FragmentTable while > + it may be reallocated in TLS driver. If CryptMode is > + EfiTlsEncrypt, on input these fragments contain the TLS > + header and plain text TLS APP payload; on output these > + fragments contain the TLS header and cipher text TLS > + APP payload. If CryptMode is EfiTlsDecrypt, on input > + these fragments contain the TLS header and cipher text > + TLS APP payload; on output these fragments contain the > + TLS header and plain text TLS APP payload. > + @param[in] FragmentCount Number of fragment. > + @param[in] CryptMode Crypt mode. > + > + @retval EFI_SUCCESS The operation completed successfully. > + @retval EFI_INVALID_PARAMETER One or more of the following > conditions is TRUE: > + This is NULL. > + FragmentTable is NULL. > + FragmentCount is NULL. > + CryptoMode is invalid. > + @retval EFI_NOT_READY Current TLS session state is NOT > + EfiTlsSessionDataTransferring. > + @retval EFI_ABORTED Something wrong decryption the message. > TLS session > + status will become EfiTlsSessionError. The caller need > + call BuildResponsePacket() to generate Error Alert > + message and send it out. > + @retval EFI_OUT_OF_RESOURCES No enough resource to finish the > operation. > +**/ > +EFI_STATUS > +EFIAPI > +TlsProcessPacket ( > + IN EFI_TLS_PROTOCOL *This, > + IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable, > + IN UINT32 *FragmentCount, > + IN EFI_TLS_CRYPT_MODE CryptMode > + ); > + > +/** > + 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_PROTOCOL 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 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_OUT_OF_RESOURCES Required system resources could not > be allocated. > +**/ > +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_PROTOCOL 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 input, it > means > + the size of Data buffer. On output, it means the size > + of copied Data buffer if EFI_SUCCESS, and means the > + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. > + > + @retval EFI_SUCCESS The TLS configuration 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 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/TlsProtocol.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.<BR> > + > + 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 IMPLIED. > + > +**/ > + > +#include "TlsImpl.h" > + > +EFI_TLS_PROTOCOL mTlsProtocol = { > + TlsSetSessionData, > + TlsGetSessionData, > + TlsBuildResponsePacket, > + TlsProcessPacket > +}; > + > +/** > + Set TLS session data. > + > + The SetSessionData() function set data for a new TLS session. All session > data should > + be set before BuildResponsePacket() invoked. > + > + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. > + @param[in] DataType TLS session data type. > + @param[in] Data Pointer to session data. > + @param[in] DataSize Total size of session data. > + > + @retval EFI_SUCCESS The TLS session data is set successfully. > + @retval EFI_INVALID_PARAMETER One or more of the following > conditions is TRUE: > + This is NULL. > + Data is NULL. > + DataSize is 0. > + @retval EFI_UNSUPPORTED The DataType is unsupported. > + @retval EFI_ACCESS_DENIED If the DataType is one of below: > + EfiTlsClientRandom > + EfiTlsServerRandom > + EfiTlsKeyMaterial > + @retval EFI_NOT_READY Current TLS session state is NOT > + EfiTlsSessionStateNotStarted. > + @retval EFI_OUT_OF_RESOURCES Required system resources could not > be allocated. > +**/ > +EFI_STATUS > +EFIAPI > +TlsSetSessionData ( > + IN EFI_TLS_PROTOCOL *This, > + IN EFI_TLS_SESSION_DATA_TYPE DataType, > + IN VOID *Data, > + IN UINTN DataSize > + ) > +{ > + EFI_STATUS Status; > + TLS_INSTANCE *Instance; > + UINT16 *CipherId; > + UINTN Index; > + > + EFI_TPL OldTpl; > + > + Status = EFI_SUCCESS; > + CipherId = NULL; > + > + if (This == NULL || Data == NULL || DataSize == 0) { > + return EFI_INVALID_PARAMETER; > + } > + > + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); > + > + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); > + > + if (DataType != EfiTlsSessionState && Instance->TlsSessionState != > EfiTlsSessionNotStarted){ > + Status = EFI_NOT_READY; > + goto ON_EXIT; > + } > + > + switch (DataType) { > + // > + // Session Configuration > + // > + case EfiTlsVersion: > + if (DataSize != sizeof (EFI_TLS_VERSION)) { > + Status = EFI_INVALID_PARAMETER; > + goto ON_EXIT; > + } > + > + Status = TlsSetVersion (Instance->TlsConn, ((EFI_TLS_VERSION *) Data)- > >Major, ((EFI_TLS_VERSION *) Data)->Minor); > + break; > + case EfiTlsConnectionEnd: > + if (DataSize != sizeof (EFI_TLS_CONNECTION_END)) { > + Status = EFI_INVALID_PARAMETER; > + goto ON_EXIT; > + } > + > + Status = TlsSetConnectionEnd (Instance->TlsConn, > *((EFI_TLS_CONNECTION_END *) Data)); > + break; > + case EfiTlsCipherList: > + CipherId = AllocatePool (DataSize); > + if (CipherId == NULL) { > + Status = EFI_OUT_OF_RESOURCES; > + goto ON_EXIT; > + } > + > + for (Index = 0; Index < DataSize / sizeof (EFI_TLS_CIPHER); Index++) { > + *(CipherId +Index) = HTONS (*(((UINT16 *) Data) + Index)); > + } > + > + Status = TlsSetCipherList (Instance->TlsConn, CipherId, DataSize / sizeof > (EFI_TLS_CIPHER)); > + > + FreePool (CipherId); > + break; > + case EfiTlsCompressionMethod: > + // > + // TLS seems only define one CompressionMethod.null, which specifies > that data exchanged via the > + // record protocol will not be compressed. > + // More information from OpenSSL: > http://www.openssl.org/docs/manmaster/ssl/SSL_COMP_add_compressio > n_method.html > + // The TLS RFC does however not specify compression methods or their > corresponding identifiers, > + // so there is currently no compatible way to integrate compression with > unknown peers. > + // It is therefore currently not recommended to integrate compression > into applications. > + // Applications for non-public use may agree on certain compression > methods. > + // Using different compression methods with the same identifier will lead > to connection failure. > + // > + for (Index = 0; Index < DataSize / sizeof (EFI_TLS_COMPRESSION); > Index++) { > + Status = TlsSetCompressionMethod (*((UINT8 *) Data + Index)); > + if (EFI_ERROR (Status)) { > + break; > + } > + } > + > + break; > + case EfiTlsExtensionData: > + Status = EFI_UNSUPPORTED; > + goto ON_EXIT; > + case EfiTlsVerifyMethod: > + if (DataSize != sizeof (EFI_TLS_VERIFY)) { > + Status = EFI_INVALID_PARAMETER; > + goto ON_EXIT; > + } > + > + TlsSetVerify (Instance->TlsConn, *((UINT32 *) Data)); > + break; > + case EfiTlsSessionID: > + if (DataSize != sizeof (EFI_TLS_SESSION_ID)) { > + Status = EFI_INVALID_PARAMETER; > + goto ON_EXIT; > + } > + > + Status = TlsSetSessionId ( > + Instance->TlsConn, > + ((EFI_TLS_SESSION_ID *) Data)->Data, > + ((EFI_TLS_SESSION_ID *) Data)->Length > + ); > + break; > + case EfiTlsSessionState: > + if (DataSize != sizeof (EFI_TLS_SESSION_STATE)) { > + Status = EFI_INVALID_PARAMETER; > + goto ON_EXIT; > + } > + > + Instance->TlsSessionState = *(EFI_TLS_SESSION_STATE *) Data; > + break; > + // > + // Session information > + // > + case EfiTlsClientRandom: > + Status = EFI_ACCESS_DENIED; > + break; > + case EfiTlsServerRandom: > + Status = EFI_ACCESS_DENIED; > + break; > + case EfiTlsKeyMaterial: > + Status = EFI_ACCESS_DENIED; > + break; > + // > + // Unsupported type. > + // > + default: > + Status = EFI_UNSUPPORTED; > + } > + > +ON_EXIT: > + gBS->RestoreTPL (OldTpl); > + return Status; > +} > + > +/** > + Get TLS session data. > + > + The GetSessionData() function return the TLS session information. > + > + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. > + @param[in] DataType TLS session data type. > + @param[in, out] Data Pointer to session data. > + @param[in, out] DataSize Total size of session data. On input, it means > + the size of Data buffer. On output, it means the size > + of copied Data buffer if EFI_SUCCESS, and means the > + size of desired Data buffer if EFI_BUFFER_TOO_SMALL. > + > + @retval EFI_SUCCESS The TLS session data is got successfully. > + @retval EFI_INVALID_PARAMETER One or more of the following > conditions is TRUE: > + This is NULL. > + DataSize is NULL. > + Data is NULL if *DataSize is not zero. > + @retval EFI_UNSUPPORTED The DataType is unsupported. > + @retval EFI_NOT_FOUND The TLS session data is not found. > + @retval EFI_NOT_READY The DataType is not ready in current session > state. > + @retval EFI_BUFFER_TOO_SMALL The buffer is too small to hold the data. > +**/ > +EFI_STATUS > +EFIAPI > +TlsGetSessionData ( > + IN EFI_TLS_PROTOCOL *This, > + IN EFI_TLS_SESSION_DATA_TYPE DataType, > + IN OUT VOID *Data, OPTIONAL > + IN OUT UINTN *DataSize > + ) > +{ > + EFI_STATUS Status; > + TLS_INSTANCE *Instance; > + > + EFI_TPL OldTpl; > + > + Status = EFI_SUCCESS; > + > + if (This == NULL || DataSize == NULL || (Data == NULL && *DataSize != 0)) > { > + return EFI_INVALID_PARAMETER; > + } > + > + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); > + > + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); > + > + if (Instance->TlsSessionState == EfiTlsSessionNotStarted && > + (DataType == EfiTlsSessionID || DataType == EfiTlsClientRandom || > + DataType == EfiTlsServerRandom || DataType == EfiTlsKeyMaterial)) { > + Status = EFI_NOT_READY; > + goto ON_EXIT; > + } > + > + switch (DataType) { > + case EfiTlsVersion: > + if (*DataSize < sizeof (EFI_TLS_VERSION)) { > + *DataSize = sizeof (EFI_TLS_VERSION); > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > + } > + *DataSize = sizeof (EFI_TLS_VERSION); > + *((UINT16 *) Data) = HTONS (TlsGetVersion (Instance->TlsConn)); > + break; > + case EfiTlsConnectionEnd: > + if (*DataSize < sizeof (EFI_TLS_CONNECTION_END)) { > + *DataSize = sizeof (EFI_TLS_CONNECTION_END); > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > + } > + *DataSize = sizeof (EFI_TLS_CONNECTION_END); > + *((UINT8 *) Data) = TlsGetConnectionEnd (Instance->TlsConn); > + break; > + case EfiTlsCipherList: > + // > + // Get the current session cipher suite. > + // > + if (*DataSize < sizeof (EFI_TLS_CIPHER)) { > + *DataSize = sizeof (EFI_TLS_CIPHER); > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > + } > + *DataSize = sizeof(EFI_TLS_CIPHER); > + Status = TlsGetCurrentCipher (Instance->TlsConn, (UINT16 *) Data); > + *((UINT16 *) Data) = HTONS (*((UINT16 *) Data)); > + break; > + case EfiTlsCompressionMethod: > + // > + // Get the current session compression method. > + // > + if (*DataSize < sizeof (EFI_TLS_COMPRESSION)) { > + *DataSize = sizeof (EFI_TLS_COMPRESSION); > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > + } > + *DataSize = sizeof (EFI_TLS_COMPRESSION); > + Status = TlsGetCurrentCompressionId (Instance->TlsConn, (UINT8 *) > Data); > + break; > + case EfiTlsExtensionData: > + Status = EFI_UNSUPPORTED; > + goto ON_EXIT; > + case EfiTlsVerifyMethod: > + if (*DataSize < sizeof (EFI_TLS_VERIFY)) { > + *DataSize = sizeof (EFI_TLS_VERIFY); > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > + } > + *DataSize = sizeof (EFI_TLS_VERIFY); > + *((UINT32 *) Data) = TlsGetVerify (Instance->TlsConn); > + break; > + case EfiTlsSessionID: > + if (*DataSize < sizeof (EFI_TLS_SESSION_ID)) { > + *DataSize = sizeof (EFI_TLS_SESSION_ID); > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > + } > + *DataSize = sizeof (EFI_TLS_SESSION_ID); > + Status = TlsGetSessionId ( > + Instance->TlsConn, > + ((EFI_TLS_SESSION_ID *) Data)->Data, > + &(((EFI_TLS_SESSION_ID *) Data)->Length) > + ); > + break; > + case EfiTlsSessionState: > + if (*DataSize < sizeof (EFI_TLS_SESSION_STATE)) { > + *DataSize = sizeof (EFI_TLS_SESSION_STATE); > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > + } > + *DataSize = sizeof (EFI_TLS_SESSION_STATE); > + CopyMem (Data, &Instance->TlsSessionState, *DataSize); > + break; > + case EfiTlsClientRandom: > + if (*DataSize < sizeof (EFI_TLS_RANDOM)) { > + *DataSize = sizeof (EFI_TLS_RANDOM); > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > + } > + *DataSize = sizeof (EFI_TLS_RANDOM); > + TlsGetClientRandom (Instance->TlsConn, (UINT8 *) Data); > + break; > + case EfiTlsServerRandom: > + if (*DataSize < sizeof (EFI_TLS_RANDOM)) { > + *DataSize = sizeof (EFI_TLS_RANDOM); > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > + } > + *DataSize = sizeof (EFI_TLS_RANDOM); > + TlsGetServerRandom (Instance->TlsConn, (UINT8 *) Data); > + break; > + case EfiTlsKeyMaterial: > + if (*DataSize < sizeof (EFI_TLS_MASTER_SECRET)) { > + *DataSize = sizeof (EFI_TLS_MASTER_SECRET); > + Status = EFI_BUFFER_TOO_SMALL; > + goto ON_EXIT; > + } > + *DataSize = sizeof (EFI_TLS_MASTER_SECRET); > + Status = TlsGetKeyMaterial (Instance->TlsConn, (UINT8 *) Data); > + break; > + // > + // Unsupported type. > + // > + default: > + Status = EFI_UNSUPPORTED; > + } > + > +ON_EXIT: > + gBS->RestoreTPL (OldTpl); > + return Status; > +} > + > +/** > + Build response packet according to TLS state machine. This function is only > valid for > + alert, handshake and change_cipher_spec content type. > + > + The BuildResponsePacket() function builds TLS response packet in > response to the TLS > + request packet specified by RequestBuffer and RequestSize. If > RequestBuffer is NULL and > + RequestSize is 0, and TLS session status is EfiTlsSessionNotStarted, the TLS > session > + will be initiated and the response packet needs to be ClientHello. If > RequestBuffer is > + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionClosing, > the TLS > + session will be closed and response packet needs to be CloseNotify. If > RequestBuffer is > + NULL and RequestSize is 0, and TLS session status is EfiTlsSessionError, the > TLS > + session has errors and the response packet needs to be Alert message > based on error > + type. > + > + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. > + @param[in] RequestBuffer Pointer to the most recently received TLS > packet. NULL > + means TLS need initiate the TLS session and response > + packet need to be ClientHello. > + @param[in] RequestSize Packet size in bytes for the most recently > received TLS > + packet. 0 is only valid when RequestBuffer is NULL. > + @param[out] Buffer Pointer to the buffer to hold the built packet. > + @param[in, out] BufferSize Pointer to the buffer size in bytes. On input, > it is > + the buffer size provided by the caller. On output, it > + is the buffer size in fact needed to contain the > + packet. > + > + @retval EFI_SUCCESS The required TLS packet is built successfully. > + @retval EFI_INVALID_PARAMETER One or more of the following > conditions is TRUE: > + This is NULL. > + RequestBuffer is NULL but RequestSize is NOT 0. > + RequestSize is 0 but RequestBuffer is NOT NULL. > + BufferSize is NULL. > + Buffer is NULL if *BufferSize is not zero. > + @retval EFI_BUFFER_TOO_SMALL BufferSize is too small to hold the > response packet. > + @retval EFI_NOT_READY Current TLS session state is NOT ready to > build > + ResponsePacket. > + @retval EFI_ABORTED Something wrong build response packet. > +**/ > +EFI_STATUS > +EFIAPI > +TlsBuildResponsePacket ( > + IN EFI_TLS_PROTOCOL *This, > + IN UINT8 *RequestBuffer, OPTIONAL > + IN UINTN RequestSize, OPTIONAL > + OUT UINT8 *Buffer, OPTIONAL > + IN OUT UINTN *BufferSize > + ) > +{ > + EFI_STATUS Status; > + TLS_INSTANCE *Instance; > + EFI_TPL OldTpl; > + > + Status = EFI_SUCCESS; > + > + if ((This == NULL) || (BufferSize == NULL) || > + (RequestBuffer == NULL && RequestSize != 0) || > + (RequestBuffer != NULL && RequestSize == 0) || > + (Buffer == NULL && *BufferSize !=0)) { > + return EFI_INVALID_PARAMETER; > + } > + > + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); > + > + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); > + > + if(RequestBuffer == NULL && RequestSize == 0) { > + switch (Instance->TlsSessionState) { > + case EfiTlsSessionNotStarted: > + // > + // ClientHello. > + // > + Status = TlsDoHandshake ( > + Instance->TlsConn, > + NULL, > + 0, > + Buffer, > + BufferSize > + ); > + if (EFI_ERROR (Status)) { > + goto ON_EXIT; > + } > + > + // > + // *BufferSize should not be zero when ClientHello. > + // > + if (*BufferSize == 0) { > + Status = EFI_ABORTED; > + goto ON_EXIT; > + } > + > + Instance->TlsSessionState = EfiTlsSessionHandShaking; > + > + break; > + case EfiTlsSessionClosing: > + // > + // TLS session will be closed and response packet needs to be > CloseNotify. > + // > + Status = TlsCloseNotify ( > + Instance->TlsConn, > + Buffer, > + BufferSize > + ); > + if (EFI_ERROR (Status)) { > + goto ON_EXIT; > + } > + > + // > + // *BufferSize should not be zero when build CloseNotify message. > + // > + if (*BufferSize == 0) { > + Status = EFI_ABORTED; > + goto ON_EXIT; > + } > + > + break; > + case EfiTlsSessionError: > + // > + // TLS session has errors and the response packet needs to be Alert > + // message based on error type. > + // > + Status = 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 = 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 = TlsDoHandshake ( > + Instance->TlsConn, > + RequestBuffer, > + RequestSize, > + Buffer, > + BufferSize > + ); > + if (EFI_ERROR (Status)) { > + goto ON_EXIT; > + } > + > + if (!TlsInHandshake (Instance->TlsConn)) { > + Instance->TlsSessionState = EfiTlsSessionDataTransferring; > + } > + } else { > + // > + // Must be alert message, Decrypt it and build the ResponsePacket. > + // > + ASSERT (((TLS_RECORD_HEADER *) RequestBuffer)->ContentType == > TLS_CONTENT_TYPE_ALERT); > + > + Status = TlsHandeAlert ( > + Instance->TlsConn, > + RequestBuffer, > + RequestSize, > + Buffer, > + BufferSize > + ); > + if (EFI_ERROR (Status)) { > + if (Status != EFI_BUFFER_TOO_SMALL) { > + Instance->TlsSessionState = EfiTlsSessionError; > + } > + > + goto ON_EXIT; > + } > + } > + } > + > +ON_EXIT: > + gBS->RestoreTPL (OldTpl); > + return Status; > +} > + > +/** > + Decrypt or encrypt TLS packet during session. This function is only valid > after > + session connected and for application_data content type. > + > + The ProcessPacket () function process each inbound or outbound TLS APP > packet. > + > + @param[in] This Pointer to the EFI_TLS_PROTOCOL instance. > + @param[in, out] FragmentTable Pointer to a list of fragment. The caller > will take > + responsible to handle the original FragmentTable while > + it may be reallocated in TLS driver. If CryptMode is > + EfiTlsEncrypt, on input these fragments contain the TLS > + header and plain text TLS APP payload; on output these > + fragments contain the TLS header and cipher text TLS > + APP payload. If CryptMode is EfiTlsDecrypt, on input > + these fragments contain the TLS header and cipher text > + TLS APP payload; on output these fragments contain the > + TLS header and plain text TLS APP payload. > + @param[in] FragmentCount Number of fragment. > + @param[in] CryptMode Crypt mode. > + > + @retval EFI_SUCCESS The operation completed successfully. > + @retval EFI_INVALID_PARAMETER One or more of the following > conditions is TRUE: > + This is NULL. > + FragmentTable is NULL. > + FragmentCount is NULL. > + CryptoMode is invalid. > + @retval EFI_NOT_READY Current TLS session state is NOT > + EfiTlsSessionDataTransferring. > + @retval EFI_ABORTED Something wrong decryption the message. > TLS session > + status will become EfiTlsSessionError. The caller need > + call BuildResponsePacket() to generate Error Alert > + message and send it out. > + @retval EFI_OUT_OF_RESOURCES No enough resource to finish the > operation. > +**/ > +EFI_STATUS > +EFIAPI > +TlsProcessPacket ( > + IN EFI_TLS_PROTOCOL *This, > + IN OUT EFI_TLS_FRAGMENT_DATA **FragmentTable, > + IN UINT32 *FragmentCount, > + IN EFI_TLS_CRYPT_MODE CryptMode > + ) > +{ > + EFI_STATUS Status; > + TLS_INSTANCE *Instance; > + > + EFI_TPL OldTpl; > + > + Status = EFI_SUCCESS; > + > + if (This == NULL || FragmentTable == NULL || FragmentCount == NULL) { > + return EFI_INVALID_PARAMETER; > + } > + > + OldTpl = gBS->RaiseTPL (TPL_CALLBACK); > + > + Instance = TLS_INSTANCE_FROM_PROTOCOL_THIS (This); > + > + if (Instance->TlsSessionState != EfiTlsSessionDataTransferring) { > + Status = EFI_NOT_READY; > + goto ON_EXIT; > + } > + > + // > + // Packet sent or received may have multiply TLS record > message(Application data type). > + // So,on input these fragments contain the TLS header and TLS APP > payload; > + // on output these fragments also contain the TLS header and TLS APP > payload. > + // > + switch (CryptMode) { > + case EfiTlsEncrypt: > + Status = TlsEcryptPacket (Instance, FragmentTable, FragmentCount); > + break; > + case EfiTlsDecrypt: > + Status = TlsDecryptPacket (Instance, FragmentTable, FragmentCount); > + break; > + default: > + return EFI_INVALID_PARAMETER; > + } > + > +ON_EXIT: > + gBS->RestoreTPL (OldTpl); > + return Status; > +} > -- > 1.9.5.msysgit.1 ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-12-16 7:30 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2016-12-15 7:22 [PATCH v2 05/10] NetworkPkg/TlsDxe: TlsDxe driver implementation over OpenSSL Jiaxin Wu 2016-12-16 6:16 ` Ye, Ting 2016-12-16 7:30 ` Wu, Jiaxin
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox