audk/SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvision...

483 lines
14 KiB
C

/** @file
This library provides 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/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/SecureBootVariableProvisionLib.h>
/**
Enroll a key/certificate based on a default variable.
@param[in] VariableName The name of the key/database.
@param[in] DefaultName The name of the default variable.
@param[in] VendorGuid The namespace (ie. vendor GUID) of the variable
@retval EFI_OUT_OF_RESOURCES Out of memory while allocating AuthHeader.
@retval EFI_SUCCESS Successful enrollment.
@return Error codes from GetTime () and SetVariable ().
**/
STATIC
EFI_STATUS
EnrollFromDefault (
IN CHAR16 *VariableName,
IN CHAR16 *DefaultName,
IN EFI_GUID *VendorGuid
)
{
VOID *Data;
UINTN DataSize;
EFI_STATUS Status;
Status = EFI_SUCCESS;
DataSize = 0;
Status = GetVariable2 (DefaultName, &gEfiGlobalVariableGuid, &Data, &DataSize);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "error: GetVariable (\"%s): %r\n", DefaultName, Status));
return Status;
}
CreateTimeBasedPayload (&DataSize, (UINT8 **)&Data);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status));
return Status;
}
//
// Allocate memory for auth variable
//
Status = gRT->SetVariable (
VariableName,
VendorGuid,
(EFI_VARIABLE_NON_VOLATILE |
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS |
EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS),
DataSize,
Data
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "error: %a (\"%s\", %g): %r\n", __FUNCTION__, VariableName,
VendorGuid, Status));
}
if (Data != NULL) {
FreePool (Data);
}
return Status;
}
/** Initializes PKDefault variable with data from FFS section.
@retval EFI_SUCCESS Variable was initialized successfully.
@retval EFI_UNSUPPORTED Variable already exists.
**/
EFI_STATUS
SecureBootInitPKDefault (
IN VOID
)
{
EFI_SIGNATURE_LIST *EfiSig;
UINTN SigListsSize;
EFI_STATUS Status;
UINT8 *Data;
UINTN DataSize;
//
// Check if variable exists, if so do not change it
//
Status = GetVariable2 (EFI_PK_DEFAULT_VARIABLE_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize);
if (Status == EFI_SUCCESS) {
DEBUG ((DEBUG_INFO, "Variable %s exists. Old value is preserved\n", EFI_PK_DEFAULT_VARIABLE_NAME));
FreePool (Data);
return EFI_UNSUPPORTED;
}
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
return Status;
}
//
// Variable does not exist, can be initialized
//
DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_PK_DEFAULT_VARIABLE_NAME));
Status = SecureBootFetchData (&gDefaultPKFileGuid, &SigListsSize, &EfiSig);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Content for %s not found\n", EFI_PK_DEFAULT_VARIABLE_NAME));
return Status;
}
Status = gRT->SetVariable (
EFI_PK_DEFAULT_VARIABLE_NAME,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
SigListsSize,
(VOID *)EfiSig
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Failed to set %s\n", EFI_PK_DEFAULT_VARIABLE_NAME));
}
FreePool (EfiSig);
return Status;
}
/** Initializes KEKDefault variable with data from FFS section.
@retval EFI_SUCCESS Variable was initialized successfully.
@retval EFI_UNSUPPORTED Variable already exists.
**/
EFI_STATUS
SecureBootInitKEKDefault (
IN VOID
)
{
EFI_SIGNATURE_LIST *EfiSig;
UINTN SigListsSize;
EFI_STATUS Status;
UINT8 *Data;
UINTN DataSize;
//
// Check if variable exists, if so do not change it
//
Status = GetVariable2 (EFI_KEK_DEFAULT_VARIABLE_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize);
if (Status == EFI_SUCCESS) {
DEBUG ((DEBUG_INFO, "Variable %s exists. Old value is preserved\n", EFI_KEK_DEFAULT_VARIABLE_NAME));
FreePool (Data);
return EFI_UNSUPPORTED;
}
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
return Status;
}
//
// Variable does not exist, can be initialized
//
DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_KEK_DEFAULT_VARIABLE_NAME));
Status = SecureBootFetchData (&gDefaultKEKFileGuid, &SigListsSize, &EfiSig);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Content for %s not found\n", EFI_KEK_DEFAULT_VARIABLE_NAME));
return Status;
}
Status = gRT->SetVariable (
EFI_KEK_DEFAULT_VARIABLE_NAME,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
SigListsSize,
(VOID *)EfiSig
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Failed to set %s\n", EFI_KEK_DEFAULT_VARIABLE_NAME));
}
FreePool (EfiSig);
return Status;
}
/** Initializes dbDefault variable with data from FFS section.
@retval EFI_SUCCESS Variable was initialized successfully.
@retval EFI_UNSUPPORTED Variable already exists.
**/
EFI_STATUS
SecureBootInitDbDefault (
IN VOID
)
{
EFI_SIGNATURE_LIST *EfiSig;
UINTN SigListsSize;
EFI_STATUS Status;
UINT8 *Data;
UINTN DataSize;
Status = GetVariable2 (EFI_DB_DEFAULT_VARIABLE_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize);
if (Status == EFI_SUCCESS) {
DEBUG ((DEBUG_INFO, "Variable %s exists. Old value is preserved\n", EFI_DB_DEFAULT_VARIABLE_NAME));
FreePool (Data);
return EFI_UNSUPPORTED;
}
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
return Status;
}
DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_DB_DEFAULT_VARIABLE_NAME));
Status = SecureBootFetchData (&gDefaultdbFileGuid, &SigListsSize, &EfiSig);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gRT->SetVariable (
EFI_DB_DEFAULT_VARIABLE_NAME,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
SigListsSize,
(VOID *)EfiSig
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Failed to set %s\n", EFI_DB_DEFAULT_VARIABLE_NAME));
}
FreePool (EfiSig);
return Status;
}
/** Initializes dbxDefault variable with data from FFS section.
@retval EFI_SUCCESS Variable was initialized successfully.
@retval EFI_UNSUPPORTED Variable already exists.
**/
EFI_STATUS
SecureBootInitDbxDefault (
IN VOID
)
{
EFI_SIGNATURE_LIST *EfiSig;
UINTN SigListsSize;
EFI_STATUS Status;
UINT8 *Data;
UINTN DataSize;
//
// Check if variable exists, if so do not change it
//
Status = GetVariable2 (EFI_DBX_DEFAULT_VARIABLE_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize);
if (Status == EFI_SUCCESS) {
DEBUG ((DEBUG_INFO, "Variable %s exists. Old value is preserved\n", EFI_DBX_DEFAULT_VARIABLE_NAME));
FreePool (Data);
return EFI_UNSUPPORTED;
}
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
return Status;
}
//
// Variable does not exist, can be initialized
//
DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_DBX_DEFAULT_VARIABLE_NAME));
Status = SecureBootFetchData (&gDefaultdbxFileGuid, &SigListsSize, &EfiSig);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Content for %s not found\n", EFI_DBX_DEFAULT_VARIABLE_NAME));
return Status;
}
Status = gRT->SetVariable (
EFI_DBX_DEFAULT_VARIABLE_NAME,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
SigListsSize,
(VOID *)EfiSig
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Failed to set %s\n", EFI_DBX_DEFAULT_VARIABLE_NAME));
}
FreePool (EfiSig);
return Status;
}
/** Initializes dbtDefault variable with data from FFS section.
@retval EFI_SUCCESS Variable was initialized successfully.
@retval EFI_UNSUPPORTED Variable already exists.
**/
EFI_STATUS
SecureBootInitDbtDefault (
IN VOID
)
{
EFI_SIGNATURE_LIST *EfiSig;
UINTN SigListsSize;
EFI_STATUS Status;
UINT8 *Data;
UINTN DataSize;
//
// Check if variable exists, if so do not change it
//
Status = GetVariable2 (EFI_DBT_DEFAULT_VARIABLE_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize);
if (Status == EFI_SUCCESS) {
DEBUG ((DEBUG_INFO, "Variable %s exists. Old value is preserved\n", EFI_DBT_DEFAULT_VARIABLE_NAME));
FreePool (Data);
return EFI_UNSUPPORTED;
}
if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
return Status;
}
//
// Variable does not exist, can be initialized
//
DEBUG ((DEBUG_INFO, "Variable %s does not exist.\n", EFI_DBT_DEFAULT_VARIABLE_NAME));
Status = SecureBootFetchData (&gDefaultdbtFileGuid, &SigListsSize, &EfiSig);
if (EFI_ERROR (Status)) {
return Status;
}
Status = gRT->SetVariable (
EFI_DBT_DEFAULT_VARIABLE_NAME,
&gEfiGlobalVariableGuid,
EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS,
SigListsSize,
(VOID *)EfiSig
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_INFO, "Failed to set %s\n", EFI_DBT_DEFAULT_VARIABLE_NAME));
}
FreePool (EfiSig);
return EFI_SUCCESS;
}
/**
Sets the content of the 'db' variable based on 'dbDefault' variable content.
@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
EnrollDbFromDefault (
VOID
)
{
EFI_STATUS Status;
Status = EnrollFromDefault (
EFI_IMAGE_SECURITY_DATABASE,
EFI_DB_DEFAULT_VARIABLE_NAME,
&gEfiImageSecurityDatabaseGuid
);
return Status;
}
/**
Sets the content of the 'dbx' variable based on 'dbxDefault' variable content.
@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
EnrollDbxFromDefault (
VOID
)
{
EFI_STATUS Status;
Status = EnrollFromDefault (
EFI_IMAGE_SECURITY_DATABASE1,
EFI_DBX_DEFAULT_VARIABLE_NAME,
&gEfiImageSecurityDatabaseGuid
);
return Status;
}
/**
Sets the content of the 'dbt' variable based on 'dbtDefault' variable content.
@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
EnrollDbtFromDefault (
VOID
)
{
EFI_STATUS Status;
Status = EnrollFromDefault (
EFI_IMAGE_SECURITY_DATABASE2,
EFI_DBT_DEFAULT_VARIABLE_NAME,
&gEfiImageSecurityDatabaseGuid);
return Status;
}
/**
Sets the content of the 'KEK' variable based on 'KEKDefault' variable content.
@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
EnrollKEKFromDefault (
VOID
)
{
EFI_STATUS Status;
Status = EnrollFromDefault (
EFI_KEY_EXCHANGE_KEY_NAME,
EFI_KEK_DEFAULT_VARIABLE_NAME,
&gEfiGlobalVariableGuid
);
return Status;
}
/**
Sets the content of the 'KEK' variable based on 'KEKDefault' variable content.
@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
EnrollPKFromDefault (
VOID
)
{
EFI_STATUS Status;
Status = EnrollFromDefault (
EFI_PLATFORM_KEY_NAME,
EFI_PK_DEFAULT_VARIABLE_NAME,
&gEfiGlobalVariableGuid
);
return Status;
}