From d33896d88d9d32d516129e92e25b80f8fddc6f7b Mon Sep 17 00:00:00 2001 From: Guo Mang Date: Wed, 25 Apr 2018 17:23:25 +0800 Subject: Remove Core Package Remove Core Package since we will use EDK2 code from edk2 repository: https://github.com/tianocore/edk2 Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Guo Mang --- .../SecureBootConfigDxe/SecureBootConfigImpl.c | 4080 -------------------- 1 file changed, 4080 deletions(-) delete mode 100644 Core/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c (limited to 'Core/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c') diff --git a/Core/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/Core/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c deleted file mode 100644 index 2eaf24633d..0000000000 --- a/Core/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ /dev/null @@ -1,4080 +0,0 @@ -/** @file - HII Config Access protocol implementation of SecureBoot configuration module. - -Copyright (c) 2011 - 2017, 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. - -**/ - -#include "SecureBootConfigImpl.h" - -CHAR16 mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION"; - -SECUREBOOT_CONFIG_PRIVATE_DATA mSecureBootConfigPrivateDateTemplate = { - SECUREBOOT_CONFIG_PRIVATE_DATA_SIGNATURE, - { - SecureBootExtractConfig, - SecureBootRouteConfig, - SecureBootCallback - } -}; - -HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath = { - { - { - HARDWARE_DEVICE_PATH, - HW_VENDOR_DP, - { - (UINT8) (sizeof (VENDOR_DEVICE_PATH)), - (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) - } - }, - SECUREBOOT_CONFIG_FORM_SET_GUID - }, - { - END_DEVICE_PATH_TYPE, - END_ENTIRE_DEVICE_PATH_SUBTYPE, - { - (UINT8) (END_DEVICE_PATH_LENGTH), - (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) - } - } -}; - - -BOOLEAN mIsEnterSecureBootForm = FALSE; - -// -// OID ASN.1 Value for Hash Algorithms -// -UINT8 mHashOidValue[] = { - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, // OBJ_md5 - 0x2B, 0x0E, 0x03, 0x02, 0x1A, // OBJ_sha1 - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, // OBJ_sha224 - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, // OBJ_sha256 - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, // OBJ_sha384 - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, // OBJ_sha512 - }; - -HASH_TABLE mHash[] = { - { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL }, - { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final}, - { L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final}, - { L"SHA512", 64, &mHashOidValue[40], 9, Sha512GetContextSize, Sha512Init, Sha512Update, Sha512Final} -}; - -// -// Variable Definitions -// -UINT32 mPeCoffHeaderOffset = 0; -WIN_CERTIFICATE *mCertificate = NULL; -IMAGE_TYPE mImageType; -UINT8 *mImageBase = NULL; -UINTN mImageSize = 0; -UINT8 mImageDigest[MAX_DIGEST_SIZE]; -UINTN mImageDigestSize; -EFI_GUID mCertType; -EFI_IMAGE_SECURITY_DATA_DIRECTORY *mSecDataDir = NULL; -EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION mNtHeader; - -// -// Possible DER-encoded certificate file suffixes, end with NULL pointer. -// -CHAR16* mDerEncodedSuffix[] = { - L".cer", - L".der", - L".crt", - NULL -}; -CHAR16* mSupportX509Suffix = L"*.cer/der/crt"; - -SECUREBOOT_CONFIG_PRIVATE_DATA *gSecureBootPrivateData = NULL; - -/** - This code cleans up enrolled file by closing file & free related resources attached to - enrolled file. - - @param[in] FileContext FileContext cached in SecureBootConfig driver - -**/ -VOID -CloseEnrolledFile( - IN SECUREBOOT_FILE_CONTEXT *FileContext -) -{ - if (FileContext->FHandle != NULL) { - CloseFile (FileContext->FHandle); - FileContext->FHandle = NULL; - } - - if (FileContext->FileName != NULL){ - FreePool(FileContext->FileName); - FileContext->FileName = NULL; - } - FileContext->FileType = UNKNOWN_FILE_TYPE; - -} - -/** - This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix. - - @param[in] FileSuffix The suffix of the input certificate file - - @retval TRUE It's a DER-encoded certificate. - @retval FALSE It's NOT a DER-encoded certificate. - -**/ -BOOLEAN -IsDerEncodeCertificate ( - IN CONST CHAR16 *FileSuffix -) -{ - UINTN Index; - for (Index = 0; mDerEncodedSuffix[Index] != NULL; Index++) { - if (StrCmp (FileSuffix, mDerEncodedSuffix[Index]) == 0) { - return TRUE; - } - } - return FALSE; -} - -/** - This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format -The function reads file content but won't open/close given FileHandle. - - @param[in] FileHandle The FileHandle to be checked - - @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format. - @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format. - -**/ -BOOLEAN -IsAuthentication2Format ( - IN EFI_FILE_HANDLE FileHandle -) -{ - EFI_STATUS Status; - EFI_VARIABLE_AUTHENTICATION_2 *Auth2; - BOOLEAN IsAuth2Format; - - IsAuth2Format = FALSE; - - // - // Read the whole file content - // - Status = ReadFileContent( - FileHandle, - (VOID **) &mImageBase, - &mImageSize, - 0 - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - Auth2 = (EFI_VARIABLE_AUTHENTICATION_2 *)mImageBase; - if (Auth2->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) { - goto ON_EXIT; - } - - if (CompareGuid(&gEfiCertPkcs7Guid, &Auth2->AuthInfo.CertType)) { - IsAuth2Format = TRUE; - } - -ON_EXIT: - // - // Do not close File. simply check file content - // - if (mImageBase != NULL) { - FreePool (mImageBase); - mImageBase = NULL; - } - - return IsAuth2Format; -} - -/** - Set Secure Boot option into variable space. - - @param[in] VarValue The option of Secure Boot. - - @retval EFI_SUCCESS The operation is finished successfully. - @retval Others Other errors as indicated. - -**/ -EFI_STATUS -SaveSecureBootVariable ( - IN UINT8 VarValue - ) -{ - EFI_STATUS Status; - - Status = gRT->SetVariable ( - EFI_SECURE_BOOT_ENABLE_NAME, - &gEfiSecureBootEnableDisableGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, - sizeof (UINT8), - &VarValue - ); - 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 resourses 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 - ); -} - -/** - Generate the PK signature list from the X509 Certificate storing file (.cer) - - @param[in] X509File FileHandle of X509 Certificate storing file. - @param[out] PkCert Point to the data buffer to store the signature list. - - @return EFI_UNSUPPORTED Unsupported Key Length. - @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list. - -**/ -EFI_STATUS -CreatePkX509SignatureList ( - IN EFI_FILE_HANDLE X509File, - OUT EFI_SIGNATURE_LIST **PkCert - ) -{ - EFI_STATUS Status; - UINT8 *X509Data; - UINTN X509DataSize; - EFI_SIGNATURE_DATA *PkCertData; - - X509Data = NULL; - PkCertData = NULL; - X509DataSize = 0; - - Status = ReadFileContent (X509File, (VOID**) &X509Data, &X509DataSize, 0); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - ASSERT (X509Data != NULL); - - // - // Allocate space for PK certificate list and initialize it. - // Create PK database entry with SignatureHeaderSize equals 0. - // - *PkCert = (EFI_SIGNATURE_LIST*) AllocateZeroPool ( - sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 - + X509DataSize - ); - if (*PkCert == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - (*PkCert)->SignatureListSize = (UINT32) (sizeof(EFI_SIGNATURE_LIST) - + sizeof(EFI_SIGNATURE_DATA) - 1 - + X509DataSize); - (*PkCert)->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); - (*PkCert)->SignatureHeaderSize = 0; - CopyGuid (&(*PkCert)->SignatureType, &gEfiCertX509Guid); - PkCertData = (EFI_SIGNATURE_DATA*) ((UINTN)(*PkCert) - + sizeof(EFI_SIGNATURE_LIST) - + (*PkCert)->SignatureHeaderSize); - CopyGuid (&PkCertData->SignatureOwner, &gEfiGlobalVariableGuid); - // - // Fill the PK database with PKpub data from X509 certificate file. - // - CopyMem (&(PkCertData->SignatureData[0]), X509Data, X509DataSize); - -ON_EXIT: - - if (X509Data != NULL) { - FreePool (X509Data); - } - - if (EFI_ERROR(Status) && *PkCert != NULL) { - FreePool (*PkCert); - *PkCert = NULL; - } - - return Status; -} - -/** - Enroll new PK into the System without original PK's authentication. - - The SignatureOwner GUID will be the same with PK's vendorguid. - - @param[in] PrivateData The module's private data. - - @retval EFI_SUCCESS New PK enrolled successfully. - @retval EFI_INVALID_PARAMETER The parameter is invalid. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - -**/ -EFI_STATUS -EnrollPlatformKey ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA* Private - ) -{ - EFI_STATUS Status; - UINT32 Attr; - UINTN DataSize; - EFI_SIGNATURE_LIST *PkCert; - UINT16* FilePostFix; - UINTN NameLength; - - if (Private->FileContext->FileName == NULL) { - return EFI_INVALID_PARAMETER; - } - - PkCert = NULL; - - Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Parse the file's postfix. Only support DER encoded X.509 certificate files. - // - NameLength = StrLen (Private->FileContext->FileName); - if (NameLength <= 4) { - return EFI_INVALID_PARAMETER; - } - FilePostFix = Private->FileContext->FileName + NameLength - 4; - if (!IsDerEncodeCertificate(FilePostFix)) { - DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix)); - return EFI_INVALID_PARAMETER; - } - DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName)); - DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix)); - - // - // Prase the selected PK file and generature PK certificate list. - // - Status = CreatePkX509SignatureList ( - Private->FileContext->FHandle, - &PkCert - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - ASSERT (PkCert != NULL); - - // - // Set Platform Key variable. - // - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS - | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; - DataSize = PkCert->SignatureListSize; - Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &PkCert); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); - goto ON_EXIT; - } - - Status = gRT->SetVariable( - EFI_PLATFORM_KEY_NAME, - &gEfiGlobalVariableGuid, - Attr, - DataSize, - PkCert - ); - if (EFI_ERROR (Status)) { - if (Status == EFI_OUT_OF_RESOURCES) { - DEBUG ((EFI_D_ERROR, "Enroll PK failed with out of resource.\n")); - } - goto ON_EXIT; - } - -ON_EXIT: - - if (PkCert != NULL) { - FreePool(PkCert); - } - - CloseEnrolledFile(Private->FileContext); - - 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). - - @param[in] PrivateData The module's private data. - - @retval EFI_SUCCESS New KEK enrolled successfully. - @retval EFI_INVALID_PARAMETER The parameter is invalid. - @retval EFI_UNSUPPORTED Unsupported command. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - -**/ -EFI_STATUS -EnrollRsa2048ToKek ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private - ) -{ - EFI_STATUS Status; - UINT32 Attr; - UINTN DataSize; - EFI_SIGNATURE_LIST *KekSigList; - UINTN KeyBlobSize; - UINT8 *KeyBlob; - CPL_KEY_INFO *KeyInfo; - EFI_SIGNATURE_DATA *KEKSigData; - UINTN KekSigListSize; - UINT8 *KeyBuffer; - UINTN KeyLenInBytes; - - Attr = 0; - DataSize = 0; - KeyBuffer = NULL; - KeyBlobSize = 0; - KeyBlob = NULL; - KeyInfo = NULL; - KEKSigData = NULL; - KekSigList = NULL; - KekSigListSize = 0; - - // - // Form the KeKpub certificate list into EFI_SIGNATURE_LIST type. - // First, We have to parse out public key data from the pbk key file. - // - Status = ReadFileContent ( - Private->FileContext->FHandle, - (VOID**) &KeyBlob, - &KeyBlobSize, - 0 - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - ASSERT (KeyBlob != NULL); - KeyInfo = (CPL_KEY_INFO *) KeyBlob; - if (KeyInfo->KeyLengthInBits / 8 != WIN_CERT_UEFI_RSA2048_SIZE) { - DEBUG ((DEBUG_ERROR, "Unsupported key length, Only RSA2048 is supported.\n")); - Status = EFI_UNSUPPORTED; - goto ON_EXIT; - } - - // - // Convert the Public key to fix octet string format represented in RSA PKCS#1. - // - KeyLenInBytes = KeyInfo->KeyLengthInBits / 8; - KeyBuffer = AllocateZeroPool (KeyLenInBytes); - if (KeyBuffer == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - Int2OctStr ( - (UINTN*) (KeyBlob + sizeof (CPL_KEY_INFO)), - KeyLenInBytes / sizeof (UINTN), - KeyBuffer, - KeyLenInBytes - ); - CopyMem(KeyBlob + sizeof(CPL_KEY_INFO), KeyBuffer, KeyLenInBytes); - - // - // Form an new EFI_SIGNATURE_LIST. - // - KekSigListSize = sizeof(EFI_SIGNATURE_LIST) - + sizeof(EFI_SIGNATURE_DATA) - 1 - + WIN_CERT_UEFI_RSA2048_SIZE; - - KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize); - if (KekSigList == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - KekSigList->SignatureListSize = sizeof(EFI_SIGNATURE_LIST) - + sizeof(EFI_SIGNATURE_DATA) - 1 - + WIN_CERT_UEFI_RSA2048_SIZE; - KekSigList->SignatureHeaderSize = 0; - KekSigList->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + WIN_CERT_UEFI_RSA2048_SIZE; - CopyGuid (&KekSigList->SignatureType, &gEfiCertRsa2048Guid); - - KEKSigData = (EFI_SIGNATURE_DATA*)((UINT8*)KekSigList + sizeof(EFI_SIGNATURE_LIST)); - CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID); - CopyMem ( - KEKSigData->SignatureData, - KeyBlob + sizeof(CPL_KEY_INFO), - WIN_CERT_UEFI_RSA2048_SIZE - ); - - // - // Check if KEK entry has been already existed. - // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the - // new KEK to original variable. - // - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS - | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; - Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); - goto ON_EXIT; - } - - Status = gRT->GetVariable( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - NULL, - &DataSize, - NULL - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - Attr |= EFI_VARIABLE_APPEND_WRITE; - } else if (Status != EFI_NOT_FOUND) { - goto ON_EXIT; - } - - // - // Done. Now we have formed the correct KEKpub database item, just set it into variable storage, - // - Status = gRT->SetVariable( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - Attr, - KekSigListSize, - KekSigList - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - -ON_EXIT: - - CloseEnrolledFile(Private->FileContext); - - if (Private->SignatureGUID != NULL) { - FreePool (Private->SignatureGUID); - Private->SignatureGUID = NULL; - } - - if (KeyBlob != NULL) { - FreePool (KeyBlob); - } - if (KeyBuffer != NULL) { - FreePool (KeyBuffer); - } - if (KekSigList != NULL) { - FreePool (KekSigList); - } - - return Status; -} - -/** - Enroll a new KEK item from X509 certificate file. - - @param[in] PrivateData The module's private data. - - @retval EFI_SUCCESS New X509 is enrolled successfully. - @retval EFI_INVALID_PARAMETER The parameter is invalid. - @retval EFI_UNSUPPORTED Unsupported command. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - -**/ -EFI_STATUS -EnrollX509ToKek ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private - ) -{ - EFI_STATUS Status; - UINTN X509DataSize; - VOID *X509Data; - EFI_SIGNATURE_DATA *KEKSigData; - EFI_SIGNATURE_LIST *KekSigList; - UINTN DataSize; - UINTN KekSigListSize; - UINT32 Attr; - - X509Data = NULL; - X509DataSize = 0; - KekSigList = NULL; - KekSigListSize = 0; - DataSize = 0; - KEKSigData = NULL; - - Status = ReadFileContent ( - Private->FileContext->FHandle, - &X509Data, - &X509DataSize, - 0 - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - ASSERT (X509Data != NULL); - - KekSigListSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize; - KekSigList = (EFI_SIGNATURE_LIST*) AllocateZeroPool (KekSigListSize); - if (KekSigList == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - // - // Fill Certificate Database parameters. - // - KekSigList->SignatureListSize = (UINT32) KekSigListSize; - KekSigList->SignatureHeaderSize = 0; - KekSigList->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); - CopyGuid (&KekSigList->SignatureType, &gEfiCertX509Guid); - - KEKSigData = (EFI_SIGNATURE_DATA*) ((UINT8*) KekSigList + sizeof (EFI_SIGNATURE_LIST)); - CopyGuid (&KEKSigData->SignatureOwner, Private->SignatureGUID); - CopyMem (KEKSigData->SignatureData, X509Data, X509DataSize); - - // - // Check if KEK been already existed. - // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the - // new kek to original variable - // - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS - | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; - Status = CreateTimeBasedPayload (&KekSigListSize, (UINT8**) &KekSigList); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); - goto ON_EXIT; - } - - Status = gRT->GetVariable( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - NULL, - &DataSize, - NULL - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - Attr |= EFI_VARIABLE_APPEND_WRITE; - } else if (Status != EFI_NOT_FOUND) { - goto ON_EXIT; - } - - Status = gRT->SetVariable( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - Attr, - KekSigListSize, - KekSigList - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - -ON_EXIT: - - CloseEnrolledFile(Private->FileContext); - - if (Private->SignatureGUID != NULL) { - FreePool (Private->SignatureGUID); - Private->SignatureGUID = NULL; - } - - if (KekSigList != NULL) { - FreePool (KekSigList); - } - - return Status; -} - -/** - Enroll new KEK into the System without PK's authentication. - The SignatureOwner GUID will be Private->SignatureGUID. - - @param[in] PrivateData The module's private data. - - @retval EFI_SUCCESS New KEK enrolled successful. - @retval EFI_INVALID_PARAMETER The parameter is invalid. - @retval others Fail to enroll KEK data. - -**/ -EFI_STATUS -EnrollKeyExchangeKey ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private - ) -{ - UINT16* FilePostFix; - EFI_STATUS Status; - UINTN NameLength; - - if ((Private->FileContext->FHandle == NULL) || (Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) { - return EFI_INVALID_PARAMETER; - } - - Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Parse the file's postfix. Supports DER-encoded X509 certificate, - // and .pbk as RSA public key file. - // - NameLength = StrLen (Private->FileContext->FileName); - if (NameLength <= 4) { - return EFI_INVALID_PARAMETER; - } - FilePostFix = Private->FileContext->FileName + NameLength - 4; - if (IsDerEncodeCertificate(FilePostFix)) { - return EnrollX509ToKek (Private); - } else if (CompareMem (FilePostFix, L".pbk",4) == 0) { - return EnrollRsa2048ToKek (Private); - } else { - // - // File type is wrong, simply close it - // - CloseEnrolledFile(Private->FileContext); - - return EFI_INVALID_PARAMETER; - } -} - -/** - Enroll a new X509 certificate into Signature Database (DB or DBX or DBT) without - KEK's authentication. - - @param[in] PrivateData The module's private data. - @param[in] VariableName Variable name of signature database, must be - EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1. - - @retval EFI_SUCCESS New X509 is enrolled successfully. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - -**/ -EFI_STATUS -EnrollX509toSigDB ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, - IN CHAR16 *VariableName - ) -{ - EFI_STATUS Status; - UINTN X509DataSize; - VOID *X509Data; - EFI_SIGNATURE_LIST *SigDBCert; - EFI_SIGNATURE_DATA *SigDBCertData; - VOID *Data; - UINTN DataSize; - UINTN SigDBSize; - UINT32 Attr; - - X509DataSize = 0; - SigDBSize = 0; - DataSize = 0; - X509Data = NULL; - SigDBCert = NULL; - SigDBCertData = NULL; - Data = NULL; - - Status = ReadFileContent ( - Private->FileContext->FHandle, - &X509Data, - &X509DataSize, - 0 - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - ASSERT (X509Data != NULL); - - SigDBSize = sizeof(EFI_SIGNATURE_LIST) + sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize; - - Data = AllocateZeroPool (SigDBSize); - if (Data == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - // - // Fill Certificate Database parameters. - // - SigDBCert = (EFI_SIGNATURE_LIST*) Data; - SigDBCert->SignatureListSize = (UINT32) SigDBSize; - SigDBCert->SignatureHeaderSize = 0; - SigDBCert->SignatureSize = (UINT32) (sizeof(EFI_SIGNATURE_DATA) - 1 + X509DataSize); - CopyGuid (&SigDBCert->SignatureType, &gEfiCertX509Guid); - - SigDBCertData = (EFI_SIGNATURE_DATA*) ((UINT8* ) SigDBCert + sizeof (EFI_SIGNATURE_LIST)); - CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID); - CopyMem ((UINT8* ) (SigDBCertData->SignatureData), X509Data, X509DataSize); - - // - // Check if signature database entry has been already existed. - // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the - // new signature data to original variable - // - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS - | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; - Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); - goto ON_EXIT; - } - - Status = gRT->GetVariable( - VariableName, - &gEfiImageSecurityDatabaseGuid, - NULL, - &DataSize, - NULL - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - Attr |= EFI_VARIABLE_APPEND_WRITE; - } else if (Status != EFI_NOT_FOUND) { - goto ON_EXIT; - } - - Status = gRT->SetVariable( - VariableName, - &gEfiImageSecurityDatabaseGuid, - Attr, - SigDBSize, - Data - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - -ON_EXIT: - - CloseEnrolledFile(Private->FileContext); - - if (Private->SignatureGUID != NULL) { - FreePool (Private->SignatureGUID); - Private->SignatureGUID = NULL; - } - - if (Data != NULL) { - FreePool (Data); - } - - if (X509Data != NULL) { - FreePool (X509Data); - } - - return Status; -} - -/** - Check whether signature is in specified database. - - @param[in] VariableName Name of database variable that is searched in. - @param[in] Signature Pointer to signature that is searched for. - @param[in] SignatureSize Size of Signature. - - @return TRUE Found the signature in the variable database. - @return FALSE Not found the signature in the variable database. - -**/ -BOOLEAN -IsSignatureFoundInDatabase ( - IN CHAR16 *VariableName, - IN UINT8 *Signature, - IN UINTN SignatureSize - ) -{ - EFI_STATUS Status; - EFI_SIGNATURE_LIST *CertList; - EFI_SIGNATURE_DATA *Cert; - UINTN DataSize; - UINT8 *Data; - UINTN Index; - UINTN CertCount; - BOOLEAN IsFound; - - // - // Read signature database variable. - // - IsFound = FALSE; - Data = NULL; - DataSize = 0; - Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL); - if (Status != EFI_BUFFER_TOO_SMALL) { - return FALSE; - } - - Data = (UINT8 *) AllocateZeroPool (DataSize); - if (Data == NULL) { - return FALSE; - } - - Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data); - if (EFI_ERROR (Status)) { - goto Done; - } - - // - // Enumerate all signature data in SigDB to check if executable's signature exists. - // - CertList = (EFI_SIGNATURE_LIST *) Data; - while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) { - CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; - Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); - if ((CertList->SignatureSize == sizeof(EFI_SIGNATURE_DATA) - 1 + SignatureSize) && (CompareGuid(&CertList->SignatureType, &gEfiCertX509Guid))) { - for (Index = 0; Index < CertCount; Index++) { - if (CompareMem (Cert->SignatureData, Signature, SignatureSize) == 0) { - // - // Find the signature in database. - // - IsFound = TRUE; - break; - } - Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize); - } - - if (IsFound) { - break; - } - } - - DataSize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); - } - -Done: - if (Data != NULL) { - FreePool (Data); - } - - return IsFound; -} - -/** - Calculate the hash of a certificate data with the specified hash algorithm. - - @param[in] CertData The certificate data to be hashed. - @param[in] CertSize The certificate size in bytes. - @param[in] HashAlg The specified hash algorithm. - @param[out] CertHash The output digest of the certificate - - @retval TRUE Successfully got the hash of the CertData. - @retval FALSE Failed to get the hash of CertData. - -**/ -BOOLEAN -CalculateCertHash ( - IN UINT8 *CertData, - IN UINTN CertSize, - IN UINT32 HashAlg, - OUT UINT8 *CertHash - ) -{ - BOOLEAN Status; - VOID *HashCtx; - UINTN CtxSize; - UINT8 *TBSCert; - UINTN TBSCertSize; - - HashCtx = NULL; - Status = FALSE; - - if (HashAlg >= HASHALG_MAX) { - return FALSE; - } - - // - // Retrieve the TBSCertificate for Hash Calculation. - // - if (!X509GetTBSCert (CertData, CertSize, &TBSCert, &TBSCertSize)) { - return FALSE; - } - - // - // 1. Initialize context of hash. - // - CtxSize = mHash[HashAlg].GetContextSize (); - HashCtx = AllocatePool (CtxSize); - ASSERT (HashCtx != NULL); - - // - // 2. Initialize a hash context. - // - Status = mHash[HashAlg].HashInit (HashCtx); - if (!Status) { - goto Done; - } - - // - // 3. Calculate the hash. - // - Status = mHash[HashAlg].HashUpdate (HashCtx, TBSCert, TBSCertSize); - if (!Status) { - goto Done; - } - - // - // 4. Get the hash result. - // - ZeroMem (CertHash, mHash[HashAlg].DigestLength); - Status = mHash[HashAlg].HashFinal (HashCtx, CertHash); - -Done: - if (HashCtx != NULL) { - FreePool (HashCtx); - } - - return Status; -} - -/** - Check whether the hash of an X.509 certificate is in forbidden database (DBX). - - @param[in] Certificate Pointer to X.509 Certificate that is searched for. - @param[in] CertSize Size of X.509 Certificate. - - @return TRUE Found the certificate hash in the forbidden database. - @return FALSE Certificate hash is Not found in the forbidden database. - -**/ -BOOLEAN -IsCertHashFoundInDbx ( - IN UINT8 *Certificate, - IN UINTN CertSize - ) -{ - BOOLEAN IsFound; - EFI_STATUS Status; - EFI_SIGNATURE_LIST *DbxList; - EFI_SIGNATURE_DATA *CertHash; - UINTN CertHashCount; - UINTN Index; - UINT32 HashAlg; - UINT8 CertDigest[MAX_DIGEST_SIZE]; - UINT8 *DbxCertHash; - UINTN SiglistHeaderSize; - UINT8 *Data; - UINTN DataSize; - - IsFound = FALSE; - HashAlg = HASHALG_MAX; - Data = NULL; - - // - // Read signature database variable. - // - DataSize = 0; - Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL); - if (Status != EFI_BUFFER_TOO_SMALL) { - return FALSE; - } - - Data = (UINT8 *) AllocateZeroPool (DataSize); - if (Data == NULL) { - return FALSE; - } - - Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data); - if (EFI_ERROR (Status)) { - goto Done; - } - - // - // Check whether the certificate hash exists in the forbidden database. - // - DbxList = (EFI_SIGNATURE_LIST *) Data; - while ((DataSize > 0) && (DataSize >= DbxList->SignatureListSize)) { - // - // Determine Hash Algorithm of Certificate in the forbidden database. - // - if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) { - HashAlg = HASHALG_SHA256; - } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) { - HashAlg = HASHALG_SHA384; - } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) { - HashAlg = HASHALG_SHA512; - } else { - DataSize -= DbxList->SignatureListSize; - DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize); - continue; - } - - // - // Calculate the hash value of current db certificate for comparision. - // - if (!CalculateCertHash (Certificate, CertSize, HashAlg, CertDigest)) { - goto Done; - } - - SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize; - CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) DbxList + SiglistHeaderSize); - CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize; - for (Index = 0; Index < CertHashCount; Index++) { - // - // Iterate each Signature Data Node within this CertList for verify. - // - DbxCertHash = CertHash->SignatureData; - if (CompareMem (DbxCertHash, CertDigest, mHash[HashAlg].DigestLength) == 0) { - // - // Hash of Certificate is found in forbidden database. - // - IsFound = TRUE; - goto Done; - } - CertHash = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertHash + DbxList->SignatureSize); - } - - DataSize -= DbxList->SignatureListSize; - DbxList = (EFI_SIGNATURE_LIST *) ((UINT8 *) DbxList + DbxList->SignatureListSize); - } - -Done: - if (Data != NULL) { - FreePool (Data); - } - - return IsFound; -} - -/** - Check whether the signature list exists in given variable data. - - It searches the signature list for the ceritificate hash by CertType. - If the signature list is found, get the offset of Database for the - next hash of a certificate. - - @param[in] Database Variable data to save signature list. - @param[in] DatabaseSize Variable size. - @param[in] SignatureType The type of the signature. - @param[out] Offset The offset to save a new hash of certificate. - - @return TRUE The signature list is found in the forbidden database. - @return FALSE The signature list is not found in the forbidden database. -**/ -BOOLEAN -GetSignaturelistOffset ( - IN EFI_SIGNATURE_LIST *Database, - IN UINTN DatabaseSize, - IN EFI_GUID *SignatureType, - OUT UINTN *Offset - ) -{ - EFI_SIGNATURE_LIST *SigList; - UINTN SiglistSize; - - if ((Database == NULL) || (DatabaseSize == 0)) { - *Offset = 0; - return FALSE; - } - - SigList = Database; - SiglistSize = DatabaseSize; - while ((SiglistSize > 0) && (SiglistSize >= SigList->SignatureListSize)) { - if (CompareGuid (&SigList->SignatureType, SignatureType)) { - *Offset = DatabaseSize - SiglistSize; - return TRUE; - } - SiglistSize -= SigList->SignatureListSize; - SigList = (EFI_SIGNATURE_LIST *) ((UINT8 *) SigList + SigList->SignatureListSize); - } - *Offset = 0; - return FALSE; -} - -/** - Enroll a new X509 certificate hash into Signature Database (dbx) without - KEK's authentication. - - @param[in] PrivateData The module's private data. - @param[in] HashAlg The hash algorithm to enroll the certificate. - @param[in] RevocationDate The revocation date of the certificate. - @param[in] RevocationTime The revocation time of the certificate. - @param[in] AlwaysRevocation Indicate whether the certificate is always revoked. - - @retval EFI_SUCCESS New X509 is enrolled successfully. - @retval EFI_INVALID_PARAMETER The parameter is invalid. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - -**/ -EFI_STATUS -EnrollX509HashtoSigDB ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, - IN UINT32 HashAlg, - IN EFI_HII_DATE *RevocationDate, - IN EFI_HII_TIME *RevocationTime, - IN BOOLEAN AlwaysRevocation - ) -{ - EFI_STATUS Status; - UINTN X509DataSize; - VOID *X509Data; - EFI_SIGNATURE_LIST *SignatureList; - UINTN SignatureListSize; - UINT8 *Data; - UINT8 *NewData; - UINTN DataSize; - UINTN DbSize; - UINT32 Attr; - EFI_SIGNATURE_DATA *SignatureData; - UINTN SignatureSize; - EFI_GUID SignatureType; - UINTN Offset; - UINT8 CertHash[MAX_DIGEST_SIZE]; - UINT16* FilePostFix; - UINTN NameLength; - EFI_TIME *Time; - - X509DataSize = 0; - DbSize = 0; - X509Data = NULL; - SignatureData = NULL; - SignatureList = NULL; - Data = NULL; - NewData = NULL; - - if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) { - return EFI_INVALID_PARAMETER; - } - - Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Parse the file's postfix. - // - NameLength = StrLen (Private->FileContext->FileName); - if (NameLength <= 4) { - return EFI_INVALID_PARAMETER; - } - FilePostFix = Private->FileContext->FileName + NameLength - 4; - if (!IsDerEncodeCertificate(FilePostFix)) { - // - // Only supports DER-encoded X509 certificate. - // - return EFI_INVALID_PARAMETER; - } - - // - // Get the certificate from file and calculate its hash. - // - Status = ReadFileContent ( - Private->FileContext->FHandle, - &X509Data, - &X509DataSize, - 0 - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - ASSERT (X509Data != NULL); - - if (!CalculateCertHash (X509Data, X509DataSize, HashAlg, CertHash)) { - goto ON_EXIT; - } - - // - // Get the variable for enrollment. - // - DataSize = 0; - Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, NULL); - if (Status == EFI_BUFFER_TOO_SMALL) { - Data = (UINT8 *) AllocateZeroPool (DataSize); - if (Data == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - Status = gRT->GetVariable (EFI_IMAGE_SECURITY_DATABASE1, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, Data); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - } - - // - // Allocate memory for Signature and fill the Signature - // - SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + sizeof (EFI_TIME) + mHash[HashAlg].DigestLength; - SignatureData = (EFI_SIGNATURE_DATA *) AllocateZeroPool (SignatureSize); - if (SignatureData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - CopyGuid (&SignatureData->SignatureOwner, Private->SignatureGUID); - CopyMem (SignatureData->SignatureData, CertHash, mHash[HashAlg].DigestLength); - - // - // Fill the time. - // - if (!AlwaysRevocation) { - Time = (EFI_TIME *)(&SignatureData->SignatureData + mHash[HashAlg].DigestLength); - Time->Year = RevocationDate->Year; - Time->Month = RevocationDate->Month; - Time->Day = RevocationDate->Day; - Time->Hour = RevocationTime->Hour; - Time->Minute = RevocationTime->Minute; - Time->Second = RevocationTime->Second; - } - - // - // Determine the GUID for certificate hash. - // - switch (HashAlg) { - case HASHALG_SHA256: - SignatureType = gEfiCertX509Sha256Guid; - break; - case HASHALG_SHA384: - SignatureType = gEfiCertX509Sha384Guid; - break; - case HASHALG_SHA512: - SignatureType = gEfiCertX509Sha512Guid; - break; - default: - return FALSE; - } - - // - // Add signature into the new variable data buffer - // - if (GetSignaturelistOffset((EFI_SIGNATURE_LIST *)Data, DataSize, &SignatureType, &Offset)) { - // - // Add the signature to the found signaturelist. - // - DbSize = DataSize + SignatureSize; - NewData = AllocateZeroPool (DbSize); - if (NewData == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - SignatureList = (EFI_SIGNATURE_LIST *)(Data + Offset); - SignatureListSize = (UINTN) ReadUnaligned32 ((UINT32 *)&SignatureList->SignatureListSize); - CopyMem (NewData, Data, Offset + SignatureListSize); - - SignatureList = (EFI_SIGNATURE_LIST *)(NewData + Offset); - WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32)(SignatureListSize + SignatureSize)); - - Offset += SignatureListSize; - CopyMem (NewData + Offset, SignatureData, SignatureSize); - CopyMem (NewData + Offset + SignatureSize, Data + Offset, DataSize - Offset); - - FreePool (Data); - Data = NewData; - DataSize = DbSize; - } else { - // - // Create a new signaturelist, and add the signature into the signaturelist. - // - DbSize = DataSize + sizeof(EFI_SIGNATURE_LIST) + SignatureSize; - NewData = AllocateZeroPool (DbSize); - if (NewData == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - // - // Fill Certificate Database parameters. - // - SignatureList = (EFI_SIGNATURE_LIST*) (NewData + DataSize); - SignatureListSize = sizeof(EFI_SIGNATURE_LIST) + SignatureSize; - WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureListSize, (UINT32) SignatureListSize); - WriteUnaligned32 ((UINT32 *) &SignatureList->SignatureSize, (UINT32) SignatureSize); - CopyGuid (&SignatureList->SignatureType, &SignatureType); - CopyMem ((UINT8* ) SignatureList + sizeof (EFI_SIGNATURE_LIST), SignatureData, SignatureSize); - if ((DataSize != 0) && (Data != NULL)) { - CopyMem (NewData, Data, DataSize); - FreePool (Data); - } - Data = NewData; - DataSize = DbSize; - } - - Status = CreateTimeBasedPayload (&DataSize, (UINT8**) &Data); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS - | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; - Status = gRT->SetVariable( - EFI_IMAGE_SECURITY_DATABASE1, - &gEfiImageSecurityDatabaseGuid, - Attr, - DataSize, - Data - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - -ON_EXIT: - - CloseEnrolledFile(Private->FileContext); - - if (Private->SignatureGUID != NULL) { - FreePool (Private->SignatureGUID); - Private->SignatureGUID = NULL; - } - - if (Data != NULL) { - FreePool (Data); - } - - if (SignatureData != NULL) { - FreePool (SignatureData); - } - - if (X509Data != NULL) { - FreePool (X509Data); - } - - return Status; -} - -/** - Check whether a certificate from a file exists in dbx. - - @param[in] PrivateData The module's private data. - @param[in] VariableName Variable name of signature database, must be - EFI_IMAGE_SECURITY_DATABASE1. - - @retval TRUE The X509 certificate is found in dbx successfully. - @retval FALSE The X509 certificate is not found in dbx. -**/ -BOOLEAN -IsX509CertInDbx ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, - IN CHAR16 *VariableName - ) -{ - EFI_STATUS Status; - UINTN X509DataSize; - VOID *X509Data; - BOOLEAN IsFound; - - // - // Read the certificate from file - // - X509DataSize = 0; - X509Data = NULL; - Status = ReadFileContent ( - Private->FileContext->FHandle, - &X509Data, - &X509DataSize, - 0 - ); - if (EFI_ERROR (Status)) { - return FALSE; - } - - // - // Check the raw certificate. - // - IsFound = FALSE; - if (IsSignatureFoundInDatabase (EFI_IMAGE_SECURITY_DATABASE1, X509Data, X509DataSize)) { - IsFound = TRUE; - goto ON_EXIT; - } - - // - // Check the hash of certificate. - // - if (IsCertHashFoundInDbx (X509Data, X509DataSize)) { - IsFound = TRUE; - goto ON_EXIT; - } - -ON_EXIT: - if (X509Data != NULL) { - FreePool (X509Data); - } - - return IsFound; -} - -/** - Reads contents of a PE/COFF image in memory buffer. - - Caution: This function may receive untrusted input. - PE/COFF image is external input, so this function will make sure the PE/COFF image content - read is within the image buffer. - - @param FileHandle Pointer to the file handle to read the PE/COFF image. - @param FileOffset Offset into the PE/COFF image to begin the read operation. - @param ReadSize On input, the size in bytes of the requested read operation. - On output, the number of bytes actually read. - @param Buffer Output buffer that contains the data read from the PE/COFF image. - - @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size -**/ -EFI_STATUS -EFIAPI -SecureBootConfigImageRead ( - IN VOID *FileHandle, - IN UINTN FileOffset, - IN OUT UINTN *ReadSize, - OUT VOID *Buffer - ) -{ - UINTN EndPosition; - - if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) { - return EFI_INVALID_PARAMETER; - } - - if (MAX_ADDRESS - FileOffset < *ReadSize) { - return EFI_INVALID_PARAMETER; - } - - EndPosition = FileOffset + *ReadSize; - if (EndPosition > mImageSize) { - *ReadSize = (UINT32)(mImageSize - FileOffset); - } - - if (FileOffset >= mImageSize) { - *ReadSize = 0; - } - - CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize); - - return EFI_SUCCESS; -} - -/** - Load PE/COFF image information into internal buffer and check its validity. - - @retval EFI_SUCCESS Successful - @retval EFI_UNSUPPORTED Invalid PE/COFF file - @retval EFI_ABORTED Serious error occurs, like file I/O error etc. - -**/ -EFI_STATUS -LoadPeImage ( - VOID - ) -{ - EFI_IMAGE_DOS_HEADER *DosHdr; - EFI_IMAGE_NT_HEADERS32 *NtHeader32; - EFI_IMAGE_NT_HEADERS64 *NtHeader64; - PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; - EFI_STATUS Status; - - NtHeader32 = NULL; - NtHeader64 = NULL; - - ZeroMem (&ImageContext, sizeof (ImageContext)); - ImageContext.Handle = (VOID *) mImageBase; - ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecureBootConfigImageRead; - - // - // Get information about the image being loaded - // - Status = PeCoffLoaderGetImageInfo (&ImageContext); - if (EFI_ERROR (Status)) { - // - // The information can't be got from the invalid PeImage - // - DEBUG ((DEBUG_INFO, "SecureBootConfigDxe: PeImage invalid. \n")); - return Status; - } - - // - // Read the Dos header - // - DosHdr = (EFI_IMAGE_DOS_HEADER*)(mImageBase); - if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) - { - // - // DOS image header is present, - // So read the PE header after the DOS image header - // - mPeCoffHeaderOffset = DosHdr->e_lfanew; - } - else - { - mPeCoffHeaderOffset = 0; - } - - // - // Read PE header and check the signature validity and machine compatibility - // - NtHeader32 = (EFI_IMAGE_NT_HEADERS32*) (mImageBase + mPeCoffHeaderOffset); - if (NtHeader32->Signature != EFI_IMAGE_NT_SIGNATURE) - { - return EFI_UNSUPPORTED; - } - - mNtHeader.Pe32 = NtHeader32; - - // - // Check the architecture field of PE header and get the Certificate Data Directory data - // Note the size of FileHeader field is constant for both IA32 and X64 arch - // - if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA32) - || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_EBC) - || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_ARMTHUMB_MIXED)) { - // - // 32-bits Architecture - // - mImageType = ImageType_IA32; - mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]); - } - else if ((NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_IA64) - || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_X64) - || (NtHeader32->FileHeader.Machine == EFI_IMAGE_MACHINE_AARCH64)) { - // - // 64-bits Architecture - // - mImageType = ImageType_X64; - NtHeader64 = (EFI_IMAGE_NT_HEADERS64 *) (mImageBase + mPeCoffHeaderOffset); - mSecDataDir = (EFI_IMAGE_SECURITY_DATA_DIRECTORY*) &(NtHeader64->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]); - } else { - return EFI_UNSUPPORTED; - } - - return EFI_SUCCESS; -} - -/** - Calculate hash of Pe/Coff image based on the authenticode image hashing in - PE/COFF Specification 8.0 Appendix A - - Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in - the function LoadPeImage (). - - @param[in] HashAlg Hash algorithm type. - - @retval TRUE Successfully hash image. - @retval FALSE Fail in hash image. - -**/ -BOOLEAN -HashPeImage ( - IN UINT32 HashAlg - ) -{ - BOOLEAN Status; - UINT16 Magic; - EFI_IMAGE_SECTION_HEADER *Section; - VOID *HashCtx; - UINTN CtxSize; - UINT8 *HashBase; - UINTN HashSize; - UINTN SumOfBytesHashed; - EFI_IMAGE_SECTION_HEADER *SectionHeader; - UINTN Index; - UINTN Pos; - - HashCtx = NULL; - SectionHeader = NULL; - Status = FALSE; - - if (HashAlg != HASHALG_SHA256) { - return FALSE; - } - - // - // Initialize context of hash. - // - ZeroMem (mImageDigest, MAX_DIGEST_SIZE); - - mImageDigestSize = SHA256_DIGEST_SIZE; - mCertType = gEfiCertSha256Guid; - - CtxSize = mHash[HashAlg].GetContextSize(); - - HashCtx = AllocatePool (CtxSize); - ASSERT (HashCtx != NULL); - - // 1. Load the image header into memory. - - // 2. Initialize a SHA hash context. - Status = mHash[HashAlg].HashInit(HashCtx); - if (!Status) { - goto Done; - } - // - // Measuring PE/COFF Image Header; - // But CheckSum field and SECURITY data directory (certificate) are excluded - // - if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - // - // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value - // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the - // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - // - Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; - } else { - // - // Get the magic value from the PE/COFF Optional Header - // - Magic = mNtHeader.Pe32->OptionalHeader.Magic; - } - - // - // 3. Calculate the distance from the base of the image header to the image checksum address. - // 4. Hash the image header from its base to beginning of the image checksum. - // - HashBase = mImageBase; - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - // - // Use PE32 offset. - // - HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN) HashBase; - } else { - // - // Use PE32+ offset. - // - HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN) HashBase; - } - - Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); - if (!Status) { - goto Done; - } - // - // 5. Skip over the image checksum (it occupies a single ULONG). - // 6. Get the address of the beginning of the Cert Directory. - // 7. Hash everything from the end of the checksum to the start of the Cert Directory. - // - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - // - // Use PE32 offset. - // - HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32); - HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase; - } else { - // - // Use PE32+ offset. - // - HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32); - HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase; - } - - Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); - if (!Status) { - goto Done; - } - // - // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.) - // 9. Hash everything from the end of the Cert Directory to the end of image header. - // - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - // - // Use PE32 offset - // - HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; - HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN) mImageBase); - } else { - // - // Use PE32+ offset. - // - HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; - HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN) mImageBase); - } - - Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); - if (!Status) { - goto Done; - } - // - // 10. Set the SUM_OF_BYTES_HASHED to the size of the header. - // - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - // - // Use PE32 offset. - // - SumOfBytesHashed = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders; - } else { - // - // Use PE32+ offset - // - SumOfBytesHashed = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders; - } - - // - // 11. Build a temporary table of pointers to all the IMAGE_SECTION_HEADER - // structures in the image. The 'NumberOfSections' field of the image - // header indicates how big the table should be. Do not include any - // IMAGE_SECTION_HEADERs in the table whose 'SizeOfRawData' field is zero. - // - SectionHeader = (EFI_IMAGE_SECTION_HEADER *) AllocateZeroPool (sizeof (EFI_IMAGE_SECTION_HEADER) * mNtHeader.Pe32->FileHeader.NumberOfSections); - ASSERT (SectionHeader != NULL); - // - // 12. Using the 'PointerToRawData' in the referenced section headers as - // a key, arrange the elements in the table in ascending order. In other - // words, sort the section headers according to the disk-file offset of - // the section. - // - Section = (EFI_IMAGE_SECTION_HEADER *) ( - mImageBase + - mPeCoffHeaderOffset + - sizeof (UINT32) + - sizeof (EFI_IMAGE_FILE_HEADER) + - mNtHeader.Pe32->FileHeader.SizeOfOptionalHeader - ); - for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) { - Pos = Index; - while ((Pos > 0) && (Section->PointerToRawData < SectionHeader[Pos - 1].PointerToRawData)) { - CopyMem (&SectionHeader[Pos], &SectionHeader[Pos - 1], sizeof (EFI_IMAGE_SECTION_HEADER)); - Pos--; - } - CopyMem (&SectionHeader[Pos], Section, sizeof (EFI_IMAGE_SECTION_HEADER)); - Section += 1; - } - - // - // 13. Walk through the sorted table, bring the corresponding section - // into memory, and hash the entire section (using the 'SizeOfRawData' - // field in the section header to determine the amount of data to hash). - // 14. Add the section's 'SizeOfRawData' to SUM_OF_BYTES_HASHED . - // 15. Repeat steps 13 and 14 for all the sections in the sorted table. - // - for (Index = 0; Index < mNtHeader.Pe32->FileHeader.NumberOfSections; Index++) { - Section = &SectionHeader[Index]; - if (Section->SizeOfRawData == 0) { - continue; - } - HashBase = mImageBase + Section->PointerToRawData; - HashSize = (UINTN) Section->SizeOfRawData; - - Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); - if (!Status) { - goto Done; - } - - SumOfBytesHashed += HashSize; - } - - // - // 16. If the file size is greater than SUM_OF_BYTES_HASHED, there is extra - // data in the file that needs to be added to the hash. This data begins - // at file offset SUM_OF_BYTES_HASHED and its length is: - // FileSize - (CertDirectory->Size) - // - if (mImageSize > SumOfBytesHashed) { - HashBase = mImageBase + SumOfBytesHashed; - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - // - // Use PE32 offset. - // - HashSize = (UINTN)( - mImageSize - - mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - - SumOfBytesHashed); - } else { - // - // Use PE32+ offset. - // - HashSize = (UINTN)( - mImageSize - - mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY].Size - - SumOfBytesHashed); - } - - Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); - if (!Status) { - goto Done; - } - } - - Status = mHash[HashAlg].HashFinal(HashCtx, mImageDigest); - -Done: - if (HashCtx != NULL) { - FreePool (HashCtx); - } - if (SectionHeader != NULL) { - FreePool (SectionHeader); - } - return Status; -} - -/** - Recognize the Hash algorithm in PE/COFF Authenticode and calculate hash of - Pe/Coff image based on the authenticated image hashing in PE/COFF Specification - 8.0 Appendix A - - @retval EFI_UNSUPPORTED Hash algorithm is not supported. - @retval EFI_SUCCESS Hash successfully. - -**/ -EFI_STATUS -HashPeImageByType ( - VOID - ) -{ - UINT8 Index; - WIN_CERTIFICATE_EFI_PKCS *PkcsCertData; - - PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *) (mImageBase + mSecDataDir->Offset); - - for (Index = 0; Index < HASHALG_MAX; Index++) { - // - // Check the Hash algorithm in PE/COFF Authenticode. - // According to PKCS#7 Definition: - // SignedData ::= SEQUENCE { - // version Version, - // digestAlgorithms DigestAlgorithmIdentifiers, - // contentInfo ContentInfo, - // .... } - // The DigestAlgorithmIdentifiers can be used to determine the hash algorithm in PE/COFF hashing - // This field has the fixed offset (+32) in final Authenticode ASN.1 data. - // Fixed offset (+32) is calculated based on two bytes of length encoding. - // - if ((*(PkcsCertData->CertData + 1) & TWO_BYTE_ENCODE) != TWO_BYTE_ENCODE) { - // - // Only support two bytes of Long Form of Length Encoding. - // - continue; - } - - // - if (CompareMem (PkcsCertData->CertData + 32, mHash[Index].OidValue, mHash[Index].OidLength) == 0) { - break; - } - } - - if (Index == HASHALG_MAX) { - return EFI_UNSUPPORTED; - } - - // - // HASH PE Image based on Hash algorithm in PE/COFF Authenticode. - // - if (!HashPeImage(Index)) { - return EFI_UNSUPPORTED; - } - - return EFI_SUCCESS; -} - -/** - Enroll a new executable's signature into Signature Database. - - @param[in] PrivateData The module's private data. - @param[in] VariableName Variable name of signature database, must be - EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1 - or EFI_IMAGE_SECURITY_DATABASE2. - - @retval EFI_SUCCESS New signature is enrolled successfully. - @retval EFI_INVALID_PARAMETER The parameter is invalid. - @retval EFI_UNSUPPORTED Unsupported command. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - -**/ -EFI_STATUS -EnrollAuthentication2Descriptor ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, - IN CHAR16 *VariableName - ) -{ - EFI_STATUS Status; - VOID *Data; - UINTN DataSize; - UINT32 Attr; - - Data = NULL; - - // - // DBT only support DER-X509 Cert Enrollment - // - if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) { - return EFI_UNSUPPORTED; - } - - // - // Read the whole file content - // - Status = ReadFileContent( - Private->FileContext->FHandle, - (VOID **) &mImageBase, - &mImageSize, - 0 - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - ASSERT (mImageBase != NULL); - - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS - | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; - - // - // Check if SigDB variable has been already existed. - // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the - // new signature data to original variable - // - DataSize = 0; - Status = gRT->GetVariable( - VariableName, - &gEfiImageSecurityDatabaseGuid, - NULL, - &DataSize, - NULL - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - Attr |= EFI_VARIABLE_APPEND_WRITE; - } else if (Status != EFI_NOT_FOUND) { - goto ON_EXIT; - } - - // - // Diretly set AUTHENTICATION_2 data to SetVariable - // - Status = gRT->SetVariable( - VariableName, - &gEfiImageSecurityDatabaseGuid, - Attr, - mImageSize, - mImageBase - ); - - DEBUG((DEBUG_INFO, "Enroll AUTH_2 data to Var:%s Status: %x\n", VariableName, Status)); - -ON_EXIT: - - CloseEnrolledFile(Private->FileContext); - - if (Data != NULL) { - FreePool (Data); - } - - if (mImageBase != NULL) { - FreePool (mImageBase); - mImageBase = NULL; - } - - return Status; - -} - - -/** - Enroll a new executable's signature into Signature Database. - - @param[in] PrivateData The module's private data. - @param[in] VariableName Variable name of signature database, must be - EFI_IMAGE_SECURITY_DATABASE, EFI_IMAGE_SECURITY_DATABASE1 - or EFI_IMAGE_SECURITY_DATABASE2. - - @retval EFI_SUCCESS New signature is enrolled successfully. - @retval EFI_INVALID_PARAMETER The parameter is invalid. - @retval EFI_UNSUPPORTED Unsupported command. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - -**/ -EFI_STATUS -EnrollImageSignatureToSigDB ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, - IN CHAR16 *VariableName - ) -{ - EFI_STATUS Status; - EFI_SIGNATURE_LIST *SigDBCert; - EFI_SIGNATURE_DATA *SigDBCertData; - VOID *Data; - UINTN DataSize; - UINTN SigDBSize; - UINT32 Attr; - WIN_CERTIFICATE_UEFI_GUID *GuidCertData; - - Data = NULL; - GuidCertData = NULL; - - if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) { - return EFI_UNSUPPORTED; - } - - // - // Form the SigDB certificate list. - // Format the data item into EFI_SIGNATURE_LIST type. - // - // We need to parse executable's signature data from specified signed executable file. - // In current implementation, we simply trust the pass-in signed executable file. - // In reality, it's OS's responsibility to verify the signed executable file. - // - - // - // Read the whole file content - // - Status = ReadFileContent( - Private->FileContext->FHandle, - (VOID **) &mImageBase, - &mImageSize, - 0 - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - ASSERT (mImageBase != NULL); - - Status = LoadPeImage (); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - if (mSecDataDir->SizeOfCert == 0) { - if (!HashPeImage (HASHALG_SHA256)) { - Status = EFI_SECURITY_VIOLATION; - goto ON_EXIT; - } - } else { - - // - // Read the certificate data - // - mCertificate = (WIN_CERTIFICATE *)(mImageBase + mSecDataDir->Offset); - - if (mCertificate->wCertificateType == WIN_CERT_TYPE_EFI_GUID) { - GuidCertData = (WIN_CERTIFICATE_UEFI_GUID*) mCertificate; - if (CompareMem (&GuidCertData->CertType, &gEfiCertTypeRsa2048Sha256Guid, sizeof(EFI_GUID)) != 0) { - Status = EFI_ABORTED; - goto ON_EXIT; - } - - if (!HashPeImage (HASHALG_SHA256)) { - Status = EFI_ABORTED; - goto ON_EXIT;; - } - - } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) { - - Status = HashPeImageByType (); - if (EFI_ERROR (Status)) { - goto ON_EXIT;; - } - } else { - Status = EFI_ABORTED; - goto ON_EXIT; - } - } - - // - // Create a new SigDB entry. - // - SigDBSize = sizeof(EFI_SIGNATURE_LIST) - + sizeof(EFI_SIGNATURE_DATA) - 1 - + (UINT32) mImageDigestSize; - - Data = (UINT8*) AllocateZeroPool (SigDBSize); - if (Data == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - // - // Adjust the Certificate Database parameters. - // - SigDBCert = (EFI_SIGNATURE_LIST*) Data; - SigDBCert->SignatureListSize = (UINT32) SigDBSize; - SigDBCert->SignatureHeaderSize = 0; - SigDBCert->SignatureSize = sizeof(EFI_SIGNATURE_DATA) - 1 + (UINT32) mImageDigestSize; - CopyGuid (&SigDBCert->SignatureType, &mCertType); - - SigDBCertData = (EFI_SIGNATURE_DATA*)((UINT8*)SigDBCert + sizeof(EFI_SIGNATURE_LIST)); - CopyGuid (&SigDBCertData->SignatureOwner, Private->SignatureGUID); - CopyMem (SigDBCertData->SignatureData, mImageDigest, mImageDigestSize); - - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS - | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; - Status = CreateTimeBasedPayload (&SigDBSize, (UINT8**) &Data); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); - goto ON_EXIT; - } - - // - // Check if SigDB variable has been already existed. - // If true, use EFI_VARIABLE_APPEND_WRITE attribute to append the - // new signature data to original variable - // - DataSize = 0; - Status = gRT->GetVariable( - VariableName, - &gEfiImageSecurityDatabaseGuid, - NULL, - &DataSize, - NULL - ); - if (Status == EFI_BUFFER_TOO_SMALL) { - Attr |= EFI_VARIABLE_APPEND_WRITE; - } else if (Status != EFI_NOT_FOUND) { - goto ON_EXIT; - } - - // - // Enroll the variable. - // - Status = gRT->SetVariable( - VariableName, - &gEfiImageSecurityDatabaseGuid, - Attr, - SigDBSize, - Data - ); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - -ON_EXIT: - - CloseEnrolledFile(Private->FileContext); - - if (Private->SignatureGUID != NULL) { - FreePool (Private->SignatureGUID); - Private->SignatureGUID = NULL; - } - - if (Data != NULL) { - FreePool (Data); - } - - if (mImageBase != NULL) { - FreePool (mImageBase); - mImageBase = NULL; - } - - return Status; -} - -/** - Enroll signature into DB/DBX/DBT without KEK's authentication. - The SignatureOwner GUID will be Private->SignatureGUID. - - @param[in] PrivateData The module's private data. - @param[in] VariableName Variable name of signature database, must be - EFI_IMAGE_SECURITY_DATABASE or EFI_IMAGE_SECURITY_DATABASE1. - - @retval EFI_SUCCESS New signature enrolled successfully. - @retval EFI_INVALID_PARAMETER The parameter is invalid. - @retval others Fail to enroll signature data. - -**/ -EFI_STATUS -EnrollSignatureDatabase ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, - IN CHAR16 *VariableName - ) -{ - UINT16* FilePostFix; - EFI_STATUS Status; - UINTN NameLength; - - if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == NULL) || (Private->SignatureGUID == NULL)) { - return EFI_INVALID_PARAMETER; - } - - Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Parse the file's postfix. - // - NameLength = StrLen (Private->FileContext->FileName); - if (NameLength <= 4) { - return EFI_INVALID_PARAMETER; - } - FilePostFix = Private->FileContext->FileName + NameLength - 4; - if (IsDerEncodeCertificate (FilePostFix)) { - // - // Supports DER-encoded X509 certificate. - // - return EnrollX509toSigDB (Private, VariableName); - } else if (IsAuthentication2Format(Private->FileContext->FHandle)){ - return EnrollAuthentication2Descriptor(Private, VariableName); - } else { - return EnrollImageSignatureToSigDB (Private, VariableName); - } -} - -/** - List all signatures in specified signature database (e.g. KEK/DB/DBX/DBT) - by GUID in the page for user to select and delete as needed. - - @param[in] PrivateData Module's private data. - @param[in] VariableName The variable name of the vendor's signature database. - @param[in] VendorGuid A unique identifier for the vendor. - @param[in] LabelNumber Label number to insert opcodes. - @param[in] FormId Form ID of current page. - @param[in] QuestionIdBase Base question id of the signature list. - - @retval EFI_SUCCESS Success to update the signature list page - @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. - -**/ -EFI_STATUS -UpdateDeletePage ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData, - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN UINT16 LabelNumber, - IN EFI_FORM_ID FormId, - IN EFI_QUESTION_ID QuestionIdBase - ) -{ - EFI_STATUS Status; - UINT32 Index; - UINTN CertCount; - UINTN GuidIndex; - VOID *StartOpCodeHandle; - VOID *EndOpCodeHandle; - EFI_IFR_GUID_LABEL *StartLabel; - EFI_IFR_GUID_LABEL *EndLabel; - UINTN DataSize; - UINT8 *Data; - EFI_SIGNATURE_LIST *CertList; - EFI_SIGNATURE_DATA *Cert; - UINT32 ItemDataSize; - CHAR16 *GuidStr; - EFI_STRING_ID GuidID; - EFI_STRING_ID Help; - - Data = NULL; - CertList = NULL; - Cert = NULL; - GuidStr = NULL; - StartOpCodeHandle = NULL; - EndOpCodeHandle = NULL; - - // - // Initialize the container for dynamic opcodes. - // - StartOpCodeHandle = HiiAllocateOpCodeHandle (); - if (StartOpCodeHandle == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - EndOpCodeHandle = HiiAllocateOpCodeHandle (); - if (EndOpCodeHandle == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - // - // Create Hii Extend Label OpCode. - // - StartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( - StartOpCodeHandle, - &gEfiIfrTianoGuid, - NULL, - sizeof (EFI_IFR_GUID_LABEL) - ); - StartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - StartLabel->Number = LabelNumber; - - EndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( - EndOpCodeHandle, - &gEfiIfrTianoGuid, - NULL, - sizeof (EFI_IFR_GUID_LABEL) - ); - EndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - EndLabel->Number = LABEL_END; - - // - // Read Variable. - // - DataSize = 0; - Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data); - if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { - goto ON_EXIT; - } - - Data = (UINT8 *) AllocateZeroPool (DataSize); - if (Data == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, Data); - if (EFI_ERROR (Status)) { - goto ON_EXIT; - } - - GuidStr = AllocateZeroPool (100); - if (GuidStr == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - // - // Enumerate all KEK pub data. - // - ItemDataSize = (UINT32) DataSize; - CertList = (EFI_SIGNATURE_LIST *) Data; - GuidIndex = 0; - - while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { - - if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid)) { - Help = STRING_TOKEN (STR_CERT_TYPE_RSA2048_SHA256_GUID); - } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { - Help = STRING_TOKEN (STR_CERT_TYPE_PCKS7_GUID); - } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid)) { - Help = STRING_TOKEN (STR_CERT_TYPE_SHA1_GUID); - } else if (CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid)) { - Help = STRING_TOKEN (STR_CERT_TYPE_SHA256_GUID); - } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid)) { - Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA256_GUID); - } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid)) { - Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA384_GUID); - } else if (CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid)) { - Help = STRING_TOKEN (STR_CERT_TYPE_X509_SHA512_GUID); - } else { - // - // The signature type is not supported in current implementation. - // - ItemDataSize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); - continue; - } - - CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; - for (Index = 0; Index < CertCount; Index++) { - Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList - + sizeof (EFI_SIGNATURE_LIST) - + CertList->SignatureHeaderSize - + Index * CertList->SignatureSize); - // - // Display GUID and help - // - GuidToString (&Cert->SignatureOwner, GuidStr, 100); - GuidID = HiiSetString (PrivateData->HiiHandle, 0, GuidStr, NULL); - HiiCreateCheckBoxOpCode ( - StartOpCodeHandle, - (EFI_QUESTION_ID) (QuestionIdBase + GuidIndex++), - 0, - 0, - GuidID, - Help, - EFI_IFR_FLAG_CALLBACK, - 0, - NULL - ); - } - - ItemDataSize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); - } - -ON_EXIT: - HiiUpdateForm ( - PrivateData->HiiHandle, - &gSecureBootConfigFormSetGuid, - FormId, - StartOpCodeHandle, - EndOpCodeHandle - ); - - if (StartOpCodeHandle != NULL) { - HiiFreeOpCodeHandle (StartOpCodeHandle); - } - - if (EndOpCodeHandle != NULL) { - HiiFreeOpCodeHandle (EndOpCodeHandle); - } - - if (Data != NULL) { - FreePool (Data); - } - - if (GuidStr != NULL) { - FreePool (GuidStr); - } - - return EFI_SUCCESS; -} - -/** - Delete a KEK entry from KEK database. - - @param[in] PrivateData Module's private data. - @param[in] QuestionId Question id of the KEK item to delete. - - @retval EFI_SUCCESS Delete kek item successfully. - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. - -**/ -EFI_STATUS -DeleteKeyExchangeKey ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData, - IN EFI_QUESTION_ID QuestionId - ) -{ - EFI_STATUS Status; - UINTN DataSize; - UINT8 *Data; - UINT8 *OldData; - UINT32 Attr; - UINT32 Index; - EFI_SIGNATURE_LIST *CertList; - EFI_SIGNATURE_LIST *NewCertList; - EFI_SIGNATURE_DATA *Cert; - UINTN CertCount; - UINT32 Offset; - BOOLEAN IsKEKItemFound; - UINT32 KekDataSize; - UINTN DeleteKekIndex; - UINTN GuidIndex; - - Data = NULL; - OldData = NULL; - CertList = NULL; - Cert = NULL; - Attr = 0; - DeleteKekIndex = QuestionId - OPTION_DEL_KEK_QUESTION_ID; - - Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get original KEK variable. - // - DataSize = 0; - Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, NULL, &DataSize, NULL); - if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) { - goto ON_EXIT; - } - - OldData = (UINT8*)AllocateZeroPool(DataSize); - if (OldData == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - Status = gRT->GetVariable (EFI_KEY_EXCHANGE_KEY_NAME, &gEfiGlobalVariableGuid, &Attr, &DataSize, OldData); - if (EFI_ERROR(Status)) { - goto ON_EXIT; - } - - // - // Allocate space for new variable. - // - Data = (UINT8*) AllocateZeroPool (DataSize); - if (Data == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - // - // Enumerate all KEK pub data and erasing the target item. - // - IsKEKItemFound = FALSE; - KekDataSize = (UINT32) DataSize; - CertList = (EFI_SIGNATURE_LIST *) OldData; - Offset = 0; - GuidIndex = 0; - while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) { - if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) || - CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid)) { - CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize)); - NewCertList = (EFI_SIGNATURE_LIST *)(Data + Offset); - Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); - Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); - CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; - for (Index = 0; Index < CertCount; Index++) { - if (GuidIndex == DeleteKekIndex ) { - // - // Find it! Skip it! - // - NewCertList->SignatureListSize -= CertList->SignatureSize; - IsKEKItemFound = TRUE; - } else { - // - // This item doesn't match. Copy it to the Data buffer. - // - CopyMem (Data + Offset, Cert, CertList->SignatureSize); - Offset += CertList->SignatureSize; - } - GuidIndex++; - Cert = (EFI_SIGNATURE_DATA *) ((UINT8*) Cert + CertList->SignatureSize); - } - } else { - // - // This List doesn't match. Copy it to the Data buffer. - // - CopyMem (Data + Offset, CertList, CertList->SignatureListSize); - Offset += CertList->SignatureListSize; - } - - KekDataSize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST*) ((UINT8*) CertList + CertList->SignatureListSize); - } - - if (!IsKEKItemFound) { - // - // Doesn't find the Kek Item! - // - Status = EFI_NOT_FOUND; - goto ON_EXIT; - } - - // - // Delete the Signature header if there is no signature in the list. - // - KekDataSize = Offset; - CertList = (EFI_SIGNATURE_LIST*) Data; - Offset = 0; - ZeroMem (OldData, KekDataSize); - while ((KekDataSize > 0) && (KekDataSize >= CertList->SignatureListSize)) { - CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; - DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount)); - if (CertCount != 0) { - CopyMem (OldData + Offset, CertList, CertList->SignatureListSize); - Offset += CertList->SignatureListSize; - } - KekDataSize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); - } - - DataSize = Offset; - if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { - Status = CreateTimeBasedPayload (&DataSize, &OldData); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); - goto ON_EXIT; - } - } - - Status = gRT->SetVariable( - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - Attr, - DataSize, - OldData - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status)); - goto ON_EXIT; - } - -ON_EXIT: - if (Data != NULL) { - FreePool(Data); - } - - if (OldData != NULL) { - FreePool(OldData); - } - - return UpdateDeletePage ( - PrivateData, - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - LABEL_KEK_DELETE, - FORMID_DELETE_KEK_FORM, - OPTION_DEL_KEK_QUESTION_ID - ); -} - -/** - Delete a signature entry from siganture database. - - @param[in] PrivateData Module's private data. - @param[in] VariableName The variable name of the vendor's signature database. - @param[in] VendorGuid A unique identifier for the vendor. - @param[in] LabelNumber Label number to insert opcodes. - @param[in] FormId Form ID of current page. - @param[in] QuestionIdBase Base question id of the signature list. - @param[in] DeleteIndex Signature index to delete. - - @retval EFI_SUCCESS Delete siganture successfully. - @retval EFI_NOT_FOUND Can't find the signature item, - @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. -**/ -EFI_STATUS -DeleteSignature ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData, - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid, - IN UINT16 LabelNumber, - IN EFI_FORM_ID FormId, - IN EFI_QUESTION_ID QuestionIdBase, - IN UINTN DeleteIndex - ) -{ - EFI_STATUS Status; - UINTN DataSize; - UINT8 *Data; - UINT8 *OldData; - UINT32 Attr; - UINT32 Index; - EFI_SIGNATURE_LIST *CertList; - EFI_SIGNATURE_LIST *NewCertList; - EFI_SIGNATURE_DATA *Cert; - UINTN CertCount; - UINT32 Offset; - BOOLEAN IsItemFound; - UINT32 ItemDataSize; - UINTN GuidIndex; - - Data = NULL; - OldData = NULL; - CertList = NULL; - Cert = NULL; - Attr = 0; - - Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Get original signature list data. - // - DataSize = 0; - Status = gRT->GetVariable (VariableName, VendorGuid, NULL, &DataSize, NULL); - if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { - goto ON_EXIT; - } - - OldData = (UINT8 *) AllocateZeroPool (DataSize); - if (OldData == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - Status = gRT->GetVariable (VariableName, VendorGuid, &Attr, &DataSize, OldData); - if (EFI_ERROR(Status)) { - goto ON_EXIT; - } - - // - // Allocate space for new variable. - // - Data = (UINT8*) AllocateZeroPool (DataSize); - if (Data == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto ON_EXIT; - } - - // - // Enumerate all signature data and erasing the target item. - // - IsItemFound = FALSE; - ItemDataSize = (UINT32) DataSize; - CertList = (EFI_SIGNATURE_LIST *) OldData; - Offset = 0; - GuidIndex = 0; - while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { - if (CompareGuid (&CertList->SignatureType, &gEfiCertRsa2048Guid) || - CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) || - CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) || - CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) || - CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) || - CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) || - CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid) - ) { - // - // Copy EFI_SIGNATURE_LIST header then calculate the signature count in this list. - // - CopyMem (Data + Offset, CertList, (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize)); - NewCertList = (EFI_SIGNATURE_LIST*) (Data + Offset); - Offset += (sizeof(EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); - Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); - CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; - for (Index = 0; Index < CertCount; Index++) { - if (GuidIndex == DeleteIndex) { - // - // Find it! Skip it! - // - NewCertList->SignatureListSize -= CertList->SignatureSize; - IsItemFound = TRUE; - } else { - // - // This item doesn't match. Copy it to the Data buffer. - // - CopyMem (Data + Offset, (UINT8*)(Cert), CertList->SignatureSize); - Offset += CertList->SignatureSize; - } - GuidIndex++; - Cert = (EFI_SIGNATURE_DATA *) ((UINT8 *) Cert + CertList->SignatureSize); - } - } else { - // - // This List doesn't match. Just copy it to the Data buffer. - // - CopyMem (Data + Offset, (UINT8*)(CertList), CertList->SignatureListSize); - Offset += CertList->SignatureListSize; - } - - ItemDataSize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); - } - - if (!IsItemFound) { - // - // Doesn't find the signature Item! - // - Status = EFI_NOT_FOUND; - goto ON_EXIT; - } - - // - // Delete the EFI_SIGNATURE_LIST header if there is no signature in the list. - // - ItemDataSize = Offset; - CertList = (EFI_SIGNATURE_LIST *) Data; - Offset = 0; - ZeroMem (OldData, ItemDataSize); - while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { - CertCount = (CertList->SignatureListSize - sizeof (EFI_SIGNATURE_LIST) - CertList->SignatureHeaderSize) / CertList->SignatureSize; - DEBUG ((DEBUG_INFO, " CertCount = %x\n", CertCount)); - if (CertCount != 0) { - CopyMem (OldData + Offset, (UINT8*)(CertList), CertList->SignatureListSize); - Offset += CertList->SignatureListSize; - } - ItemDataSize -= CertList->SignatureListSize; - CertList = (EFI_SIGNATURE_LIST *) ((UINT8 *) CertList + CertList->SignatureListSize); - } - - DataSize = Offset; - if ((Attr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { - Status = CreateTimeBasedPayload (&DataSize, &OldData); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); - goto ON_EXIT; - } - } - - Status = gRT->SetVariable( - VariableName, - VendorGuid, - Attr, - DataSize, - OldData - ); - if (EFI_ERROR (Status)) { - DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r\n", Status)); - goto ON_EXIT; - } - -ON_EXIT: - if (Data != NULL) { - FreePool(Data); - } - - if (OldData != NULL) { - FreePool(OldData); - } - - return UpdateDeletePage ( - PrivateData, - VariableName, - VendorGuid, - LabelNumber, - FormId, - QuestionIdBase - ); -} - -/** - - Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT - and STR_CUR_SECURE_BOOT_MODE_CONTENT. - - @param[in] PrivateData Module's private data. - - @return EFI_SUCCESS Update secure boot strings successfully. - @return other Fail to update secure boot strings. - -**/ -EFI_STATUS -UpdateSecureBootString( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private - ) -{ - UINT8 *SecureBoot; - - SecureBoot = NULL; - - // - // Get current secure boot state. - // - GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL); - if (SecureBoot == NULL) { - return EFI_NOT_FOUND; - } - - if (*SecureBoot == SECURE_BOOT_MODE_ENABLE) { - HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL); - } else { - HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL); - } - - FreePool(SecureBoot); - - return EFI_SUCCESS; -} - -/** - This function extracts configuration from variable. - - @param[in] Private Point to SecureBoot configuration driver private data. - @param[in, out] ConfigData Point to SecureBoot configuration private data. - -**/ -VOID -SecureBootExtractConfigFromVariable ( - IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, - IN OUT SECUREBOOT_CONFIGURATION *ConfigData - ) -{ - UINT8 *SecureBootEnable; - UINT8 *SetupMode; - UINT8 *SecureBootMode; - EFI_TIME CurrTime; - - SecureBootEnable = NULL; - SetupMode = NULL; - SecureBootMode = NULL; - - // - // Initilize the Date and Time using system time. - // - ConfigData->CertificateFormat = HASHALG_RAW; - ConfigData->AlwaysRevocation = TRUE; - gRT->GetTime (&CurrTime, NULL); - ConfigData->RevocationDate.Year = CurrTime.Year; - ConfigData->RevocationDate.Month = CurrTime.Month; - ConfigData->RevocationDate.Day = CurrTime.Day; - ConfigData->RevocationTime.Hour = CurrTime.Hour; - ConfigData->RevocationTime.Minute = CurrTime.Minute; - ConfigData->RevocationTime.Second = 0; - if (Private->FileContext->FHandle != NULL) { - ConfigData->FileEnrollType = Private->FileContext->FileType; - } else { - ConfigData->FileEnrollType = UNKNOWN_FILE_TYPE; - } - - // - // If it is Physical Presence User, set the PhysicalPresent to true. - // - if (UserPhysicalPresent()) { - ConfigData->PhysicalPresent = TRUE; - } else { - ConfigData->PhysicalPresent = FALSE; - } - - // - // If there is no PK then the Delete Pk button will be gray. - // - GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL); - if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) { - ConfigData->HasPk = FALSE; - } else { - ConfigData->HasPk = TRUE; - } - - // - // Check SecureBootEnable & Pk status, fix the inconsistence. - // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable - // Checkbox. - // - ConfigData->AttemptSecureBoot = FALSE; - GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL); - - // - // Fix Pk, SecureBootEnable inconsistence - // - if ((SetupMode != NULL) && (*SetupMode) == USER_MODE) { - ConfigData->HideSecureBoot = FALSE; - if ((SecureBootEnable != NULL) && (*SecureBootEnable == SECURE_BOOT_ENABLE)) { - ConfigData->AttemptSecureBoot = TRUE; - } - } else { - ConfigData->HideSecureBoot = TRUE; - } - - // - // Get the SecureBootMode from CustomMode variable. - // - GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL); - if (SecureBootMode == NULL) { - ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE; - } else { - ConfigData->SecureBootMode = *(SecureBootMode); - } - - if (SecureBootEnable != NULL) { - FreePool (SecureBootEnable); - } - if (SetupMode != NULL) { - FreePool (SetupMode); - } - if (SecureBootMode != NULL) { - FreePool (SecureBootMode); - } -} - -/** - This function allows a caller to extract the current configuration for one - or more named elements from the target driver. - - @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param[in] Request A null-terminated Unicode string in - format. - @param[out] Progress On return, points to a character in the Request - string. Points to the string's null terminator if - request was successful. Points to the most recent - '&' before the first failing name/value pair (or - the beginning of the string if the failure is in - the first name/value pair) if the request was not - successful. - @param[out] Results A null-terminated Unicode string in - format which has all values filled - in for the names in the Request string. String to - be allocated by the called function. - - @retval EFI_SUCCESS The Results is filled with the requested values. - @retval EFI_OUT_OF_RESOURCES Not enough memory to store the results. - @retval EFI_INVALID_PARAMETER Request is illegal syntax, or unknown name. - @retval EFI_NOT_FOUND Routing data doesn't match any storage in this - driver. - -**/ -EFI_STATUS -EFIAPI -SecureBootExtractConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Request, - OUT EFI_STRING *Progress, - OUT EFI_STRING *Results - ) -{ - EFI_STATUS Status; - UINTN BufferSize; - UINTN Size; - SECUREBOOT_CONFIGURATION Configuration; - EFI_STRING ConfigRequest; - EFI_STRING ConfigRequestHdr; - SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData; - BOOLEAN AllocatedRequest; - - if (Progress == NULL || Results == NULL) { - return EFI_INVALID_PARAMETER; - } - - AllocatedRequest = FALSE; - ConfigRequestHdr = NULL; - ConfigRequest = NULL; - Size = 0; - - ZeroMem (&Configuration, sizeof (Configuration)); - PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); - *Progress = Request; - - if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) { - return EFI_NOT_FOUND; - } - - ZeroMem(&Configuration, sizeof(SECUREBOOT_CONFIGURATION)); - - // - // Get Configuration from Variable. - // - SecureBootExtractConfigFromVariable (PrivateData, &Configuration); - - BufferSize = sizeof (SECUREBOOT_CONFIGURATION); - ConfigRequest = Request; - if ((Request == NULL) || (StrStr (Request, L"OFFSET") == NULL)) { - // - // Request is set to NULL or OFFSET is NULL, construct full request string. - // - // Allocate and fill a buffer large enough to hold the template - // followed by "&OFFSET=0&WIDTH=WWWWWWWWWWWWWWWW" followed by a Null-terminator - // - ConfigRequestHdr = HiiConstructConfigHdr (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, PrivateData->DriverHandle); - Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); - ConfigRequest = AllocateZeroPool (Size); - ASSERT (ConfigRequest != NULL); - AllocatedRequest = TRUE; - UnicodeSPrint (ConfigRequest, Size, L"%s&OFFSET=0&WIDTH=%016LX", ConfigRequestHdr, (UINT64)BufferSize); - FreePool (ConfigRequestHdr); - ConfigRequestHdr = NULL; - } - - Status = gHiiConfigRouting->BlockToConfig ( - gHiiConfigRouting, - ConfigRequest, - (UINT8 *) &Configuration, - BufferSize, - Results, - Progress - ); - - // - // Free the allocated config request string. - // - if (AllocatedRequest) { - FreePool (ConfigRequest); - } - - // - // Set Progress string to the original request string. - // - if (Request == NULL) { - *Progress = NULL; - } else if (StrStr (Request, L"OFFSET") == NULL) { - *Progress = Request + StrLen (Request); - } - - return Status; -} - -/** - This function processes the results of changes in configuration. - - @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param[in] Configuration A null-terminated Unicode string in - format. - @param[out] Progress A pointer to a string filled in with the offset of - the most recent '&' before the first failing - name/value pair (or the beginning of the string if - the failure is in the first name/value pair) or - the terminating NULL if all was successful. - - @retval EFI_SUCCESS The Results is processed successfully. - @retval EFI_INVALID_PARAMETER Configuration is NULL. - @retval EFI_NOT_FOUND Routing data doesn't match any storage in this - driver. - -**/ -EFI_STATUS -EFIAPI -SecureBootRouteConfig ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN CONST EFI_STRING Configuration, - OUT EFI_STRING *Progress - ) -{ - SECUREBOOT_CONFIGURATION IfrNvData; - UINTN BufferSize; - SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData; - EFI_STATUS Status; - - if (Configuration == NULL || Progress == NULL) { - return EFI_INVALID_PARAMETER; - } - - *Progress = Configuration; - if (!HiiIsConfigHdrMatch (Configuration, &gSecureBootConfigFormSetGuid, mSecureBootStorageName)) { - return EFI_NOT_FOUND; - } - - PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); - - // - // Get Configuration from Variable. - // - SecureBootExtractConfigFromVariable (PrivateData, &IfrNvData); - - // - // Map the Configuration to the configuration block. - // - BufferSize = sizeof (SECUREBOOT_CONFIGURATION); - Status = gHiiConfigRouting->ConfigToBlock ( - gHiiConfigRouting, - Configuration, - (UINT8 *)&IfrNvData, - &BufferSize, - Progress - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // - // Store Buffer Storage back to EFI variable if needed - // - if (!IfrNvData.HideSecureBoot) { - Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot); - if (EFI_ERROR (Status)) { - return Status; - } - } - - *Progress = Configuration + StrLen (Configuration); - return EFI_SUCCESS; -} - -/** - This function is called to provide results data to the driver. - - @param[in] This Points to the EFI_HII_CONFIG_ACCESS_PROTOCOL. - @param[in] Action Specifies the type of action taken by the browser. - @param[in] QuestionId A unique value which is sent to the original - exporting driver so that it can identify the type - of data to expect. - @param[in] Type The type of value for the question. - @param[in] Value A pointer to the data being sent to the original - exporting driver. - @param[out] ActionRequest On return, points to the action requested by the - callback function. - - @retval EFI_SUCCESS The callback successfully handled the action. - @retval EFI_OUT_OF_RESOURCES Not enough storage is available to hold the - variable and its data. - @retval EFI_DEVICE_ERROR The variable could not be saved. - @retval EFI_UNSUPPORTED The specified Action is not supported by the - callback. - -**/ -EFI_STATUS -EFIAPI -SecureBootCallback ( - IN CONST EFI_HII_CONFIG_ACCESS_PROTOCOL *This, - IN EFI_BROWSER_ACTION Action, - IN EFI_QUESTION_ID QuestionId, - IN UINT8 Type, - IN EFI_IFR_TYPE_VALUE *Value, - OUT EFI_BROWSER_ACTION_REQUEST *ActionRequest - ) -{ - EFI_INPUT_KEY Key; - EFI_STATUS Status; - RETURN_STATUS RStatus; - SECUREBOOT_CONFIG_PRIVATE_DATA *Private; - UINTN BufferSize; - SECUREBOOT_CONFIGURATION *IfrNvData; - UINT16 LabelId; - UINT8 *SecureBootEnable; - UINT8 *Pk; - UINT8 *SecureBootMode; - UINT8 *SetupMode; - CHAR16 PromptString[100]; - EFI_DEVICE_PATH_PROTOCOL *File; - UINTN NameLength; - UINT16 *FilePostFix; - SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData; - - Status = EFI_SUCCESS; - SecureBootEnable = NULL; - SecureBootMode = NULL; - SetupMode = NULL; - File = NULL; - - if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) { - return EFI_INVALID_PARAMETER; - } - - Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); - - gSecureBootPrivateData = Private; - - // - // Retrieve uncommitted data from Browser - // - BufferSize = sizeof (SECUREBOOT_CONFIGURATION); - IfrNvData = AllocateZeroPool (BufferSize); - if (IfrNvData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - - HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData); - - if (Action == EFI_BROWSER_ACTION_FORM_OPEN) { - if (QuestionId == KEY_SECURE_BOOT_MODE) { - // - // Update secure boot strings when opening this form - // - Status = UpdateSecureBootString(Private); - SecureBootExtractConfigFromVariable (Private, IfrNvData); - mIsEnterSecureBootForm = TRUE; - } else { - // - // When entering SecureBoot OPTION Form - // always close opened file & free resource - // - if ((QuestionId == KEY_SECURE_BOOT_PK_OPTION) || - (QuestionId == KEY_SECURE_BOOT_KEK_OPTION) || - (QuestionId == KEY_SECURE_BOOT_DB_OPTION) || - (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) || - (QuestionId == KEY_SECURE_BOOT_DBT_OPTION)) { - CloseEnrolledFile(Private->FileContext); - } - } - goto EXIT; - } - - if (Action == EFI_BROWSER_ACTION_RETRIEVE) { - Status = EFI_UNSUPPORTED; - if (QuestionId == KEY_SECURE_BOOT_MODE) { - if (mIsEnterSecureBootForm) { - Value->u8 = SECURE_BOOT_MODE_STANDARD; - Status = EFI_SUCCESS; - } - } - goto EXIT; - } - - if ((Action != EFI_BROWSER_ACTION_CHANGED) && - (Action != EFI_BROWSER_ACTION_CHANGING) && - (Action != EFI_BROWSER_ACTION_FORM_CLOSE) && - (Action != EFI_BROWSER_ACTION_DEFAULT_STANDARD)) { - Status = EFI_UNSUPPORTED; - goto EXIT; - } - - if (Action == EFI_BROWSER_ACTION_CHANGING) { - - switch (QuestionId) { - case KEY_SECURE_BOOT_ENABLE: - GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL); - if (NULL != SecureBootEnable) { - FreePool (SecureBootEnable); - if (EFI_ERROR (SaveSecureBootVariable (Value->u8))) { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"Only Physical Presence User could disable secure boot!", - NULL - ); - Status = EFI_UNSUPPORTED; - } else { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"Configuration changed, please reset the platform to take effect!", - NULL - ); - } - } - break; - - case KEY_SECURE_BOOT_KEK_OPTION: - case KEY_SECURE_BOOT_DB_OPTION: - case KEY_SECURE_BOOT_DBX_OPTION: - case KEY_SECURE_BOOT_DBT_OPTION: - PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); - // - // Clear Signature GUID. - // - ZeroMem (IfrNvData->SignatureGuid, sizeof (IfrNvData->SignatureGuid)); - if (Private->SignatureGUID == NULL) { - Private->SignatureGUID = (EFI_GUID *) AllocateZeroPool (sizeof (EFI_GUID)); - if (Private->SignatureGUID == NULL) { - return EFI_OUT_OF_RESOURCES; - } - } - - // - // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page - // - SecureBootExtractConfigFromVariable (PrivateData, IfrNvData); - - if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) { - LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB; - } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) { - LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBX; - } else if (QuestionId == KEY_SECURE_BOOT_DBT_OPTION) { - LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DBT; - } else { - LabelId = FORMID_ENROLL_KEK_FORM; - } - - // - // Refresh selected file. - // - CleanUpPage (LabelId, Private); - break; - case KEY_SECURE_BOOT_PK_OPTION: - LabelId = FORMID_ENROLL_PK_FORM; - // - // Refresh selected file. - // - CleanUpPage (LabelId, Private); - break; - - case FORMID_ENROLL_PK_FORM: - ChooseFile (NULL, NULL, UpdatePKFromFile, &File); - break; - - case FORMID_ENROLL_KEK_FORM: - ChooseFile (NULL, NULL, UpdateKEKFromFile, &File); - break; - - case SECUREBOOT_ENROLL_SIGNATURE_TO_DB: - ChooseFile (NULL, NULL, UpdateDBFromFile, &File); - break; - - case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX: - ChooseFile (NULL, NULL, UpdateDBXFromFile, &File); - - if (Private->FileContext->FHandle != NULL) { - // - // Parse the file's postfix. - // - NameLength = StrLen (Private->FileContext->FileName); - if (NameLength <= 4) { - return FALSE; - } - FilePostFix = Private->FileContext->FileName + NameLength - 4; - - if (IsDerEncodeCertificate (FilePostFix)) { - // - // Supports DER-encoded X509 certificate. - // - IfrNvData->FileEnrollType = X509_CERT_FILE_TYPE; - } else if (IsAuthentication2Format(Private->FileContext->FHandle)){ - IfrNvData->FileEnrollType = AUTHENTICATION_2_FILE_TYPE; - } else { - IfrNvData->FileEnrollType = PE_IMAGE_FILE_TYPE; - } - Private->FileContext->FileType = IfrNvData->FileEnrollType; - - // - // Clean up Certificate Format if File type is not X509 DER - // - if (IfrNvData->FileEnrollType != X509_CERT_FILE_TYPE) { - IfrNvData->CertificateFormat = HASHALG_RAW; - } - DEBUG((DEBUG_ERROR, "IfrNvData->FileEnrollType %d\n", Private->FileContext->FileType)); - } - - break; - - case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT: - ChooseFile (NULL, NULL, UpdateDBTFromFile, &File); - break; - - case KEY_SECURE_BOOT_DELETE_PK: - if (Value->u8) { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"Are you sure you want to delete PK? Secure boot will be disabled!", - L"Press 'Y' to delete PK and exit, 'N' to discard change and return", - NULL - ); - if (Key.UnicodeChar == 'y' || Key.UnicodeChar == 'Y') { - Status = DeletePlatformKey (); - if (EFI_ERROR (Status)) { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"Only Physical Presence User could delete PK in custom mode!", - NULL - ); - } - } - } - break; - - case KEY_DELETE_KEK: - UpdateDeletePage ( - Private, - EFI_KEY_EXCHANGE_KEY_NAME, - &gEfiGlobalVariableGuid, - LABEL_KEK_DELETE, - FORMID_DELETE_KEK_FORM, - OPTION_DEL_KEK_QUESTION_ID - ); - break; - - case SECUREBOOT_DELETE_SIGNATURE_FROM_DB: - UpdateDeletePage ( - Private, - EFI_IMAGE_SECURITY_DATABASE, - &gEfiImageSecurityDatabaseGuid, - LABEL_DB_DELETE, - SECUREBOOT_DELETE_SIGNATURE_FROM_DB, - OPTION_DEL_DB_QUESTION_ID - ); - break; - - case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX: - UpdateDeletePage ( - Private, - EFI_IMAGE_SECURITY_DATABASE1, - &gEfiImageSecurityDatabaseGuid, - LABEL_DBX_DELETE, - SECUREBOOT_DELETE_SIGNATURE_FROM_DBX, - OPTION_DEL_DBX_QUESTION_ID - ); - - break; - - case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT: - UpdateDeletePage ( - Private, - EFI_IMAGE_SECURITY_DATABASE2, - &gEfiImageSecurityDatabaseGuid, - LABEL_DBT_DELETE, - SECUREBOOT_DELETE_SIGNATURE_FROM_DBT, - OPTION_DEL_DBT_QUESTION_ID - ); - - break; - - case KEY_VALUE_SAVE_AND_EXIT_KEK: - Status = EnrollKeyExchangeKey (Private); - if (EFI_ERROR (Status)) { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"ERROR: Unsupported file type!", - L"Only supports DER-encoded X509 certificate", - NULL - ); - } - break; - - case KEY_VALUE_SAVE_AND_EXIT_DB: - Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE); - if (EFI_ERROR (Status)) { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"ERROR: Unsupported file type!", - L"Only supports DER-encoded X509 certificate and executable EFI image", - NULL - ); - } - break; - - case KEY_VALUE_SAVE_AND_EXIT_DBX: - if (IsX509CertInDbx (Private, EFI_IMAGE_SECURITY_DATABASE1)) { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"Enrollment failed! Same certificate had already been in the dbx!", - NULL - ); - - // - // Cert already exists in DBX. Close opened file before exit. - // - CloseEnrolledFile(Private->FileContext); - break; - } - - if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) { - Status = EnrollX509HashtoSigDB ( - Private, - IfrNvData->CertificateFormat, - &IfrNvData->RevocationDate, - &IfrNvData->RevocationTime, - IfrNvData->AlwaysRevocation - ); - IfrNvData->CertificateFormat = HASHALG_RAW; - } else { - Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1); - } - if (EFI_ERROR (Status)) { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"ERROR: Unsupported file type!", - L"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image", - NULL - ); - } - break; - - case KEY_VALUE_SAVE_AND_EXIT_DBT: - Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE2); - if (EFI_ERROR (Status)) { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"ERROR: Unsupported file type!", - L"Only supports DER-encoded X509 certificate.", - NULL - ); - } - break; - case KEY_VALUE_SAVE_AND_EXIT_PK: - Status = EnrollPlatformKey (Private); - if (EFI_ERROR (Status)) { - UnicodeSPrint ( - PromptString, - sizeof (PromptString), - L"Only DER encoded certificate file (%s) is supported.", - mSupportX509Suffix - ); - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"ERROR: Unsupported file type!", - PromptString, - NULL - ); - } - break; - default: - if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) && - (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) { - DeleteKeyExchangeKey (Private, QuestionId); - } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) && - (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) { - DeleteSignature ( - Private, - EFI_IMAGE_SECURITY_DATABASE, - &gEfiImageSecurityDatabaseGuid, - LABEL_DB_DELETE, - SECUREBOOT_DELETE_SIGNATURE_FROM_DB, - OPTION_DEL_DB_QUESTION_ID, - QuestionId - OPTION_DEL_DB_QUESTION_ID - ); - } else if ((QuestionId >= OPTION_DEL_DBX_QUESTION_ID) && - (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) { - DeleteSignature ( - Private, - EFI_IMAGE_SECURITY_DATABASE1, - &gEfiImageSecurityDatabaseGuid, - LABEL_DBX_DELETE, - SECUREBOOT_DELETE_SIGNATURE_FROM_DBX, - OPTION_DEL_DBX_QUESTION_ID, - QuestionId - OPTION_DEL_DBX_QUESTION_ID - ); - } else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) && - (QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE))) { - DeleteSignature ( - Private, - EFI_IMAGE_SECURITY_DATABASE2, - &gEfiImageSecurityDatabaseGuid, - LABEL_DBT_DELETE, - SECUREBOOT_DELETE_SIGNATURE_FROM_DBT, - OPTION_DEL_DBT_QUESTION_ID, - QuestionId - OPTION_DEL_DBT_QUESTION_ID - ); - } - break; - - case KEY_VALUE_NO_SAVE_AND_EXIT_PK: - case KEY_VALUE_NO_SAVE_AND_EXIT_KEK: - case KEY_VALUE_NO_SAVE_AND_EXIT_DB: - case KEY_VALUE_NO_SAVE_AND_EXIT_DBX: - case KEY_VALUE_NO_SAVE_AND_EXIT_DBT: - CloseEnrolledFile(Private->FileContext); - - if (Private->SignatureGUID != NULL) { - FreePool (Private->SignatureGUID); - Private->SignatureGUID = NULL; - } - break; - } - } else if (Action == EFI_BROWSER_ACTION_CHANGED) { - switch (QuestionId) { - case KEY_SECURE_BOOT_ENABLE: - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; - break; - case KEY_SECURE_BOOT_MODE: - mIsEnterSecureBootForm = FALSE; - break; - case KEY_SECURE_BOOT_KEK_GUID: - case KEY_SECURE_BOOT_SIGNATURE_GUID_DB: - case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX: - case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT: - ASSERT (Private->SignatureGUID != NULL); - RStatus = StrToGuid (IfrNvData->SignatureGuid, Private->SignatureGUID); - if (RETURN_ERROR (RStatus) || (IfrNvData->SignatureGuid[GUID_STRING_LENGTH] != L'\0')) { - Status = EFI_INVALID_PARAMETER; - break; - } - - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; - break; - case KEY_SECURE_BOOT_DELETE_PK: - GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL); - if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) { - IfrNvData->DeletePk = TRUE; - IfrNvData->HasPk = FALSE; - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; - } else { - IfrNvData->DeletePk = FALSE; - IfrNvData->HasPk = TRUE; - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; - } - if (SetupMode != NULL) { - FreePool (SetupMode); - } - break; - default: - break; - } - } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) { - if (QuestionId == KEY_HIDE_SECURE_BOOT) { - GetVariable2 (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID**)&Pk, NULL); - if (Pk == NULL) { - IfrNvData->HideSecureBoot = TRUE; - } else { - FreePool (Pk); - IfrNvData->HideSecureBoot = FALSE; - } - Value->b = IfrNvData->HideSecureBoot; - } - } else if (Action == EFI_BROWSER_ACTION_FORM_CLOSE) { - // - // Force the platform back to Standard Mode once user leave the setup screen. - // - GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL); - if (NULL != SecureBootMode && *SecureBootMode == CUSTOM_SECURE_BOOT_MODE) { - IfrNvData->SecureBootMode = STANDARD_SECURE_BOOT_MODE; - SetSecureBootMode(STANDARD_SECURE_BOOT_MODE); - } - if (SecureBootMode != NULL) { - FreePool (SecureBootMode); - } - } - -EXIT: - - if (!EFI_ERROR (Status)) { - BufferSize = sizeof (SECUREBOOT_CONFIGURATION); - HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL); - } - - FreePool (IfrNvData); - - if (File != NULL){ - FreePool(File); - File = NULL; - } - - return EFI_SUCCESS; -} - -/** - This function publish the SecureBoot configuration Form. - - @param[in, out] PrivateData Points to SecureBoot configuration private data. - - @retval EFI_SUCCESS HII Form is installed successfully. - @retval EFI_OUT_OF_RESOURCES Not enough resource for HII Form installation. - @retval Others Other errors as indicated. - -**/ -EFI_STATUS -InstallSecureBootConfigForm ( - IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData - ) -{ - EFI_STATUS Status; - EFI_HII_HANDLE HiiHandle; - EFI_HANDLE DriverHandle; - EFI_HII_CONFIG_ACCESS_PROTOCOL *ConfigAccess; - - DriverHandle = NULL; - ConfigAccess = &PrivateData->ConfigAccess; - Status = gBS->InstallMultipleProtocolInterfaces ( - &DriverHandle, - &gEfiDevicePathProtocolGuid, - &mSecureBootHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - ConfigAccess, - NULL - ); - if (EFI_ERROR (Status)) { - return Status; - } - - PrivateData->DriverHandle = DriverHandle; - - // - // Publish the HII package list - // - HiiHandle = HiiAddPackages ( - &gSecureBootConfigFormSetGuid, - DriverHandle, - SecureBootConfigDxeStrings, - SecureBootConfigBin, - NULL - ); - if (HiiHandle == NULL) { - gBS->UninstallMultipleProtocolInterfaces ( - DriverHandle, - &gEfiDevicePathProtocolGuid, - &mSecureBootHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - ConfigAccess, - NULL - ); - return EFI_OUT_OF_RESOURCES; - } - - PrivateData->HiiHandle = HiiHandle; - - PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT)); - - if (PrivateData->FileContext == NULL) { - UninstallSecureBootConfigForm (PrivateData); - return EFI_OUT_OF_RESOURCES; - } - - // - // Init OpCode Handle and Allocate space for creation of Buffer - // - mStartOpCodeHandle = HiiAllocateOpCodeHandle (); - if (mStartOpCodeHandle == NULL) { - UninstallSecureBootConfigForm (PrivateData); - return EFI_OUT_OF_RESOURCES; - } - - mEndOpCodeHandle = HiiAllocateOpCodeHandle (); - if (mEndOpCodeHandle == NULL) { - UninstallSecureBootConfigForm (PrivateData); - return EFI_OUT_OF_RESOURCES; - } - - // - // Create Hii Extend Label OpCode as the start opcode - // - mStartLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( - mStartOpCodeHandle, - &gEfiIfrTianoGuid, - NULL, - sizeof (EFI_IFR_GUID_LABEL) - ); - mStartLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - - // - // Create Hii Extend Label OpCode as the end opcode - // - mEndLabel = (EFI_IFR_GUID_LABEL *) HiiCreateGuidOpCode ( - mEndOpCodeHandle, - &gEfiIfrTianoGuid, - NULL, - sizeof (EFI_IFR_GUID_LABEL) - ); - mEndLabel->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; - mEndLabel->Number = LABEL_END; - - return EFI_SUCCESS; -} - -/** - This function removes SecureBoot configuration Form. - - @param[in, out] PrivateData Points to SecureBoot configuration private data. - -**/ -VOID -UninstallSecureBootConfigForm ( - IN OUT SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData - ) -{ - // - // Uninstall HII package list - // - if (PrivateData->HiiHandle != NULL) { - HiiRemovePackages (PrivateData->HiiHandle); - PrivateData->HiiHandle = NULL; - } - - // - // Uninstall HII Config Access Protocol - // - if (PrivateData->DriverHandle != NULL) { - gBS->UninstallMultipleProtocolInterfaces ( - PrivateData->DriverHandle, - &gEfiDevicePathProtocolGuid, - &mSecureBootHiiVendorDevicePath, - &gEfiHiiConfigAccessProtocolGuid, - &PrivateData->ConfigAccess, - NULL - ); - PrivateData->DriverHandle = NULL; - } - - if (PrivateData->SignatureGUID != NULL) { - FreePool (PrivateData->SignatureGUID); - } - - if (PrivateData->FileContext != NULL) { - FreePool (PrivateData->FileContext); - } - - FreePool (PrivateData); - - if (mStartOpCodeHandle != NULL) { - HiiFreeOpCodeHandle (mStartOpCodeHandle); - } - - if (mEndOpCodeHandle != NULL) { - HiiFreeOpCodeHandle (mEndOpCodeHandle); - } -} -- cgit v1.2.3