Files
system76-edk2/SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.c
Grzegorz Bernacki 9732659698 SecurityPkg: Create library for enrolling Secure Boot variables.
This commits add library, which consist functions to
enrolll Secure Boot keys and initialize Secure Boot
default variables. Some of the functions was moved
 from SecureBootConfigImpl.c file.

Signed-off-by: Grzegorz Bernacki <gjb@semihalf.com>
Reviewed-by: Sunny Wang <sunny.wang@arm.com>
Reviewed-by: Jiewen Yao <Jiewen.yao@intel.com>
2021-08-03 07:26:41 +00:00

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;
}