| /** @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; |
| } |