Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Hao Wu <hao.a.wu@intel.com> Reviewed-by: Siyuan Fu <siyuan.fu@intel.com> Reviewed-by: Jiaxin Wu <jiaxin.wu@intel.com>
		
			
				
	
	
		
			498 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			498 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @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;
 | 
						|
}
 | 
						|
 |