diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.c b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.c new file mode 100644 index 0000000000..8741780899 --- /dev/null +++ b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.c @@ -0,0 +1,644 @@ +/** @file + Enroll default PK, KEK, DB and DBX + + Copyright (C) 2014, Red Hat, Inc. + + This program and the accompanying materials are licensed and made available + under the terms and conditions of the BSD License which accompanies this + distribution. The full text of the license may be found at + http://opensource.org/licenses/bsd-license. + + THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT + WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + **/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define EFI_MICROSOFT_KEK_CERT_GUID \ + { 0xA23665E3, 0xACA6, 0x4F6D, {0x80, 0xCC, 0x34, 0x1E, 0x7D, 0x7B, 0x8C, 0xC6} } + +#define EFI_SECUREBOOT_PK_CERT_GUID \ + { 0xF8104268, 0xA364, 0x45F5, {0x8E, 0x00, 0xAB, 0xA3, 0xFD, 0xEA, 0x12, 0xBE} } + +#define EFI_MICROSOFT_DB1_CERT_GUID \ + { 0x26A517B0, 0xE3FD, 0x46C2, {0x89, 0x32, 0xE9, 0x26, 0xBF, 0x98, 0x94, 0x1F} } + +#define EFI_MICROSOFT_DB2_CERT_GUID \ + { 0x91D2E32B, 0x0134, 0x4306, {0xBA, 0x90, 0x54, 0xED, 0xCB, 0xF3, 0x49, 0xCA} } + +#define EFI_MICROSOFT_DBX_GUID \ + { 0x74BB6E72, 0x2A56, 0x4D0E, {0xA5, 0xB3, 0x5D, 0x39, 0xFC, 0x2E, 0xE3, 0x46} } + +#define EFI_MICROSOFT_OWNER_GUID \ + { 0x77FA9ABD, 0x0359, 0x4D32, {0xBD, 0x60, 0x28, 0xF4, 0xE7, 0x8F, 0x78, 0x4B} } + +EFI_GUID gEfiSecureBootDb1CertGuid = EFI_MICROSOFT_DB1_CERT_GUID; +EFI_GUID gEfiSecureBootDb2CertGuid = EFI_MICROSOFT_DB2_CERT_GUID; +EFI_GUID gEfiSecureBootDbxCrlGuid = EFI_MICROSOFT_DBX_GUID; +EFI_GUID gEfiSecureBootKekCertGuid = EFI_MICROSOFT_KEK_CERT_GUID; +EFI_GUID gEfiSecureBootPkCertGuid = EFI_SECUREBOOT_PK_CERT_GUID; +EFI_GUID gEfiMicrosoftOwnerGuid = EFI_MICROSOFT_OWNER_GUID; + +// +// The most important thing about the variable payload is that it is a list of +// lists, where the element size of any given *inner* list is constant. +// +// Since X509 certificates vary in size, each of our *inner* lists will contain +// one element only (one X.509 certificate). This is explicitly mentioned in +// the UEFI specification, in "28.4.1 Signature Database", in a Note. +// +// The list structure looks as follows: +// +// struct EFI_VARIABLE_AUTHENTICATION_2 { | +// struct EFI_TIME { | +// UINT16 Year; | +// UINT8 Month; | +// UINT8 Day; | +// UINT8 Hour; | +// UINT8 Minute; | +// UINT8 Second; | +// UINT8 Pad1; | +// UINT32 Nanosecond; | +// INT16 TimeZone; | +// UINT8 Daylight; | +// UINT8 Pad2; | +// } TimeStamp; | +// | +// struct WIN_CERTIFICATE_UEFI_GUID { | | +// struct WIN_CERTIFICATE { | | +// UINT32 dwLength; ----------------------------------------+ | +// UINT16 wRevision; | | +// UINT16 wCertificateType; | | +// } Hdr; | +- DataSize +// | | +// EFI_GUID CertType; | | +// UINT8 CertData[1] = { <--- "struct hack" | | +// struct EFI_SIGNATURE_LIST { | | | +// EFI_GUID SignatureType; | | | +// UINT32 SignatureListSize; -------------------------+ | | +// UINT32 SignatureHeaderSize; | | | +// UINT32 SignatureSize; ---------------------------+ | | | +// UINT8 SignatureHeader[SignatureHeaderSize]; | | | | +// v | | | +// struct EFI_SIGNATURE_DATA { | | | | +// EFI_GUID SignatureOwner; | | | | +// UINT8 SignatureData[1] = { <--- "struct hack" | | | | +// X.509 payload | | | | +// } | | | | +// } Signatures[]; | | | +// } SigLists[]; | | +// }; | | +// } AuthInfo; | | +// }; | +// +// Given that the "struct hack" invokes undefined behavior (which is why C99 +// introduced the flexible array member), and because subtracting those pesky +// sizes of 1 is annoying, and because the format is fully specified in the +// UEFI specification, we'll introduce two matching convenience structures that +// are customized for our X.509 purposes. +// + +#pragma pack(1) +typedef struct { + EFI_TIME TimeStamp; + + // + // dwLength covers data below + // + UINT32 dwLength; + UINT16 wRevision; + UINT16 wCertificateType; + EFI_GUID CertType; +} SINGLE_HEADER; + +typedef struct { + // + // SignatureListSize covers data below + // + EFI_GUID SignatureType; + UINT32 SignatureListSize; + UINT32 SignatureHeaderSize; // constant 0 + UINT32 SignatureSize; + + // + // SignatureSize covers data below + // + EFI_GUID SignatureOwner; + + // + // X.509 certificate follows + // +} REPEATING_HEADER; +#pragma pack() + +/** + Enroll a set of certificates in a global variable, overwriting it. + + The variable will be rewritten with NV+BS+RT+AT attributes. + + @param[in] VariableName The name of the variable to overwrite. + + @param[in] VendorGuid The namespace (ie. vendor GUID) of the variable to + overwrite. + + @param[in] CertType The GUID determining the type of all the + certificates in the set that is passed in. For + example, gEfiCertX509Guid stands for DER-encoded + X.509 certificates, while gEfiCertSha256Guid stands + for SHA256 image hashes. + + @param[in] ... A list of + + IN CONST UINT8 *Cert, + IN UINTN CertSize, + IN CONST EFI_GUID *OwnerGuid + + triplets. If the first component of a triplet is + NULL, then the other two components are not + accessed, and processing is terminated. The list of + certificates is enrolled in the variable specified, + overwriting it. The OwnerGuid component identifies + the agent installing the certificate. + + @retval EFI_INVALID_PARAMETER The triplet list is empty (ie. the first Cert + value is NULL), or one of the CertSize values + is 0, or one of the CertSize values would + overflow the accumulated UINT32 data size. + + @retval EFI_OUT_OF_RESOURCES Out of memory while formatting variable + payload. + + @retval EFI_SUCCESS Enrollment successful; the variable has been + overwritten (or created). + + @return Error codes from gRT->GetTime() and + gRT->SetVariable(). + **/ +STATIC +EFI_STATUS +EFIAPI +EnrollListOfCerts ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN EFI_GUID *CertType, + ... + ) +{ + UINTN DataSize; + SINGLE_HEADER *SingleHeader; + REPEATING_HEADER *RepeatingHeader; + VA_LIST Marker; + CONST UINT8 *Cert; + EFI_STATUS Status; + UINT8 *Data; + UINT8 *Position; + + Status = EFI_SUCCESS; + + // + // compute total size first, for UINT32 range check, and allocation + // + DataSize = sizeof *SingleHeader; + VA_START (Marker, CertType); + for (Cert = VA_ARG (Marker, CONST UINT8 *); + Cert != NULL; + Cert = VA_ARG (Marker, CONST UINT8 *)) { + UINTN CertSize; + + CertSize = VA_ARG (Marker, UINTN); + (VOID)VA_ARG (Marker, CONST EFI_GUID *); + + if (CertSize == 0 || + CertSize > MAX_UINT32 - sizeof *RepeatingHeader || + DataSize > MAX_UINT32 - sizeof *RepeatingHeader - CertSize) { + Status = EFI_INVALID_PARAMETER; + break; + } + DataSize += sizeof *RepeatingHeader + CertSize; + } + VA_END (Marker); + + if (DataSize == sizeof *SingleHeader) { + Status = EFI_INVALID_PARAMETER; + } + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: Invalid certificate parameters\n")); + goto Out; + } + + Data = AllocatePool (DataSize); + if (Data == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Out; + } + + Position = Data; + + SingleHeader = (SINGLE_HEADER *)Position; + Status = gRT->GetTime (&SingleHeader->TimeStamp, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_INFO, "SecureBootSetup: GetTime failed\n")); + // Fill in dummy values + SingleHeader->TimeStamp.Year = 2018; + SingleHeader->TimeStamp.Month = 1; + SingleHeader->TimeStamp.Day = 1; + SingleHeader->TimeStamp.Hour = 0; + SingleHeader->TimeStamp.Minute = 0; + SingleHeader->TimeStamp.Second = 0; + Status = EFI_SUCCESS; + } + SingleHeader->TimeStamp.Pad1 = 0; + SingleHeader->TimeStamp.Nanosecond = 0; + SingleHeader->TimeStamp.TimeZone = 0; + SingleHeader->TimeStamp.Daylight = 0; + SingleHeader->TimeStamp.Pad2 = 0; + + // + // This looks like a bug in edk2. According to the UEFI specification, + // dwLength is "The length of the entire certificate, including the length of + // the header, in bytes". That shouldn't stop right after CertType -- it + // should include everything below it. + // + SingleHeader->dwLength = sizeof *SingleHeader - sizeof SingleHeader->TimeStamp; + SingleHeader->wRevision = 0x0200; + SingleHeader->wCertificateType = WIN_CERT_TYPE_EFI_GUID; + CopyGuid (&SingleHeader->CertType, &gEfiCertPkcs7Guid); + Position += sizeof *SingleHeader; + + VA_START (Marker, CertType); + for (Cert = VA_ARG (Marker, CONST UINT8 *); + Cert != NULL; + Cert = VA_ARG (Marker, CONST UINT8 *)) { + UINTN CertSize; + CONST EFI_GUID *OwnerGuid; + + CertSize = VA_ARG (Marker, UINTN); + OwnerGuid = VA_ARG (Marker, CONST EFI_GUID *); + + RepeatingHeader = (REPEATING_HEADER *)Position; + CopyGuid (&RepeatingHeader->SignatureType, CertType); + RepeatingHeader->SignatureListSize = + (UINT32)(sizeof *RepeatingHeader + CertSize); + RepeatingHeader->SignatureHeaderSize = 0; + RepeatingHeader->SignatureSize = + (UINT32)(sizeof RepeatingHeader->SignatureOwner + CertSize); + CopyGuid (&RepeatingHeader->SignatureOwner, OwnerGuid); + Position += sizeof *RepeatingHeader; + + CopyMem (Position, Cert, CertSize); + Position += CertSize; + } + VA_END (Marker); + + ASSERT (Data + DataSize == Position); + + Status = gRT->SetVariable (VariableName, VendorGuid, + (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_RUNTIME_ACCESS | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS), + DataSize, Data); + + FreePool (Data); + +Out: + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: %a(\"%s\", %g): %r\n", __FUNCTION__, VariableName, + VendorGuid, Status)); + } + return Status; +} + + +STATIC +EFI_STATUS +EFIAPI +GetExact ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + OUT VOID *Data, + IN UINTN DataSize, + IN BOOLEAN AllowMissing + ) +{ + UINTN Size; + EFI_STATUS Status; + + Size = DataSize; + Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &Size, Data); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND && AllowMissing) { + ZeroMem (Data, DataSize); + return EFI_SUCCESS; + } + + DEBUG ((EFI_D_ERROR, "SecureBootSetup: GetVariable(\"%s\", %g): %r\n", VariableName, + VendorGuid, Status)); + return Status; + } + + if (Size != DataSize) { + DEBUG ((EFI_D_INFO, "SecureBootSetup: GetVariable(\"%s\", %g): expected size 0x%Lx, " + "got 0x%Lx\n", VariableName, VendorGuid, (UINT64)DataSize, (UINT64)Size)); + return EFI_PROTOCOL_ERROR; + } + + return EFI_SUCCESS; +} + +typedef struct { + UINT8 SetupMode; + UINT8 SecureBoot; + UINT8 SecureBootEnable; + UINT8 CustomMode; + UINT8 VendorKeys; +} SETTINGS; + +STATIC +EFI_STATUS +EFIAPI +GetSettings ( + OUT SETTINGS *Settings, + BOOLEAN AllowMissing + ) +{ + EFI_STATUS Status; + + ZeroMem (Settings, sizeof(SETTINGS)); + + Status = GetExact (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, + &Settings->SetupMode, sizeof Settings->SetupMode, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, + &Settings->SecureBoot, sizeof Settings->SecureBoot, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, &Settings->SecureBootEnable, + sizeof Settings->SecureBootEnable, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, + &Settings->CustomMode, sizeof Settings->CustomMode, AllowMissing); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = GetExact (EFI_VENDOR_KEYS_VARIABLE_NAME, &gEfiGlobalVariableGuid, + &Settings->VendorKeys, sizeof Settings->VendorKeys, AllowMissing); + return Status; +} + +STATIC +VOID +EFIAPI +PrintSettings ( + IN CONST SETTINGS *Settings + ) +{ + DEBUG ((EFI_D_INFO, "SecureBootSetup: SetupMode=%d SecureBoot=%d SecureBootEnable=%d " + "CustomMode=%d VendorKeys=%d\n", Settings->SetupMode, Settings->SecureBoot, + Settings->SecureBootEnable, Settings->CustomMode, Settings->VendorKeys)); +} + +/** + Install SecureBoot certificates once the VariableDriver is running. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context +**/ +VOID +EFIAPI +InstallSecureBootHook ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + VOID *Protocol; + SETTINGS Settings; + + UINT8 *MicrosoftPCA = 0; + UINTN MicrosoftPCASize; + UINT8 *MicrosoftUefiCA = 0; + UINTN MicrosoftUefiCASize; + UINT8 *MicrosoftKEK = 0; + UINTN MicrosoftKEKSize; + UINT8 *SecureBootPk = 0; + UINTN SecureBootPkSize; + UINT8 *MicrosoftDbx = 0; + UINTN MicrosoftDbxSize; + + Status = gBS->LocateProtocol (&gEfiVariableWriteArchProtocolGuid, NULL, (VOID **)&Protocol); + if (EFI_ERROR (Status)) { + return; + } + + Status = GetSettings (&Settings, TRUE); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: Failed to get current settings\n")); + return; + } + + if (Settings.SetupMode != SETUP_MODE) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: already in User Mode\n")); + return; + } + PrintSettings (&Settings); + + if (Settings.CustomMode != CUSTOM_SECURE_BOOT_MODE) { + Settings.CustomMode = CUSTOM_SECURE_BOOT_MODE; + Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, + (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS), + sizeof Settings.CustomMode, &Settings.CustomMode); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME, + &gEfiCustomModeEnableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + } + + Status = GetSectionFromAnyFv(&gEfiSecureBootDb1CertGuid, EFI_SECTION_RAW, 0, (void **)&MicrosoftPCA, &MicrosoftPCASize); + ASSERT_EFI_ERROR (Status); + + Status = GetSectionFromAnyFv(&gEfiSecureBootDb2CertGuid, EFI_SECTION_RAW, 0, (void **)&MicrosoftUefiCA, &MicrosoftUefiCASize); + ASSERT_EFI_ERROR (Status); + + Status = GetSectionFromAnyFv(&gEfiSecureBootKekCertGuid, EFI_SECTION_RAW, 0, (void **)&MicrosoftKEK, &MicrosoftKEKSize); + ASSERT_EFI_ERROR (Status); + + Status = GetSectionFromAnyFv(&gEfiSecureBootPkCertGuid, EFI_SECTION_RAW, 0, (void **)&SecureBootPk, &SecureBootPkSize); + ASSERT_EFI_ERROR (Status); + + Status = GetSectionFromAnyFv(&gEfiSecureBootDbxCrlGuid, EFI_SECTION_RAW, 0, (void **)&MicrosoftDbx, &MicrosoftDbxSize); + ASSERT_EFI_ERROR (Status); + + Status = gRT->SetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, + (EFI_VARIABLE_NON_VOLATILE | + EFI_VARIABLE_BOOTSERVICE_ACCESS | + EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS), + MicrosoftDbxSize, MicrosoftDbx); + ASSERT_EFI_ERROR (Status); + + Status = EnrollListOfCerts ( + EFI_IMAGE_SECURITY_DATABASE, + &gEfiImageSecurityDatabaseGuid, + &gEfiCertX509Guid, + MicrosoftPCA, MicrosoftPCASize, &gEfiMicrosoftOwnerGuid, + MicrosoftUefiCA, MicrosoftUefiCASize, &gEfiMicrosoftOwnerGuid, + NULL); + ASSERT_EFI_ERROR (Status); + + Status = EnrollListOfCerts ( + EFI_KEY_EXCHANGE_KEY_NAME, + &gEfiGlobalVariableGuid, + &gEfiCertX509Guid, + SecureBootPk, SecureBootPkSize, &gEfiCallerIdGuid, + MicrosoftKEK, MicrosoftKEKSize, &gEfiMicrosoftOwnerGuid, + NULL); + ASSERT_EFI_ERROR (Status); + + Status = EnrollListOfCerts ( + EFI_PLATFORM_KEY_NAME, + &gEfiGlobalVariableGuid, + &gEfiCertX509Guid, + SecureBootPk, SecureBootPkSize, &gEfiGlobalVariableGuid, + NULL); + ASSERT_EFI_ERROR (Status); + + FreePool (MicrosoftPCA); + FreePool (MicrosoftUefiCA); + FreePool (MicrosoftKEK); + FreePool (SecureBootPk); + FreePool (MicrosoftDbx); + + Settings.CustomMode = STANDARD_SECURE_BOOT_MODE; + Status = gRT->SetVariable (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof Settings.CustomMode, &Settings.CustomMode); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: SetVariable(\"%s\", %g): %r\n", EFI_CUSTOM_MODE_NAME, + &gEfiCustomModeEnableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + + // FIXME: Force SecureBoot to ON. The AuthService will do this if authenticated variables + // are supported, which aren't as the SMM handler isn't able to verify them. + + Settings.SecureBootEnable = SECURE_BOOT_ENABLE; + Status = gRT->SetVariable (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof Settings.SecureBootEnable, &Settings.SecureBootEnable); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: SetVariable(\"%s\", %g): %r\n", EFI_SECURE_BOOT_ENABLE_NAME, + &gEfiSecureBootEnableDisableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + + Settings.SecureBoot = SECURE_BOOT_ENABLE; + Status = gRT->SetVariable (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, + EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, + sizeof Settings.SecureBoot, &Settings.SecureBoot); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: SetVariable(\"%s\", %g): %r\n", EFI_SECURE_BOOT_MODE_NAME, + &gEfiGlobalVariableGuid, Status)); + ASSERT_EFI_ERROR (Status); + } + + Status = GetSettings (&Settings, FALSE); + ASSERT_EFI_ERROR (Status); + + // + // Final sanity check: + // + // [SetupMode] + // (read-only, standardized by UEFI) + // / \_ + // 0 1, default + // / \_ + // PK enrolled no PK enrolled yet, + // (this is called "User Mode") PK enrollment possible + // | + // | + // [SecureBootEnable] + // (read-write, edk2-specific, boot service only) + // / \_ + // 0 1, default + // / \_ + // [SecureBoot]=0 [SecureBoot]=1 + // (read-only, standardized by UEFI) (read-only, standardized by UEFI) + // images are not verified images are verified, platform is + // operating in Secure Boot mode + // | + // | + // [CustomMode] + // (read-write, edk2-specific, boot service only) + // / \_ + // 0, default 1 + // / \_ + // PK, KEK, db, dbx PK, KEK, db, dbx + // updates are verified updates are not verified + // + + PrintSettings (&Settings); + + if (Settings.SetupMode != 0 || Settings.SecureBoot != 1 || + Settings.SecureBootEnable != 1 || Settings.CustomMode != 0 || + Settings.VendorKeys != 0) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: disabled\n")); + return; + } + + DEBUG ((EFI_D_INFO, "SecureBootSetup: SecureBoot enabled\n")); +} + +EFI_STATUS +EFIAPI +DriverEntry ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + + VOID *TcgProtocol; + VOID *Registration; + + Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **) &TcgProtocol); + if (!EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "SecureBootSetup: Started too late." + "TPM is already running!\n")); + return EFI_DEVICE_ERROR; + } + + // + // Create event callback, because we need access variable on SecureBootPolicyVariable + // We should use VariableWriteArch instead of VariableArch, because Variable driver + // may update SecureBoot value based on last setting. + // + EfiCreateProtocolNotifyEvent ( + &gEfiVariableWriteArchProtocolGuid, + TPL_CALLBACK, + InstallSecureBootHook, + NULL, + &Registration); + + return EFI_SUCCESS; +} diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.inf b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.inf new file mode 100644 index 0000000000..c7b14556a0 --- /dev/null +++ b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.inf @@ -0,0 +1,54 @@ +## @file +# This file handels SecureBoot setup. +# +# Copyright (c) 2013 - 2019, Intel Corporation. All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SecureBootSetup + MODULE_UNI_FILE = SecureBootSetup.uni + FILE_GUID = 14693BD4-D114-4177-979E-37F279BAD620 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 0.1 + ENTRY_POINT = DriverEntry + +# +# VALID_ARCHITECTURES = IA32 X64 +# + +[Sources] + SecureBootSetup.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + +[Guids] + gEfiCertPkcs7Guid + gEfiCertX509Guid + gEfiCustomModeEnableGuid + gEfiGlobalVariableGuid + gEfiImageSecurityDatabaseGuid + gEfiSecureBootEnableDisableGuid + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + UefiRuntimeServicesTableLib + UefiDriverEntryPoint + DxeServicesLib + UefiBootServicesTableLib + +[Protocols] + gEfiTcgProtocolGuid ## CONSUMES + gEfiVariableWriteArchProtocolGuid ## NOTIFY + +[Depex] + AFTER gEfiVariableWriteArchProtocolGuid \ No newline at end of file diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.uni b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.uni new file mode 100644 index 0000000000..0ea5d32872 --- /dev/null +++ b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetup.uni @@ -0,0 +1,21 @@ +// /** @file +// Provides authenticated variable service for IPF platform +// +// This module installs variable arch protocol and variable write arch protocol to provide +// four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo. +// +// Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Provides authenticated variable service for IPF platform" + +#string STR_MODULE_DESCRIPTION #language en-US "This module installs variable arch protocol and variable write arch protocol to provide four EFI_RUNTIME_SERVICES: SetVariable, GetVariable, GetNextVariableName and QueryVariableInfo." diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetupExtra.uni b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetupExtra.uni new file mode 100644 index 0000000000..9811340573 --- /dev/null +++ b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/SecureBootSetupExtra.uni @@ -0,0 +1,17 @@ +// /** @file +// EsalVariableDxeSal Localized Strings and Content +// +// Copyright (c) 2013 - 2014, Intel Corporation. All rights reserved.
+// +// This program and the accompanying materials +// are licensed and made available under the terms and conditions of the BSD License +// which accompanies this distribution. The full text of the license may be found at +// http://opensource.org/licenses/bsd-license.php +// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +// +// **/ + +#string STR_PROPERTIES_MODULE_NAME +#language en-US +"9elements Secure Boot DXE" diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/README b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/README new file mode 100644 index 0000000000..5182454b97 --- /dev/null +++ b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/README @@ -0,0 +1,8 @@ +# PK certificate generation + +* Do not save private key for re-usage. +* Generate a RSA 2048 / SHA256 x509 certificate +* Exponent should be 65537 +* Microsoft certificates can be found here: https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/windows-secure-boot-key-creation-and-management-guidance + +openssl req -outform DER -newkey rsa:2048 -keyout /dev/null -passout file:<(head -c 40 /dev/urandom) -x509 -days 365 -out pk.crt diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/crl.bin b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/crl.bin new file mode 100644 index 0000000000..728316fd8d Binary files /dev/null and b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/crl.bin differ diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/db-1.crt b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/db-1.crt new file mode 100644 index 0000000000..a6d001c219 Binary files /dev/null and b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/db-1.crt differ diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/db-2.crt b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/db-2.crt new file mode 100644 index 0000000000..9aa6ac6c79 Binary files /dev/null and b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/db-2.crt differ diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/kek.crt b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/kek.crt new file mode 100644 index 0000000000..2787083e0c Binary files /dev/null and b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/kek.crt differ diff --git a/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/pk.crt b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/pk.crt new file mode 100644 index 0000000000..a374b28a5e Binary files /dev/null and b/UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/pk.crt differ diff --git a/UefiPayloadPkg/UefiPayloadPkg.dsc b/UefiPayloadPkg/UefiPayloadPkg.dsc index 8a88865d3f..2b18049603 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.dsc +++ b/UefiPayloadPkg/UefiPayloadPkg.dsc @@ -101,6 +101,10 @@ DEFINE RTC_TARGET_REGISTER = 0x71 DEFINE SERIAL_DRIVER_ENABLE = TRUE + # + # Security options: + # + DEFINE SECURE_BOOT_ENABLE = FALSE [BuildOptions] *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES @@ -163,6 +167,10 @@ CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf SafeIntLib|MdePkg/Library/BaseSafeIntLib/BaseSafeIntLib.inf DxeHobListLib|UefiPayloadPkg/Library/DxeHobListLib/DxeHobListLib.inf +!if $(SECURE_BOOT_ENABLE) == TRUE + SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf + SecureBootVariableProvisionLib|SecurityPkg/Library/SecureBootVariableProvisionLib/SecureBootVariableProvisionLib.inf +!endif !if $(UNIVERSAL_PAYLOAD) == TRUE HobLib|UefiPayloadPkg/Library/DxeHobLib/DxeHobLib.inf @@ -244,7 +252,6 @@ DebugLib|MdePkg/Library/BaseDebugLibSerialPort/BaseDebugLibSerialPort.inf LockBoxLib|MdeModulePkg/Library/LockBoxNullLib/LockBoxNullLib.inf FileExplorerLib|MdeModulePkg/Library/FileExplorerLib/FileExplorerLib.inf - AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf TpmMeasurementLib|MdeModulePkg/Library/TpmMeasurementLibNull/TpmMeasurementLibNull.inf VarCheckLib|MdeModulePkg/Library/VarCheckLib/VarCheckLib.inf VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLib.inf @@ -255,6 +262,9 @@ SmmStoreLib|UefiPayloadPkg/Library/SblSMMStoreLib/SblSMMStoreLib.inf !endif +[LibraryClasses.common] + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf + [LibraryClasses.common.SEC] HobLib|UefiPayloadPkg/Library/PayloadEntryHobLib/HobLib.inf PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf @@ -272,6 +282,17 @@ !endif CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf + +!if $(SECURE_BOOT_ENABLE) == TRUE + AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf + # re-use the UserPhysicalPresent() dummy implementation from the ovmf tree + PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf +!else + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf +!endif [LibraryClasses.common.DXE_DRIVER] PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf @@ -284,12 +305,35 @@ CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf VmgExitLib|UefiCpuPkg/Library/VmgExitLibNull/VmgExitLibNull.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf + +!if $(SECURE_BOOT_ENABLE) == TRUE + AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf + # re-use the UserPhysicalPresent() dummy implementation from the ovmf tree + PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf +!else + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf +!endif [LibraryClasses.common.DXE_RUNTIME_DRIVER] PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf ReportStatusCodeLib|MdeModulePkg/Library/RuntimeDxeReportStatusCodeLib/RuntimeDxeReportStatusCodeLib.inf VariablePolicyLib|MdeModulePkg/Library/VariablePolicyLib/VariablePolicyLibRuntimeDxe.inf + BaseCryptLib|CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf + OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf + IntrinsicLib|CryptoPkg/Library/IntrinsicLib/IntrinsicLib.inf + RngLib|MdePkg/Library/BaseRngLibTimerLib/BaseRngLibTimerLib.inf + +!if $(SECURE_BOOT_ENABLE) == TRUE + AuthVariableLib|SecurityPkg/Library/AuthVariableLib/AuthVariableLib.inf + # re-use the UserPhysicalPresent() dummy implementation from the ovmf tree + PlatformSecureLib|OvmfPkg/Library/PlatformSecureLib/PlatformSecureLib.inf +!else + AuthVariableLib|MdeModulePkg/Library/AuthVariableLibNull/AuthVariableLibNull.inf +!endif [LibraryClasses.common.UEFI_DRIVER,LibraryClasses.common.UEFI_APPLICATION] PcdLib|MdePkg/Library/DxePcdLib/DxePcdLib.inf @@ -454,7 +498,22 @@ # # Components that produce the architectural protocols # - MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf + MdeModulePkg/Universal/SecurityStubDxe/SecurityStubDxe.inf { + +!if $(SECURE_BOOT_ENABLE) == TRUE + NULL|SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.inf +!endif +!if $(TPM_ENABLE) == TRUE + NULL|SecurityPkg/Library/DxeTpmMeasureBootLib/DxeTpmMeasureBootLib.inf + NULL|SecurityPkg/Library/DxeTpm2MeasureBootLib/DxeTpm2MeasureBootLib.inf +!endif + } + +!if $(SECURE_BOOT_ENABLE) == TRUE + SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf + SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf +!endif + UefiCpuPkg/CpuDxe/CpuDxe.inf MdeModulePkg/Universal/BdsDxe/BdsDxe.inf MdeModulePkg/Logo/LogoDxe.inf @@ -476,8 +535,12 @@ PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf !if $(EMU_VARIABLE_ENABLE) == TRUE MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf - MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf + MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf { + + NULL|MdeModulePkg/Library/VarCheckUefiLib/VarCheckUefiLib.inf + } !endif + # # Following are the DXE drivers # diff --git a/UefiPayloadPkg/UefiPayloadPkg.fdf b/UefiPayloadPkg/UefiPayloadPkg.fdf index 5b3e0e6159..5cdf6cce1c 100644 --- a/UefiPayloadPkg/UefiPayloadPkg.fdf +++ b/UefiPayloadPkg/UefiPayloadPkg.fdf @@ -92,6 +92,10 @@ APRIORI DXE { INF UefiPayloadPkg/BlSMMStoreDxe/BlSMMStoreDxe.inf # After DevicePathDxe INF MdeModulePkg/Universal/FaultTolerantWriteDxe/FaultTolerantWriteDxe.inf # After BlSMMStoreDxe, RuntimeDxe INF MdeModulePkg/Universal/Variable/RuntimeDxe/VariableRuntimeDxe.inf # After FaultTolerantWriteDxe +!if $(SECURE_BOOT_ENABLE) == TRUE + INF PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf + INF SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf # After SMBusConfigLoader and PcatRealTimeClockRuntimeDxe, before Tcg2Dxe +!endif } # @@ -226,6 +230,35 @@ INF MdeModulePkg/Universal/Acpi/AcpiTableDxe/AcpiTableDxe.inf # INF SecurityPkg/RandomNumberGenerator/RngDxe/RngDxe.inf +# +# Security +# +!if $(SECURE_BOOT_ENABLE) == TRUE + INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf + INF SecurityPkg/VariableAuthenticated/SecureBootDefaultKeysDxe/SecureBootDefaultKeysDxe.inf + + FILE FREEFORM = 85254ea7-4759-4fc4-82d4-5eed5fb0a4a0 { + SECTION RAW = UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/pk.crt + SECTION UI = "PK Default" + } + + FILE FREEFORM = 6f64916e-9f7a-4c35-b952-cd041efb05a3 { + SECTION RAW = UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/kek.crt + SECTION UI = "KEK Default" + } + + FILE FREEFORM = c491d352-7623-4843-accc-2791a7574421 { + SECTION RAW = UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/db-1.crt + SECTION RAW = UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/db-2.crt + SECTION UI = "DB Default" + } + + FILE FREEFORM = 5740766a-718e-4dc0-9935-c36f7d3f884f { + SECTION RAW = UefiPayloadPkg/SecureBootEnrollDefaultKeys/keys/crl.bin + SECTION UI = "DBX Default" + } +!endif + # # Shell # @@ -346,3 +379,16 @@ SET gEfiMdeModulePkgTokenSpaceGuid.PcdFlashNvStorageFtwSpareSize = $(BLOCK_SIZE) FILE RAW = $(NAMED_GUID) { RAW RAW |.raw } + +[RULE.COMMON.USER_DEFINED] + FILE FREEFORM = $(NAMED_GUID) { + RAW BIN |.crt + RAW BIN |.bin + } + +[RULE.COMMON.USER_DEFINED.BINARY] + FILE FREEFORM = $(NAMED_GUID) { + RAW BIN |.crt + RAW BIN |.bin + UI STRING="$(MODULE_NAME)" Optional + }