summaryrefslogtreecommitdiffstats
path: root/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c')
-rw-r--r--src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c421
1 files changed, 421 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c
new file mode 100644
index 00000000..b611ef9b
--- /dev/null
+++ b/src/VBox/Devices/EFI/Firmware/SecurityPkg/Library/AuthVariableLib/AuthVariableLib.c
@@ -0,0 +1,421 @@
+/** @file
+ Implement authentication services for the authenticated variables.
+
+ Caution: This module requires additional review when modified.
+ This driver will have external input - variable data. It may be input in SMM mode.
+ This external input must be validated carefully to avoid security issue like
+ buffer overflow, integer overflow.
+ Variable attribute should also be checked to avoid authentication bypass.
+ The whole SMM authentication variable design relies on the integrity of flash part and SMM.
+ which is assumed to be protected by platform. All variable code and metadata in flash/SMM Memory
+ may not be modified without authorization. If platform fails to protect these resources,
+ the authentication service provided in this driver will be broken, and the behavior is undefined.
+
+Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "AuthServiceInternal.h"
+
+///
+/// Global database array for scratch
+///
+UINT8 *mCertDbStore;
+UINT32 mMaxCertDbSize;
+UINT32 mPlatformMode;
+UINT8 mVendorKeyState;
+
+EFI_GUID mSignatureSupport[] = {EFI_CERT_SHA1_GUID, EFI_CERT_SHA256_GUID, EFI_CERT_RSA2048_GUID, EFI_CERT_X509_GUID};
+
+//
+// Hash context pointer
+//
+VOID *mHashCtx = NULL;
+
+VARIABLE_ENTRY_PROPERTY mAuthVarEntry[] = {
+ {
+ &gEfiSecureBootEnableDisableGuid,
+ EFI_SECURE_BOOT_ENABLE_NAME,
+ {
+ VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+ 0,
+ VARIABLE_ATTRIBUTE_NV_BS,
+ sizeof (UINT8),
+ sizeof (UINT8)
+ }
+ },
+ {
+ &gEfiCustomModeEnableGuid,
+ EFI_CUSTOM_MODE_NAME,
+ {
+ VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+ 0,
+ VARIABLE_ATTRIBUTE_NV_BS,
+ sizeof (UINT8),
+ sizeof (UINT8)
+ }
+ },
+ {
+ &gEfiVendorKeysNvGuid,
+ EFI_VENDOR_KEYS_NV_VARIABLE_NAME,
+ {
+ VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+ VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
+ VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
+ sizeof (UINT8),
+ sizeof (UINT8)
+ }
+ },
+ {
+ &gEfiCertDbGuid,
+ EFI_CERT_DB_NAME,
+ {
+ VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+ VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
+ VARIABLE_ATTRIBUTE_NV_BS_RT_AT,
+ sizeof (UINT32),
+ MAX_UINTN
+ }
+ },
+ {
+ &gEfiCertDbGuid,
+ EFI_CERT_DB_VOLATILE_NAME,
+ {
+ VAR_CHECK_VARIABLE_PROPERTY_REVISION,
+ VAR_CHECK_VARIABLE_PROPERTY_READ_ONLY,
+ VARIABLE_ATTRIBUTE_BS_RT_AT,
+ sizeof (UINT32),
+ MAX_UINTN
+ }
+ },
+};
+
+VOID **mAuthVarAddressPointer[9];
+
+AUTH_VAR_LIB_CONTEXT_IN *mAuthVarLibContextIn = NULL;
+
+/**
+ Initialization for authenticated variable services.
+ If this initialization returns error status, other APIs will not work
+ and expect to be not called then.
+
+ @param[in] AuthVarLibContextIn Pointer to input auth variable lib context.
+ @param[out] AuthVarLibContextOut Pointer to output auth variable lib context.
+
+ @retval EFI_SUCCESS Function successfully executed.
+ @retval EFI_INVALID_PARAMETER If AuthVarLibContextIn == NULL or AuthVarLibContextOut == NULL.
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate enough resource.
+ @retval EFI_UNSUPPORTED Unsupported to process authenticated variable.
+
+**/
+EFI_STATUS
+EFIAPI
+AuthVariableLibInitialize (
+ IN AUTH_VAR_LIB_CONTEXT_IN *AuthVarLibContextIn,
+ OUT AUTH_VAR_LIB_CONTEXT_OUT *AuthVarLibContextOut
+ )
+{
+ EFI_STATUS Status;
+ UINT32 VarAttr;
+ UINT8 *Data;
+ UINTN DataSize;
+ UINTN CtxSize;
+ UINT8 SecureBootMode;
+ UINT8 SecureBootEnable;
+ UINT8 CustomMode;
+ UINT32 ListSize;
+
+ if ((AuthVarLibContextIn == NULL) || (AuthVarLibContextOut == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ mAuthVarLibContextIn = AuthVarLibContextIn;
+
+ //
+ // Initialize hash context.
+ //
+ CtxSize = Sha256GetContextSize ();
+ mHashCtx = AllocateRuntimePool (CtxSize);
+ if (mHashCtx == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Reserve runtime buffer for certificate database. The size excludes variable header and name size.
+ // Use EFI_CERT_DB_VOLATILE_NAME size since it is longer.
+ //
+ mMaxCertDbSize = (UINT32) (mAuthVarLibContextIn->MaxAuthVariableSize - sizeof (EFI_CERT_DB_VOLATILE_NAME));
+ mCertDbStore = AllocateRuntimePool (mMaxCertDbSize);
+ if (mCertDbStore == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = AuthServiceInternalFindVariable (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID **) &Data, &DataSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_INFO, "Variable %s does not exist.\n", EFI_PLATFORM_KEY_NAME));
+ } else {
+ DEBUG ((EFI_D_INFO, "Variable %s exists.\n", EFI_PLATFORM_KEY_NAME));
+ }
+
+ //
+ // Create "SetupMode" variable with BS+RT attribute set.
+ //
+ if (EFI_ERROR (Status)) {
+ mPlatformMode = SETUP_MODE;
+ } else {
+ mPlatformMode = USER_MODE;
+ }
+ Status = AuthServiceInternalUpdateVariable (
+ EFI_SETUP_MODE_NAME,
+ &gEfiGlobalVariableGuid,
+ &mPlatformMode,
+ sizeof(UINT8),
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Create "SignatureSupport" variable with BS+RT attribute set.
+ //
+ Status = AuthServiceInternalUpdateVariable (
+ EFI_SIGNATURE_SUPPORT_NAME,
+ &gEfiGlobalVariableGuid,
+ mSignatureSupport,
+ sizeof(mSignatureSupport),
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // If "SecureBootEnable" variable exists, then update "SecureBoot" variable.
+ // If "SecureBootEnable" variable is SECURE_BOOT_ENABLE and in USER_MODE, Set "SecureBoot" variable to SECURE_BOOT_MODE_ENABLE.
+ // If "SecureBootEnable" variable is SECURE_BOOT_DISABLE, Set "SecureBoot" variable to SECURE_BOOT_MODE_DISABLE.
+ //
+ SecureBootEnable = SECURE_BOOT_DISABLE;
+ Status = AuthServiceInternalFindVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID **) &Data, &DataSize);
+ if (!EFI_ERROR (Status)) {
+ if (mPlatformMode == USER_MODE){
+ SecureBootEnable = *(UINT8 *) Data;
+ }
+ } else if (mPlatformMode == USER_MODE) {
+ //
+ // "SecureBootEnable" not exist, initialize it in USER_MODE.
+ //
+ SecureBootEnable = SECURE_BOOT_ENABLE;
+ Status = AuthServiceInternalUpdateVariable (
+ EFI_SECURE_BOOT_ENABLE_NAME,
+ &gEfiSecureBootEnableDisableGuid,
+ &SecureBootEnable,
+ sizeof (UINT8),
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Create "SecureBoot" variable with BS+RT attribute set.
+ //
+ if (SecureBootEnable == SECURE_BOOT_ENABLE && mPlatformMode == USER_MODE) {
+ SecureBootMode = SECURE_BOOT_MODE_ENABLE;
+ } else {
+ SecureBootMode = SECURE_BOOT_MODE_DISABLE;
+ }
+ Status = AuthServiceInternalUpdateVariable (
+ EFI_SECURE_BOOT_MODE_NAME,
+ &gEfiGlobalVariableGuid,
+ &SecureBootMode,
+ sizeof (UINT8),
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SETUP_MODE_NAME, mPlatformMode));
+ DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_MODE_NAME, SecureBootMode));
+ DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_SECURE_BOOT_ENABLE_NAME, SecureBootEnable));
+
+ //
+ // Initialize "CustomMode" in STANDARD_SECURE_BOOT_MODE state.
+ //
+ CustomMode = STANDARD_SECURE_BOOT_MODE;
+ Status = AuthServiceInternalUpdateVariable (
+ EFI_CUSTOM_MODE_NAME,
+ &gEfiCustomModeEnableGuid,
+ &CustomMode,
+ sizeof (UINT8),
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_CUSTOM_MODE_NAME, CustomMode));
+
+ //
+ // Check "certdb" variable's existence.
+ // If it doesn't exist, then create a new one with
+ // EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.
+ //
+ Status = AuthServiceInternalFindVariable (
+ EFI_CERT_DB_NAME,
+ &gEfiCertDbGuid,
+ (VOID **) &Data,
+ &DataSize
+ );
+ if (EFI_ERROR (Status)) {
+ VarAttr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+ ListSize = sizeof (UINT32);
+ Status = AuthServiceInternalUpdateVariable (
+ EFI_CERT_DB_NAME,
+ &gEfiCertDbGuid,
+ &ListSize,
+ sizeof (UINT32),
+ VarAttr
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ } else {
+ //
+ // Clean up Certs to make certDB & Time based auth variable consistent
+ //
+ Status = CleanCertsFromDb();
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "Clean up CertDB fail! Status %x\n", Status));
+ return Status;
+ }
+ }
+
+ //
+ // Create "certdbv" variable with RT+BS+AT set.
+ //
+ VarAttr = EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS;
+ ListSize = sizeof (UINT32);
+ Status = AuthServiceInternalUpdateVariable (
+ EFI_CERT_DB_VOLATILE_NAME,
+ &gEfiCertDbGuid,
+ &ListSize,
+ sizeof (UINT32),
+ VarAttr
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check "VendorKeysNv" variable's existence and create "VendorKeys" variable accordingly.
+ //
+ Status = AuthServiceInternalFindVariable (EFI_VENDOR_KEYS_NV_VARIABLE_NAME, &gEfiVendorKeysNvGuid, (VOID **) &Data, &DataSize);
+ if (!EFI_ERROR (Status)) {
+ mVendorKeyState = *(UINT8 *)Data;
+ } else {
+ //
+ // "VendorKeysNv" not exist, initialize it in VENDOR_KEYS_VALID state.
+ //
+ mVendorKeyState = VENDOR_KEYS_VALID;
+ Status = AuthServiceInternalUpdateVariable (
+ EFI_VENDOR_KEYS_NV_VARIABLE_NAME,
+ &gEfiVendorKeysNvGuid,
+ &mVendorKeyState,
+ sizeof (UINT8),
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ //
+ // Create "VendorKeys" variable with BS+RT attribute set.
+ //
+ Status = AuthServiceInternalUpdateVariable (
+ EFI_VENDOR_KEYS_VARIABLE_NAME,
+ &gEfiGlobalVariableGuid,
+ &mVendorKeyState,
+ sizeof (UINT8),
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((EFI_D_INFO, "Variable %s is %x\n", EFI_VENDOR_KEYS_VARIABLE_NAME, mVendorKeyState));
+
+ AuthVarLibContextOut->StructVersion = AUTH_VAR_LIB_CONTEXT_OUT_STRUCT_VERSION;
+ AuthVarLibContextOut->StructSize = sizeof (AUTH_VAR_LIB_CONTEXT_OUT);
+ AuthVarLibContextOut->AuthVarEntry = mAuthVarEntry;
+ AuthVarLibContextOut->AuthVarEntryCount = ARRAY_SIZE (mAuthVarEntry);
+ mAuthVarAddressPointer[0] = (VOID **) &mCertDbStore;
+ mAuthVarAddressPointer[1] = (VOID **) &mHashCtx;
+ mAuthVarAddressPointer[2] = (VOID **) &mAuthVarLibContextIn;
+ mAuthVarAddressPointer[3] = (VOID **) &(mAuthVarLibContextIn->FindVariable),
+ mAuthVarAddressPointer[4] = (VOID **) &(mAuthVarLibContextIn->FindNextVariable),
+ mAuthVarAddressPointer[5] = (VOID **) &(mAuthVarLibContextIn->UpdateVariable),
+ mAuthVarAddressPointer[6] = (VOID **) &(mAuthVarLibContextIn->GetScratchBuffer),
+ mAuthVarAddressPointer[7] = (VOID **) &(mAuthVarLibContextIn->CheckRemainingSpaceForConsistency),
+ mAuthVarAddressPointer[8] = (VOID **) &(mAuthVarLibContextIn->AtRuntime),
+ AuthVarLibContextOut->AddressPointer = mAuthVarAddressPointer;
+ AuthVarLibContextOut->AddressPointerCount = ARRAY_SIZE (mAuthVarAddressPointer);
+
+ return Status;
+}
+
+/**
+ Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set.
+
+ @param[in] VariableName Name of the variable.
+ @param[in] VendorGuid Variable vendor GUID.
+ @param[in] Data Data pointer.
+ @param[in] DataSize Size of Data.
+ @param[in] Attributes Attribute value of the variable.
+
+ @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as
+ defined by the Attributes.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+ @retval EFI_WRITE_PROTECTED Variable is write-protected.
+ @retval EFI_OUT_OF_RESOURCES There is not enough resource.
+ @retval EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS
+ set, but the AuthInfo does NOT pass the validation
+ check carried out by the firmware.
+ @retval EFI_UNSUPPORTED Unsupported to process authenticated variable.
+
+**/
+EFI_STATUS
+EFIAPI
+AuthVariableLibProcessVariable (
+ IN CHAR16 *VariableName,
+ IN EFI_GUID *VendorGuid,
+ IN VOID *Data,
+ IN UINTN DataSize,
+ IN UINT32 Attributes
+ )
+{
+ EFI_STATUS Status;
+
+ if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_PLATFORM_KEY_NAME) == 0)){
+ Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, Attributes, TRUE);
+ } else if (CompareGuid (VendorGuid, &gEfiGlobalVariableGuid) && (StrCmp (VariableName, EFI_KEY_EXCHANGE_KEY_NAME) == 0)) {
+ Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, Attributes, FALSE);
+ } else if (CompareGuid (VendorGuid, &gEfiImageSecurityDatabaseGuid) &&
+ ((StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE) == 0) ||
+ (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE1) == 0) ||
+ (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0)
+ )) {
+ Status = ProcessVarWithPk (VariableName, VendorGuid, Data, DataSize, Attributes, FALSE);
+ if (EFI_ERROR (Status)) {
+ Status = ProcessVarWithKek (VariableName, VendorGuid, Data, DataSize, Attributes);
+ }
+ } else {
+ Status = ProcessVariable (VariableName, VendorGuid, Data, DataSize, Attributes);
+ }
+
+ return Status;
+}