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