diff options
Diffstat (limited to 'NetworkPkg/TlsDxe/TlsDriver.c')
-rw-r--r-- | NetworkPkg/TlsDxe/TlsDriver.c | 496 |
1 files changed, 496 insertions, 0 deletions
diff --git a/NetworkPkg/TlsDxe/TlsDriver.c b/NetworkPkg/TlsDxe/TlsDriver.c new file mode 100644 index 0000000..38bf599 --- /dev/null +++ b/NetworkPkg/TlsDxe/TlsDriver.c @@ -0,0 +1,496 @@ +/** @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 + ) +{ + TLS_SERVICE *TlsService; + + ASSERT (Service != NULL); + + *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 EFI_SUCCESS; +} + +/** + 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 (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; +} |