From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-lj1-f176.google.com (mail-lj1-f176.google.com [209.85.208.176]) by mx.groups.io with SMTP id smtpd.web10.57507.1622553177009996246 for ; Tue, 01 Jun 2021 06:12:57 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@semihalf-com.20150623.gappssmtp.com header.s=20150623 header.b=j+5YkQGz; spf=none, err=SPF record not found (domain: semihalf.com, ip: 209.85.208.176, mailfrom: gjb@semihalf.com) Received: by mail-lj1-f176.google.com with SMTP id t17so9456966ljk.7 for ; Tue, 01 Jun 2021 06:12:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=semihalf-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=WH5lS1oA5HaFh8R4m+u/dAp1PiPyX5aI19yySTZt4QQ=; b=j+5YkQGz9G7/jBBocaJradTrVfh+Ivo+j96y+P/fn3F42bpfcQfX4PBLijinmD2n8F 9q6ng7m49zI/Bw705VRdTukmqP2TFwtl/3+xu32FCOxFrcgocIAx5EMVwxkymNfWxkal EsvGbkFLo4fBVqSnSuYMix2SX+rTmlSK6VeTcsbdbGhQIKUPLtc321IhRSt5hFAekrOG ytPJfyhktI+gpdq937/uXmzSOSVUV8yTEZh7/OYNVKyKpEdk2vAjnpLBh7ZAbROfdreN kAzV4KvXZxXDZbGjgUwXolKqqiwhsLZavm7SvtuiIlQwljK51aWtRq6OkYlJj6T+DqOl jTqg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=WH5lS1oA5HaFh8R4m+u/dAp1PiPyX5aI19yySTZt4QQ=; b=W2LEbdM/nKgxovsajElJlTR2EpEROqIN7sgOCb4waKkUNCkVhjb4WMoHn4MJ1PNxXI BxAlJJT6i88iUWZZ5NarXiMThELC+W/V/ZsBa6IOocGeSBBBEBs7s2xiYWb9ygnxZjI0 9dB2F2FRoaWAsCsyX/OodjW4oFsZZfmcFZPxsVTthhd62bGKd5S2cdt42//44olghMWs mB+w5D/uTljeEdp2KlFbk1Qz8ZWz5deMpuBTge7XCU6LOy4yh0qUS7QiPi2VckpgMTX5 +ThafUKYzJoDsDjjQVz73jISToIBKHG1ELNpNzYyeJHhep7CwWnsSz2DcWMbQVoov34+ tbDQ== X-Gm-Message-State: AOAM530gB5r66s/bKpKGKbAkkQAjavl09tRfSFP6ms+OAmL9UtEAfGAl Zg67xmfIniu2SczQhE9NMkX2Uf+11mhtVrUW X-Google-Smtp-Source: ABdhPJz/0scBcSKD8TF8YSmvFtPU8WX1SSEmfm8W9sG1jfbDP3i5fyI0j+cvelqki1TGWS/mr0x6pw== X-Received: by 2002:a2e:7018:: with SMTP id l24mr2196716ljc.12.1622553174175; Tue, 01 Jun 2021 06:12:54 -0700 (PDT) Return-Path: Received: from gilgamesh.lab.semihalf.net ([83.142.187.85]) by smtp.gmail.com with ESMTPSA id y5sm1681460lfa.148.2021.06.01.06.12.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 01 Jun 2021 06:12:53 -0700 (PDT) From: "Grzegorz Bernacki" To: devel@edk2.groups.io Cc: leif@nuviainc.com, ardb+tianocore@kernel.org, Samer.El-Haj-Mahmoud@arm.com, sunny.Wang@arm.com, mw@semihalf.com, upstream@semihalf.com, jiewen.yao@intel.com, jian.j.wang@intel.com, min.m.xu@intel.com, lersek@redhat.com, Grzegorz Bernacki Subject: [PATCH v2 1/6] SecurityPkg: Create library for setting Secure Boot variables. Date: Tue, 1 Jun 2021 15:12:24 +0200 Message-Id: <20210601131229.630611-3-gjb@semihalf.com> X-Mailer: git-send-email 2.29.0 In-Reply-To: <20210601131229.630611-1-gjb@semihalf.com> References: <20210601131229.630611-1-gjb@semihalf.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit This commits add library, which consist functions related creation/removal Secure Boot variables. Some of the functions was moved from SecureBootConfigImpl.c file. Signed-off-by: Grzegorz Bernacki --- SecurityPkg/SecurityPkg.dsc | 1 + SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf | 79 ++ SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf | 1 + SecurityPkg/Include/Library/SecureBootVariableLib.h | 252 +++++ SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.c | 979 ++++++++++++++++++++ SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c | 189 +--- SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.uni | 16 + 7 files changed, 1329 insertions(+), 188 deletions(-) create mode 100644 SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf create mode 100644 SecurityPkg/Include/Library/SecureBootVariableLib.h create mode 100644 SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.c create mode 100644 SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.uni diff --git a/SecurityPkg/SecurityPkg.dsc b/SecurityPkg/SecurityPkg.dsc index bd4b810bce..854f250625 100644 --- a/SecurityPkg/SecurityPkg.dsc +++ b/SecurityPkg/SecurityPkg.dsc @@ -70,6 +70,7 @@ RpmcLib|SecurityPkg/Library/RpmcLibNull/RpmcLibNull.inf TcgEventLogRecordLib|SecurityPkg/Library/TcgEventLogRecordLib/TcgEventLogRecordLib.inf MmUnblockMemoryLib|MdePkg/Library/MmUnblockMemoryLib/MmUnblockMemoryLibNull.inf + SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf [LibraryClasses.ARM] # diff --git a/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf b/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf new file mode 100644 index 0000000000..84367841d5 --- /dev/null +++ b/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf @@ -0,0 +1,79 @@ +## @file +# Provides initialization of Secure Boot keys and databases. +# +# Copyright (c) 2021, ARM Ltd. All rights reserved.
+# Copyright (c) 2021, Semihalf All rights reserved.
+# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = SecureBootVariableLib + MODULE_UNI_FILE = SecureBootVariableLib.uni + FILE_GUID = D4FFF5CA-6D8E-4DBD-8A4B-7C7CEBD97F6F + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = SecureBootVariableLib|DXE_DRIVER DXE_RUNTIME_DRIVER UEFI_APPLICATION + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = IA32 X64 AARCH64 +# + +[Sources] + SecureBootVariableLib.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + SecurityPkg/SecurityPkg.dec + CryptoPkg/CryptoPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + MemoryAllocationLib + BaseCryptLib + DxeServicesLib + +[Guids] + ## CONSUMES ## Variable:L"SetupMode" + ## PRODUCES ## Variable:L"SetupMode" + ## CONSUMES ## Variable:L"SecureBoot" + ## PRODUCES ## Variable:L"SecureBoot" + ## PRODUCES ## Variable:L"PK" + ## PRODUCES ## Variable:L"KEK" + ## CONSUMES ## Variable:L"PKDefault" + ## CONSUMES ## Variable:L"KEKDefault" + ## CONSUMES ## Variable:L"dbDefault" + ## CONSUMES ## Variable:L"dbxDefault" + ## CONSUMES ## Variable:L"dbtDefault" + gEfiGlobalVariableGuid + + ## SOMETIMES_CONSUMES ## Variable:L"DB" + ## SOMETIMES_CONSUMES ## Variable:L"DBX" + ## SOMETIMES_CONSUMES ## Variable:L"DBT" + gEfiImageSecurityDatabaseGuid + + ## CONSUMES ## Variable:L"SecureBootEnable" + ## PRODUCES ## Variable:L"SecureBootEnable" + gEfiSecureBootEnableDisableGuid + + ## CONSUMES ## Variable:L"CustomMode" + ## PRODUCES ## Variable:L"CustomMode" + gEfiCustomModeEnableGuid + + gEfiCertTypeRsa2048Sha256Guid ## CONSUMES + gEfiCertX509Guid ## CONSUMES + gEfiCertPkcs7Guid ## CONSUMES + + gDefaultPKFileGuid + gDefaultKEKFileGuid + gDefaultdbFileGuid + gDefaultdbxFileGuid + gDefaultdbtFileGuid + diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf index 573efa6379..30d9cd8025 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigDxe.inf @@ -54,6 +54,7 @@ DevicePathLib FileExplorerLib PeCoffLib + SecureBootVariableLib [Guids] ## SOMETIMES_CONSUMES ## Variable:L"CustomMode" diff --git a/SecurityPkg/Include/Library/SecureBootVariableLib.h b/SecurityPkg/Include/Library/SecureBootVariableLib.h new file mode 100644 index 0000000000..2961c93a36 --- /dev/null +++ b/SecurityPkg/Include/Library/SecureBootVariableLib.h @@ -0,0 +1,252 @@ +/** @file + Provides a function to enroll keys based on default values. + +Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2018 Hewlett Packard Enterprise Development LP
+Copyright (c) 2021, ARM Ltd. All rights reserved.
+Copyright (c) 2021, Semihalf All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __SECURE_BOOT_VARIABLE_LIB_H__ +#define __SECURE_BOOT_VARIABLE_LIB_H__ + +/** + + Set the platform secure boot mode into "Custom" or "Standard" mode. + + @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or + CUSTOM_SECURE_BOOT_MODE. + + @return EFI_SUCCESS The platform has switched to the special mode successfully. + @return other Fail to operate the secure boot mode. + +--*/ +EFI_STATUS +SetSecureBootMode ( + IN UINT8 SecureBootMode +); + +/** + Fetches the value of SetupMode variable. + + @param[out] SetupMode Pointer to UINT8 for SetupMode output + + @retval other Error codes from GetVariable. +--*/ +BOOLEAN +EFIAPI +GetSetupMode ( + OUT UINT8 *SetupMode +); + +/** + Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2 + descriptor with the input data. NO authentication is required in this function. + + @param[in, out] DataSize On input, the size of Data buffer in bytes. + On output, the size of data returned in Data + buffer in bytes. + @param[in, out] Data On input, Pointer to data buffer to be wrapped or + pointer to NULL to wrap an empty payload. + On output, Pointer to the new payload date buffer allocated from pool, + it's caller's responsibility to free the memory when finish using it. + + @retval EFI_SUCCESS Create time based payload successfully. + @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 +CreateTimeBasedPayload ( + IN OUT UINTN *DataSize, + IN OUT UINT8 **Data +); + +/** + 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 +); + +/** + Clears the content of the 'db' variable. + + @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 +DeleteDb ( + VOID +); + +/** + 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 +); + +/** + Clears the content of the 'dbx' variable. + + @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 +DeleteDbx ( + VOID +); + +/** + 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 +); + +/** + Clears the content of the 'dbt' variable. + + @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 +DeleteDbt ( + VOID +); + +/** + 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 +); + +/** + Clears the content of the 'KEK' variable. + + @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 +DeleteKEK ( + VOID +); + +/** + Sets the content of the 'PK' variable based on 'PKDefault' 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 +); + +/** + Clears the content of the 'PK' variable. + + @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 +DeletePlatformKey ( + VOID +); + +/** 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 + ); + +/** 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 + ); + +/** 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 + ); + +/** 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 + ); + +/** 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 + ); +#endif diff --git a/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.c b/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.c new file mode 100644 index 0000000000..16bad5530a --- /dev/null +++ b/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.c @@ -0,0 +1,979 @@ +/** @file + This library provides functions to set/clear Secure Boot + keys and databases. + +Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2018 Hewlett Packard Enterprise Development LP
+Copyright (c) 2021, ARM Ltd. All rights reserved.
+Copyright (c) 2021, Semihalf All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Library/DxeServicesLib.h" + +/** Creates EFI Signature List structure. + + @param[in] Data A pointer to signature data. + @param[in] Size Size of signature data. + @param[out] SigList Created Signature List. + + @retval EFI_SUCCESS Signature List was created successfully. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +--*/ +STATIC +EFI_STATUS +CreateSigList ( + IN VOID *Data, + IN UINTN Size, + OUT EFI_SIGNATURE_LIST **SigList + ) +{ + UINTN SigListSize; + EFI_SIGNATURE_LIST *TmpSigList; + EFI_SIGNATURE_DATA *SigData; + + // + // Allocate data for Signature Database + // + SigListSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1 + Size; + TmpSigList = (EFI_SIGNATURE_LIST *) AllocateZeroPool (SigListSize); + if (TmpSigList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Only gEfiCertX509Guid type is supported + // + TmpSigList->SignatureListSize = (UINT32)SigListSize; + TmpSigList->SignatureSize = (UINT32) (sizeof (EFI_SIGNATURE_DATA) - 1 + Size); + TmpSigList->SignatureHeaderSize = 0; + CopyGuid (&TmpSigList->SignatureType, &gEfiCertX509Guid); + + // + // Copy key data + // + SigData = (EFI_SIGNATURE_DATA *) (TmpSigList + 1); + CopyGuid (&SigData->SignatureOwner, &gEfiGlobalVariableGuid); + CopyMem (&SigData->SignatureData[0], Data, Size); + + *SigList = TmpSigList; + + return EFI_SUCCESS; +} + +/** Adds new signature list to signature database. + + @param[in] SigLists A pointer to signature database. + @param[in] SiglListAppend A signature list to be added. + @param[out] *SigListOut Created signature database. + @param[out] SigListsSize A size of created signature database. + + @retval EFI_SUCCESS Signature List was added successfully. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +--*/ +STATIC +EFI_STATUS +ConcatenateSigList ( + IN EFI_SIGNATURE_LIST *SigLists, + IN EFI_SIGNATURE_LIST *SigListAppend, + OUT EFI_SIGNATURE_LIST **SigListOut, + IN OUT UINTN *SigListsSize +) +{ + EFI_SIGNATURE_LIST *TmpSigList; + UINT8 *Offset; + UINTN NewSigListsSize; + + NewSigListsSize = *SigListsSize + SigListAppend->SignatureListSize; + + TmpSigList = (EFI_SIGNATURE_LIST *) AllocateZeroPool (NewSigListsSize); + if (TmpSigList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyMem (TmpSigList, SigLists, *SigListsSize); + + Offset = (UINT8 *)TmpSigList; + Offset += *SigListsSize; + CopyMem ((VOID *)Offset, SigListAppend, SigListAppend->SignatureListSize); + + *SigListsSize = NewSigListsSize; + *SigListOut = TmpSigList; + return EFI_SUCCESS; +} + +/** + Create a EFI Signature List with data fetched from section specified as a argument. + Found keys are verified using RsaGetPublicKeyFromX509(). + + @param[in] KeyFileGuid A pointer to to the FFS filename GUID + @param[out] SigListsSize A pointer to size of signature list + @param[out] SigListsOut a pointer to a callee-allocated buffer with signature lists + + @retval EFI_SUCCESS Create time based payload successfully. + @retval EFI_NOT_FOUND Section with key has not been found. + @retval EFI_INVALID_PARAMETER Embedded key has a wrong format. + @retval Others Unexpected error happens. + +--*/ +STATIC +EFI_STATUS +SecureBootFetchData ( + IN EFI_GUID *KeyFileGuid, + OUT UINTN *SigListsSize, + OUT EFI_SIGNATURE_LIST **SigListOut +) +{ + EFI_SIGNATURE_LIST *EfiSig; + EFI_SIGNATURE_LIST *TmpEfiSig; + EFI_SIGNATURE_LIST *TmpEfiSig2; + EFI_STATUS Status; + VOID *Buffer; + VOID *RsaPubKey; + UINTN Size; + UINTN KeyIndex; + + + KeyIndex = 0; + EfiSig = NULL; + *SigListsSize = 0; + while (1) { + Status = GetSectionFromAnyFv ( + KeyFileGuid, + EFI_SECTION_RAW, + KeyIndex, + &Buffer, + &Size + ); + + if (Status == EFI_SUCCESS) { + RsaPubKey = NULL; + if (RsaGetPublicKeyFromX509 (Buffer, Size, &RsaPubKey) == FALSE) { + DEBUG ((DEBUG_ERROR, "%a: Invalid key format: %d\n", __FUNCTION__, KeyIndex)); + if (EfiSig != NULL) { + FreePool(EfiSig); + } + FreePool(Buffer); + return EFI_INVALID_PARAMETER; + } + + Status = CreateSigList (Buffer, Size, &TmpEfiSig); + + // + // Concatenate lists if more than one section found + // + if (KeyIndex == 0) { + EfiSig = TmpEfiSig; + *SigListsSize = TmpEfiSig->SignatureListSize; + } else { + ConcatenateSigList (EfiSig, TmpEfiSig, &TmpEfiSig2, SigListsSize); + FreePool (EfiSig); + FreePool (TmpEfiSig); + EfiSig = TmpEfiSig2; + } + + KeyIndex++; + FreePool (Buffer); + } if (Status == EFI_NOT_FOUND) { + break; + } + }; + + if (KeyIndex == 0) { + return EFI_NOT_FOUND; + } + + *SigListOut = EfiSig; + + return EFI_SUCCESS; +} + +/** + Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2 + descriptor with the input data. NO authentication is required in this function. + + @param[in, out] DataSize On input, the size of Data buffer in bytes. + On output, the size of data returned in Data + buffer in bytes. + @param[in, out] Data On input, Pointer to data buffer to be wrapped or + pointer to NULL to wrap an empty payload. + On output, Pointer to the new payload date buffer allocated from pool, + it's caller's responsibility to free the memory when finish using it. + + @retval EFI_SUCCESS Create time based payload successfully. + @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 +CreateTimeBasedPayload ( + IN OUT UINTN *DataSize, + IN OUT UINT8 **Data + ) +{ + EFI_STATUS Status; + UINT8 *NewData; + UINT8 *Payload; + UINTN PayloadSize; + EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; + UINTN DescriptorSize; + EFI_TIME Time; + + if (Data == NULL || DataSize == NULL) { + return EFI_INVALID_PARAMETER; + } + + // + // In Setup mode or Custom mode, the variable does not need to be signed but the + // parameters to the SetVariable() call still need to be prepared as authenticated + // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate + // data in it. + // + Payload = *Data; + PayloadSize = *DataSize; + + DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); + NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize); + if (NewData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + if ((Payload != NULL) && (PayloadSize != 0)) { + CopyMem (NewData + DescriptorSize, Payload, PayloadSize); + } + + DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); + + ZeroMem (&Time, sizeof (EFI_TIME)); + Status = gRT->GetTime (&Time, NULL); + if (EFI_ERROR (Status)) { + FreePool(NewData); + return Status; + } + Time.Pad1 = 0; + Time.Nanosecond = 0; + Time.TimeZone = 0; + Time.Daylight = 0; + Time.Pad2 = 0; + CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME)); + + DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); + DescriptorData->AuthInfo.Hdr.wRevision = 0x0200; + DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; + CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid); + + if (Payload != NULL) { + FreePool(Payload); + } + + *DataSize = DescriptorSize + PayloadSize; + *Data = NewData; + return EFI_SUCCESS; +} + +/** + Internal helper function to delete a Variable given its name and GUID, NO authentication + required. + + @param[in] VariableName Name of the Variable. + @param[in] VendorGuid GUID of the Variable. + + @retval EFI_SUCCESS Variable deleted successfully. + @retval Others The driver failed to start the device. + +--*/ +EFI_STATUS +DeleteVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid + ) +{ + EFI_STATUS Status; + VOID* Variable; + UINT8 *Data; + UINTN DataSize; + UINT32 Attr; + + GetVariable2 (VariableName, VendorGuid, &Variable, NULL); + if (Variable == NULL) { + return EFI_SUCCESS; + } + FreePool (Variable); + + Data = NULL; + DataSize = 0; + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS + | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + + Status = CreateTimeBasedPayload (&DataSize, &Data); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status)); + return Status; + } + + Status = gRT->SetVariable ( + VariableName, + VendorGuid, + Attr, + DataSize, + Data + ); + if (Data != NULL) { + FreePool (Data); + } + return Status; +} + +/** + + Set the platform secure boot mode into "Custom" or "Standard" mode. + + @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or + CUSTOM_SECURE_BOOT_MODE. + + @return EFI_SUCCESS The platform has switched to the special mode successfully. + @return other Fail to operate the secure boot mode. + +--*/ +EFI_STATUS +SetSecureBootMode ( + IN UINT8 SecureBootMode + ) +{ + return gRT->SetVariable ( + EFI_CUSTOM_MODE_NAME, + &gEfiCustomModeEnableGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (UINT8), + &SecureBootMode + ); +} + + +/** + 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; +} + +/** + Fetches the value of SetupMode variable. + + @param[out] SetupMode Pointer to UINT8 for SetupMode output + + @retval other Retval from GetVariable. +--*/ +BOOLEAN +EFIAPI +GetSetupMode ( + OUT UINT8 *SetupMode +) +{ + UINTN Size; + EFI_STATUS Status; + + Size = sizeof (*SetupMode); + Status = gRT->GetVariable ( + EFI_SETUP_MODE_NAME, + &gEfiGlobalVariableGuid, + NULL, + &Size, + SetupMode + ); + if (EFI_ERROR (Status)) { + return Status; + } + + 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; +} + +/** + Clears the content of the 'db' variable. + + @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 +DeleteDb ( + VOID +) +{ + EFI_STATUS Status; + + Status = DeleteVariable ( + EFI_IMAGE_SECURITY_DATABASE, + &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; +} + +/** + Clears the content of the 'dbx' variable. + + @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 +DeleteDbx ( + VOID +) +{ + EFI_STATUS Status; + + Status = DeleteVariable ( + EFI_IMAGE_SECURITY_DATABASE1, + &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; +} + +/** + Clears the content of the 'dbt' variable. + + @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 +DeleteDbt ( + VOID +) +{ + EFI_STATUS Status; + + Status = DeleteVariable ( + EFI_IMAGE_SECURITY_DATABASE2, + &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; +} + +/** + Clears the content of the 'KEK' variable. + + @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 +DeleteKEK ( + VOID +) +{ + EFI_STATUS Status; + + Status = DeleteVariable ( + EFI_KEY_EXCHANGE_KEY_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; +} + +/** + Remove the PK variable. + + @retval EFI_SUCCESS Delete PK successfully. + @retval Others Could not allow to delete PK. + +--*/ +EFI_STATUS +DeletePlatformKey ( + VOID +) +{ + EFI_STATUS Status; + + Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); + if (EFI_ERROR (Status)) { + return Status; + } + + Status = DeleteVariable ( + EFI_PLATFORM_KEY_NAME, + &gEfiGlobalVariableGuid + ); + return Status; +} diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index e82bfe7757..67e5e594ed 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -9,6 +9,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include "SecureBootConfigImpl.h" #include +#include CHAR16 mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION"; @@ -237,168 +238,6 @@ SaveSecureBootVariable ( return Status; } -/** - Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2 - descriptor with the input data. NO authentication is required in this function. - - @param[in, out] DataSize On input, the size of Data buffer in bytes. - On output, the size of data returned in Data - buffer in bytes. - @param[in, out] Data On input, Pointer to data buffer to be wrapped or - pointer to NULL to wrap an empty payload. - On output, Pointer to the new payload date buffer allocated from pool, - it's caller's responsibility to free the memory when finish using it. - - @retval EFI_SUCCESS Create time based payload successfully. - @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 -CreateTimeBasedPayload ( - IN OUT UINTN *DataSize, - IN OUT UINT8 **Data - ) -{ - EFI_STATUS Status; - UINT8 *NewData; - UINT8 *Payload; - UINTN PayloadSize; - EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; - UINTN DescriptorSize; - EFI_TIME Time; - - if (Data == NULL || DataSize == NULL) { - return EFI_INVALID_PARAMETER; - } - - // - // In Setup mode or Custom mode, the variable does not need to be signed but the - // parameters to the SetVariable() call still need to be prepared as authenticated - // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate - // data in it. - // - Payload = *Data; - PayloadSize = *DataSize; - - DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); - NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize); - if (NewData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - if ((Payload != NULL) && (PayloadSize != 0)) { - CopyMem (NewData + DescriptorSize, Payload, PayloadSize); - } - - DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); - - ZeroMem (&Time, sizeof (EFI_TIME)); - Status = gRT->GetTime (&Time, NULL); - if (EFI_ERROR (Status)) { - FreePool(NewData); - return Status; - } - Time.Pad1 = 0; - Time.Nanosecond = 0; - Time.TimeZone = 0; - Time.Daylight = 0; - Time.Pad2 = 0; - CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME)); - - DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); - DescriptorData->AuthInfo.Hdr.wRevision = 0x0200; - DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; - CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid); - - if (Payload != NULL) { - FreePool(Payload); - } - - *DataSize = DescriptorSize + PayloadSize; - *Data = NewData; - return EFI_SUCCESS; -} - -/** - Internal helper function to delete a Variable given its name and GUID, NO authentication - required. - - @param[in] VariableName Name of the Variable. - @param[in] VendorGuid GUID of the Variable. - - @retval EFI_SUCCESS Variable deleted successfully. - @retval Others The driver failed to start the device. - -**/ -EFI_STATUS -DeleteVariable ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid - ) -{ - EFI_STATUS Status; - VOID* Variable; - UINT8 *Data; - UINTN DataSize; - UINT32 Attr; - - GetVariable2 (VariableName, VendorGuid, &Variable, NULL); - if (Variable == NULL) { - return EFI_SUCCESS; - } - FreePool (Variable); - - Data = NULL; - DataSize = 0; - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; - - Status = CreateTimeBasedPayload (&DataSize, &Data); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); - return Status; - } - - Status = gRT->SetVariable ( - VariableName, - VendorGuid, - Attr, - DataSize, - Data - ); - if (Data != NULL) { - FreePool (Data); - } - return Status; -} - -/** - - Set the platform secure boot mode into "Custom" or "Standard" mode. - - @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or - CUSTOM_SECURE_BOOT_MODE. - - @return EFI_SUCCESS The platform has switched to the special mode successfully. - @return other Fail to operate the secure boot mode. - -**/ -EFI_STATUS -SetSecureBootMode ( - IN UINT8 SecureBootMode - ) -{ - return gRT->SetVariable ( - EFI_CUSTOM_MODE_NAME, - &gEfiCustomModeEnableGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, - sizeof (UINT8), - &SecureBootMode - ); -} - /** This code checks if the encode type and key strength of X.509 certificate is qualified. @@ -646,32 +485,6 @@ ON_EXIT: return Status; } -/** - Remove the PK variable. - - @retval EFI_SUCCESS Delete PK successfully. - @retval Others Could not allow to delete PK. - -**/ -EFI_STATUS -DeletePlatformKey ( - VOID -) -{ - EFI_STATUS Status; - - Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); - if (EFI_ERROR (Status)) { - return Status; - } - - Status = DeleteVariable ( - EFI_PLATFORM_KEY_NAME, - &gEfiGlobalVariableGuid - ); - return Status; -} - /** Enroll a new KEK item from public key storing file (*.pbk). diff --git a/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.uni b/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.uni new file mode 100644 index 0000000000..2c51e4db53 --- /dev/null +++ b/SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.uni @@ -0,0 +1,16 @@ +// /** @file +// +// Provides initialization of Secure Boot keys and databases. +// +// Copyright (c) 2021, ARM Ltd. All rights reserved.
+// Copyright (c) 2021, Semihalf All rights reserved.
+// +// SPDX-License-Identifier: BSD-2-Clause-Patent +// +// **/ + + +#string STR_MODULE_ABSTRACT #language en-US "Provides function to initialize PK, KEK and databases based on default variables." + +#string STR_MODULE_DESCRIPTION #language en-US "Provides function to initialize PK, KEK and databases based on default variables." + -- 2.25.1