REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the SecurityPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Jian J Wang <jian.j.wang@intel.com>
		
			
				
	
	
		
			516 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			516 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   This library provides helper functions to set/clear Secure Boot
 | |
|   keys and databases.
 | |
| 
 | |
|   Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
 | |
|   (C) Copyright 2018 Hewlett Packard Enterprise Development LP<BR>
 | |
|   Copyright (c) 2021, ARM Ltd. All rights reserved.<BR>
 | |
|   Copyright (c) 2021, Semihalf All rights reserved.<BR>
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| **/
 | |
| #include <Guid/GlobalVariable.h>
 | |
| #include <Guid/AuthenticatedVariableFormat.h>
 | |
| #include <Guid/ImageAuthentication.h>
 | |
| #include <Library/BaseCryptLib.h>
 | |
| #include <Library/BaseLib.h>
 | |
| #include <Library/BaseMemoryLib.h>
 | |
| #include <Library/DebugLib.h>
 | |
| #include <Library/UefiLib.h>
 | |
| #include <Library/MemoryAllocationLib.h>
 | |
| #include <Library/UefiRuntimeServicesTableLib.h>
 | |
| #include <Library/SecureBootVariableLib.h>
 | |
| #include "Library/DxeServicesLib.h"
 | |
| 
 | |
| /** Creates EFI Signature List structure.
 | |
| 
 | |
|   @param[in]      Data     A pointer to signature data.
 | |
|   @param[in]      Size     Size of signature data.
 | |
|   @param[out]     SigList  Created Signature List.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           Signature List was created successfully.
 | |
|   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate memory.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| CreateSigList (
 | |
|   IN VOID                 *Data,
 | |
|   IN UINTN                Size,
 | |
|   OUT EFI_SIGNATURE_LIST  **SigList
 | |
|   )
 | |
| {
 | |
|   UINTN               SigListSize;
 | |
|   EFI_SIGNATURE_LIST  *TmpSigList;
 | |
|   EFI_SIGNATURE_DATA  *SigData;
 | |
| 
 | |
|   //
 | |
|   // Allocate data for Signature Database
 | |
|   //
 | |
|   SigListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Size;
 | |
|   TmpSigList  = (EFI_SIGNATURE_LIST *)AllocateZeroPool (SigListSize);
 | |
|   if (TmpSigList == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Only gEfiCertX509Guid type is supported
 | |
|   //
 | |
|   TmpSigList->SignatureListSize   = (UINT32)SigListSize;
 | |
|   TmpSigList->SignatureSize       = (UINT32)(sizeof (EFI_SIGNATURE_DATA) - 1 + Size);
 | |
|   TmpSigList->SignatureHeaderSize = 0;
 | |
|   CopyGuid (&TmpSigList->SignatureType, &gEfiCertX509Guid);
 | |
| 
 | |
|   //
 | |
|   // Copy key data
 | |
|   //
 | |
|   SigData = (EFI_SIGNATURE_DATA *)(TmpSigList + 1);
 | |
|   CopyGuid (&SigData->SignatureOwner, &gEfiGlobalVariableGuid);
 | |
|   CopyMem (&SigData->SignatureData[0], Data, Size);
 | |
| 
 | |
|   *SigList = TmpSigList;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /** Adds new signature list to signature database.
 | |
| 
 | |
|   @param[in]      SigLists        A pointer to signature database.
 | |
|   @param[in]      SigListAppend  A signature list to be added.
 | |
|   @param[out]     *SigListOut     Created signature database.
 | |
|   @param[in, out] SigListsSize    A size of created signature database.
 | |
| 
 | |
|   @retval  EFI_SUCCESS           Signature List was added successfully.
 | |
|   @retval  EFI_OUT_OF_RESOURCES  Failed to allocate memory.
 | |
| **/
 | |
| STATIC
 | |
| EFI_STATUS
 | |
| ConcatenateSigList (
 | |
|   IN  EFI_SIGNATURE_LIST  *SigLists,
 | |
|   IN  EFI_SIGNATURE_LIST  *SigListAppend,
 | |
|   OUT EFI_SIGNATURE_LIST  **SigListOut,
 | |
|   IN OUT UINTN            *SigListsSize
 | |
|   )
 | |
