mirror of
https://github.com/acidanthera/audk.git
synced 2025-04-08 17:05:09 +02:00
SecurityPkg: SecureBootVariableLib: Added newly supported interfaces
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3911 This change updated the interfaces provided by SecureBootVariableLib. The new additions provided interfaces to enroll single authenticated variable from input, a helper function to query secure boot status, enroll all secure boot variables from UefiSecureBoot.h defined data structures, a as well as a routine that deletes all secure boot related variables. Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Min Xu <min.m.xu@intel.com> Signed-off-by: Kun Qin <kun.qin@microsoft.com> Reviewed-by: Jiewen Yao <Jiewen.yao@intel.com> Acked-by: Michael Kubacki <michael.kubacki@microsoft.com>
This commit is contained in:
parent
6de7c084db
commit
6eb4079475
SecurityPkg
Include/Library
Library/SecureBootVariableLib
@ -43,6 +43,19 @@ GetSetupMode (
|
||||
OUT UINT8 *SetupMode
|
||||
);
|
||||
|
||||
/**
|
||||
Helper function to quickly determine whether SecureBoot is enabled.
|
||||
|
||||
@retval TRUE SecureBoot is verifiably enabled.
|
||||
@retval FALSE SecureBoot is either disabled or an error prevented checking.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
IsSecureBootEnabled (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
Create a EFI Signature List with data supplied from input argument.
|
||||
The input certificates from KeyInfo parameter should be DER-encoded
|
||||
@ -161,4 +174,60 @@ DeletePlatformKey (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
This function will delete the secure boot keys, thus
|
||||
disabling secure boot.
|
||||
|
||||
@return EFI_SUCCESS or underlying failure code.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DeleteSecureBootVariables (
|
||||
VOID
|
||||
);
|
||||
|
||||
/**
|
||||
A helper function to take in a variable payload, wrap it in the
|
||||
proper authenticated variable structure, and install it in the
|
||||
EFI variable space.
|
||||
|
||||
@param[in] VariableName The name of the key/database.
|
||||
@param[in] VendorGuid The namespace (ie. vendor GUID) of the variable
|
||||
@param[in] DataSize Size parameter for target secure boot variable.
|
||||
@param[in] Data Pointer to signature list formatted secure boot variable content.
|
||||
|
||||
@retval EFI_SUCCESS The enrollment for authenticated variable was successful.
|
||||
@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
|
||||
EFIAPI
|
||||
EnrollFromInput (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN UINTN DataSize,
|
||||
IN VOID *Data
|
||||
);
|
||||
|
||||
/**
|
||||
Similar to DeleteSecureBootVariables, this function is used to unilaterally
|
||||
force the state of related SB variables (db, dbx, dbt, KEK, PK, etc.) to be
|
||||
the built-in, hardcoded default vars.
|
||||
|
||||
@param[in] SecureBootPayload Payload information for secure boot related keys.
|
||||
|
||||
@retval EFI_SUCCESS SecureBoot keys are now set to defaults.
|
||||
@retval EFI_ABORTED SecureBoot keys are not empty. Please delete keys first
|
||||
or follow standard methods of altering keys (ie. use the signing system).
|
||||
@retval EFI_SECURITY_VIOLATION Failed to create the PK.
|
||||
@retval Others Something failed in one of the subfunctions.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SetSecureBootVariablesToDefault (
|
||||
IN CONST SECURE_BOOT_PAYLOAD_INFO *SecureBootPayload
|
||||
);
|
||||
|
||||
#endif
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiRuntimeServicesTableLib.h>
|
||||
#include <Library/SecureBootVariableLib.h>
|
||||
#include <Library/PlatformPKProtectionLib.h>
|
||||
|
||||
// This time can be used when deleting variables, as it should be greater than any variable time.
|
||||
EFI_TIME mMaxTimestamp = {
|
||||
@ -37,6 +38,24 @@ EFI_TIME mMaxTimestamp = {
|
||||
0x00
|
||||
};
|
||||
|
||||
//
|
||||
// This epoch time is the date that is used when creating SecureBoot default variables.
|
||||
// NOTE: This is a placeholder date that doesn't correspond to anything else.
|
||||
//
|
||||
EFI_TIME mDefaultPayloadTimestamp = {
|
||||
1970, // Year (1970)
|
||||
1, // Month (Jan)
|
||||
1, // Day (1)
|
||||
0, // Hour
|
||||
0, // Minute
|
||||
0, // Second
|
||||
0, // Pad1
|
||||
0, // Nanosecond
|
||||
0, // Timezone (Dummy value)
|
||||
0, // Daylight (Dummy value)
|
||||
0 // Pad2
|
||||
};
|
||||
|
||||
/** Creates EFI Signature List structure.
|
||||
|
||||
@param[in] Data A pointer to signature data.
|
||||
@ -413,6 +432,44 @@ GetSetupMode (
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Helper function to quickly determine whether SecureBoot is enabled.
|
||||
|
||||
@retval TRUE SecureBoot is verifiably enabled.
|
||||
@retval FALSE SecureBoot is either disabled or an error prevented checking.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
IsSecureBootEnabled (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 *SecureBoot;
|
||||
|
||||
SecureBoot = NULL;
|
||||
|
||||
Status = GetEfiGlobalVariable2 (EFI_SECURE_BOOT_MODE_NAME, (VOID **)&SecureBoot, NULL);
|
||||
//
|
||||
// Skip verification if SecureBoot variable doesn't exist.
|
||||
//
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "Cannot check SecureBoot variable %r \n ", Status));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Skip verification if SecureBoot is disabled but not AuditMode
|
||||
//
|
||||
if (*SecureBoot == SECURE_BOOT_MODE_DISABLE) {
|
||||
FreePool (SecureBoot);
|
||||
return FALSE;
|
||||
} else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Clears the content of the 'db' variable.
|
||||
|
||||
@ -531,3 +588,311 @@ DeletePlatformKey (
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function will delete the secure boot keys, thus
|
||||
disabling secure boot.
|
||||
|
||||
@return EFI_SUCCESS or underlying failure code.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DeleteSecureBootVariables (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status, TempStatus;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a - Attempting to delete the Secure Boot variables.\n", __FUNCTION__));
|
||||
|
||||
//
|
||||
// Step 1: Notify that a PK update is coming shortly...
|
||||
Status = DisablePKProtection ();
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a - Failed to signal PK update start! %r\n", __FUNCTION__, Status));
|
||||
// Classify this as a PK deletion error.
|
||||
Status = EFI_ABORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Step 2: Attempt to delete the PK.
|
||||
// Let's try to nuke the PK, why not...
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = DeletePlatformKey ();
|
||||
DEBUG ((DEBUG_INFO, "%a - PK Delete = %r\n", __FUNCTION__, Status));
|
||||
// If the PK is not found, then our work here is done.
|
||||
if (Status == EFI_NOT_FOUND) {
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
// If any other error occurred, let's inform the caller that the PK delete in particular failed.
|
||||
else if (EFI_ERROR (Status)) {
|
||||
Status = EFI_ABORTED;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Step 3: Attempt to delete remaining keys/databases...
|
||||
// Now that the PK is deleted (assuming Status == EFI_SUCCESS) the system is in SETUP_MODE.
|
||||
// Arguably we could leave these variables in place and let them be deleted by whoever wants to
|
||||
// update all the SecureBoot variables. However, for cleanliness sake, let's try to
|
||||
// get rid of them here.
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// If any of THESE steps have an error, report the error but attempt to delete all keys.
|
||||
// Using TempStatus will prevent an error from being trampled by an EFI_SUCCESS.
|
||||
// Overwrite Status ONLY if TempStatus is an error.
|
||||
//
|
||||
// If the error is EFI_NOT_FOUND, we can safely ignore it since we were trying to delete
|
||||
// the variables anyway.
|
||||
//
|
||||
TempStatus = DeleteKEK ();
|
||||
DEBUG ((DEBUG_INFO, "%a - KEK Delete = %r\n", __FUNCTION__, TempStatus));
|
||||
if (EFI_ERROR (TempStatus) && (TempStatus != EFI_NOT_FOUND)) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
TempStatus = DeleteDb ();
|
||||
DEBUG ((DEBUG_INFO, "%a - db Delete = %r\n", __FUNCTION__, TempStatus));
|
||||
if (EFI_ERROR (TempStatus) && (TempStatus != EFI_NOT_FOUND)) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
TempStatus = DeleteDbx ();
|
||||
DEBUG ((DEBUG_INFO, "%a - dbx Delete = %r\n", __FUNCTION__, TempStatus));
|
||||
if (EFI_ERROR (TempStatus) && (TempStatus != EFI_NOT_FOUND)) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
TempStatus = DeleteDbt ();
|
||||
DEBUG ((DEBUG_INFO, "%a - dbt Delete = %r\n", __FUNCTION__, TempStatus));
|
||||
if (EFI_ERROR (TempStatus) && (TempStatus != EFI_NOT_FOUND)) {
|
||||
Status = EFI_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}// DeleteSecureBootVariables()
|
||||
|
||||
/**
|
||||
A helper function to take in a variable payload, wrap it in the
|
||||
proper authenticated variable structure, and install it in the
|
||||
EFI variable space.
|
||||
|
||||
@param[in] VariableName The name of the key/database.
|
||||
@param[in] VendorGuid The namespace (ie. vendor GUID) of the variable
|
||||
@param[in] DataSize Size parameter for target secure boot variable.
|
||||
@param[in] Data Pointer to signature list formatted secure boot variable content.
|
||||
|
||||
@retval EFI_SUCCESS The enrollment for authenticated variable was successful.
|
||||
@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
|
||||
EFIAPI
|
||||
EnrollFromInput (
|
||||
IN CHAR16 *VariableName,
|
||||
IN EFI_GUID *VendorGuid,
|
||||
IN UINTN DataSize,
|
||||
IN VOID *Data
|
||||
)
|
||||
{
|
||||
VOID *Payload;
|
||||
UINTN PayloadSize;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Payload = NULL;
|
||||
|
||||
if ((VariableName == NULL) || (VendorGuid == 0)) {
|
||||
DEBUG ((DEBUG_ERROR, "Input vendor variable invalid: %p and %p\n", VariableName, VendorGuid));
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
if ((Data == NULL) || (DataSize == 0)) {
|
||||
// You might as well just use DeleteVariable...
|
||||
DEBUG ((DEBUG_ERROR, "Input argument invalid: %p: %x\n", Data, DataSize));
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
// Bring in the noise...
|
||||
PayloadSize = DataSize;
|
||||
Payload = AllocateZeroPool (DataSize);
|
||||
// Bring in the funk...
|
||||
if (Payload == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
} else {
|
||||
CopyMem (Payload, Data, DataSize);
|
||||
}
|
||||
|
||||
Status = CreateTimeBasedPayload (&PayloadSize, (UINT8 **)&Payload, &mDefaultPayloadTimestamp);
|
||||
if (EFI_ERROR (Status) || (Payload == NULL)) {
|
||||
DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r\n", Status));
|
||||
Payload = NULL;
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// 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),
|
||||
PayloadSize,
|
||||
Payload
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((
|
||||
DEBUG_ERROR,
|
||||
"error: %a (\"%s\", %g): %r\n",
|
||||
__FUNCTION__,
|
||||
VariableName,
|
||||
VendorGuid,
|
||||
Status
|
||||
));
|
||||
}
|
||||
|
||||
Exit:
|
||||
//
|
||||
// Always Put Away Your Toys
|
||||
// Payload will be reassigned by CreateTimeBasedPayload()...
|
||||
if (Payload != NULL) {
|
||||
FreePool (Payload);
|
||||
Payload = NULL;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Similar to DeleteSecureBootVariables, this function is used to unilaterally
|
||||
force the state of related SB variables (db, dbx, dbt, KEK, PK, etc.) to be
|
||||
the built-in, hardcoded default vars.
|
||||
|
||||
@param[in] SecureBootPayload Payload information for secure boot related keys.
|
||||
|
||||
@retval EFI_SUCCESS SecureBoot keys are now set to defaults.
|
||||
@retval EFI_ABORTED SecureBoot keys are not empty. Please delete keys first
|
||||
or follow standard methods of altering keys (ie. use the signing system).
|
||||
@retval EFI_SECURITY_VIOLATION Failed to create the PK.
|
||||
@retval Others Something failed in one of the subfunctions.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SetSecureBootVariablesToDefault (
|
||||
IN CONST SECURE_BOOT_PAYLOAD_INFO *SecureBootPayload
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT8 *Data;
|
||||
UINTN DataSize;
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a() Entry\n", __FUNCTION__));
|
||||
|
||||
if (SecureBootPayload == NULL) {
|
||||
DEBUG ((DEBUG_ERROR, "%a - Invalid SecureBoot payload is supplied!\n", __FUNCTION__));
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Right off the bat, if SecureBoot is currently enabled, bail.
|
||||
if (IsSecureBootEnabled ()) {
|
||||
DEBUG ((DEBUG_ERROR, "%a - Cannot set default keys while SecureBoot is enabled!\n", __FUNCTION__));
|
||||
return EFI_ABORTED;
|
||||
}
|
||||
|
||||
DEBUG ((DEBUG_INFO, "%a - Setting up key %s!\n", __FUNCTION__, SecureBootPayload->SecureBootKeyName));
|
||||
|
||||
//
|
||||
// Start running down the list, creating variables in our wake.
|
||||
// dbx is a good place to start.
|
||||
Data = (UINT8 *)SecureBootPayload->DbxPtr;
|
||||
DataSize = SecureBootPayload->DbxSize;
|
||||
Status = EnrollFromInput (
|
||||
EFI_IMAGE_SECURITY_DATABASE1,
|
||||
&gEfiImageSecurityDatabaseGuid,
|
||||
DataSize,
|
||||
Data
|
||||
);
|
||||
|
||||
// If that went well, try the db (make sure to pick the right one!).
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Data = (UINT8 *)SecureBootPayload->DbPtr;
|
||||
DataSize = SecureBootPayload->DbSize;
|
||||
Status = EnrollFromInput (
|
||||
EFI_IMAGE_SECURITY_DATABASE,
|
||||
&gEfiImageSecurityDatabaseGuid,
|
||||
DataSize,
|
||||
Data
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a - Failed to enroll DB %r!\n", __FUNCTION__, Status));
|
||||
}
|
||||
} else {
|
||||
DEBUG ((DEBUG_ERROR, "%a - Failed to enroll DBX %r!\n", __FUNCTION__, Status));
|
||||
}
|
||||
|
||||
// Keep it going. Keep it going. dbt if supplied...
|
||||
if (!EFI_ERROR (Status) && (SecureBootPayload->DbtPtr != NULL)) {
|
||||
Data = (UINT8 *)SecureBootPayload->DbtPtr;
|
||||
DataSize = SecureBootPayload->DbtSize;
|
||||
Status = EnrollFromInput (
|
||||
EFI_IMAGE_SECURITY_DATABASE2,
|
||||
&gEfiImageSecurityDatabaseGuid,
|
||||
DataSize,
|
||||
Data
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a - Failed to enroll DBT %r!\n", __FUNCTION__, Status));
|
||||
}
|
||||
}
|
||||
|
||||
// Keep it going. Keep it going. KEK...
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Data = (UINT8 *)SecureBootPayload->KekPtr;
|
||||
DataSize = SecureBootPayload->KekSize;
|
||||
Status = EnrollFromInput (
|
||||
EFI_KEY_EXCHANGE_KEY_NAME,
|
||||
&gEfiGlobalVariableGuid,
|
||||
DataSize,
|
||||
Data
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a - Failed to enroll KEK %r!\n", __FUNCTION__, Status));
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Finally! The Big Daddy of them all.
|
||||
// The PK!
|
||||
//
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Finally, install the key.
|
||||
Data = (UINT8 *)SecureBootPayload->PkPtr;
|
||||
DataSize = SecureBootPayload->PkSize;
|
||||
Status = EnrollFromInput (
|
||||
EFI_PLATFORM_KEY_NAME,
|
||||
&gEfiGlobalVariableGuid,
|
||||
DataSize,
|
||||
Data
|
||||
);
|
||||
|
||||
//
|
||||
// Report PK creation errors.
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((DEBUG_ERROR, "%a - Failed to update the PK! - %r\n", __FUNCTION__, Status));
|
||||
Status = EFI_SECURITY_VIOLATION;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
@ -38,6 +38,9 @@
|
||||
BaseMemoryLib
|
||||
DebugLib
|
||||
MemoryAllocationLib
|
||||
PlatformPKProtectionLib
|
||||
UefiLib
|
||||
UefiRuntimeServicesTableLib
|
||||
|
||||
[Guids]
|
||||
## CONSUMES ## Variable:L"SetupMode"
|
||||
|
Loading…
x
Reference in New Issue
Block a user