Reviewed-by: Fu Siyuan <[email protected]>
> -----Original Message----- > From: Wu, Jiaxin > Sent: Wednesday, February 24, 2016 4:15 PM > To: [email protected] > Cc: Ye, Ting <[email protected]>; Fu, Siyuan <[email protected]>; Long, > Qin <[email protected]> > Subject: [Patch 4/6] NetworkPkg: TlsDxe driver implementation over OpenSSL > > This patch is the implementation of EFI TLS Protocol > and EFI TLS Configuration Protocol Interfaces. > > Cc: Ye Ting <[email protected]> > Cc: Fu Siyuan <[email protected]> > Cc: Long Qin <[email protected]> > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Jiaxin Wu <[email protected]> > --- > NetworkPkg/NetworkPkg.dsc | 3 + > NetworkPkg/TlsDxe/TlsConfigProtocol.c | 152 +++++++++ > NetworkPkg/TlsDxe/TlsDriver.c | 499 +++++++++++++++++++++++++++ > NetworkPkg/TlsDxe/TlsDriver.h | 237 +++++++++++++ > NetworkPkg/TlsDxe/TlsDxe.inf | 67 ++++ > NetworkPkg/TlsDxe/TlsDxe.uni | 25 ++ > NetworkPkg/TlsDxe/TlsDxeExtra.uni | 20 ++ > NetworkPkg/TlsDxe/TlsImpl.c | 280 +++++++++++++++ > NetworkPkg/TlsDxe/TlsImpl.h | 342 +++++++++++++++++++ > NetworkPkg/TlsDxe/TlsProtocol.c | 627 > ++++++++++++++++++++++++++++++++++ > 10 files changed, 2252 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/NetworkPkg.dsc b/NetworkPkg/NetworkPkg.dsc > index 0695dc1..2712a6a 100644 > --- a/NetworkPkg/NetworkPkg.dsc > +++ b/NetworkPkg/NetworkPkg.dsc > @@ -47,10 +47,12 @@ > TcpIoLib|MdeModulePkg/Library/DxeTcpIoLib/DxeTcpIoLib.inf > HttpLib|MdeModulePkg/Library/DxeHttpLib/DxeHttpLib.inf > BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf > OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf > IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf > + OpensslTlsLib|CryptoPkg/Library/OpensslLib/OpensslTlsLib.inf > + TlsLib|CryptoPkg/Library/TlsLib/TlsLib.inf > > DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/Base > DebugPrintErrorLevelLib.inf > FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf > SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf > > [LibraryClasses.common.UEFI_DRIVER] > @@ -103,10 +105,11 @@ > NetworkPkg/Mtftp6Dxe/Mtftp6Dxe.inf > NetworkPkg/DnsDxe/DnsDxe.inf > NetworkPkg/HttpDxe/HttpDxe.inf > NetworkPkg/HttpUtilitiesDxe/HttpUtilitiesDxe.inf > NetworkPkg/HttpBootDxe/HttpBootDxe.inf > + NetworkPkg/TlsDxe/TlsDxe.inf > > NetworkPkg/Application/IfConfig6/IfConfig6.inf > NetworkPkg/Application/IpsecConfig/IpSecConfig.inf > NetworkPkg/Application/VConfig/VConfig.inf > > diff --git a/NetworkPkg/TlsDxe/TlsConfigProtocol.c > b/NetworkPkg/TlsDxe/TlsConfigProtocol.c > new file mode 100644 > index 0000000..2855be1 > --- /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..d7d0cd3 > --- /dev/null > +++ b/NetworkPkg/TlsDxe/TlsDriver.c > @@ -0,0 +1,499 @@ > +/** @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 > availabe 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..cf767fb > --- /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 > availabe 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..9c5864e > --- /dev/null > +++ b/NetworkPkg/TlsDxe/TlsDxe.inf > @@ -0,0 +1,67 @@ > +## @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..48677d4 > --- /dev/null > +++ b/NetworkPkg/TlsDxe/TlsDxeExtra.uni > @@ -0,0 +1,20 @@ > +// /** @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..8cb1c15 > --- /dev/null > +++ b/NetworkPkg/TlsDxe/TlsImpl.c > @@ -0,0 +1,280 @@ > +/** @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 > + cypher 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 > + ) > +{ > + UINTN Index; > + UINT32 BytesCopied; > + UINT32 BufferInSize; > + UINT8 *BufferIn; > + UINT8 *BufferInPtr; > + TLSRecordHeader *RecordHeaderIn; > + UINT16 ThisPlainMessageSize; > + TLSRecordHeader *TempRecordHeader; > + UINT16 ThisMessageSize; > + UINT32 BufferOutSize; > + UINT8 *BufferOut; > + INTN Ret; > + > + BytesCopied = 0; > + BufferInSize = 0; > + BufferIn = NULL; > + BufferInPtr = NULL; > + RecordHeaderIn = NULL; > + TempRecordHeader = NULL; > + BufferOutSize = 0; > + BufferOut = NULL; > + Ret = 0; > + > + // > + // Calculate the size accroding 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) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // 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) { > + FreePool (BufferIn); > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Parsing buffer. > + // > + BufferInPtr = BufferIn; > + TempRecordHeader = (TLSRecordHeader *) BufferOut; > + while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { > + RecordHeaderIn = (TLSRecordHeader *) BufferInPtr; > + ASSERT (RecordHeaderIn->ContentType == > TLS_CONTENT_TYPE_APPLICATION_DATA); > + ThisPlainMessageSize = RecordHeaderIn->Length; > + > + TlsWrite (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn + 1), > ThisPlainMessageSize); > + if (TlsInStateError (TlsInstance->TlsConn)) { > + FreePool (BufferIn); > + TlsInstance->TlsSessionState = EfiTlsSessionError; > + return EFI_ABORTED; > + } > + > + Ret = TlsCtrlTrafficOut (TlsInstance->TlsConn, (UINT8 > *)(TempRecordHeader), MAX_BUFFER_SIZE); > + > + if (Ret > 0) { > + ThisMessageSize = (UINT16) Ret; > + } else { > + ThisMessageSize = 0; > + } > + > + BufferOutSize += ThisMessageSize; > + > + BufferInPtr += RECORD_HEADER_LEN + ThisPlainMessageSize; > + TempRecordHeader += ThisMessageSize; > + } > + > + FreePool (BufferIn); > + > + // > + // The caller will take responsible to handle the original fragment table. > + // > + *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA)); > + if (*FragmentTable == NULL) { > + FreePool (BufferOut); > + return EFI_OUT_OF_RESOURCES; > + } > + > + (*FragmentTable)[0].FragmentBuffer = BufferOut; > + (*FragmentTable)[0].FragmentLength = BufferOutSize; > + *FragmentCount = 1; > + > + return EFI_SUCCESS; > +} > + > +/** > + 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 > + cypher 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 > + ) > +{ > + UINTN Index; > + UINT32 BytesCopied; > + UINT8 *BufferIn; > + UINT32 BufferInSize; > + UINT8 *BufferInPtr; > + TLSRecordHeader *RecordHeaderIn; > + UINT16 ThisCipherMessageSize; > + TLSRecordHeader *TempRecordHeader; > + UINT16 ThisPlainMessageSize; > + UINT8 *BufferOut; > + UINT32 BufferOutSize; > + INTN Ret; > + > + BytesCopied = 0; > + BufferIn = NULL; > + BufferInSize = 0; > + BufferInPtr = NULL; > + RecordHeaderIn = NULL; > + TempRecordHeader = NULL; > + BufferOut = NULL; > + BufferOutSize = 0; > + Ret = 0; > + > + // > + // Calculate the size accroding 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) { > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // 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) { > + FreePool (BufferIn); > + return EFI_OUT_OF_RESOURCES; > + } > + > + // > + // Parsing buffer. Received packet may have multiply TLS record message. > + // > + BufferInPtr = BufferIn; > + TempRecordHeader = (TLSRecordHeader *) BufferOut; > + while ((UINTN) BufferInPtr < (UINTN) BufferIn + BufferInSize) { > + RecordHeaderIn = (TLSRecordHeader *) BufferInPtr; > + ASSERT (RecordHeaderIn->ContentType == > TLS_CONTENT_TYPE_APPLICATION_DATA); > + ThisCipherMessageSize = NTOHS (RecordHeaderIn->Length); > + > + Ret = TlsCtrlTrafficIn (TlsInstance->TlsConn, (UINT8 *) (RecordHeaderIn), > RECORD_HEADER_LEN + ThisCipherMessageSize); > + if (Ret != RECORD_HEADER_LEN + ThisCipherMessageSize) { > + FreePool (BufferIn); > + TlsInstance->TlsSessionState = EfiTlsSessionError; > + return EFI_ABORTED; > + } > + > + Ret = 0; > + Ret = TlsRead (TlsInstance->TlsConn, (UINT8 *) (TempRecordHeader + 1), > MAX_BUFFER_SIZE); > + if (TlsInStateError (TlsInstance->TlsConn)) { > + FreePool (BufferIn); > + TlsInstance->TlsSessionState = EfiTlsSessionError; > + return EFI_ABORTED; > + } > + > + if (Ret > 0) { > + ThisPlainMessageSize = (UINT16) Ret; > + } else { > + 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); > + > + // > + // The caller will take responsible to handle the original fragment table > + // > + *FragmentTable = AllocateZeroPool (sizeof (EFI_TLS_FRAGMENT_DATA)); > + if (*FragmentTable == NULL) { > + FreePool (BufferOut); > + return EFI_OUT_OF_RESOURCES; > + } > + > + (*FragmentTable)[0].FragmentBuffer = BufferOut; > + (*FragmentTable)[0].FragmentLength = BufferOutSize; > + *FragmentCount = 1; > + > + return EFI_SUCCESS; > +} > diff --git a/NetworkPkg/TlsDxe/TlsImpl.h b/NetworkPkg/TlsDxe/TlsImpl.h > new file mode 100644 > index 0000000..9eee6e7 > --- /dev/null > +++ b/NetworkPkg/TlsDxe/TlsImpl.h > @@ -0,0 +1,342 @@ > +/** @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 "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 16384 /// 2^14 > + > +#pragma pack (push, 1) > + > +//TLS Version > +#define TLS10_PROTOCOL_VERSION_MAJOR 0x03 > +#define TLS10_PROTOCOL_VERSION_MINOR 0x01 > +#define TLS11_PROTOCOL_VERSION_MAJOR 0x03 > +#define TLS11_PROTOCOL_VERSION_MINOR 0x02 > +#define TLS12_PROTOCOL_VERSION_MAJOR 0x03 > +#define TLS12_PROTOCOL_VERSION_MINOR 0x03 > + > +// > +//Content Type > +// > +typedef enum { > + TLS_CONTENT_TYPE_CHANGE_CIPHER_SPEC = 20, > + TLS_CONTENT_TYPE_ALERT = 21, > + TLS_CONTENT_TYPE_HANDSHAKE = 22, > + TLS_CONTENT_TYPE_APPLICATION_DATA = 23, > +} TLS_CONTENT_TYPE; > + > +typedef struct { > + UINT8 ContentType; > + EFI_TLS_VERSION Version; > + UINT16 Length; > +} TLSRecordHeader; > + > +#pragma pack (pop) > + > +/** > + 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 > + cypher 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 > + cypher 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 > cypher text TLS > + APP payload. If CryptMode is > EfiTlsDecrypt, on input > + these fragments contain the TLS header and > cypher 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..92cd472 > --- /dev/null > +++ b/NetworkPkg/TlsDxe/TlsProtocol.c > @@ -0,0 +1,627 @@ > +/** @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 || TlsInStateError (Instance->TlsConn)) { > + 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; > + } > + > + if (TlsInStateError (Instance->TlsConn)) { > + Instance->TlsSessionState = EfiTlsSessionError; > + } > + } else { > + // > + // Must be alert message, Decrypt it and build the ResponsePacket. > + // > + ASSERT (((TLSRecordHeader *) 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 > cypher text TLS > + APP payload. If CryptMode is > EfiTlsDecrypt, on input > + these fragments contain the TLS header and > cypher 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 _______________________________________________ edk2-devel mailing list [email protected] https://lists.01.org/mailman/listinfo/edk2-devel