| {
 | |
|   EFI_SIGNATURE_LIST  *TmpSigList;
 | |
|   UINT8               *Offset;
 | |
|   UINTN               NewSigListsSize;
 | |
| 
 | |
|   NewSigListsSize = *SigListsSize + SigListAppend->SignatureListSize;
 | |
| 
 | |
|   TmpSigList = (EFI_SIGNATURE_LIST *)AllocateZeroPool (NewSigListsSize);
 | |
|   if (TmpSigList == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   CopyMem (TmpSigList, SigLists, *SigListsSize);
 | |
| 
 | |
|   Offset  = (UINT8 *)TmpSigList;
 | |
|   Offset += *SigListsSize;
 | |
|   CopyMem ((VOID *)Offset, SigListAppend, SigListAppend->SignatureListSize);
 | |
| 
 | |
|   *SigListsSize = NewSigListsSize;
 | |
|   *SigListOut   = TmpSigList;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create a EFI Signature List with data fetched from section specified as a argument.
 | |
|   Found keys are verified using RsaGetPublicKeyFromX509().
 | |
| 
 | |
|   @param[in]        KeyFileGuid    A pointer to to the FFS filename GUID
 | |
|   @param[out]       SigListsSize   A pointer to size of signature list
 | |
|   @param[out]       SigListOut    a pointer to a callee-allocated buffer with signature lists
 | |
| 
 | |
|   @retval EFI_SUCCESS              Create time based payload successfully.
 | |
|   @retval EFI_NOT_FOUND            Section with key has not been found.
 | |
|   @retval EFI_INVALID_PARAMETER    Embedded key has a wrong format.
 | |
|   @retval Others                   Unexpected error happens.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| SecureBootFetchData (
 | |
|   IN  EFI_GUID            *KeyFileGuid,
 | |
|   OUT UINTN               *SigListsSize,
 | |
|   OUT EFI_SIGNATURE_LIST  **SigListOut
 | |
|   )
 | |
| {
 | |
|   EFI_SIGNATURE_LIST  *EfiSig;
 | |
|   EFI_SIGNATURE_LIST  *TmpEfiSig;
 | |
|   EFI_SIGNATURE_LIST  *TmpEfiSig2;
 | |
|   EFI_STATUS          Status;
 | |
|   VOID                *Buffer;
 | |
|   VOID                *RsaPubKey;
 | |
|   UINTN               Size;
 | |
|   UINTN               KeyIndex;
 | |
| 
 | |
|   KeyIndex      = 0;
 | |
|   EfiSig        = NULL;
 | |
|   *SigListsSize = 0;
 | |
|   while (1) {
 | |
|     Status = GetSectionFromAnyFv (
 | |
|                KeyFileGuid,
 | |
|                EFI_SECTION_RAW,
 | |
|                KeyIndex,
 | |
|                &Buffer,
 | |
|                &Size
 | |
|                );
 | |
| 
 | |
|     if (Status == EFI_SUCCESS) {
 | |
|       RsaPubKey = NULL;
 | |
|       if (RsaGetPublicKeyFromX509 (Buffer, Size, &RsaPubKey) == FALSE) {
 | |
|         DEBUG ((DEBUG_ERROR, "%a: Invalid key format: %d\n", __FUNCTION__, KeyIndex));
 | |
|         if (EfiSig != NULL) {
 | |
|           FreePool (EfiSig);
 | |
|         }
 | |
| 
 | |
|         FreePool (Buffer);
 | |
|         return EFI_INVALID_PARAMETER;
 | |
|       }
 | |
| 
 | |
|       Status = CreateSigList (Buffer, Size, &TmpEfiSig);
 | |
| 
 | |
|       //
 | |
|       // Concatenate lists if more than one section found
 | |
|       //
 | |
|       if (KeyIndex == 0) {
 | |
|         EfiSig        = TmpEfiSig;
 | |
|         *SigListsSize = TmpEfiSig->SignatureListSize;
 | |
|       } else {
 | |
|         ConcatenateSigList (EfiSig, TmpEfiSig, &TmpEfiSig2, SigListsSize);
 | |
|         FreePool (EfiSig);
 | |
|         FreePool (TmpEfiSig);
 | |
|         EfiSig = TmpEfiSig2;
 | |
|       }
 | |
| 
 | |
|       KeyIndex++;
 | |
|       FreePool (Buffer);
 | |
|     }
 | |
| 
 | |
|     if (Status == EFI_NOT_FOUND) {
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (KeyIndex == 0) {
 | |
|     return EFI_NOT_FOUND;
 | |
|   }
 | |
| 
 | |
|   *SigListOut = EfiSig;
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2
 | |
|   descriptor with the input data. NO authentication is required in this function.
 | |
| 
 | |
|   @param[in, out]   DataSize       On input, the size of Data buffer in bytes.
 | |
|                                    On output, the size of data returned in Data
 | |
|                                    buffer in bytes.
 | |
|   @param[in, out]   Data           On input, Pointer to data buffer to be wrapped or
 | |
|                                    pointer to NULL to wrap an empty payload.
 | |
|                                    On output, Pointer to the new payload date buffer allocated from pool,
 | |
|                                    it's caller's responsibility to free the memory when finish using it.
 | |
| 
 | |
|   @retval EFI_SUCCESS              Create time based payload successfully.
 | |
|   @retval EFI_OUT_OF_RESOURCES     There are not enough memory resources to create time based payload.
 | |
|   @retval EFI_INVALID_PARAMETER    The parameter is invalid.
 | |
|   @retval Others                   Unexpected error happens.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| CreateTimeBasedPayload (
 | |
|   IN OUT UINTN  *DataSize,
 | |
|   IN OUT UINT8  **Data
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                     Status;
 | |
|   UINT8                          *NewData;
 | |
|   UINT8                          *Payload;
 | |
|   UINTN                          PayloadSize;
 | |
|   EFI_VARIABLE_AUTHENTICATION_2  *DescriptorData;
 | |
|   UINTN                          DescriptorSize;
 | |
|   EFI_TIME                       Time;
 | |
| 
 | |
|   if ((Data == NULL) || (DataSize == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // In Setup mode or Custom mode, the variable does not need to be signed but the
 | |
|   // parameters to the SetVariable() call still need to be prepared as authenticated
 | |
|   // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate
 | |
|   // data in it.
 | |
|   //
 | |
|   Payload     = *Data;
 | |
|   PayloadSize = *DataSize;
 | |
| 
 | |
|   DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
 | |
|   NewData        = (UINT8 *)AllocateZeroPool (DescriptorSize + PayloadSize);
 | |
|   if (NewData == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   if ((Payload != NULL) && (PayloadSize != 0)) {
 | |
|     CopyMem (NewData + DescriptorSize, Payload, PayloadSize);
 | |
|   }
 | |
| 
 | |
|   DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *)(NewData);
 | |
| 
 | |
|   ZeroMem (&Time, sizeof (EFI_TIME));
 | |
|   Status = gRT->GetTime (&Time, NULL);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     FreePool (NewData);
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Time.Pad1       = 0;
 | |
|   Time.Nanosecond = 0;
 | |
|   Time.TimeZone   = 0;
 | |
|   Time.Daylight   = 0;
 | |
|   Time.Pad2       = 0;
 | |
|   CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME));
 | |
| 
 | |
|   DescriptorData->AuthInfo.Hdr.dwLength         = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData);
 | |
|   DescriptorData->AuthInfo.Hdr.wRevision        = 0x0200;
 | |
|   DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
 | |
|   CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid);
 | |
| 
 | |
|   if (Payload != NULL) {
 | |
|     FreePool (Payload);
 | |
|   }
 | |
| 
 | |
|   *DataSize = DescriptorSize + PayloadSize;
 | |
|   *Data     = NewData;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Internal helper function to delete a Variable given its name and GUID, NO authentication
 | |
|   required.
 | |
| 
 | |
|   @param[in]      VariableName            Name of the Variable.
 | |
|   @param[in]      VendorGuid              GUID of the Variable.
 | |
| 
 | |
|   @retval EFI_SUCCESS              Variable deleted successfully.
 | |
|   @retval Others                   The driver failed to start the device.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| DeleteVariable (
 | |
|   IN  CHAR16    *VariableName,
 | |
|   IN  EFI_GUID  *VendorGuid
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
|   VOID        *Variable;
 | |
|   UINT8       *Data;
 | |
|   UINTN       DataSize;
 | |
|   UINT32      Attr;
 | |
| 
 | |
|   GetVariable2 (VariableName, VendorGuid, &Variable, NULL);
 | |
|   if (Variable == NULL) {
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   FreePool (Variable);
 | |
| 
 | |
|   Data     = NULL;
 | |
|   DataSize = 0;
 | |
|   Attr     = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
 | |
|              | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
 | |
| 
 | |
|   Status = CreateTimeBasedPayload (&DataSize, &Data);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = gRT->SetVariable (
 | |
|                   VariableName,
 | |
|                   VendorGuid,
 | |
|                   Attr,
 | |
|                   DataSize,
 | |
|                   Data
 | |
|                   );
 | |
|   if (Data != NULL) {
 | |
|     FreePool (Data);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
| 
 | |
|   Set the platform secure boot mode into "Custom" or "Standard" mode.
 | |
| 
 | |
|   @param[in]   SecureBootMode        New secure boot mode: STANDARD_SECURE_BOOT_MODE or
 | |
|                                      CUSTOM_SECURE_BOOT_MODE.
 | |
| 
 | |
|   @return EFI_SUCCESS                The platform has switched to the special mode successfully.
 | |
|   @return other                      Fail to operate the secure boot mode.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| SetSecureBootMode (
 | |
|   IN  UINT8  SecureBootMode
 | |
|   )
 | |
| {
 | |
|   return gRT->SetVariable (
 | |
|                 EFI_CUSTOM_MODE_NAME,
 | |
|                 &gEfiCustomModeEnableGuid,
 | |
|                 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
 | |
|                 sizeof (UINT8),
 | |
|                 &SecureBootMode
 | |
|                 );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Fetches the value of SetupMode variable.
 | |
| 
 | |
|   @param[out] SetupMode             Pointer to UINT8 for SetupMode output
 | |
| 
 | |
|   @retval other                     Retval from GetVariable.
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| GetSetupMode (
 | |
|   OUT UINT8  *SetupMode
 | |
|   )
 | |
| {
 | |
|   UINTN       Size;
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Size   = sizeof (*SetupMode);
 | |
|   Status = gRT->GetVariable (
 | |
|                   EFI_SETUP_MODE_NAME,
 | |
|                   &gEfiGlobalVariableGuid,
 | |
|                   NULL,
 | |
|                   &Size,
 | |
|                   SetupMode
 | |
|                   );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Clears the content of the 'db' variable.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES      If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
 | |
|                                     while VendorGuid is NULL.
 | |
|   @retval other                     Errors from GetVariable2 (), GetTime () and SetVariable ()
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| DeleteDb (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = DeleteVariable (
 | |
|              EFI_IMAGE_SECURITY_DATABASE,
 | |
|              &gEfiImageSecurityDatabaseGuid
 | |
|              );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Clears the content of the 'dbx' variable.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES      If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
 | |
|                                     while VendorGuid is NULL.
 | |
|   @retval other                     Errors from GetVariable2 (), GetTime () and SetVariable ()
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| DeleteDbx (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = DeleteVariable (
 | |
|              EFI_IMAGE_SECURITY_DATABASE1,
 | |
|              &gEfiImageSecurityDatabaseGuid
 | |
|              );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Clears the content of the 'dbt' variable.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES      If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
 | |
|                                     while VendorGuid is NULL.
 | |
|   @retval other                     Errors from GetVariable2 (), GetTime () and SetVariable ()
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| DeleteDbt (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = DeleteVariable (
 | |
|              EFI_IMAGE_SECURITY_DATABASE2,
 | |
|              &gEfiImageSecurityDatabaseGuid
 | |
|              );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Clears the content of the 'KEK' variable.
 | |
| 
 | |
|   @retval EFI_OUT_OF_RESOURCES      If memory allocation for EFI_VARIABLE_AUTHENTICATION_2 fails
 | |
|                                     while VendorGuid is NULL.
 | |
|   @retval other                     Errors from GetVariable2 (), GetTime () and SetVariable ()
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| DeleteKEK (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = DeleteVariable (
 | |
|              EFI_KEY_EXCHANGE_KEY_NAME,
 | |
|              &gEfiGlobalVariableGuid
 | |
|              );
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Remove the PK variable.
 | |
| 
 | |
|   @retval EFI_SUCCESS    Delete PK successfully.
 | |
|   @retval Others         Could not allow to delete PK.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| EFIAPI
 | |
| DeletePlatformKey (
 | |
|   VOID
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS  Status;
 | |
| 
 | |
|   Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE);
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   Status = DeleteVariable (
 | |
|              EFI_PLATFORM_KEY_NAME,
 | |
|              &gEfiGlobalVariableGuid
 | |
|              );
 | |
|   return Status;
 | |
| }
 |