diff --git a/DasharoModulePkg/Application/SovereignBootWizard/BootOptionParsing.c b/DasharoModulePkg/Application/SovereignBootWizard/BootOptionParsing.c index 9aed6bbbaa..996ae7eb4d 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/BootOptionParsing.c +++ b/DasharoModulePkg/Application/SovereignBootWizard/BootOptionParsing.c @@ -11,7 +11,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent /// /// Boot Option from variable Menu /// -SV_MENU_OPTION BootOptionMenu = { +SV_MENU_OPTION mBootOptionMenu = { SOVEREIGN_BOOT_MENU_OPTION_SIGNATURE, { NULL }, 0 @@ -489,15 +489,14 @@ CheckIfEntryIsDuplicate ( } Index = 0; - while (Index < BootOptionMenu.MenuNumber) { - BootloaderEntry = GetMenuEntry (&BootOptionMenu, Index++); + while (Index < mBootOptionMenu.MenuNumber) { + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, Index++); if (BootloaderEntry == NULL) { DEBUG ((DEBUG_WARN, "Bootloader entry is NULL\n")); continue; } if (MenuPathsAreEqual (MenuEntry, BootloaderEntry)) { - DEBUG ((DEBUG_WARN, "Found duplicate entry\n")); return TRUE; } } @@ -640,7 +639,7 @@ FillMenuEntryFromDevicePath ( /** - Build the BootOptionMenu according to BootOrder Variable. + Build the mBootOptionMenu according to BootOrder Variable. This Routine will access the Boot#### to get EFI_LOAD_OPTION. @param CallbackData The BMM context data. @@ -666,7 +665,7 @@ GetBootOptions ( MenuCount = 0; BootOrderListSize = 0; BootOrderList = NULL; - InitializeListHead (&BootOptionMenu.Head); + InitializeListHead (&mBootOptionMenu.Head); DEBUG ((DEBUG_INFO, "Locating boot options\n")); @@ -679,8 +678,8 @@ GetBootOptions ( return Status; } - InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); - BootOptionMenu.MenuNumber = 1; + InsertTailList (&mBootOptionMenu.Head, &NewMenuEntry->Link); + mBootOptionMenu.MenuNumber = 1; return EFI_SUCCESS; } @@ -712,7 +711,7 @@ GetBootOptions ( return Status; } - InsertTailList (&BootOptionMenu.Head, &NewMenuEntry->Link); + InsertTailList (&mBootOptionMenu.Head, &NewMenuEntry->Link); MenuCount++; } @@ -720,16 +719,16 @@ GetBootOptions ( FREE_NON_NULL (BootOrderList); - BootOptionMenu.MenuNumber = MenuCount; + mBootOptionMenu.MenuNumber = MenuCount; - Status = ScanFileSystemsForBootOptions (Private, &BootOptionMenu); + Status = ScanFileSystemsForBootOptions (Private, &mBootOptionMenu); if (EFI_ERROR (Status)) { DEBUG ((DEBUG_ERROR, "Scanning of filesystems failed with %r\n", Status)); } - DEBUG ((DEBUG_INFO, "Found %d boot options \n", BootOptionMenu.MenuNumber)); + DEBUG ((DEBUG_INFO, "Found %d boot options \n", mBootOptionMenu.MenuNumber)); - if (BootOptionMenu.MenuNumber == 0) { + if (mBootOptionMenu.MenuNumber == 0) { return EFI_NOT_FOUND; } @@ -777,12 +776,13 @@ UpdateBootloaderPage ( IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private ) { - SV_MENU_ENTRY *BootloaderEntry; - EFI_STRING NewString; - EFI_STATUS Status; + SV_MENU_ENTRY *BootloaderEntry; + SV_SECURITY_CONTEXT *SecurityContext; + EFI_STRING NewString; + EFI_STATUS Status; - while (mBootloaderIndex < BootOptionMenu.MenuNumber) { - BootloaderEntry = GetMenuEntry (&BootOptionMenu, mBootloaderIndex); + while (mBootloaderIndex < mBootOptionMenu.MenuNumber) { + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, mBootloaderIndex); if (BootloaderEntry == NULL) { return EFI_NO_MEDIA; } @@ -794,6 +794,7 @@ UpdateBootloaderPage ( if (BootloaderEntry->SecurityContext == NULL) { Status = FillSecurityContext(BootloaderEntry); if (EFI_ERROR (Status)) { + Private->FormData.ImageUnsigned = TRUE; DEBUG ((DEBUG_ERROR, "Failed to fill security context for bootloader %u\n", mBootloaderIndex)); return EFI_NO_MEDIA; } @@ -803,15 +804,17 @@ UpdateBootloaderPage ( if (Status == EFI_NO_MEDIA) { DEBUG ((DEBUG_INFO, "No more keys/certificates for bootloader %u\n", mBootloaderIndex)); // No more keys/certs to show for this bootloader, proceed to the next one - mCertIndex = 0; - mBootloaderIndex++; - continue; + if (!mAltAccessMode) { + mCertIndex = 0; + mBootloaderIndex++; + continue; + } } break; } - if (mBootloaderIndex >= BootOptionMenu.MenuNumber) { + if (mBootloaderIndex >= mBootOptionMenu.MenuNumber) { DEBUG ((DEBUG_INFO, "No more keys/certificates/bootloaders to show\n")); return EFI_NO_MEDIA; } @@ -838,6 +841,43 @@ UpdateBootloaderPage ( HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_BOOTOPT_DESCRIPTION), L"Not Found!", NULL); } + if (mAltAccessMode && (BootloaderEntry->SecurityContext != NULL)) { + NewString = NULL; + SecurityContext = (SV_SECURITY_CONTEXT *)BootloaderEntry->SecurityContext; + Status = ParseHashValue (SecurityContext->ImageDigest, + SecurityContext->ImageDigestSize, + &NewString); + if (!EFI_ERROR (Status)) { + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_BOOTLOADER_HASH_HEX), NewString, NULL); + FREE_NON_NULL (NewString); + } else { + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_BOOTLOADER_HASH_HEX), L"Image hash could not be obtained.", NULL); + } + + Private->FormData.ImageUnsigned = (!SecurityContext->ImageIsSigned || + (SecurityContext->NumCertificates == 0)); + + if (SecurityContext->ImageIsInDbx) { + Private->FormData.ImageTrusted = IMAGE_STATE_UNTRUSTED; + } else if (SecurityContext->ImageIsInDb) { + Private->FormData.ImageTrusted = IMAGE_STATE_TRUSTED; + } else { + Private->FormData.ImageTrusted = IMAGE_STATE_UNDECIDED; + } + + DEBUG ((DEBUG_INFO, "UpdateBootloaderPage:\n" + " ImageIsSigned: %u\n" + " ImageIsVerified: %u\n" + " ImageIsInDb: %u\n" + " ImageIsInDbx: %u\n" + " ImageTrusted: %u\n", + SecurityContext->ImageIsSigned, + SecurityContext->ImageIsVerified, + SecurityContext->ImageIsInDb, + SecurityContext->ImageIsInDbx, + Private->FormData.ImageTrusted)); + } + return Status; } @@ -882,13 +922,13 @@ FreeBootMenuEntries ( { SV_MENU_ENTRY *BootloaderEntry; - if (BootOptionMenu.MenuNumber == 0) { + if (mBootOptionMenu.MenuNumber == 0) { return; } - while (!IsListEmpty (&BootOptionMenu.Head)) { + while (!IsListEmpty (&mBootOptionMenu.Head)) { BootloaderEntry = CR ( - BootOptionMenu.Head.ForwardLink, + mBootOptionMenu.Head.ForwardLink, SV_MENU_ENTRY, Link, SOVEREIGN_BOOT_MENU_ENTRY_SIGNATURE); @@ -896,5 +936,5 @@ FreeBootMenuEntries ( FreeBootMenuEntry (BootloaderEntry); } - BootOptionMenu.MenuNumber = 0; + mBootOptionMenu.MenuNumber = 0; } diff --git a/DasharoModulePkg/Application/SovereignBootWizard/InteractiveModeImpl.c b/DasharoModulePkg/Application/SovereignBootWizard/InteractiveModeImpl.c new file mode 100644 index 0000000000..121a07dc03 --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/InteractiveModeImpl.c @@ -0,0 +1,3982 @@ +/** @file +Sovereign Boot Wizard Interactive Mode implementation. + +Copyright (c) 2025, 3mdeb Sp z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "SovereignBootWizard.h" +#include "InteractiveModeImpl.h" + +EFI_STATUS +FormatHelpInfo ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN EFI_SIGNATURE_LIST *ListEntry, + IN EFI_SIGNATURE_DATA *DataEntry, + OUT EFI_STRING_ID *StringId + ); + +EFI_STATUS +GetCommonNameFromX509 ( + IN EFI_SIGNATURE_LIST *ListEntry, + IN EFI_SIGNATURE_DATA *DataEntry, + OUT CHAR16 **BufferToReturn + ); + +UINT8 +GetSignatureFormat ( + IN EFI_SIGNATURE_LIST *ListEntry, + IN OUT EFI_STRING_ID *ListFormat OPTIONAL, + IN OUT EFI_STRING_ID *EntryFormat OPTIONAL, + IN OUT EFI_STRING_ID *ListType OPTIONAL + ); + +// +// Variable Definitions +// +WIN_CERTIFICATE *mCertificate = NULL; +EFI_IMAGE_SECURITY_DATA_DIRECTORY *mSecDataDir = NULL; +UINT8 *mImageBase = NULL; +UINTN mImageSize = 0; +// +// 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"; + +// +// Prompt strings during certificate enrollment. +// +CHAR16 *mX509EnrollPromptTitle[] = { + L"", + L"ERROR: Unsupported file type!", + L"ERROR: Unsupported certificate!", + NULL +}; +CHAR16 *mX509EnrollPromptString[] = { + L"", + L"Only DER encoded certificate file (*.cer/der/crt) is supported.", + L"Public key length should be equal to or greater than 2048 bits.", + NULL +}; + +#define EFI_SB_MICROSOFT_OWNER_GUID \ + { 0x77FA9ABD, 0x0359, 0x4D32, {0xBD, 0x60, 0x28, 0xF4, 0xE7, 0x8F, 0x78, 0x4B} } + +EFI_GUID gEfiSbMicrosoftOwnerGuid = EFI_SB_MICROSOFT_OWNER_GUID; + +/** + Read file content into BufferPtr, the size of the allocate buffer + is *FileSize plus AdditionAllocateSize. + + @param[in] FileHandle The file to be read. + @param[in, out] BufferPtr Pointers to the pointer of allocated buffer. + @param[out] FileSize Size of input file + @param[in] AdditionAllocateSize Addition size the buffer need to be allocated. + In case the buffer need to contain others besides the file content. + + @retval EFI_SUCCESS The file was read into the buffer. + @retval EFI_INVALID_PARAMETER A parameter was invalid. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval others Unexpected error. + +**/ +EFI_STATUS +ReadFile ( + IN EFI_FILE_HANDLE FileHandle, + IN OUT VOID **BufferPtr, + OUT UINTN *FileSize, + IN UINTN AdditionAllocateSize + ) + +{ + UINTN BufferSize; + UINT64 SourceFileSize; + VOID *Buffer; + EFI_STATUS Status; + + if ((FileHandle == NULL) || (FileSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + Buffer = NULL; + + // + // Get the file size + // + Status = FileHandle->SetPosition (FileHandle, (UINT64)-1); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status = FileHandle->GetPosition (FileHandle, &SourceFileSize); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status = FileHandle->SetPosition (FileHandle, 0); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + BufferSize = (UINTN)SourceFileSize + AdditionAllocateSize; + Buffer = AllocateZeroPool (BufferSize); + if (Buffer == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + BufferSize = (UINTN)SourceFileSize; + *FileSize = BufferSize; + + Status = FileHandle->Read (FileHandle, &BufferSize, Buffer); + if (EFI_ERROR (Status) || (BufferSize != *FileSize)) { + FREE_NON_NULL (Buffer); + Status = EFI_BAD_BUFFER_SIZE; + goto ON_EXIT; + } + +ON_EXIT: + + *BufferPtr = Buffer; + return Status; +} + +/** + Close an open file handle. + + @param[in] FileHandle The file handle to close. + +**/ +VOID +CloseFile ( + IN EFI_FILE_HANDLE FileHandle + ) +{ + if (FileHandle != NULL) { + FileHandle->Close (FileHandle); + } +} + +/** + Convert a nonnegative integer to an octet string of a specified length. + + @param[in] Integer Pointer to the nonnegative integer to be converted + @param[in] IntSizeInWords Length of integer buffer in words + @param[out] OctetString Converted octet string of the specified length + @param[in] OSSizeInBytes Intended length of resulting octet string in bytes + +Returns: + + @retval EFI_SUCCESS Data conversion successfully + @retval EFI_BUFFER_TOOL_SMALL Buffer is too small for output string + +**/ +EFI_STATUS +EFIAPI +Int2OctStr ( + IN CONST UINTN *Integer, + IN UINTN IntSizeInWords, + OUT UINT8 *OctetString, + IN UINTN OSSizeInBytes + ) +{ + CONST UINT8 *Ptr1; + UINT8 *Ptr2; + + for (Ptr1 = (CONST UINT8 *)Integer, Ptr2 = OctetString + OSSizeInBytes - 1; + Ptr1 < (UINT8 *)(Integer + IntSizeInWords) && Ptr2 >= OctetString; + Ptr1++, Ptr2--) + { + *Ptr2 = *Ptr1; + } + + for ( ; Ptr1 < (CONST UINT8 *)(Integer + IntSizeInWords) && *Ptr1 == 0; Ptr1++) { + } + + if (Ptr1 < (CONST UINT8 *)(Integer + IntSizeInWords)) { + return EFI_BUFFER_TOO_SMALL; + } + + if (Ptr2 >= OctetString) { + ZeroMem (OctetString, Ptr2 - OctetString + 1); + } + + return EFI_SUCCESS; +} + +/** + Worker function that prints an EFI_GUID into specified Buffer. + + @param[in] Guid Pointer to GUID to print. + @param[in] Buffer Buffer to print Guid into. + @param[in] BufferSize Size of Buffer. + + @retval Number of characters printed. + +**/ +UINTN +GuidToString ( + IN EFI_GUID *Guid, + IN CHAR16 *Buffer, + IN UINTN BufferSize + ) +{ + UINTN Size; + + Size = UnicodeSPrint ( + Buffer, + BufferSize, + L"%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", + (UINTN)Guid->Data1, + (UINTN)Guid->Data2, + (UINTN)Guid->Data3, + (UINTN)Guid->Data4[0], + (UINTN)Guid->Data4[1], + (UINTN)Guid->Data4[2], + (UINTN)Guid->Data4[3], + (UINTN)Guid->Data4[4], + (UINTN)Guid->Data4[5], + (UINTN)Guid->Data4[6], + (UINTN)Guid->Data4[7] + ); + + // + // SPrint will null terminate the string. The -1 skips the null + // + return Size - 1; +} + + +VOID *mStartOpCodeHandle = NULL; +VOID *mEndOpCodeHandle = NULL; +EFI_IFR_GUID_LABEL *mStartLabel = NULL; +EFI_IFR_GUID_LABEL *mEndLabel = NULL; +UINT8 *mSignatureTypes = NULL; + +/** + Refresh the global UpdateData structure. + +**/ +VOID +RefreshUpdateData ( + VOID + ) +{ + // + // Free current updated date + // + if (mStartOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mStartOpCodeHandle); + } + + // + // Create new OpCode Handle + // + mStartOpCodeHandle = HiiAllocateOpCodeHandle (); + + // + // 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; +} + +/** + Clean up the dynamic opcode at label and form specified by both LabelId. + + @param[in] LabelId It is both the Form ID and Label ID for opcode deletion. + @param[in] PrivateData Module private data. + +**/ +VOID +CleanUpPage ( + IN UINT16 FormId, + IN UINT16 LabelId, + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + RefreshUpdateData (); + + // Remove all op-codes from dynamic page + mStartLabel->Number = LabelId; + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSovereignBootWizardFormSetGuid, + FormId, + mStartOpCodeHandle, // Label LabelId + mEndOpCodeHandle // LABEL_END + ); +} + +/** + Extract filename from device path. The returned buffer is allocated using AllocateCopyPool. + The caller is responsible for freeing the allocated buffer using FreePool(). If return NULL + means not enough memory resource. + + @param DevicePath Device path. + + @retval NULL Not enough memory resource for AllocateCopyPool. + @retval Other A new allocated string that represents the file name. + +**/ +CHAR16 * +ExtractFileNameFromDevicePath ( + IN EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CHAR16 *String; + CHAR16 *MatchString; + CHAR16 *LastMatch; + CHAR16 *FileName; + UINTN Length; + + ASSERT (DevicePath != NULL); + + String = UiDevicePathToStr (gPrivateData->DevPathToText, DevicePath); + MatchString = String; + LastMatch = String; + FileName = NULL; + + while (MatchString != NULL) { + LastMatch = MatchString + 1; + MatchString = StrStr (LastMatch, L"\\"); + } + + Length = StrLen (LastMatch); + FileName = AllocateCopyPool ((Length + 1) * sizeof (CHAR16), LastMatch); + if (FileName != NULL) { + *(FileName + Length) = 0; + } + + FREE_NON_NULL (String); + + return FileName; +} + +/** + Update the form base on the selected file. + + @param FilePath Point to the file path. + @param FormId The form need to display. + + @retval TRUE Exit caller function. + @retval FALSE Not exit caller function. + +**/ +BOOLEAN +UpdatePage ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN EFI_FORM_ID FormId, + IN UINT16 Label + ) +{ + CHAR16 *FileName; + EFI_STRING_ID StringToken; + + FileName = NULL; + + if (FilePath != NULL) { + FileName = ExtractFileNameFromDevicePath (FilePath); + } + + if (FileName == NULL) { + // + // FileName = NULL has two case: + // 1. FilePath == NULL, not select file. + // 2. FilePath != NULL, but ExtractFileNameFromDevicePath return NULL not enough memory resource. + // In these two case, no need to update the form, and exit the caller function. + // + return TRUE; + } + + StringToken = HiiSetString (gPrivateData->HiiHandle, 0, FileName, NULL); + + gPrivateData->FileContext->FileName = FileName; + + EfiOpenFileByDevicePath ( + &FilePath, + &gPrivateData->FileContext->FHandle, + EFI_FILE_MODE_READ, + 0 + ); + // + // Create Subtitle op-code for the display string of the option. + // + RefreshUpdateData (); + mStartLabel->Number = Label; + + HiiCreateSubTitleOpCode ( + mStartOpCodeHandle, + StringToken, + 0, + 0, + 0 + ); + + HiiUpdateForm ( + gPrivateData->HiiHandle, + &gSovereignBootWizardFormSetGuid, + FormId, + mStartOpCodeHandle, // Label FormId + mEndOpCodeHandle // LABEL_END + ); + + return TRUE; +} + +/** + Update the DB form base on the input file path info. + + @param FilePath Point to the file path. + + @retval TRUE Exit caller function. + @retval FALSE Not exit caller function. +**/ +BOOLEAN +EFIAPI +UpdateDBFromFile ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ) +{ + return UpdatePage ( + FilePath, + SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB, + LABEL_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB); +} + +/** + Update the DBX form base on the input file path info. + + @param FilePath Point to the file path. + + @retval TRUE Exit caller function. + @retval FALSE Not exit caller function. +**/ +BOOLEAN +EFIAPI +UpdateDBXFromFile ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ) +{ + return UpdatePage ( + FilePath, + SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX, + LABEL_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX); +} + +/** + This code cleans up enrolled file by closing file & free related resources attached to + enrolled file. + + @param[in] FileContext FileContext cached in Sovereign Boot Wizard driver + +**/ +VOID +CloseEnrolledFile ( + IN SOVEREIGNBOOT_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 = ReadFile ( + 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 + // + FREE_NON_NULL (mImageBase); + + return IsAuth2Format; +} + +/** + This code checks if the encode type and key strength of X.509 + certificate is qualified. + + @param[in] X509FileContext FileContext of X.509 certificate storing + file. + @param[out] Error Error type checked in the certificate. + + @return EFI_SUCCESS The certificate checked successfully. + @return EFI_INVALID_PARAMETER The parameter is invalid. + @return EFI_OUT_OF_RESOURCES Memory allocation failed. + +**/ +EFI_STATUS +CheckX509Certificate ( + IN SOVEREIGNBOOT_FILE_CONTEXT *X509FileContext, + OUT ENROLL_KEY_ERROR *Error + ) +{ + EFI_STATUS Status; + UINT16 *FilePostFix; + UINTN NameLength; + UINT8 *X509Data; + UINTN X509DataSize; + void *X509PubKey; + UINTN PubKeyModSize; + + if (X509FileContext->FileName == NULL) { + *Error = Unsupported_Type; + return EFI_INVALID_PARAMETER; + } + + X509Data = NULL; + X509DataSize = 0; + X509PubKey = NULL; + PubKeyModSize = 0; + + // + // Parse the file's postfix. Only support DER encoded X.509 certificate files. + // + NameLength = StrLen (X509FileContext->FileName); + if (NameLength <= 4) { + DEBUG ((DEBUG_ERROR, "Wrong X509 NameLength\n")); + *Error = Unsupported_Type; + return EFI_INVALID_PARAMETER; + } + + FilePostFix = X509FileContext->FileName + NameLength - 4; + if (!IsDerEncodeCertificate (FilePostFix)) { + DEBUG ((DEBUG_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.\n", mSupportX509Suffix)); + *Error = Unsupported_Type; + return EFI_INVALID_PARAMETER; + } + + DEBUG ((DEBUG_INFO, "FileName= %s\n", X509FileContext->FileName)); + DEBUG ((DEBUG_INFO, "FilePostFix = %s\n", FilePostFix)); + + // + // Read the certificate file content + // + Status = ReadFile (X509FileContext->FHandle, (VOID **)&X509Data, &X509DataSize, 0); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Error occurred while reading the file.\n")); + goto ON_EXIT; + } + + // + // Parse the public key context. + // + if (RsaGetPublicKeyFromX509 (X509Data, X509DataSize, &X509PubKey) == FALSE) { + DEBUG ((DEBUG_ERROR, "Error occurred while parsing the pubkey from certificate.\n")); + Status = EFI_INVALID_PARAMETER; + *Error = Unsupported_Type; + goto ON_EXIT; + } + + // + // Parse Module size of public key using interface provided by CryptoPkg, which is + // actually the size of public key. + // + if (X509PubKey != NULL) { + RsaGetKey (X509PubKey, RsaKeyN, NULL, &PubKeyModSize); + if (PubKeyModSize < CER_PUBKEY_MIN_SIZE) { + DEBUG ((DEBUG_ERROR, "Unqualified PK size, key size should be equal to or greater than 2048 bits.\n")); + Status = EFI_INVALID_PARAMETER; + *Error = Unqualified_Key; + } + + RsaFree (X509PubKey); + } + +ON_EXIT: + FREE_NON_NULL (X509Data); + + return Status; +} + +/** + 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 SOVEREIGN_BOOT_WIZARD_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; + EFI_TIME Time; + + X509DataSize = 0; + SigDBSize = 0; + DataSize = 0; + X509Data = NULL; + SigDBCert = NULL; + SigDBCertData = NULL; + Data = NULL; + + Status = ReadFile ( + 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, &gSovereignBootWizardFormSetGuid); + 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 = GetCurrentTime (&Time); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status)); + goto ON_EXIT; + } + + Status = CreateTimeBasedPayload (&SigDBSize, (UINT8 **)&Data, &Time); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_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); + + FREE_NON_NULL (Data); + FREE_NON_NULL (X509Data); + + return Status; +} + +/** + Check whether the signature list exists in given variable data. + + It searches the signature list for the certificate 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 SOVEREIGN_BOOT_WIZARD_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; + EFI_TIME NewTime; + + X509DataSize = 0; + DbSize = 0; + X509Data = NULL; + SignatureData = NULL; + SignatureList = NULL; + Data = NULL; + NewData = NULL; + + if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == 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 = ReadFile ( + 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) + GetDigestLength(HashAlg); + SignatureData = (EFI_SIGNATURE_DATA *)AllocateZeroPool (SignatureSize); + if (SignatureData == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CopyGuid (&SignatureData->SignatureOwner, &gSovereignBootWizardFormSetGuid); + CopyMem (SignatureData->SignatureData, CertHash, GetDigestLength(HashAlg)); + + // + // Fill the time. + // + if (!AlwaysRevocation) { + Time = (EFI_TIME *)(&SignatureData->SignatureData + GetDigestLength(HashAlg)); + 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); + + FREE_NON_NULL (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 = GetCurrentTime (&NewTime); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status)); + goto ON_EXIT; + } + + Status = CreateTimeBasedPayload (&DataSize, (UINT8 **)&Data, &NewTime); + 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); + + FREE_NON_NULL (Data); + FREE_NON_NULL (SignatureData); + FREE_NON_NULL (X509Data); + + return Status; +} + +/** + Check whether a certificate from a file exists in dbx. + + @param[in] PrivateData The module's private data. + + @retval TRUE The X509 certificate is found in dbx successfully. + @retval FALSE The X509 certificate is not found in dbx. +**/ +BOOLEAN +IsX509CertInDbx ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private + ) +{ + EFI_STATUS Status; + UINTN X509DataSize; + VOID *X509Data; + BOOLEAN IsFound; + + // + // Read the certificate from file + // + X509DataSize = 0; + X509Data = NULL; + Status = ReadFile ( + Private->FileContext->FHandle, + &X509Data, + &X509DataSize, + 0 + ); + if (EFI_ERROR (Status)) { + return FALSE; + } + + // + // Check the raw certificate. + // + IsFound = FALSE; + Status = IsSignatureFoundInDatabase ( + EFI_IMAGE_SECURITY_DATABASE1, + X509Data, + &gEfiCertX509Guid, + X509DataSize, + &IsFound); + if (EFI_ERROR (Status)) { + IsFound = FALSE; + goto ON_EXIT; + } + + if (IsFound) { + goto ON_EXIT; + } + + // + // Check the hash of certificate. + // + IsFound = FALSE; + Status = IsCertHashFoundInDbx ( + X509Data, + X509DataSize, + NULL, + 0, + NULL, + &IsFound); + if (EFI_ERROR (Status)) { + IsFound = FALSE; + goto ON_EXIT; + } + +ON_EXIT: + FREE_NON_NULL (X509Data); + + return IsFound; +} + +/** + Enroll a new signature of executable 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 SOVEREIGN_BOOT_WIZARD_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 = ReadFile ( + 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; + } + + // + // Directly 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); + + FREE_NON_NULL (Data); + FREE_NON_NULL (mImageBase); + + return Status; +} + +/** + Enroll a new signature of executable 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 SOVEREIGN_BOOT_WIZARD_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; + WIN_CERTIFICATE_EFI_PKCS *PkcsCertData; + EFI_TIME Time; + UINT32 HashAlg; + EFI_GUID CertType; + UINTN ImageDigestSize; + UINT8 ImageDigest[MAX_DIGEST_SIZE]; + + 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 signature data of executable 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 = ReadFile ( + Private->FileContext->FHandle, + (VOID **)&mImageBase, + &mImageSize, + 0 + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + ASSERT (mImageBase != NULL); + + Status = GetImageSecDataDir (mImageBase, mImageSize, (EFI_IMAGE_DATA_DIRECTORY **)&mSecDataDir); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + if (mSecDataDir->SizeOfCert == 0) { + Status = EFI_SECURITY_VIOLATION; + HashAlg = HASHALG_MAX; + while (HashAlg > 0) { + HashAlg--; + + if (HashPeImage (mImageBase, mImageSize, HashAlg, ImageDigest, &ImageDigestSize, &CertType)) { + Status = EFI_SUCCESS; + break; + } + + } + + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to get hash digest: %r", Status)); + 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 (mImageBase, mImageSize, HASHALG_SHA256, ImageDigest, &ImageDigestSize, &CertType)) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + } else if (mCertificate->wCertificateType == WIN_CERT_TYPE_PKCS_SIGNED_DATA) { + PkcsCertData = (WIN_CERTIFICATE_EFI_PKCS *)mCertificate; + if (PkcsCertData->Hdr.dwLength <= sizeof (PkcsCertData->Hdr)) { + Status = EFI_ABORTED; + goto ON_EXIT; + } + Status = HashPeImageByType ( + mImageBase, + mImageSize, + PkcsCertData->CertData, + PkcsCertData->Hdr.dwLength - sizeof (PkcsCertData->Hdr), + ImageDigest, + &ImageDigestSize, + &CertType); + 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)ImageDigestSize; + + 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)ImageDigestSize; + CopyGuid (&SigDBCert->SignatureType, &CertType); + + SigDBCertData = (EFI_SIGNATURE_DATA *)((UINT8 *)SigDBCert + sizeof (EFI_SIGNATURE_LIST)); + CopyGuid (&SigDBCertData->SignatureOwner, &gSovereignBootWizardFormSetGuid); + CopyMem (SigDBCertData->SignatureData, ImageDigest, ImageDigestSize); + + Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS + | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; + Status = GetCurrentTime (&Time); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status)); + goto ON_EXIT; + } + + Status = CreateTimeBasedPayload (&SigDBSize, (UINT8 **)&Data, &Time); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_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); + + FREE_NON_NULL (Data); + FREE_NON_NULL (mImageBase); + + return Status; +} + +/** + Enroll signature into DB/DBX/DBT without KEK's authentication. + The SignatureOwner GUID will be SovereignBootWizardFormsetGuid. + + @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 SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN CHAR16 *VariableName + ) +{ + UINT16 *FilePostFix; + EFI_STATUS Status; + UINTN NameLength; + + if ((Private->FileContext->FileName == NULL) || (Private->FileContext->FHandle == 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 SOVEREIGN_BOOT_WIZARD_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 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 *DataWalker; + UINT32 ItemDataSize; + EFI_STRING_ID HelpStringId; + EFI_STRING_ID FormatStringId; + EFI_STRING_ID EntryTypeStringId; + EFI_STRING EntryTypeString; + EFI_STRING FormatNameString; + UINT8 SignatureType; + CHAR16 *CertCN; + CHAR16 NameBuffer[BUFFER_MAX_SIZE]; + + Data = NULL; + CertList = NULL; + DataWalker = NULL; + StartOpCodeHandle = NULL; + EndOpCodeHandle = NULL; + FormatNameString = NULL; + EntryTypeString = 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; + } + + // + // Enumerate all DB data. + // + ItemDataSize = (UINT32)DataSize; + CertList = (EFI_SIGNATURE_LIST *)Data; + GuidIndex = 0; + + while ((ItemDataSize > 0) && (ItemDataSize >= CertList->SignatureListSize)) { + SignatureType = GetSignatureFormat(CertList, NULL, &FormatStringId, &EntryTypeStringId); + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)CertList + sizeof (EFI_SIGNATURE_LIST) + CertList->SignatureHeaderSize); + + FormatNameString = HiiGetString (PrivateData->HiiHandle, FormatStringId, NULL); + EntryTypeString = HiiGetString (PrivateData->HiiHandle, EntryTypeStringId, NULL); + if ((FormatNameString == NULL) || (EntryTypeString == NULL)) { + goto ON_EXIT; + } + + for (Index = 0; Index < SIGNATURE_DATA_COUNTS (CertList); Index = Index + 1) { + // + // Format name buffer. + // + ZeroMem (NameBuffer, sizeof (NameBuffer)); + if (SignatureType == SIGNATURE_TYPE_X509) { + CertCN = NULL; + if (!EFI_ERROR (GetCommonNameFromX509 (CertList, DataWalker, &CertCN)) && (StrLen(CertCN) > 0)) { + UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, GuidIndex + 1, CertCN); + } else { + UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, GuidIndex + 1, EntryTypeString); + } + FREE_NON_NULL (CertCN); + } else { + UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, GuidIndex + 1, EntryTypeString); + } + + // + // Format help info buffer. + // + Status = FormatHelpInfo (PrivateData, CertList, DataWalker, &HelpStringId); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + HiiCreateCheckBoxOpCode ( + StartOpCodeHandle, + (EFI_QUESTION_ID)(QuestionIdBase + GuidIndex++), + 0, + 0, + HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL), + HelpStringId, + EFI_IFR_FLAG_CALLBACK | EFI_IFR_FLAG_RESET_REQUIRED, + 0, + NULL + ); + + ZeroMem (NameBuffer, BUFFER_MAX_SIZE); + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + CertList->SignatureSize); + } + ItemDataSize -= CertList->SignatureListSize; + CertList = (EFI_SIGNATURE_LIST *)((UINT8 *)CertList + CertList->SignatureListSize); + } + +ON_EXIT: + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSovereignBootWizardFormSetGuid, + FormId, + StartOpCodeHandle, + EndOpCodeHandle + ); + + FREE_NON_OPCODE (StartOpCodeHandle); + FREE_NON_OPCODE (EndOpCodeHandle); + + FREE_NON_NULL (Data); + + return EFI_SUCCESS; +} + +/** + Delete a signature entry from signature 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 signature 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 SOVEREIGN_BOOT_WIZARD_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; + EFI_TIME Time; + + 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, &gEfiCertRsa2048Sha256Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertX509Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertSha1Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertSha224Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertSha384Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertSha256Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertSha512Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertSm3Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha256Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha384Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertX509Sha512Guid) || + CompareGuid (&CertList->SignatureType, &gEfiCertX509Sm3Guid) + ) + { + // + // 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 = GetCurrentTime (&Time); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status)); + goto ON_EXIT; + } + + Status = CreateTimeBasedPayload (&DataSize, &OldData, &Time); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_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: + FREE_NON_NULL (Data); + FREE_NON_NULL (OldData); + + return UpdateDeletePage ( + PrivateData, + VariableName, + VendorGuid, + LabelNumber, + FormId, + QuestionIdBase + ); +} + +/** + This function to delete signature list or data, according by DelType. + + @param[in] PrivateData Module's private data. + @param[in] DelType Indicate delete signature list or data. + @param[in] CheckedCount Indicate how many signature data have + been checked in current signature list. + + @retval EFI_SUCCESS Success to update the signature list page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +DeleteSignatureEx ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN SIGNATURE_DELETE_TYPE DelType, + IN UINT32 CheckedCount + ) +{ + EFI_STATUS Status; + EFI_SIGNATURE_LIST *ListWalker; + EFI_SIGNATURE_LIST *NewCertList; + EFI_SIGNATURE_DATA *DataWalker; + CHAR16 VariableName[BUFFER_MAX_SIZE]; + UINT32 VariableAttr; + UINTN VariableDataSize; + UINTN RemainingSize; + UINTN ListIndex; + UINTN Index; + UINTN Offset; + UINT8 *VariableData; + UINT8 *NewVariableData; + EFI_TIME Time; + + Status = EFI_SUCCESS; + VariableAttr = 0; + VariableDataSize = 0; + ListIndex = 0; + Offset = 0; + VariableData = NULL; + NewVariableData = NULL; + + if (PrivateData->VariableName == Variable_DB) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE); + } else if (PrivateData->VariableName == Variable_DBX) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1); + } else { + goto ON_EXIT; + } + + Status = gRT->GetVariable ( + VariableName, + &gEfiImageSecurityDatabaseGuid, + &VariableAttr, + &VariableDataSize, + VariableData + ); + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + goto ON_EXIT; + } + + VariableData = AllocateZeroPool (VariableDataSize); + if (VariableData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Status = gRT->GetVariable ( + VariableName, + &gEfiImageSecurityDatabaseGuid, + &VariableAttr, + &VariableDataSize, + VariableData + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + NewVariableData = AllocateZeroPool (VariableDataSize); + if (NewVariableData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + RemainingSize = VariableDataSize; + ListWalker = (EFI_SIGNATURE_LIST *)(VariableData); + if (DelType == Delete_Signature_List_All) { + VariableDataSize = 0; + } else { + // + // Traverse to target EFI_SIGNATURE_LIST but others will be skipped. + // + while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex < PrivateData->ListIndex) { + CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, ListWalker->SignatureListSize); + Offset += ListWalker->SignatureListSize; + + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + ListIndex++; + } + + // + // Handle the target EFI_SIGNATURE_LIST. + // If CheckedCount == SIGNATURE_DATA_COUNTS (ListWalker) or DelType == Delete_Signature_List_One + // it means delete the whole EFI_SIGNATURE_LIST, So we just skip this EFI_SIGNATURE_LIST. + // + if ((CheckedCount < SIGNATURE_DATA_COUNTS (ListWalker)) && (DelType == Delete_Signature_Data)) { + NewCertList = (EFI_SIGNATURE_LIST *)(NewVariableData + Offset); + // + // Copy header. + // + CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize); + Offset += sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize; + + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize); + for (Index = 0; Index < SIGNATURE_DATA_COUNTS (ListWalker); Index = Index + 1) { + if (PrivateData->CheckArray[Index]) { + // + // Delete checked signature data, and update the size of whole signature list. + // + NewCertList->SignatureListSize -= NewCertList->SignatureSize; + } else { + // + // Remain the unchecked signature data. + // + CopyMem ((UINT8 *)NewVariableData + Offset, DataWalker, ListWalker->SignatureSize); + Offset += ListWalker->SignatureSize; + } + + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize); + } + } + + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + + // + // Copy remaining data, maybe 0. + // + CopyMem ((UINT8 *)NewVariableData + Offset, ListWalker, RemainingSize); + Offset += RemainingSize; + + VariableDataSize = Offset; + } + + if ((VariableAttr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { + Status = GetCurrentTime (&Time); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to fetch valid time data: %r", Status)); + goto ON_EXIT; + } + + Status = CreateTimeBasedPayload (&VariableDataSize, &NewVariableData, &Time); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status)); + goto ON_EXIT; + } + } + + Status = gRT->SetVariable ( + VariableName, + &gEfiImageSecurityDatabaseGuid, + VariableAttr, + VariableDataSize, + NewVariableData + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r", Status)); + goto ON_EXIT; + } + +ON_EXIT: + FREE_NON_NULL (VariableData); + FREE_NON_NULL (NewVariableData); + + return Status; +} + +/** + This function extracts configuration from variable. + + @param[in] Private Point to Sovereign Boot configuration driver private data. + @param[in, out] FormData Point to Sovereign Boot form private data. + +**/ +VOID +InteractiveModeExtractConfig ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN OUT SOVEREIGN_BOOT_WIZARD_FORM_DATA *FormData + ) +{ + EFI_TIME CurrTime; + + // + // Initialize the Date and Time using system time. + // + FormData->CertificateFormat = HASHALG_RAW; + FormData->AlwaysRevocation = TRUE; + gRT->GetTime (&CurrTime, NULL); + FormData->RevocationDate.Year = CurrTime.Year; + FormData->RevocationDate.Month = CurrTime.Month; + FormData->RevocationDate.Day = CurrTime.Day; + FormData->RevocationTime.Hour = CurrTime.Hour; + FormData->RevocationTime.Minute = CurrTime.Minute; + FormData->RevocationTime.Second = 0; + if (Private->FileContext->FHandle != NULL) { + FormData->FileEnrollType = Private->FileContext->FileType; + } else { + FormData->FileEnrollType = UNKNOWN_FILE_TYPE; + } + + FormData->ListCount = Private->ListCount; +} + +UINT8 +GetSignatureFormat ( + IN EFI_SIGNATURE_LIST *ListEntry, + IN OUT EFI_STRING_ID *ListFormat OPTIONAL, + IN OUT EFI_STRING_ID *EntryFormat OPTIONAL, + IN OUT EFI_STRING_ID *ListType OPTIONAL + ) +{ + EFI_STRING_ID ListTypeId; + EFI_STRING_ID ListFormatId; + EFI_STRING_ID EntryFormatId; + UINT8 SignatureType; + + if (CompareGuid (&ListEntry->SignatureType, &gEfiCertRsa2048Guid)) { + SignatureType = SIGNATURE_TYPE_RSA2048; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_RSA2048); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_RSA_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_RSA_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertRsa2048Sha256Guid)) { + SignatureType = SIGNATURE_TYPE_RSA2048_SHA256; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_RSA_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_RSA_HASH_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Guid)) { + SignatureType = SIGNATURE_TYPE_X509; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_CERT_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_CERT_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha1Guid)) { + SignatureType = SIGNATURE_TYPE_SHA1; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA1); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_HASH_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha224Guid)) { + SignatureType = SIGNATURE_TYPE_SHA224; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA224); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_HASH_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha256Guid)) { + SignatureType = SIGNATURE_TYPE_SHA256; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA256); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_HASH_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha384Guid)) { + SignatureType = SIGNATURE_TYPE_SHA384; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA384); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_HASH_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha512Guid)) { + SignatureType = SIGNATURE_TYPE_SHA512; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA512); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_HASH_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSm3Guid)) { + SignatureType = SIGNATURE_TYPE_SM3; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SM3); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_HASH_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sha256Guid)) { + SignatureType = SIGNATURE_TYPE_X509_SHA256; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA256); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_CERT_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_CERT_HASH_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sha384Guid)) { + SignatureType = SIGNATURE_TYPE_X509_SHA384; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA384); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_CERT_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_CERT_HASH_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sha512Guid)) { + SignatureType = SIGNATURE_TYPE_X509_SHA512; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SHA512); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_CERT_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_CERT_HASH_NAME_FORMAT); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sm3Guid)) { + SignatureType = SIGNATURE_TYPE_X509_SM3; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509_SM3); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_CERT_HASH_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_CERT_HASH_NAME_FORMAT); + } else { + SignatureType = SIGNATURE_TYPE_UNKNOWN; + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_UNKNOWN); + EntryFormatId = STRING_TOKEN(STR_SIGNATURE_DATA_UNKNOWN_NAME_FORMAT); + ListFormatId = STRING_TOKEN(STR_SIGNATURE_LIST_UNKNOWN_NAME_FORMAT); + } + + if (ListFormat != NULL) { + *ListFormat = ListFormatId; + } + + if (EntryFormat != NULL) { + *EntryFormat = EntryFormatId; + } + + if (ListType != NULL) { + *ListType = ListTypeId; + } + + return SignatureType; +} + +/** + This function to load signature list, the update the menu page. + + @param[in] PrivateData Module's private data. + @param[in] LabelId 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 +LoadSignatureList ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN UINT16 LabelId, + IN EFI_FORM_ID FormId, + IN EFI_QUESTION_ID QuestionIdBase + ) +{ + EFI_STATUS Status; + EFI_STRING_ID ListType; + EFI_STRING_ID FormatNameStringId; + EFI_STRING FormatNameString; + EFI_STRING FormatHelpString; + EFI_STRING FormatTypeString; + EFI_SIGNATURE_LIST *ListWalker; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + EFI_IFR_GUID_LABEL *StartGoto; + EFI_IFR_GUID_LABEL *EndGoto; + EFI_FORM_ID DstFormId; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + VOID *StartGotoHandle; + VOID *EndGotoHandle; + UINTN DataSize; + UINTN RemainingSize; + UINT16 Index; + UINT8 *VariableData; + CHAR16 VariableName[BUFFER_MAX_SIZE]; + CHAR16 NameBuffer[BUFFER_MAX_SIZE]; + CHAR16 HelpBuffer[BUFFER_MAX_SIZE]; + BOOLEAN GotoList; + + Status = EFI_SUCCESS; + FormatNameString = NULL; + FormatHelpString = NULL; + FormatTypeString = NULL; + StartOpCodeHandle = NULL; + EndOpCodeHandle = NULL; + StartGotoHandle = NULL; + EndGotoHandle = NULL; + Index = 0; + VariableData = NULL; + + GotoList = (LabelId == LABEL_DB_CERTS_DATA_START) || + (LabelId == LABEL_DBX_CERTS_DATA_START); + + // + // 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; + } + + if (!GotoList) { + StartGotoHandle = HiiAllocateOpCodeHandle (); + if (StartGotoHandle == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + EndGotoHandle = HiiAllocateOpCodeHandle (); + if (EndGotoHandle == 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 = LabelId; + + 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; + + if (!GotoList) { + StartGoto = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( + StartGotoHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + StartGoto->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + StartGoto->Number = LABEL_DELETE_ALL_LIST_BUTTON; + + EndGoto = (EFI_IFR_GUID_LABEL *)HiiCreateGuidOpCode ( + EndGotoHandle, + &gEfiIfrTianoGuid, + NULL, + sizeof (EFI_IFR_GUID_LABEL) + ); + EndGoto->ExtendOpCode = EFI_IFR_EXTEND_OP_LABEL; + EndGoto->Number = LABEL_END; + } + + if (PrivateData->VariableName == Variable_DB) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE); + DstFormId = FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM; + } else if (PrivateData->VariableName == Variable_DBX) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1); + DstFormId = FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM; + } else { + goto ON_EXIT; + } + // + // Read Variable, the variable name save in the PrivateData->VariableName. + // + DataSize = 0; + Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData); + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + goto ON_EXIT; + } + + VariableData = AllocateZeroPool (DataSize); + if (VariableData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + if (!GotoList) { + HiiCreateGotoOpCode ( + StartGotoHandle, + DstFormId, + STRING_TOKEN (STR_SOVEREIGN_BOOT_DELETE_ALL_LIST), + STRING_TOKEN (STR_SOVEREIGN_BOOT_DELETE_ALL_LIST), + EFI_IFR_FLAG_CALLBACK, + KEY_SOVEREIGN_BOOT_DELETE_ALL_LIST + ); + } + + RemainingSize = DataSize; + ListWalker = (EFI_SIGNATURE_LIST *)VariableData; + while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize)) { + + GetSignatureFormat (ListWalker, &FormatNameStringId, NULL, &ListType); + + ZeroMem (NameBuffer, sizeof (NameBuffer)); + FormatNameString = HiiGetString(PrivateData->HiiHandle, FormatNameStringId, NULL); + FormatTypeString = HiiGetString(PrivateData->HiiHandle, ListType, NULL); + if (FormatNameString == NULL || FormatTypeString == NULL) { + goto ON_EXIT; + } + + UnicodeSPrint ( + NameBuffer, + sizeof (NameBuffer), + FormatNameString, + Index + 1, + FormatTypeString + ); + + if (!GotoList) { + FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT), NULL); + if (FormatHelpString == NULL) { + goto ON_EXIT; + } + + ZeroMem (HelpBuffer, sizeof (HelpBuffer)); + UnicodeSPrint ( + HelpBuffer, + sizeof (HelpBuffer), + FormatHelpString, + FormatTypeString, + SIGNATURE_DATA_COUNTS (ListWalker) + ); + + HiiCreateGotoOpCode ( + StartOpCodeHandle, + SOVEREIGN_BOOT_DELETE_SIGNATURE_DATA_FORM, + HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL), + HiiSetString (PrivateData->HiiHandle, 0, HelpBuffer, NULL), + EFI_IFR_FLAG_CALLBACK, + QuestionIdBase + Index++ + ); + } else { + HiiCreateGotoOpCode ( + StartOpCodeHandle, + SOVEREIGN_BOOT_DELETE_SIGNATURE_DATA_FORM, + HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL), + STRING_TOKEN (STR_EMPTY_STRING), + EFI_IFR_FLAG_CALLBACK, + QuestionIdBase + Index++ + ); + } + + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + } + +ON_EXIT: + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSovereignBootWizardFormSetGuid, + FormId, + StartOpCodeHandle, + EndOpCodeHandle + ); + + if (!GotoList) { + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSovereignBootWizardFormSetGuid, + FormId, + StartGotoHandle, + EndGotoHandle + ); + } + + FREE_NON_OPCODE (StartOpCodeHandle); + FREE_NON_OPCODE (EndOpCodeHandle); + FREE_NON_OPCODE (StartGotoHandle); + FREE_NON_OPCODE (EndGotoHandle); + + FREE_NON_NULL (VariableData); + + PrivateData->ListCount = Index; + + return Status; +} + +/** + Parse hash value from EFI_SIGNATURE_DATA, and save in the CHAR16 type array. + The buffer is callee allocated and should be freed by the caller. + + @param[in] ListEntry The pointer point to the signature list. + @param[in] DataEntry The signature data we are processing. + @param[out] BufferToReturn Buffer to save the hash value. + + @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_SUCCESS Operation success. +**/ +EFI_STATUS +ParseHelpHashValue ( + IN EFI_SIGNATURE_LIST *ListEntry, + IN EFI_SIGNATURE_DATA *DataEntry, + OUT CHAR16 **BufferToReturn + ) +{ + UINTN Index; + UINTN BufferIndex; + UINTN TotalSize; + UINTN DataSize; + UINTN Line; + UINTN OneLineBytes; + + // + // Assume that, display 8 bytes in one line. + // + OneLineBytes = 8; + + if ((ListEntry == NULL) || (DataEntry == NULL) || (BufferToReturn == NULL)) { + return EFI_INVALID_PARAMETER; + } + + DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID); + Line = (DataSize + OneLineBytes - 1) / OneLineBytes; + + // + // Each byte will split two Hex-number, and each line need additional memory to save '\r\n'. + // + TotalSize = ((DataSize + Line) * 2 * sizeof (CHAR16)); + + *BufferToReturn = AllocateZeroPool (TotalSize); + if (*BufferToReturn == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Index = 0, BufferIndex = 0; Index < DataSize; Index = Index + 1) { + if ((Index > 0) && (Index % OneLineBytes == 0)) { + BufferIndex += UnicodeSPrint (&(*BufferToReturn)[BufferIndex], TotalSize - sizeof (CHAR16) * BufferIndex, L"\n"); + } + + BufferIndex += UnicodeSPrint (&(*BufferToReturn)[BufferIndex], TotalSize - sizeof (CHAR16) * BufferIndex, L"%02x", DataEntry->SignatureData[Index]); + } + + BufferIndex += UnicodeSPrint (&(*BufferToReturn)[BufferIndex], TotalSize - sizeof (CHAR16) * BufferIndex, L"\n"); + + return EFI_SUCCESS; +} + +/** + Function to get the common name from the X509 format certificate. + The buffer is callee allocated and should be freed by the caller. + + @param[in] ListEntry The pointer point to the signature list. + @param[in] DataEntry The signature data we are processing. + @param[out] BufferToReturn Buffer to save the CN of X509 certificate. + + @retval EFI_INVALID_PARAMETER Invalid List or Data or Buffer. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_SUCCESS Operation success. + @retval EFI_NOT_FOUND Not found CN field in the X509 certificate. +**/ +EFI_STATUS +GetCommonNameFromX509 ( + IN EFI_SIGNATURE_LIST *ListEntry, + IN EFI_SIGNATURE_DATA *DataEntry, + OUT CHAR16 **BufferToReturn + ) +{ + EFI_STATUS Status; + CHAR8 *CNBuffer; + UINTN CNBufferSize; + + Status = EFI_SUCCESS; + CNBuffer = NULL; + + CNBuffer = AllocateZeroPool (256); + if (CNBuffer == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + CNBufferSize = 256; + X509GetCommonName ( + (UINT8 *)DataEntry + sizeof (EFI_GUID), + ListEntry->SignatureSize - sizeof (EFI_GUID), + CNBuffer, + &CNBufferSize + ); + + *BufferToReturn = AllocateZeroPool (256 * sizeof (CHAR16)); + if (*BufferToReturn == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + AsciiStrToUnicodeStrS (CNBuffer, *BufferToReturn, 256); + +ON_EXIT: + FREE_NON_NULL (CNBuffer); + + return Status; +} + +/** + Format the help info for the signature data, each help info contain 3 parts. + 1. Owner Guid. + 2. Content, depends on the type of the signature list. + 3. Revocation time. + + @param[in] PrivateData Module's private data. + @param[in] ListEntry Point to the signature list. + @param[in] DataEntry Point to the signature data we are processing. + @param[out] StringId Save the string id of help info. + + @retval EFI_SUCCESS Operation success. + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +FormatHelpInfo ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN EFI_SIGNATURE_LIST *ListEntry, + IN EFI_SIGNATURE_DATA *DataEntry, + OUT EFI_STRING_ID *StringId + ) +{ + EFI_STATUS Status; + EFI_TIME *Time; + EFI_STRING_ID ListTypeId; + EFI_STRING FormatHelpString; + EFI_STRING FormatTypeString; + UINTN DataSize; + UINTN HelpInfoIndex; + UINTN TotalSize; + CHAR16 GuidString[BUFFER_MAX_SIZE]; + CHAR16 TimeString[BUFFER_MAX_SIZE]; + CHAR16 *DataString; + CHAR16 *HelpInfoString; + + Status = EFI_SUCCESS; + Time = NULL; + FormatTypeString = NULL; + HelpInfoIndex = 0; + DataString = NULL; + HelpInfoString = NULL; + + if (CompareGuid (&ListEntry->SignatureType, &gEfiCertRsa2048Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_RSA2048); + DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertRsa2048Sha256Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256); + DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509); + DataSize = ListEntry->SignatureSize - sizeof (EFI_GUID); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha1Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SHA1); + DataSize = 20; + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha224Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SHA224); + DataSize = 28; + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha256Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SHA256); + DataSize = 32; + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha384Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SHA384); + DataSize = 48; + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSha512Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SHA512); + DataSize = 64; + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertSm3Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_SM3); + DataSize = 32; + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sha256Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509_SHA256); + DataSize = 32; + Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sha384Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509_SHA384); + DataSize = 48; + Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sha512Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509_SHA512); + DataSize = 64; + Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize); + } else if (CompareGuid (&ListEntry->SignatureType, &gEfiCertX509Sm3Guid)) { + ListTypeId = STRING_TOKEN (STR_LIST_TYPE_X509_SM3); + DataSize = 32; + Time = (EFI_TIME *)(DataEntry->SignatureData + DataSize); + } else { + Status = EFI_UNSUPPORTED; + goto ON_EXIT; + } + + FormatTypeString = HiiGetString (PrivateData->HiiHandle, ListTypeId, NULL); + if (FormatTypeString == NULL) { + goto ON_EXIT; + } + + TotalSize = 1024; + HelpInfoString = AllocateZeroPool (TotalSize); + if (HelpInfoString == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + // + // Format GUID part. + // + ZeroMem (GuidString, sizeof (GuidString)); + GuidToString (&DataEntry->SignatureOwner, GuidString, BUFFER_MAX_SIZE); + FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_GUID), NULL); + if (FormatHelpString == NULL) { + goto ON_EXIT; + } + + HelpInfoIndex += UnicodeSPrint ( + &HelpInfoString[HelpInfoIndex], + TotalSize - sizeof (CHAR16) * HelpInfoIndex, + FormatHelpString, + GuidString + ); + FREE_NON_NULL (FormatHelpString); + FormatHelpString = NULL; + + if (CompareGuid (&DataEntry->SignatureOwner, &gSovereignBootWizardFormSetGuid)) { + HelpInfoIndex += UnicodeSPrint ( + &HelpInfoString[HelpInfoIndex], + TotalSize - sizeof (CHAR16) * HelpInfoIndex, + L"%s", + HiiGetString(PrivateData->HiiHandle, STRING_TOKEN(STR_SIGNATURE_DATA_HELP_GUID_SVBOOT), NULL) + ); + } else if (CompareGuid (&DataEntry->SignatureOwner, &gEfiSbMicrosoftOwnerGuid)) { + HelpInfoIndex += UnicodeSPrint ( + &HelpInfoString[HelpInfoIndex], + TotalSize - sizeof (CHAR16) * HelpInfoIndex, + L"%s", + HiiGetString(PrivateData->HiiHandle, STRING_TOKEN(STR_SIGNATURE_DATA_HELP_GUID_MS), NULL) + ); + } else if (CompareGuid (&DataEntry->SignatureOwner, &gEfiGlobalVariableGuid)) { + HelpInfoIndex += UnicodeSPrint ( + &HelpInfoString[HelpInfoIndex], + TotalSize - sizeof (CHAR16) * HelpInfoIndex, + L"%s", + HiiGetString(PrivateData->HiiHandle, STRING_TOKEN(STR_SIGNATURE_DATA_HELP_GUID_FW), NULL) + ); + } + + // + // Format hash value for each signature data entry. + // + ParseHelpHashValue (ListEntry, DataEntry, &DataString); + FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_HASH), NULL); + if (FormatHelpString == NULL) { + goto ON_EXIT; + } + + HelpInfoIndex += UnicodeSPrint ( + &HelpInfoString[HelpInfoIndex], + TotalSize - sizeof (CHAR16) * HelpInfoIndex, + FormatHelpString, + FormatTypeString, + DataSize, + DataString + ); + FREE_NON_NULL (FormatHelpString); + FormatHelpString = NULL; + + // + // Format revocation time part. + // + if (Time != NULL) { + ZeroMem (TimeString, sizeof (TimeString)); + UnicodeSPrint ( + TimeString, + sizeof (TimeString), + L"%02d-%02d-%04d %02d:%02d:%02d", + Time->Day, + Time->Month, + Time->Year, + Time->Hour, + Time->Minute, + Time->Second + ); + FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_TIME), NULL); + if (FormatHelpString == NULL) { + goto ON_EXIT; + } + + UnicodeSPrint ( + &HelpInfoString[HelpInfoIndex], + TotalSize - sizeof (CHAR16) * HelpInfoIndex, + FormatHelpString, + TimeString + ); + FREE_NON_NULL (FormatHelpString); + FormatHelpString = NULL; + } + + *StringId = HiiSetString (PrivateData->HiiHandle, 0, HelpInfoString, NULL); +ON_EXIT: + FREE_NON_NULL (DataString); + FREE_NON_NULL (HelpInfoString); + + FREE_NON_NULL (FormatTypeString); + + return Status; +} + +/** + This function to load signature data under the signature list. + + @param[in] PrivateData Module's private data. + @param[in] LabelId 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] ListIndex Indicate to load which signature list. + + @retval EFI_SUCCESS Success to update the signature list page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +LoadSignatureData ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN UINT16 LabelId, + IN EFI_FORM_ID FormId, + IN EFI_QUESTION_ID QuestionIdBase, + IN UINT16 ListIndex + ) +{ + EFI_STATUS Status; + EFI_SIGNATURE_LIST *ListWalker; + EFI_SIGNATURE_DATA *DataWalker; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + EFI_STRING_ID HelpStringId; + EFI_STRING_ID FormatStringId; + EFI_STRING_ID EntryTypeStringId; + EFI_STRING EntryTypeString; + EFI_STRING FormatNameString; + EFI_FORM_ID GotoFormId; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + UINTN DataSize; + UINTN RemainingSize; + UINT16 Index; + UINT8 *VariableData; + CHAR16 VariableName[BUFFER_MAX_SIZE]; + CHAR16 NameBuffer[BUFFER_MAX_SIZE]; + BOOLEAN GotoList; + UINT8 SignatureType; + CHAR16 *CertCN; + + Status = EFI_SUCCESS; + FormatNameString = NULL; + StartOpCodeHandle = NULL; + EndOpCodeHandle = NULL; + Index = 0; + VariableData = NULL; + + GotoList = (QuestionIdBase == OPTION_DB_ENTRIES_QUESTION_ID) || + (QuestionIdBase == OPTION_DBX_ENTRIES_QUESTION_ID); + // + // 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 = LabelId; + + 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; + + if (PrivateData->VariableName == Variable_DB) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE); + } else if (PrivateData->VariableName == Variable_DBX) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1); + } else { + goto ON_EXIT; + } + + // + // Read Variable, the variable name save in the PrivateData->VariableName. + // + DataSize = 0; + Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData); + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + goto ON_EXIT; + } + + VariableData = AllocateZeroPool (DataSize); + if (VariableData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + RemainingSize = DataSize; + ListWalker = (EFI_SIGNATURE_LIST *)VariableData; + + // + // Skip signature list. + // + while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex-- > 0) { + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + } + + SignatureType = GetSignatureFormat(ListWalker, NULL, &FormatStringId, &EntryTypeStringId); + + FormatNameString = HiiGetString (PrivateData->HiiHandle, FormatStringId, NULL); + EntryTypeString = HiiGetString (PrivateData->HiiHandle, EntryTypeStringId, NULL); + if ((FormatNameString == NULL) || (EntryTypeString == NULL)) { + goto ON_EXIT; + } + + PrivateData->DataCount = SIGNATURE_DATA_COUNTS (ListWalker); + + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize); + for (Index = 0; Index < SIGNATURE_DATA_COUNTS (ListWalker); Index = Index + 1) { + // + // Format name buffer. + // + ZeroMem (NameBuffer, sizeof (NameBuffer)); + if (SignatureType == SIGNATURE_TYPE_X509) { + CertCN = NULL; + if (!EFI_ERROR (GetCommonNameFromX509 (ListWalker, DataWalker, &CertCN)) && (StrLen(CertCN) > 0)) { + UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1, CertCN); + } else { + UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1, EntryTypeString); + } + FREE_NON_NULL (CertCN); + GotoFormId = SOVEREIGN_BOOT_WIZARD_KEY_DETAILS_FORM_ID; + } else { + UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1, EntryTypeString); + GotoFormId = SOVEREIGN_BOOT_WIZARD_HASH_DETAILS_FORM_ID; + } + + // + // Format help info buffer. + // + Status = FormatHelpInfo (PrivateData, ListWalker, DataWalker, &HelpStringId); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + if (GotoList) { + HiiCreateGotoOpCode ( + StartOpCodeHandle, + GotoFormId, + HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL), + HelpStringId, + EFI_IFR_FLAG_CALLBACK, + QuestionIdBase + Index + ); + } else { + HiiCreateCheckBoxOpCode ( + StartOpCodeHandle, + (EFI_QUESTION_ID)(QuestionIdBase + Index), + 0, + 0, + HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL), + HelpStringId, + EFI_IFR_FLAG_CALLBACK, + 0, + NULL + ); + } + + ZeroMem (NameBuffer, BUFFER_MAX_SIZE); + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize); + } + + if (GotoList) { + PrivateData->FormData.SignatureType = SignatureType; + PrivateData->FormData.SignatureRemove = TRUE; + } else { + PrivateData->FormData.SignatureRemove = FALSE; + } + + // + // Allocate a buffer to record which signature data will be checked. + // This memory buffer will be freed when exit from the SOVEREIGN_BOOT_DELETE_SIGNATURE_DATA_FORM form. + // + PrivateData->CheckArray = AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker) * sizeof (BOOLEAN)); +ON_EXIT: + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSovereignBootWizardFormSetGuid, + FormId, + StartOpCodeHandle, + EndOpCodeHandle + ); + + FREE_NON_OPCODE (StartOpCodeHandle); + FREE_NON_OPCODE (EndOpCodeHandle); + + FREE_NON_NULL (VariableData); + FREE_NON_NULL (FormatNameString); + + return Status; +} + + +/** + This function to load signature data strings under the signature data. + + @param[in] PrivateData Module's private data. + @param[in] DataIndex Indicate to load which signature data. + @param[in] ListIndex Indicate to load which signature list. + + @retval EFI_SUCCESS Success to update the signature data page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +LoadSignatureDataStrings ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN UINT16 DataIndex, + IN UINT16 ListIndex + ) +{ + EFI_STATUS Status; + EFI_SIGNATURE_LIST *ListWalker; + EFI_SIGNATURE_DATA *DataWalker; + UINTN DataSize; + UINTN RemainingSize; + UINT16 Index; + UINT8 *VariableData; + CHAR16 VariableName[BUFFER_MAX_SIZE]; + UINT8 SignatureType; + SV_CERT_ENTRY CertEntry; + + Status = EFI_SUCCESS; + Index = 0; + VariableData = NULL; + + if (PrivateData->VariableName == Variable_DB) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE); + } else if (PrivateData->VariableName == Variable_DBX) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1); + } else { + goto ON_EXIT; + } + + // + // Read Variable, the variable name save in the PrivateData->VariableName. + // + DataSize = 0; + Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData); + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + goto ON_EXIT; + } + + VariableData = AllocateZeroPool (DataSize); + if (VariableData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + Status = gRT->GetVariable (VariableName, &gEfiImageSecurityDatabaseGuid, NULL, &DataSize, VariableData); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + RemainingSize = DataSize; + ListWalker = (EFI_SIGNATURE_LIST *)VariableData; + + // + // Skip signature list. + // + while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize) && ListIndex-- > 0) { + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + } + + SignatureType = GetSignatureFormat(ListWalker, NULL, NULL, NULL); + + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize); + for (Index = 0; Index < SIGNATURE_DATA_COUNTS (ListWalker); Index = Index + 1) { + + if (Index != DataIndex) { + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize); + continue; + } + + if (SignatureType == SIGNATURE_TYPE_X509) { + CertEntry.CertDataSize = ListWalker->SignatureSize - sizeof (EFI_GUID); + CertEntry.CertData = DataWalker->SignatureData; + FillCertStrings(PrivateData, &CertEntry); + } else { + PrivateData->FormData.SignatureType = SignatureType; + FillKeyHashStrings (PrivateData, ListWalker, DataWalker); + } + + break; + } + +ON_EXIT: + + FREE_NON_NULL (VariableData); + + return Status; +} + + +/** + Format the help info for the bootloader data, each help info contain 3 parts. + 1. Description. + 2. Disk HW path. + 3. File apth. + + @param[in] PrivateData Module's private data. + @param[in] BootloaderEntry Point to the bootloader data. + @param[out] StringId Save the string id of help info. + + @retval EFI_SUCCESS Operation success. + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +FormatBlHelpInfo ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN SV_MENU_ENTRY *BootloaderEntry, + OUT EFI_STRING_ID *StringId + ) +{ + EFI_STATUS Status; + EFI_STRING FormatHelpString; + UINTN TotalSize; + CHAR16 *HelpInfoString; + + Status = EFI_SUCCESS; + HelpInfoString = NULL; + + TotalSize = 1024; + HelpInfoString = AllocateZeroPool (TotalSize); + if (HelpInfoString == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } + + FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_BOOTLOADER_HELP_FORMAT), NULL); + if (FormatHelpString == NULL) { + goto ON_EXIT; + } + + UnicodeSPrint ( + HelpInfoString, + TotalSize, + FormatHelpString, + BootloaderEntry->DisplayString, + BootloaderEntry->DevicePathString, + BootloaderEntry->FilePathString + ); + FREE_NON_NULL (FormatHelpString); + + *StringId = HiiSetString (PrivateData->HiiHandle, 0, HelpInfoString, NULL); +ON_EXIT: + FREE_NON_NULL (HelpInfoString); + + return Status; +} + +/** + This function to loads bootloader data strings under the bootloader form. + + @param[in] PrivateData Module's private data. + + @retval EFI_SUCCESS Success to update the bootloader list page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +LoadBootloaders ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + EFI_STATUS Status; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + EFI_STRING_ID HelpStringId; + EFI_STRING FormatNameString; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + UINT16 Index; + CHAR16 NameBuffer[BUFFER_MAX_SIZE]; + SV_MENU_ENTRY *BootloaderEntry; + + Status = EFI_SUCCESS; + FormatNameString = NULL; + StartOpCodeHandle = NULL; + EndOpCodeHandle = NULL; + Index = 0; + + // 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 = LABEL_BOOTLOADER_LIST_START; + + 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; + + FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_BOOTLOADER_NAME_FORMAT), NULL); + if (FormatNameString == NULL) { + Status = EFI_NOT_FOUND; + goto ON_EXIT; + } + + for (Index = 0; Index < mBootOptionMenu.MenuNumber; Index = Index + 1) { + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, Index); + if (BootloaderEntry == NULL) { + Status = EFI_NO_MEDIA; + goto ON_EXIT; + } + + // + // Format name buffer. + // + ZeroMem (NameBuffer, sizeof (NameBuffer)); + UnicodeSPrint ( + NameBuffer, + sizeof (NameBuffer), + FormatNameString, + &BootloaderEntry->FilePathString[StrLen(L"File Path: ")], + &BootloaderEntry->DisplayString[StrLen(L"Description: ")]); + + // + // Format help info buffer. + // + Status = FormatBlHelpInfo (PrivateData, BootloaderEntry, &HelpStringId); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + HiiCreateGotoOpCode ( + StartOpCodeHandle, + SOVEREIGN_BOOT_WIZARD_BL_DETAILS_FORM_ID, + HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL), + HelpStringId, + EFI_IFR_FLAG_CALLBACK, + OPTION_BL_QUESTION_ID + Index + ); + } + +ON_EXIT: + PrivateData->FormData.BootloaderCount = Index; + + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSovereignBootWizardFormSetGuid, + FORMID_SOVEREIGN_BOOT_BL_OPTION_FORM, + StartOpCodeHandle, + EndOpCodeHandle + ); + + FREE_NON_OPCODE (StartOpCodeHandle); + FREE_NON_OPCODE (EndOpCodeHandle); + + return Status; +} + + +/** + This function to loads bootloader data strings under the bootloader form. + + @param[in] PrivateData Module's private data. + + @retval EFI_SUCCESS Success to update the bootloader list page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +LoadBootloaderCertificates ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + EFI_STATUS Status; + EFI_IFR_GUID_LABEL *StartLabel; + EFI_IFR_GUID_LABEL *EndLabel; + EFI_STRING_ID NameStringId; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + UINT16 Index; + CHAR8 NameBuffer[BUFFER_MAX_SIZE]; + UINTN NameBufferSize; + CHAR16 *NewString; + SV_MENU_ENTRY *BootloaderEntry; + SV_SECURITY_CONTEXT *SecurityContext; + SV_CERT_ENTRY *CertificateEntry; + BOOLEAN MsCertFound; + BOOLEAN NonMsCertFound; + BOOLEAN FoundInDb; + BOOLEAN FoundInDbx; + BOOLEAN InvalidSigFound; + + Status = EFI_SUCCESS; + StartOpCodeHandle = NULL; + EndOpCodeHandle = NULL; + Index = 0; + MsCertFound = FALSE; + NonMsCertFound = FALSE; + FoundInDb = FALSE; + FoundInDbx = FALSE; + InvalidSigFound = FALSE; + + // 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 = LABEL_BOOTLOADER_CERT_LIST_START; + + 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; + + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, mBootloaderIndex); + if ((BootloaderEntry == NULL) || (BootloaderEntry->SecurityContext == NULL)) { + Status = EFI_NO_MEDIA; + goto ON_EXIT; + } + + SecurityContext = (SV_SECURITY_CONTEXT *)BootloaderEntry->SecurityContext; + for (Index = 0; Index < SecurityContext->NumCertificates; Index = Index + 1) { + CertificateEntry = GetCertEntry(BootloaderEntry, Index); + if (CertificateEntry == NULL) { + return EFI_NO_MEDIA; + } + + NameStringId = STRING_TOKEN(STR_CERT_NO_COMMON_NAME); + NameBufferSize = sizeof (NameBuffer); + SetMem (NameBuffer, NameBufferSize, 0); + if (!RETURN_ERROR (X509GetCommonName (CertificateEntry->CertData, + CertificateEntry->CertDataSize, + NameBuffer, + &NameBufferSize))) { + NewString = (CHAR16 *)AllocateZeroPool ((NameBufferSize + 1) * sizeof(CHAR16)); + if (NewString != NULL) { + if (!RETURN_ERROR (AsciiStrToUnicodeStrS (NameBuffer, NewString, NameBufferSize + 1))) { + NameStringId = HiiSetString (PrivateData->HiiHandle, 0, NewString, NULL); + } + FreePool (NewString); + } + } + + if (CertificateEntry->CertIsMicrosoft) { + MsCertFound = TRUE; + } else { + NonMsCertFound = TRUE; + } + + if (CertificateEntry->CertIsInDb) { + FoundInDb = TRUE; + } + + if (CertificateEntry->CertIsInDbx) { + FoundInDbx = TRUE; + } + + if (!CertificateEntry->SignatureValid || !CertificateEntry->CertIsValid) { + InvalidSigFound = TRUE; + } + + HiiCreateGotoOpCode ( + StartOpCodeHandle, + SOVEREIGN_BOOT_WIZARD_KEY_DETAILS_FORM_ID, + NameStringId, + STRING_TOKEN(STR_EMPTY_STRING), + EFI_IFR_FLAG_CALLBACK, + OPTION_BL_CERT_QUESTION_ID + Index + ); + } + + PrivateData->FormData.SignedByMs = MsCertFound; + PrivateData->FormData.SignedByMsOnly = (!NonMsCertFound && MsCertFound); + PrivateData->FormData.HasInvalidSignature = InvalidSigFound; + PrivateData->FormData.ImageHashIsInDb = SecurityContext->ImageIsInDb; + PrivateData->FormData.ImageHashIsInDbx = SecurityContext->ImageIsInDbx; + + if (SecurityContext->ImageIsSigned) { + if (!SecurityContext->ImageIsVerified || FoundInDbx || SecurityContext->ImageIsInDbx) { + PrivateData->FormData.ImageTrusted = IMAGE_STATE_UNTRUSTED; + } else if (FoundInDb || SecurityContext->ImageIsInDb) { + PrivateData->FormData.ImageTrusted = IMAGE_STATE_TRUSTED; + } else { + PrivateData->FormData.ImageTrusted = IMAGE_STATE_UNDECIDED; + } + } + + DEBUG ((DEBUG_INFO, "LoadBootloaderCertificates:\n" + " MsCertFound: %u\n" + " NonMsCertFound: %u\n" + " InvalidSigFound: %u\n" + " ImageIsSigned: %u\n" + " ImageIsVerified: %u\n" + " FoundInDbx: %u\n" + " FoundInDb: %u\n" + " ImageIsInDb: %u\n" + " ImageIsInDbx: %u\n" + " ImageTrusted: %u\n", + MsCertFound, + NonMsCertFound, + InvalidSigFound, + SecurityContext->ImageIsSigned, + SecurityContext->ImageIsVerified, + FoundInDbx, + FoundInDb, + SecurityContext->ImageIsInDb, + SecurityContext->ImageIsInDbx, + PrivateData->FormData.ImageTrusted)); + +ON_EXIT: + + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSovereignBootWizardFormSetGuid, + SOVEREIGN_BOOT_WIZARD_BL_DETAILS_FORM_ID, + StartOpCodeHandle, + EndOpCodeHandle + ); + + FREE_NON_OPCODE (StartOpCodeHandle); + FREE_NON_OPCODE (EndOpCodeHandle); + + return Status; +} + +/** + This function publish the Sovereign Boot Wizrd Interactive Mode form. + + @param[in, out] PrivateData Points to Sovereign Boot 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 +InstallInteractiveModeForm ( + IN OUT SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + PrivateData->FileContext = AllocateZeroPool (sizeof (SOVEREIGNBOOT_FILE_CONTEXT)); + + if (PrivateData->FileContext == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Init OpCode Handle and Allocate space for creation of Buffer + // + mStartOpCodeHandle = HiiAllocateOpCodeHandle (); + if (mStartOpCodeHandle == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + mEndOpCodeHandle = HiiAllocateOpCodeHandle (); + if (mEndOpCodeHandle == NULL) { + 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 Sovereign Boot Wizrd Interactive Mode form. + + @param[in, out] PrivateData Points to Sovereign Boot configuration private data. + +**/ +VOID +UninstallInteractiveModeForm ( + IN OUT SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + FREE_NON_NULL (PrivateData->FileContext); + + if (mStartOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mStartOpCodeHandle); + } + + if (mEndOpCodeHandle != NULL) { + HiiFreeOpCodeHandle (mEndOpCodeHandle); + } +} + +/** + This function removes the image hash from database. + + @param[in] PrivateData Module's private data. + + @retval EFI_SUCCESS Success to update the signature database + @retval EFI_NO_MEDIA If given bootloader was not found. + @retval EFI_NOT_FOUND If hash of the image could not be found in + database. + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +RemoveImageHashFromDatabase ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + EFI_STATUS Status; + EFI_SIGNATURE_LIST *ListWalker; + EFI_SIGNATURE_DATA *DataWalker; + CHAR16 VariableName[BUFFER_MAX_SIZE]; + UINTN VariableDataSize; + UINT32 VariableAttr; + UINTN RemainingSize; + UINTN ListIndex; + UINTN Index; + UINT8 *VariableData; + UINT8 *HashData; + UINTN DigestLen; + SV_MENU_ENTRY *BootloaderEntry; + SV_SECURITY_CONTEXT *SecurityContext; + + Status = EFI_NO_MEDIA; + VariableDataSize = 0; + ListIndex = 0; + VariableData = NULL; + + if (PrivateData->VariableName == Variable_DB) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE); + } else if (PrivateData->VariableName == Variable_DBX) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1); + } else { + goto Done; + } + + Status = gRT->GetVariable ( + VariableName, + &gEfiImageSecurityDatabaseGuid, + &VariableAttr, + &VariableDataSize, + VariableData + ); + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + goto Done; + } + + VariableData = AllocateZeroPool (VariableDataSize); + if (VariableData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status = gRT->GetVariable ( + VariableName, + &gEfiImageSecurityDatabaseGuid, + &VariableAttr, + &VariableDataSize, + VariableData + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, mBootloaderIndex); + if (BootloaderEntry == NULL || BootloaderEntry->SecurityContext == NULL) { + DEBUG ((DEBUG_ERROR, "Bootloader %u not found\n", mBootloaderIndex)); + return EFI_NO_MEDIA; + } + + SecurityContext = (SV_SECURITY_CONTEXT *)BootloaderEntry->SecurityContext; + + RemainingSize = VariableDataSize; + ListWalker = (EFI_SIGNATURE_LIST *)(VariableData); + + Status = EFI_NOT_FOUND; + while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize)) { + HashData = NULL; + if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha256Guid)) { + HashData = SecurityContext->ImageDigest; + DigestLen = SHA256_DIGEST_SIZE; + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha384Guid)) { + HashData = SecurityContext->ImageSha384Digest; + DigestLen = SHA384_DIGEST_SIZE; + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha512Guid)) { + HashData = SecurityContext->ImageSha512Digest; + DigestLen = SHA512_DIGEST_SIZE; + } else { + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + ListIndex++; + continue; + } + + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize); + for (Index = 0; Index < SIGNATURE_DATA_COUNTS (ListWalker); Index = Index + 1) { + // Remove raw certificate or certificate hash if data matches + if ((HashData != NULL) && + (CompareMem (DataWalker->SignatureData, HashData, DigestLen) == 0)) { + PrivateData->ListIndex = ListIndex; + + if (SIGNATURE_DATA_COUNTS (ListWalker) == 1) { + Status = DeleteSignatureEx (PrivateData, Delete_Signature_List_One, 1); + } else { + PrivateData->CheckArray = AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker)); + if (PrivateData->CheckArray == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + PrivateData->CheckArray[Index] = TRUE; + Status = DeleteSignatureEx (PrivateData, Delete_Signature_Data, 1); + FreePool (PrivateData->CheckArray); + PrivateData->CheckArray = NULL; + } + + goto Done; + } + + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize); + } + + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + ListIndex++; + } + +Done: + + FREE_NON_NULL (VariableData); + + return Status; +} + +/** + This function removes a certificate from database. + + @param[in] PrivateData Module's private data. + + @retval EFI_SUCCESS Success to update the signature database + @retval EFI_NO_MEDIA If given bootloader or certificate was not + found or certificate hash could not be + calculated. + @retval EFI_NOT_FOUND If the certificate or its hash was not + found in database. + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +RemoveCertificateFromDatabase ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + EFI_STATUS Status; + EFI_SIGNATURE_LIST *ListWalker; + EFI_SIGNATURE_DATA *DataWalker; + CHAR16 VariableName[BUFFER_MAX_SIZE]; + UINTN VariableDataSize; + UINT32 VariableAttr; + UINTN RemainingSize; + UINTN ListIndex; + UINTN Index; + UINT8 *VariableData; + UINT8 HashAlg; + UINT8 CertDigest[MAX_DIGEST_SIZE]; + UINTN DigestLen; + SV_MENU_ENTRY *BootloaderEntry; + SV_CERT_ENTRY *CertificateEntry; + + Status = EFI_NO_MEDIA; + VariableDataSize = 0; + ListIndex = 0; + VariableData = NULL; + + if (PrivateData->VariableName == Variable_DB) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE); + } else if (PrivateData->VariableName == Variable_DBX) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1); + } else { + goto Done; + } + + Status = gRT->GetVariable ( + VariableName, + &gEfiImageSecurityDatabaseGuid, + &VariableAttr, + &VariableDataSize, + VariableData + ); + if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) { + goto Done; + } + + VariableData = AllocateZeroPool (VariableDataSize); + if (VariableData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + + Status = gRT->GetVariable ( + VariableName, + &gEfiImageSecurityDatabaseGuid, + &VariableAttr, + &VariableDataSize, + VariableData + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, mBootloaderIndex); + if (BootloaderEntry == NULL) { + DEBUG ((DEBUG_ERROR, "Bootloader %u not found\n", mBootloaderIndex)); + return EFI_NO_MEDIA; + } + + CertificateEntry = GetCertEntry(BootloaderEntry, mCertIndex); + if (CertificateEntry == NULL) { + DEBUG ((DEBUG_ERROR, "Certificate %u not found\n", mCertIndex)); + return EFI_NO_MEDIA; + } + + RemainingSize = VariableDataSize; + ListWalker = (EFI_SIGNATURE_LIST *)(VariableData); + + Status = EFI_NOT_FOUND; + while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize)) { + HashAlg = HASHALG_MAX; + if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha256Guid)) { + HashAlg = HASHALG_SHA256; + DigestLen = SHA256_DIGEST_SIZE; + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha384Guid)) { + HashAlg = HASHALG_SHA384; + DigestLen = SHA384_DIGEST_SIZE; + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha512Guid)) { + HashAlg = HASHALG_SHA512; + DigestLen = SHA512_DIGEST_SIZE; + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Guid)) { + HashAlg = HASHALG_RAW; + } else { + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + ListIndex++; + continue; + } + + if (HashAlg < HASHALG_MAX) { + ZeroMem (CertDigest, MAX_DIGEST_SIZE); + if (!CalculateCertHash (CertificateEntry->CertData, CertificateEntry->CertDataSize, HashAlg, CertDigest)) { + Status = EFI_NO_MEDIA; + goto Done; + } + } + + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)ListWalker + sizeof (EFI_SIGNATURE_LIST) + ListWalker->SignatureHeaderSize); + for (Index = 0; Index < SIGNATURE_DATA_COUNTS (ListWalker); Index = Index + 1) { + // Remove raw certificate or certificate hash if data matches + if (((HashAlg < HASHALG_MAX) && (CompareMem (DataWalker->SignatureData, + CertDigest, + DigestLen) == 0)) || + ((HashAlg == HASHALG_RAW) && (CompareMem (DataWalker->SignatureData, + CertificateEntry->CertData, + CertificateEntry->CertDataSize) == 0))) + { + PrivateData->ListIndex = ListIndex; + + if (SIGNATURE_DATA_COUNTS (ListWalker) == 1) { + Status = DeleteSignatureEx (PrivateData, Delete_Signature_List_One, 1); + } else { + PrivateData->CheckArray = AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker)); + if (PrivateData->CheckArray == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Done; + } + PrivateData->CheckArray[Index] = TRUE; + Status = DeleteSignatureEx (PrivateData, Delete_Signature_Data, 1); + FreePool (PrivateData->CheckArray); + PrivateData->CheckArray = NULL; + } + + goto Done; + } + + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize); + } + + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + ListIndex++; + } + +Done: + + FREE_NON_NULL (VariableData); + + return Status; +} + +EFI_STATUS +RemoveImageDataFromDatabase ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + EFI_STATUS Status = EFI_SUCCESS; + SV_MENU_ENTRY *BootloaderEntry; + SV_SECURITY_CONTEXT *SecurityContext; + UINTN CertIndex; + UINTN Index; + + while (!EFI_ERROR (Status)) { + Status = RemoveImageHashFromDatabase (PrivateData); + } + + // No more entries with given image, continue with certs + if (Status == EFI_NOT_FOUND) { + Status = EFI_SUCCESS; + } else { + DEBUG ((DEBUG_INFO, "RemoveImageHashFromDatabase failed with %r\n", Status)); + return Status; + } + + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, mBootloaderIndex); + if (BootloaderEntry == NULL || BootloaderEntry->SecurityContext == NULL) { + DEBUG ((DEBUG_INFO, "RemoveImageDataFromDatabase: No bootloader entry or security context\n")); + return EFI_NOT_FOUND; + } + + SecurityContext = (SV_SECURITY_CONTEXT *)BootloaderEntry->SecurityContext; + + // Backup currently browsed certificate index + CertIndex = mCertIndex; + + for (Index = 0; Index < SecurityContext->NumCertificates; Index++) { + + mCertIndex = Index; + while (!EFI_ERROR (Status)) { + Status = RemoveCertificateFromDatabase (PrivateData); + } + + // No more entries with given, proceed with next cert + if (Status == EFI_NOT_FOUND) { + Status = EFI_SUCCESS; + continue; + } else { + DEBUG ((DEBUG_INFO, "RemoveCertificateFromDatabase %u failed with %r\n", Index, Status)); + mCertIndex = CertIndex; + return Status; + } + } + + mCertIndex = CertIndex; + + if (Status == EFI_NOT_FOUND) { + Status = EFI_SUCCESS; + } + + return Status; +} + +EFI_STATUS +RemoveImageDataFromDbx ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + PrivateData->VariableName = Variable_DBX; + + return RemoveImageDataFromDatabase(PrivateData); +} + +EFI_STATUS +RemoveImageDataFromDb ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + PrivateData->VariableName = Variable_DB; + + return RemoveImageDataFromDatabase(PrivateData); +} diff --git a/DasharoModulePkg/Application/SovereignBootWizard/InteractiveModeImpl.h b/DasharoModulePkg/Application/SovereignBootWizard/InteractiveModeImpl.h new file mode 100644 index 0000000000..dbfee7c68b --- /dev/null +++ b/DasharoModulePkg/Application/SovereignBootWizard/InteractiveModeImpl.h @@ -0,0 +1,495 @@ +/** @file +The header file of Interactive Mode implementation of Sovereign Boot +Provisioning Wizard. + +Copyright (c) 2025, 3mdeb Sp z o.o. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef __SOVEREIGNBOOT_INTERACTIVE_MODE_IMPL_H__ +#define __SOVEREIGNBOOT_INTERACTIVE_MODE_IMPL_H__ + +// +// Shared IFR form update data +// +extern VOID *mStartOpCodeHandle; +extern VOID *mEndOpCodeHandle; +extern EFI_IFR_GUID_LABEL *mStartLabel; +extern EFI_IFR_GUID_LABEL *mEndLabel; + +#define MAX_CHAR 480 +#define TWO_BYTE_ENCODE 0x82 + +#define UNKNOWN_FILE_TYPE 0 +#define X509_CERT_FILE_TYPE 1 +#define PE_IMAGE_FILE_TYPE 2 +#define AUTHENTICATION_2_FILE_TYPE 3 + +// +// Certificate public key minimum size (bytes) +// +#define CER_PUBKEY_MIN_SIZE 256 + +// +// Define KeyType for public key storing file +// +#define KEY_TYPE_RSASSA 0 + +// +// Types of errors may occur during certificate enrollment. +// +typedef enum { + None_Error = 0, + // + // Unsupported_type indicates the certificate type is not supported. + // + Unsupported_Type, + // + // Unqualified_key indicates the key strength of certificate is not + // strong enough. + // + Unqualified_Key, + Enroll_Error_Max +} ENROLL_KEY_ERROR; + +typedef enum { + Delete_Signature_List_All, + Delete_Signature_List_One, + Delete_Signature_Data +} SIGNATURE_DELETE_TYPE; + + +typedef enum { + Signature_Type_X509_Cert, + Signature_Type_X509_Cert_Hash, + Signature_Type_RSA_Key, + Signature_Type_RSA_Key_Hash, + Signature_Type_Hash, + Signature_Type_Unknown +} SIGNATURE_TYPE; + +typedef struct { + UINTN Signature; + LIST_ENTRY Head; + UINTN MenuNumber; +} SOVEREIGNBOOT_MENU_OPTION; + + +#define SIGNATURE_DATA_COUNTS(List) \ + (((List)->SignatureListSize - sizeof(EFI_SIGNATURE_LIST) - (List)->SignatureHeaderSize) / (List)->SignatureSize) + +// +// We define another format of 5th directory entry: security directory +// +typedef struct { + UINT32 Offset; // Offset of certificate + UINT32 SizeOfCert; // size of certificate appended +} EFI_IMAGE_SECURITY_DATA_DIRECTORY; + +typedef enum { + ImageType_IA32, + ImageType_X64 +} IMAGE_TYPE; + +// +// Cryptographic Key Information +// +#pragma pack(1) +typedef struct _CPL_KEY_INFO { + UINT32 KeyLengthInBits; // Key Length In Bits + UINT32 BlockSize; // Operation Block Size in Bytes + UINT32 CipherBlockSize; // Output Cipher Block Size in Bytes + UINT32 KeyType; // Key Type + UINT32 CipherMode; // Cipher Mode for Symmetric Algorithm + UINT32 Flags; // Additional Key Property Flags +} CPL_KEY_INFO; +#pragma pack() + +/** + This function extracts configuration from variable. + + @param[in] Private Point to Sovereign Boot configuration driver private data. + @param[in, out] FormData Point to Sovereign Boot form private data. + +**/ +VOID +InteractiveModeExtractConfig ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN OUT SOVEREIGN_BOOT_WIZARD_FORM_DATA *FormData + ); + +EFI_STATUS +InstallInteractiveModeForm ( + IN OUT SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ); + +VOID +UninstallInteractiveModeForm ( + IN OUT SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ); + +/** + Update the DB form base on the input file path info. + + @param FilePath Point to the file path. + + @retval TRUE Exit caller function. + @retval FALSE Not exit caller function. +**/ +BOOLEAN +EFIAPI +UpdateDBFromFile ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ); + +/** + Update the DBX form base on the input file path info. + + @param FilePath Point to the file path. + + @retval TRUE Exit caller function. + @retval FALSE Not exit caller function. +**/ +BOOLEAN +EFIAPI +UpdateDBXFromFile ( + IN EFI_DEVICE_PATH_PROTOCOL *FilePath + ); + +/** + This code cleans up enrolled file by closing file & free related resources attached to + enrolled file. + + @param[in] FileContext FileContext cached in Sovereign Boot Wizard driver + +**/ +VOID +CloseEnrolledFile ( + IN SOVEREIGNBOOT_FILE_CONTEXT *FileContext + ); + +/** + Delete a signature entry from signature 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 signature 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 SOVEREIGN_BOOT_WIZARD_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 + ); + +/** + This function to delete signature list or data, according by DelType. + + @param[in] PrivateData Module's private data. + @param[in] DelType Indicate delete signature list or data. + @param[in] CheckedCount Indicate how many signature data have + been checked in current signature list. + + @retval EFI_SUCCESS Success to update the signature list page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +DeleteSignatureEx ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN SIGNATURE_DELETE_TYPE DelType, + IN UINT32 CheckedCount + ); + +/** + This function to load signature data under the signature list. + + @param[in] PrivateData Module's private data. + @param[in] LabelId 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] ListIndex Indicate to load which signature list. + + @retval EFI_SUCCESS Success to update the signature list page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +LoadSignatureData ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN UINT16 LabelId, + IN EFI_FORM_ID FormId, + IN EFI_QUESTION_ID QuestionIdBase, + IN UINT16 ListIndex + ); + +/** + This function to load signature list, the update the menu page. + + @param[in] PrivateData Module's private data. + @param[in] LabelId 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 +LoadSignatureList ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN UINT16 LabelId, + IN EFI_FORM_ID FormId, + IN EFI_QUESTION_ID QuestionIdBase + ); + +/** + This function to load signature data strings under the signature data. + + @param[in] PrivateData Module's private data. + @param[in] DataIndex Indicate to load which signature data. + @param[in] ListIndex Indicate to load which signature list. + + @retval EFI_SUCCESS Success to update the signature data page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +LoadSignatureDataStrings ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN UINT16 DataIndex, + IN UINT16 ListIndex + ); + +/** + 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 SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN UINT32 HashAlg, + IN EFI_HII_DATE *RevocationDate, + IN EFI_HII_TIME *RevocationTime, + IN BOOLEAN AlwaysRevocation + ); + +/** + Enroll signature into DB/DBX/DBT without KEK's authentication. + The SignatureOwner GUID will be SovereignBootWizardFormsetGuid. + + @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 SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN CHAR16 *VariableName + ); + +/** + Check whether a certificate from a file exists in dbx. + + @param[in] PrivateData The module's private data. + + @retval TRUE The X509 certificate is found in dbx successfully. + @retval FALSE The X509 certificate is not found in dbx. +**/ +BOOLEAN +IsX509CertInDbx ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private + ); + + + /** + 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 SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN UINT16 LabelNumber, + IN EFI_FORM_ID FormId, + IN EFI_QUESTION_ID QuestionIdBase + ); + +/** + 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 + ); + +/** + 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 + ); + +/** + Clean up the dynamic opcode at label and form specified by both LabelId. + + @param[in] FormId It is the Form ID for opcode deletion. + @param[in] LabelId It is the Label ID for opcode deletion. + @param[in] PrivateData Module private data. + +**/ +VOID +CleanUpPage ( + IN UINT16 FormId, + IN UINT16 LabelId, + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ); + +/** + This function to loads bootloader data strings under the bootloader form. + + @param[in] PrivateData Module's private data. + + @retval EFI_SUCCESS Success to update the bootloader list page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +LoadBootloaders ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ); + +/** + This function to loads certificate list under the bootloader data. + + @param[in] PrivateData Module's private data. + + @retval EFI_SUCCESS Success to update the bootloader page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +LoadBootloaderCertificates ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ); + +/** + This function removes the image hash from database. + + @param[in] PrivateData Module's private data. + + @retval EFI_SUCCESS Success to update the signature database + @retval EFI_NO_MEDIA If given bootloader was not found. + @retval EFI_NOT_FOUND If hash of the image could not be found in + database. + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +RemoveImageHashFromDatabase ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ); + +/** + This function removes a certificate from database. + + @param[in] PrivateData Module's private data. + + @retval EFI_SUCCESS Success to update the signature database + @retval EFI_NO_MEDIA If given bootloader or certificate was not + found or certificate hash could not be + calculated. + @retval EFI_NOT_FOUND If the certificate or its hash was not + found in database. + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +RemoveCertificateFromDatabase ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ); + +/** + This function removes all data elated to an image from untrusted database. + + @param[in] PrivateData Module's private data. + + @retval EFI_SUCCESS Success to update the signature database + @retval EFI_NO_MEDIA If given bootloader or certificate was not + found or certificate hash could not be + calculated. + @retval EFI_NOT_FOUND If the certificate or its hash was not + found in database. + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +RemoveImageDataFromDbx ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ); + +/** + This function removes all data elated to an image from trusted database. + + @param[in] PrivateData Module's private data. + + @retval EFI_SUCCESS Success to update the signature database + @retval EFI_NO_MEDIA If given bootloader or certificate was not + found or certificate hash could not be + calculated. + @retval EFI_NOT_FOUND If the certificate or its hash was not + found in database. + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. +**/ +EFI_STATUS +RemoveImageDataFromDb ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ); + +#endif diff --git a/DasharoModulePkg/Application/SovereignBootWizard/KeyManagement.c b/DasharoModulePkg/Application/SovereignBootWizard/KeyManagement.c index c0872deec9..b877943307 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/KeyManagement.c +++ b/DasharoModulePkg/Application/SovereignBootWizard/KeyManagement.c @@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "SovereignBootWizard.h" +#include "InteractiveModeImpl.h" STATIC EFI_STATUS DeleteAllSecureBootVariables ( @@ -203,7 +204,8 @@ CreateSigList ( STATIC EFI_STATUS EnrollHashToSigDB ( IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, - IN CHAR16 *VariableName + IN CHAR16 *VariableName, + IN BOOLEAN EnrollImageHash ) { EFI_SIGNATURE_LIST *SigDBHash; @@ -219,7 +221,7 @@ EnrollHashToSigDB ( BOOLEAN Trust; EFI_INPUT_KEY Key; - BootloaderEntry = GetMenuEntry (&BootOptionMenu, mBootloaderIndex); + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, mBootloaderIndex); if (BootloaderEntry == NULL) { return EFI_NO_MEDIA; } @@ -229,13 +231,6 @@ EnrollHashToSigDB ( return EFI_NO_MEDIA; } - if (SecurityContext->ImageIsSigned) { - CertificateEntry = GetCertEntry (BootloaderEntry, mCertIndex); - if (CertificateEntry == NULL) { - return EFI_NO_MEDIA; - } - } - DataSize = 0; SigDBSize = 0; SigDBHash = NULL; @@ -243,7 +238,19 @@ EnrollHashToSigDB ( SigDBSize = sizeof (EFI_SIGNATURE_LIST) + sizeof (EFI_SIGNATURE_DATA) - 1; - if (SecurityContext->ImageIsSigned) { + if (EnrollImageHash || !SecurityContext->ImageIsSigned) { + SigDBSize += SHA256_DIGEST_SIZE; + Status = CreateSigList ( + SecurityContext->ImageDigest, + SecurityContext->ImageDigestSize, + &SecurityContext->HashType, + &SigDBHash + ); + } else { + CertificateEntry = GetCertEntry (BootloaderEntry, mCertIndex); + if (CertificateEntry == NULL) { + return EFI_NO_MEDIA; + } // EDK2 only checks X509 certificates in DB and DBX, so enroll whole cert to DB. // For DBX only non-CA (signer's) certificate can be checked. // Otherwise enroll SHA256 to DBX to save space. @@ -267,14 +274,6 @@ EnrollHashToSigDB ( &SigDBHash ); } - } else { - SigDBSize += SHA256_DIGEST_SIZE; - Status = CreateSigList ( - SecurityContext->ImageDigest, - SecurityContext->ImageDigestSize, - &SecurityContext->HashType, - &SigDBHash - ); } if (SigDBHash == NULL) { @@ -318,7 +317,7 @@ EnrollHashToSigDB ( goto ON_EXIT; } - if (SecurityContext->ImageIsSigned && Trust) { + if (!EnrollImageHash && SecurityContext->ImageIsSigned && Trust) { if (!CertificateEntry->CertIsValid) { do { CreatePopUp ( @@ -354,23 +353,25 @@ EnrollHashToSigDB ( goto ON_EXIT; } if (PrivateData->ConfigData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED) { - if (CertificateEntry->CertIsInDbx) { - do { - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"", - L"This certificate is currently untrusted.", - L"Removing certificates from DBX is not yet supported.", - L"Can not add the certificate as trusted." - L"", - L"Press ENTER to abort the process...", - L"", - NULL - ); - } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); - Status = EFI_ABORTED; - goto ON_EXIT; + if (CertificateEntry->CertIsInDbx || !SecurityContext->ImageIsVerified) { + Status = RemoveImageDataFromDbx (PrivateData); + if (EFI_ERROR (Status)) { + do { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"", + L"Failed to remove all bootloader entries from DBX.", + L"Can not add the certificate as trusted." + L"", + L"Press ENTER to abort the process...", + L"", + NULL + ); + } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); + Status = EFI_ABORTED; + goto ON_EXIT; + } } } } @@ -394,17 +395,19 @@ EnrollHashToSigDB ( if (Trust && (mFirstTrustedBootloader == -1)) { mFirstTrustedBootloader = (INTN)mBootloaderIndex; } - // If image is unsigned or added as untrusted we have to increment the - // bootloader index to show next one. No point in displaying other - // signatures if one of them is already in DBX, as the image will not - // pass Secure Boot verification. Otherwise move to next certificate. - if (!SecurityContext->ImageIsSigned || !Trust) { - mBootloaderIndex++; - mCertIndex = 0; - DEBUG ((DEBUG_INFO, "Moving to next bootloader %u\n", mBootloaderIndex)); - } else { - mCertIndex++; - DEBUG ((DEBUG_INFO, "Moving to next certificate %u for bootloader %u\n", mCertIndex, mBootloaderIndex)); + if (!mAltAccessMode) { + // If image is unsigned or added as untrusted we have to increment the + // bootloader index to show next one. No point in displaying other + // signatures if one of them is already in DBX, as the image will not + // pass Secure Boot verification. Otherwise move to next certificate. + if (!SecurityContext->ImageIsSigned || !Trust) { + mBootloaderIndex++; + mCertIndex = 0; + DEBUG ((DEBUG_INFO, "Moving to next bootloader %u\n", mBootloaderIndex)); + } else { + mCertIndex++; + DEBUG ((DEBUG_INFO, "Moving to next certificate %u for bootloader %u\n", mCertIndex, mBootloaderIndex)); + } } } @@ -419,8 +422,9 @@ EnrollHashToSigDB ( EFI_STATUS AddKeyOrHashAsTrustedOrUntrusted ( - SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, - BOOLEAN Trust + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN BOOLEAN Trust, + IN BOOLEAN EnrollImageHash ) { EFI_STRING Message; @@ -433,38 +437,51 @@ AddKeyOrHashAsTrustedOrUntrusted ( CHAR16 ErrorMessage[MAXIMUM_VALUE_CHARACTERS + 8]; EFI_INPUT_KEY Key; - Message = HiiGetString ( - PrivateData->HiiHandle, - Trust ? STRING_TOKEN(STR_SV_TRUST_KEY_QUESTION) : STRING_TOKEN(STR_SV_UNTRUST_KEY_QUESTION), - NULL); - HeaderString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN(STR_KEY_FINGERPRINT), NULL); - HashString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN(STR_KEY_FINGERPRINT_HASH), NULL); + PopupMessage = NULL; - // Size of the whole message plus couple new lines - PopupMessageSize = StrSize(Message) + StrSize(HeaderString) + StrSize(HashString) + 6; - PopupMessage = (CHAR16 *) AllocateZeroPool(PopupMessageSize); + if (!mAltAccessMode) { + Message = HiiGetString ( + PrivateData->HiiHandle, + Trust ? STRING_TOKEN(STR_SV_TRUST_KEY_QUESTION) : STRING_TOKEN(STR_SV_UNTRUST_KEY_QUESTION), + NULL); - if (PopupMessage == NULL) { - return EFI_OUT_OF_RESOURCES; - } + if (PrivateData->FormData.ImageUnsigned) { + HeaderString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN(STR_BOOTLOADER_HASH), NULL); + } else { + HeaderString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN(STR_KEY_FINGERPRINT), NULL); + } + HashString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN(STR_KEY_FINGERPRINT_HASH), NULL); + + // Size of the whole message plus couple new lines + PopupMessageSize = StrSize(Message) + StrSize(HeaderString) + StrSize(HashString) + 6; + PopupMessage = (CHAR16 *) AllocateZeroPool(PopupMessageSize); + + if (PopupMessage == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + UnicodeSPrint (PopupMessage, PopupMessageSize, L"%s\n%s\n%s", Message, HeaderString, HashString); + HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SV_TRUST_KEY_POPUP), PopupMessage, NULL) ; - UnicodeSPrint (PopupMessage, PopupMessageSize, L"%s\n%s\n%s", Message, HeaderString, HashString); - HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SV_TRUST_KEY_POPUP), PopupMessage, NULL) ; + Status = PrivateData->HiiPopup->CreatePopup ( + PrivateData->HiiPopup, + EfiHiiPopupStyleInfo, + EfiHiiPopupTypeYesNo, + PrivateData->HiiHandle, + STRING_TOKEN (STR_SV_TRUST_KEY_POPUP), + &UserSelection + ); + } else { + UserSelection = EfiHiiPopupSelectionYes; + } - Status = PrivateData->HiiPopup->CreatePopup ( - PrivateData->HiiPopup, - EfiHiiPopupStyleInfo, - EfiHiiPopupTypeYesNo, - PrivateData->HiiHandle, - STRING_TOKEN (STR_SV_TRUST_KEY_POPUP), - &UserSelection - ); if (UserSelection == EfiHiiPopupSelectionYes) { // Add key or hash to DB or DBX Status = EnrollHashToSigDB ( PrivateData, - Trust ? EFI_IMAGE_SECURITY_DATABASE : EFI_IMAGE_SECURITY_DATABASE1 + Trust ? EFI_IMAGE_SECURITY_DATABASE : EFI_IMAGE_SECURITY_DATABASE1, + EnrollImageHash ); if (EFI_ERROR (Status) && Status != EFI_ABORTED) { @@ -478,8 +495,8 @@ AddKeyOrHashAsTrustedOrUntrusted ( EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"", - Trust ? L"Could not add the certificate/image as trusted" : - L"Could not add the certificate/image as untrusted", + Trust ? L"Could not add the certificate/image hash as trusted" : + L"Could not add the certificate/image hash as untrusted", L"", ErrorMessage, L"", @@ -492,7 +509,7 @@ AddKeyOrHashAsTrustedOrUntrusted ( Status = EFI_ABORTED; } - FreePool (PopupMessage); + FREE_NON_NULL (PopupMessage); return Status; } diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SignatureParsing.c b/DasharoModulePkg/Application/SovereignBootWizard/SignatureParsing.c index e99fd7d54e..9ba29ed1cf 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SignatureParsing.c +++ b/DasharoModulePkg/Application/SovereignBootWizard/SignatureParsing.c @@ -293,7 +293,7 @@ CreateNewCert ( if ((SecCtx == NULL) || (CertData == NULL) || (FileBuffer == NULL) || (AuthData == NULL) || (CertEntry == NULL) || (CertDataSize == 0) || (FileSize == 0) || (AuthDataSize == 0)) { - DEBUG ((DEBUG_ERROR, "%a, Invalid parameter\n", __FUNCTION__)); + DEBUG ((DEBUG_ERROR, "CreateNewCert, Invalid parameter\n")); return EFI_INVALID_PARAMETER; } @@ -353,15 +353,39 @@ CreateNewCert ( ); if (!EFI_ERROR (Status) && IsFound) { NewCertEntry->CertIsInDb = TRUE; - } else { - NewCertEntry->CertIsInDb = FALSE; } - NewCertEntry->CertIsInDbx = IsForbiddenByDbx (AuthData, AuthDataSize, ImageDigest, ImageDigestSize); + // Check if certificate is in DBX + IsFound = FALSE; + Status = IsSignatureFoundInDatabase ( + EFI_IMAGE_SECURITY_DATABASE1, + NewCertEntry->CertData, + &gEfiCertX509Guid, + NewCertEntry->CertDataSize, + &IsFound + ); + if (!EFI_ERROR (Status) && IsFound) { + NewCertEntry->CertIsInDbx = TRUE; + } + + // Check if certificate hash is in DBX + IsFound = FALSE; + Status = IsCertHashFoundInDbx ( + NewCertEntry->CertData, + NewCertEntry->CertDataSize, + NULL, + 0, + NULL, + &IsFound + ); + if (!EFI_ERROR (Status) && IsFound) { + NewCertEntry->CertIsInDbx = TRUE; + } + NewCertEntry->SignatureValid = AuthenticodeVerify ( - AuthData, AuthDataSize, - NewCertEntry->CertData, NewCertEntry->CertDataSize, - ImageDigest, ImageDigestSize); + AuthData, AuthDataSize, + NewCertEntry->CertData, NewCertEntry->CertDataSize, + ImageDigest, ImageDigestSize); NewCertEntry->CertIsCA = CertIsCA (NewCertEntry); @@ -389,7 +413,7 @@ CreateNewCert ( } // Mark the image as unverified if it is in DBX. - if (NewCertEntry->CertIsInDbx) { + if (IsForbiddenByDbx (AuthData, AuthDataSize, ImageDigest, ImageDigestSize)) { SecCtx->ImageIsVerified = FALSE; } @@ -632,6 +656,7 @@ FillSecurityContext ( UINTN ImageSize; UINT32 AuthStatus; EFI_STATUS Status; + EFI_GUID HashType; FullFilePath = NULL; LoadCtx = (SV_LOAD_CONTEXT *)Entry->VariableContext; @@ -684,6 +709,21 @@ FillSecurityContext ( &SecCtx->ImageDigestSize, &SecCtx->HashType); + // Additional hashes for checks in interactive mode. + HashPeImage (ImageBase, + ImageSize, + HASHALG_SHA384, + SecCtx->ImageSha384Digest, + &SecCtx->ImageSha384DigestSize, + &HashType); + + HashPeImage (ImageBase, + ImageSize, + HASHALG_SHA512, + SecCtx->ImageSha512Digest, + &SecCtx->ImageSha512DigestSize, + &HashType); + // // Start Image Validation. // @@ -727,6 +767,121 @@ FillSecurityContext ( return Status; } +VOID +RefreshImageSecurityInfo ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ) +{ + SV_MENU_ENTRY *BootloaderEntry; + SV_SECURITY_CONTEXT *SecurityContext; + SV_CERT_ENTRY *CertificateEntry; + UINTN Index; + BOOLEAN MsCertFound; + BOOLEAN NonMsCertFound; + BOOLEAN FoundInDbx; + BOOLEAN FoundInDb; + BOOLEAN InvalidSigFound; + + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, mBootloaderIndex); + if (BootloaderEntry == NULL) { + return; + } + + FreeSecurityContext (BootloaderEntry->SecurityContext); + FREE_NON_NULL (BootloaderEntry->SecurityContext); + + FillSecurityContext (BootloaderEntry); + + MsCertFound = FALSE; + NonMsCertFound = FALSE; + FoundInDbx = FALSE; + FoundInDb = FALSE; + InvalidSigFound = FALSE; + + if (BootloaderEntry->SecurityContext == NULL) { + return; + } + + SecurityContext = (SV_SECURITY_CONTEXT *)BootloaderEntry->SecurityContext; + for (Index = 0; Index < SecurityContext->NumCertificates; Index = Index + 1) { + CertificateEntry = GetCertEntry(BootloaderEntry, Index); + if (CertificateEntry == NULL) { + continue; + } + + if (CertificateEntry->CertIsMicrosoft) { + MsCertFound = TRUE; + } else { + NonMsCertFound = TRUE; + } + + if (CertificateEntry->CertIsInDbx) { + FoundInDbx = TRUE; + } + + if (CertificateEntry->CertIsInDb) { + FoundInDb = TRUE; + } + + if (!CertificateEntry->SignatureValid || !CertificateEntry->CertIsValid) { + InvalidSigFound = TRUE; + } + + if (Index == mCertIndex) { + PrivateData->FormData.CertInDb = CertificateEntry->CertIsInDb; + PrivateData->FormData.CertInDbx = CertificateEntry->CertIsInDbx; + PrivateData->FormData.CertIsValid = CertificateEntry->CertIsValid; + PrivateData->FormData.CertIsMicrosoft = CertificateEntry->CertIsMicrosoft; + } + } + + PrivateData->FormData.SignedByMs = MsCertFound; + PrivateData->FormData.SignedByMsOnly = (!NonMsCertFound && MsCertFound); + PrivateData->FormData.HasInvalidSignature = InvalidSigFound; + PrivateData->FormData.ImageHashIsInDb = SecurityContext->ImageIsInDb; + PrivateData->FormData.ImageHashIsInDbx = SecurityContext->ImageIsInDbx; + + if (SecurityContext->ImageIsSigned) { + if (!SecurityContext->ImageIsVerified || FoundInDbx || SecurityContext->ImageIsInDbx) { + PrivateData->FormData.ImageTrusted = IMAGE_STATE_UNTRUSTED; + } else if (FoundInDb || SecurityContext->ImageIsInDb) { + PrivateData->FormData.ImageTrusted = IMAGE_STATE_TRUSTED; + } else { + PrivateData->FormData.ImageTrusted = IMAGE_STATE_UNDECIDED; + } + } else { + if (SecurityContext->ImageIsInDbx) { + PrivateData->FormData.ImageTrusted = IMAGE_STATE_UNTRUSTED; + } else if (SecurityContext->ImageIsInDb) { + PrivateData->FormData.ImageTrusted = IMAGE_STATE_TRUSTED; + } else { + PrivateData->FormData.ImageTrusted = IMAGE_STATE_UNDECIDED; + } + } + + DEBUG ((DEBUG_INFO, "RefreshImageSecurityInfo:\n" + " MsCertFound: %u\n" + " NonMsCertFound: %u\n" + " InvalidSigFound: %u\n" + " ImageIsSigned: %u\n" + " ImageIsVerified: %u\n" + " FoundInDbx: %u\n" + " FoundInDb: %u\n" + " ImageIsInDb: %u\n" + " ImageIsInDbx: %u\n" + " ImageTrusted: %u\n", + MsCertFound, + NonMsCertFound, + InvalidSigFound, + SecurityContext->ImageIsSigned, + SecurityContext->ImageIsVerified, + FoundInDbx, + FoundInDb, + SecurityContext->ImageIsInDb, + SecurityContext->ImageIsInDbx, + PrivateData->FormData.ImageTrusted)); +} + /** Get the Cert Entry from the list in Menu Entry. @@ -817,7 +972,7 @@ ParseHashValue ( } /** - Parse key modulus from buffer, and save in the CHAR16 type array. + Format raw hex buffer, and save in the CHAR16 type array. The buffer is callee allocated and should be freed by the caller. @param[in] Digest The pointer to the hash value. @@ -829,7 +984,7 @@ ParseHashValue ( @retval EFI_SUCCESS Operation success. **/ EFI_STATUS -ParseKeyModulus ( +FormatHexBuffer ( IN UINT8 *Digest, IN UINTN DigestSize, OUT CHAR16 **BufferToReturn @@ -898,7 +1053,7 @@ UpdateCertInfo ( EFI_STRING NewString; EFI_STATUS Status; - BootloaderEntry = GetMenuEntry (&BootOptionMenu, OptionNumber); + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, OptionNumber); if (BootloaderEntry == NULL) { return EFI_NO_MEDIA; } @@ -912,17 +1067,16 @@ UpdateCertInfo ( (SecurityContext->NumCertificates == 0)); if (Private->ConfigData.AppLaunchCause != SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED) { - if (SecurityContext->ImageIsInDb || SecurityContext->ImageIsInDbx) { - DEBUG ((DEBUG_INFO, "Bootloader %u already (un)trusted\n", OptionNumber)); - return EFI_NO_MEDIA; + if (!mAltAccessMode) { + if (SecurityContext->ImageIsInDb || SecurityContext->ImageIsInDbx) { + DEBUG ((DEBUG_INFO, "Bootloader %u already (un)trusted\n", OptionNumber)); + return EFI_NO_MEDIA; + } } } // Image is unsigned? Show its hash instead of certificates if (Private->FormData.ImageUnsigned) { - - HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_KEY_FINGERPRINT), L"Image hash (SHA-256):\n!!! Image is unsigned !!!", NULL); - Status = ParseHashValue (SecurityContext->ImageDigest, SecurityContext->ImageDigestSize, &NewString); if (!EFI_ERROR (Status)) { HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_KEY_FINGERPRINT_HASH), NewString, NULL); @@ -938,7 +1092,7 @@ UpdateCertInfo ( // Do not show images that are not verified (one of the certs in the // signatures is unstrusted/in DBX), because we won't be able to boot it // anyways. - if (!SecurityContext->ImageIsVerified) { + if (!SecurityContext->ImageIsVerified && !mAltAccessMode) { DEBUG ((DEBUG_INFO, "Image %u already untrusted\n", mBootloaderIndex)); mCertIndex = 0; return EFI_NO_MEDIA; @@ -955,17 +1109,19 @@ UpdateCertInfo ( // Do not show already trusted/utrusted, invalid or microsoft certificates if (Private->ConfigData.AppLaunchCause != SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED) { - if (CertificateEntry->CertIsMicrosoft) { - DEBUG ((DEBUG_INFO, "Certificate %u belongs to Microsoft\n", - mCertIndex)); - mCertIndex++; - continue; - } - if (CertificateEntry->CertIsInDb) { - DEBUG ((DEBUG_INFO, "Certificate %u already trusted\n", - mCertIndex)); - mCertIndex++; - continue; + if (!mAltAccessMode) { + if (CertificateEntry->CertIsMicrosoft) { + DEBUG ((DEBUG_INFO, "Certificate %u belongs to Microsoft\n", + mCertIndex)); + mCertIndex++; + continue; + } + if (CertificateEntry->CertIsInDb) { + DEBUG ((DEBUG_INFO, "Certificate %u already trusted\n", + mCertIndex)); + mCertIndex++; + continue; + } } } @@ -978,33 +1134,16 @@ UpdateCertInfo ( return EFI_NO_MEDIA; } - if (CertificateEntry->SignatureValid) { - HiiSetString ( - Private->HiiHandle, - STRING_TOKEN (STR_KEY_FINGERPRINT), - L"Certificate fingerprint (SHA-256):", - NULL - ); + if (!CertificateEntry->SignatureValid || !CertificateEntry->CertIsValid) { + Private->FormData.HasInvalidSignature = TRUE; } else { - HiiSetString ( - Private->HiiHandle, - STRING_TOKEN (STR_KEY_FINGERPRINT), - L"Certificate fingerprint (SHA-256):\n!!! Signature is invalid !!!", - NULL - ); + Private->FormData.HasInvalidSignature = FALSE; } // Special case if AppLaunchCause is SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED // We still want to show what the system attempted to boot and failed, even // if it is signed by MS certificate. - if (CertificateEntry->CertIsMicrosoft) { - HiiSetString ( - Private->HiiHandle, - STRING_TOKEN (STR_KEY_FINGERPRINT), - L"Certificate fingerprint (SHA-256):\n!!! Certificate belongs to Microsoft !!!", - NULL - ); - } + Private->FormData.SignedByMs = CertificateEntry->CertIsMicrosoft; Status = ParseHashValue (CertificateEntry->CertDigest, CertificateEntry->CertDigestSize, &NewString); if (!EFI_ERROR (Status)) { @@ -1062,7 +1201,7 @@ UpdateCertIssuerAndSubjectStrings ( IN SV_CERT_ENTRY *CertificateEntry ) { - CHAR8 StringBuffer[500]; + CHAR8 StringBuffer[BUFFER_MAX_SIZE]; UINTN StringBufferSize; CHAR16 *NewString; @@ -1190,7 +1329,7 @@ UpdateCertKeyStrings ( } NewString = NULL; - if (!EFI_ERROR (ParseKeyModulus (ModulusBuffer, PubKeyModSize, &NewString))) { + if (!EFI_ERROR (FormatHexBuffer (ModulusBuffer, PubKeyModSize, &NewString))) { HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CERT_KEY_MODULUS_HEX), NewString, NULL); } FREE_NON_NULL (NewString); @@ -1205,6 +1344,139 @@ UpdateCertKeyStrings ( FREE_NON_NULL (ModulusBuffer); } +VOID +UpdateKeyStringsFromSigList ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN EFI_SIGNATURE_DATA *Data + ) +{ + UINT8 *ModulusBuffer; + CHAR16 *NewString; + UINT16 ExponentString[20]; + + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CERT_KEY_MODULUS_HEX), L"Unknown", NULL); + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CERT_KEY_EXPONENT2), L"Unknown", NULL); + + ModulusBuffer = (UINT8 *)Data->SignatureData; + + NewString = NULL; + if (!EFI_ERROR (FormatHexBuffer (ModulusBuffer, WIN_CERT_UEFI_RSA2048_SIZE, &NewString))) { + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CERT_KEY_MODULUS_HEX), NewString, NULL); + } + FREE_NON_NULL (NewString); + + SetMem(ExponentString, sizeof (ExponentString), 0); + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CERT_KEY_EXPONENT2), L"0x10001", NULL); +} + +VOID +UpdateTimeString ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN EFI_TIME *Time + ) +{ + CHAR16 TimeString[BUFFER_MAX_SIZE]; + + ZeroMem (TimeString, sizeof (TimeString)); + UnicodeSPrint ( + TimeString, + sizeof (TimeString), + L"%02d-%02d-%04d %02d:%02d:%02d", + Time->Day, + Time->Month, + Time->Year, + Time->Hour, + Time->Minute, + Time->Second + ); + + HiiSetString(Private->HiiHandle, STRING_TOKEN(STR_SIGNATURE_DATA_REVOCATION_TIME2), TimeString, NULL); +} + +VOID +UpdateHashStringsFromSigData ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN EFI_SIGNATURE_DATA *Data, + IN UINT32 DataSize + ) +{ + CHAR16 *HexString; + + HexString = NULL; + if (!EFI_ERROR (FormatHexBuffer (Data->SignatureData, DataSize, &HexString))) { + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_RAW_HEX), HexString, NULL); + } + FREE_NON_NULL (HexString); +} + +VOID +FillKeyHashStrings ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN EFI_SIGNATURE_LIST *List, + IN EFI_SIGNATURE_DATA *Data + ) +{ + UINT32 DataSize; + EFI_TIME *Time; + + Private->FormData.IsCertHash = FALSE; + + switch (Private->FormData.SignatureType) { + case SIGNATURE_TYPE_RSA2048: + UpdateKeyStringsFromSigList (Private, Data); + return; + case SIGNATURE_TYPE_RSA2048_SHA256: + DataSize = List->SignatureSize - sizeof (EFI_GUID); + break; + case SIGNATURE_TYPE_SHA1: + DataSize = 20; + break; + case SIGNATURE_TYPE_SHA224: + DataSize = 28; + break; + case SIGNATURE_TYPE_X509_SHA256: + case SIGNATURE_TYPE_X509_SM3: + Private->FormData.IsCertHash = TRUE; + case SIGNATURE_TYPE_SHA256: + case SIGNATURE_TYPE_SM3: + DataSize = 32; + break; + case SIGNATURE_TYPE_X509_SHA384: + Private->FormData.IsCertHash = TRUE; + case SIGNATURE_TYPE_SHA384: + DataSize = 48; + break; + case SIGNATURE_TYPE_X509_SHA512: + Private->FormData.IsCertHash = TRUE; + case SIGNATURE_TYPE_SHA512: + DataSize = 64; + break; + case SIGNATURE_TYPE_UNKNOWN: + default: + UpdateHashStringsFromSigData (Private, Data, List->SignatureSize); + return; + } + + if (Private->FormData.IsCertHash) { + Time = (EFI_TIME *)(Data->SignatureData + DataSize); + UpdateTimeString (Private, Time); + } + + UpdateHashStringsFromSigData (Private, Data, DataSize); +} + +VOID +FillCertStrings ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN SV_CERT_ENTRY *CertificateEntry + ) +{ + UpdateCertValidityStrings (Private, CertificateEntry); + UpdateCertIssuerAndSubjectStrings (Private, CertificateEntry); + UpdateCertSerialNumberString (Private, CertificateEntry); + UpdateCertKeyStrings (Private, CertificateEntry); +} + EFI_STATUS UpdateCertDetails ( IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private @@ -1213,7 +1485,7 @@ UpdateCertDetails ( SV_MENU_ENTRY *BootloaderEntry; SV_CERT_ENTRY *CertificateEntry; - BootloaderEntry = GetMenuEntry (&BootOptionMenu, mBootloaderIndex); + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, mBootloaderIndex); if (BootloaderEntry == NULL) { return EFI_NO_MEDIA; } @@ -1223,10 +1495,12 @@ UpdateCertDetails ( return EFI_NO_MEDIA; } - UpdateCertValidityStrings (Private, CertificateEntry); - UpdateCertIssuerAndSubjectStrings (Private, CertificateEntry); - UpdateCertSerialNumberString (Private, CertificateEntry); - UpdateCertKeyStrings (Private, CertificateEntry); + FillCertStrings (Private, CertificateEntry); + + Private->FormData.CertInDb = CertificateEntry->CertIsInDb; + Private->FormData.CertInDbx = CertificateEntry->CertIsInDbx; + Private->FormData.CertIsValid = CertificateEntry->CertIsValid; + Private->FormData.CertIsMicrosoft = CertificateEntry->CertIsMicrosoft; return EFI_SUCCESS; } diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c index 8132746694..ebfd0db62f 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.c @@ -7,12 +7,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "SovereignBootWizard.h" +#include "InteractiveModeImpl.h" -SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *mPrivateData = NULL; +SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *mPrivateData = NULL; +SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *gPrivateData = NULL; BOOLEAN mBootloadersInitted; +BOOLEAN mAltAccessMode; STATIC CHAR16 mSvBootDataVarName[] = SV_BOOT_DATA_VAR; -STATIC CHAR16 mVarStoreName[] = L"SvBootFormData"; +STATIC CHAR16 mVarStoreName[] = SV_BOOT_VARSTORE_NAME; STATIC CHAR16 mSvBootConfigVarName[] = SV_BOOT_CONFIG_VAR; STATIC BOOLEAN mBootloadersShown; @@ -82,23 +85,25 @@ ExtractConfig ( ) { EFI_STATUS Status; - SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private; + SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData; UINTN BufferSize; EFI_STRING ConfigRequestHdr; EFI_STRING ConfigRequest; UINTN Size; - if (Progress == NULL || Results == NULL) { + if ((Progress == NULL) || (Results == NULL)) { return EFI_INVALID_PARAMETER; } *Progress = Request; - if (Request != NULL && + if ((Request != NULL) && !HiiIsConfigHdrMatch (Request, &gSovereignBootWizardFormSetGuid, mVarStoreName)) { return EFI_NOT_FOUND; } - Private = SOVEREIGN_BOOT_WIZARD_PRIVATE_FROM_THIS (This); + PrivateData = SOVEREIGN_BOOT_WIZARD_PRIVATE_FROM_THIS (This); + + InteractiveModeExtractConfig (PrivateData, &PrivateData->FormData); BufferSize = sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA); ConfigRequest = Request; @@ -109,7 +114,7 @@ ExtractConfig ( ConfigRequestHdr = HiiConstructConfigHdr ( &gSovereignBootWizardFormSetGuid, mVarStoreName, - Private->AppHandle + PrivateData->AppHandle ); Size = (StrLen (ConfigRequestHdr) + 32 + 1) * sizeof (CHAR16); ConfigRequest = AllocateZeroPool (Size); @@ -125,10 +130,10 @@ ExtractConfig ( } // Convert fields of binary structure to string representation. - Status = Private->HiiConfigRouting->BlockToConfig ( - Private->HiiConfigRouting, + Status = PrivateData->HiiConfigRouting->BlockToConfig ( + PrivateData->HiiConfigRouting, ConfigRequest, - (CONST UINT8 *) &Private->FormData, + (CONST UINT8 *) &PrivateData->FormData, BufferSize, Results, Progress @@ -140,7 +145,9 @@ ExtractConfig ( FreePool (ConfigRequest); } - if (Request != NULL && StrStr (Request, L"OFFSET") == NULL) { + if (Request == NULL) { + *Progress = NULL; + } else if (StrStr (Request, L"OFFSET") == NULL) { *Progress = Request + StrLen (Request); } @@ -176,7 +183,7 @@ RouteConfig ( { EFI_STATUS Status; UINTN BufferSize; - SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData; + SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData; if ((Configuration == NULL) || (Progress == NULL)) { return EFI_INVALID_PARAMETER; @@ -189,13 +196,11 @@ RouteConfig ( return EFI_NOT_FOUND; } - if (HiiIsConfigHdrMatch (Configuration, &gSovereignBootWizardFormSetGuid, mSvBootDataVarName)) { + if (!HiiIsConfigHdrMatch (Configuration, &gSovereignBootWizardFormSetGuid, mVarStoreName)) { return EFI_UNSUPPORTED; } - if (!HiiIsConfigHdrMatch (Configuration, &gSovereignBootWizardFormSetGuid, mSvBootConfigVarName)) { - return EFI_UNSUPPORTED; - } + InteractiveModeExtractConfig (PrivateData, &PrivateData->FormData); BufferSize = sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA); Status = PrivateData->HiiConfigRouting->ConfigToBlock ( @@ -209,13 +214,16 @@ RouteConfig ( return Status; } + *Progress = Configuration + StrLen (Configuration); + return EFI_SUCCESS; } EFI_STATUS BootTheBootloader ( SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, - UINTN BootloaderIndex + UINTN BootloaderIndex, + BOOLEAN SetFirstPriority ) { SV_MENU_ENTRY *BootloaderEntry; @@ -226,7 +234,7 @@ BootTheBootloader ( INTN OptionIndex; EFI_STATUS Status; - BootloaderEntry = GetMenuEntry (&BootOptionMenu, BootloaderIndex); + BootloaderEntry = GetMenuEntry (&mBootOptionMenu, BootloaderIndex); if (BootloaderEntry == NULL) { DEBUG ((DEBUG_INFO, "Bootloader %u entry not found\n", BootloaderIndex)); return EFI_NO_MEDIA; @@ -269,19 +277,31 @@ BootTheBootloader ( gST->ConOut->ClearScreen (gST->ConOut); } - // TODO: Make this bootloader the first boot priority if (OptionIndex == -1) { - Status = EfiBootManagerAddLoadOptionVariable (&BootOption, MAX_UINTN); + Status = EfiBootManagerAddLoadOptionVariable (&BootOption, SetFirstPriority ? 0 : MAX_UINTN); if (EFI_ERROR (Status)) { EfiBootManagerFreeLoadOption (&BootOption); EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); DEBUG ((DEBUG_ERROR, "Failed to add load option variable: %r\n", Status)); return Status; } - DEBUG ((DEBUG_INFO, "Booting %s\n", BootloaderContext->Description)); + DEBUG ((DEBUG_INFO, "Booting new option: %s\n", BootloaderContext->Description)); EfiBootManagerBoot (&BootOption); } else { - DEBUG ((DEBUG_INFO, "Booting %s\n", BootloaderContext->Description)); + if (SetFirstPriority) { + // Remove the Boot#### variable associated with the bootloader and its + // entry in Bootorder variable + EfiBootManagerDeleteLoadOptionVariable (BootOption.OptionNumber, BootOption.OptionType); + // Create the Boot#### option again with the top priority + Status = EfiBootManagerAddLoadOptionVariable (&BootOption, 0); + if (EFI_ERROR (Status)) { + EfiBootManagerFreeLoadOption (&BootOption); + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); + DEBUG ((DEBUG_ERROR, "Failed to add load option variable: %r\n", Status)); + return Status; + } + } + DEBUG ((DEBUG_INFO, "Booting option %d: %s\n", OptionIndex, BootloaderContext->Description)); EfiBootManagerBoot (&BootOptions[OptionIndex]); } @@ -308,6 +328,7 @@ PrepareBootloaders ( if (!EFI_ERROR (Status)) { mBootloadersInitted = TRUE; if (!mBootloadersShown) { + mAltAccessMode = FALSE; Status = UpdateBootloaderPage (PrivateData); mBootloadersShown = !EFI_ERROR (Status); } @@ -377,6 +398,12 @@ Callback ( SOVEREIGN_BOOT_WIZARD_NV_CONFIG SvConfig; BROWSER_SETTING_SCOPE Scope; UINTN BootloaderToBoot; + EFI_DEVICE_PATH_PROTOCOL *File; + UINTN NameLength; + UINT16 *FilePostFix; + BOOLEAN GetBrowserDataResult; + + File = NULL; if (((Value == NULL) && (Action != EFI_BROWSER_ACTION_FORM_OPEN) && (Action != EFI_BROWSER_ACTION_FORM_CLOSE)) || (ActionRequest == NULL)) @@ -387,6 +414,14 @@ Callback ( Status = EFI_SUCCESS; PrivateData = SOVEREIGN_BOOT_WIZARD_PRIVATE_FROM_THIS (This); + gPrivateData = PrivateData; + + GetBrowserDataResult = HiiGetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData); + switch (Action) { case EFI_BROWSER_ACTION_CHANGING: switch (QuestionId) { @@ -405,13 +440,13 @@ Callback ( &SvConfig ); if (EFI_ERROR (Status)) { - return Status; + goto EXIT; } // 3. Restore default keys if necessary. Maybe use NV VendorKeys to // indicate if key restoration is required. Status = RestoreSecureBootDefaults (); if (EFI_ERROR (Status)) { - return Status; + goto EXIT; } // 4. Reset the system to boot in a fresh state. Can't really avoid // the reset as we cannot exit the form in any other action than @@ -461,71 +496,40 @@ Callback ( } Status = PrivateData->FormBrowserEx2->ExecuteAction(BROWSER_ACTION_EXIT, 0); - return Status; + goto EXIT; } PrepareBootloaders(PrivateData); break; } - case DO_NOT_TRUST_KEY_FORM2_QUESTION_ID: - { - // Add cert or image hash to DBX - Status = AddKeyOrHashAsTrustedOrUntrusted(PrivateData, FALSE); - break; - } - case TRUST_KEY_FORM2_QUESTION_ID: - { - // Add cert or image hash to DB - Status = AddKeyOrHashAsTrustedOrUntrusted(PrivateData, TRUE); - break; - } - case SHOW_KEY_DETAILS_FORM2_QUESTION_ID: - { - // Update the strings when opening certificate details form - Status = UpdateCertDetails (PrivateData); - break; - } - default: - break; - } - - break; - case EFI_BROWSER_ACTION_CHANGED: - { - switch (QuestionId) { - case EXIT_FORM1_QUESTION_ID: - case EXIT_FORM2_QUESTION_ID: - case EXIT_FORM3_QUESTION_ID: - case EXIT_FORM9_QUESTION_ID: - if (PrivateData->ConfigData.AppLaunchCause == SV_BOOT_LAUNCH_VIA_SETUP) { - Scope = FormSetLevel; - } else { - Scope = SystemLevel; - } - PrivateData->FormBrowserEx2->SetScope (Scope); - Status = PrivateData->FormBrowserEx2->ExecuteAction(BROWSER_ACTION_EXIT, 0); - - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - break; - case SKIP_KEY_FORM2_QUESTION_ID: + case KEY_SKIP_KEY_FORM2: if (PrivateData->FormData.ImageUnsigned) { mBootloaderIndex++; } else { mCertIndex++; } // fallthrough - case DO_NOT_TRUST_KEY_FORM2_QUESTION_ID: - case TRUST_KEY_FORM2_QUESTION_ID: + case KEY_DO_NOT_TRUST_KEY_FORM2: + case KEY_TRUST_KEY_FORM2: + if (QuestionId == KEY_DO_NOT_TRUST_KEY_FORM2) { + // Add cert or image hash to DBX + mAltAccessMode = FALSE; + Status = AddKeyOrHashAsTrustedOrUntrusted(PrivateData, FALSE, FALSE); + } else if (QuestionId == KEY_TRUST_KEY_FORM2) { + // Add cert or image hash to DB + mAltAccessMode = FALSE; + Status = AddKeyOrHashAsTrustedOrUntrusted(PrivateData, TRUE, FALSE); + } if (mBootloadersInitted) { Status = UpdateBootloaderPage (PrivateData); if (Status == EFI_NO_MEDIA) { // If we failed image verification and do not trust the image, simply exit - if (QuestionId == DO_NOT_TRUST_KEY_FORM2_QUESTION_ID && + if (QuestionId == KEY_DO_NOT_TRUST_KEY_FORM2 && PrivateData->ConfigData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED) { PrivateData->FormBrowserEx2->SetScope (SystemLevel); Status = PrivateData->FormBrowserEx2->ExecuteAction(BROWSER_ACTION_EXIT, 0); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - return Status; + goto EXIT; } do { CreatePopUp ( @@ -562,7 +566,7 @@ Callback ( ); } while (Key.UnicodeChar != CHAR_CARRIAGE_RETURN); // 4. Boot the first trusted bootloader. - BootTheBootloader(PrivateData, (UINTN)mFirstTrustedBootloader); + BootTheBootloader(PrivateData, (UINTN)mFirstTrustedBootloader, TRUE); // If we return from the bootloader, exit the form completely. mBootloaderIndex = 0; if (PrivateData->ConfigData.AppLaunchCause == SV_BOOT_LAUNCH_VIA_SETUP) { @@ -635,10 +639,10 @@ Callback ( } } break; - case TRUST_KEY_AND_BOOT_FORM2_QUESTION_ID: + case KEY_TRUST_KEY_AND_BOOT_FORM2: BootloaderToBoot = mBootloaderIndex; // Add cert or image hash to DB - Status = AddKeyOrHashAsTrustedOrUntrusted(PrivateData, TRUE); + Status = AddKeyOrHashAsTrustedOrUntrusted(PrivateData, TRUE, FALSE); if (EFI_ERROR (Status)) { // If we are already provisioned and fail, simply exit the wizard. // If the image verification fails, a string will be shown on the @@ -652,14 +656,14 @@ Callback ( PrivateData->FormBrowserEx2->SetScope (Scope); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; } - return Status; + goto EXIT; } // If we failed image verification and decided to trust the image, simply boot it if (PrivateData->ConfigData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED) { - Status = BootTheBootloader (PrivateData, BootloaderToBoot); + Status = BootTheBootloader (PrivateData, BootloaderToBoot, FALSE); PrivateData->FormBrowserEx2->SetScope (SystemLevel); *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - return Status; + goto EXIT; } // All is left here is to enroll PK to enable Secure Boot, set @@ -676,7 +680,7 @@ Callback ( NULL ); gBS->Stall (2 * 1000 * 1000); - Status = BootTheBootloader (PrivateData, BootloaderToBoot); + Status = BootTheBootloader (PrivateData, BootloaderToBoot, TRUE); // Do not go back to wizard after booting if (PrivateData->ConfigData.AppLaunchCause == SV_BOOT_LAUNCH_VIA_SETUP) { Scope = FormSetLevel; @@ -702,6 +706,682 @@ Callback ( ); } break; + case KEY_SHOW_KEY_DETAILS_FORM2: + { + PrivateData->FormData.BlCertView = FALSE; + // Update the strings when opening certificate details form + Status = UpdateCertDetails (PrivateData); + break; + } + case KEY_ADD_CERT_TO_DBX: + { + // Add cert or image hash to DBX + mAltAccessMode = TRUE; + Status = AddKeyOrHashAsTrustedOrUntrusted(PrivateData, FALSE, FALSE); + RefreshImageSecurityInfo (PrivateData); + HiiSetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData, + NULL); + GetBrowserDataResult = FALSE; + break; + } + case KEY_ADD_CERT_TO_DB: + { + // Add cert or image hash to DB + mAltAccessMode = TRUE; + Status = AddKeyOrHashAsTrustedOrUntrusted(PrivateData, TRUE, FALSE); + RefreshImageSecurityInfo (PrivateData); + HiiSetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData, + NULL); + GetBrowserDataResult = FALSE; + break; + } + case KEY_REMOVE_CERT_FROM_DB: + { + PrivateData->VariableName = Variable_DB; + Status = RemoveCertificateFromDatabase (PrivateData); + RefreshImageSecurityInfo (PrivateData); + HiiSetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData, + NULL); + GetBrowserDataResult = FALSE; + break; + } + case KEY_REMOVE_CERT_FROM_DBX: + { + PrivateData->VariableName = Variable_DBX; + Status = RemoveCertificateFromDatabase (PrivateData); + RefreshImageSecurityInfo (PrivateData); + HiiSetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData, + NULL); + GetBrowserDataResult = FALSE; + break; + } + case KEY_ADD_HASH_TO_DBX: + { + // Add cert or image hash to DBX + mAltAccessMode = TRUE; + Status = AddKeyOrHashAsTrustedOrUntrusted(PrivateData, FALSE, TRUE); + RefreshImageSecurityInfo (PrivateData); + HiiSetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData, + NULL); + GetBrowserDataResult = FALSE; + break; + } + case KEY_ADD_HASH_TO_DB: + { + // Add cert or image hash to DB + mAltAccessMode = TRUE; + Status = AddKeyOrHashAsTrustedOrUntrusted(PrivateData, TRUE, TRUE); + RefreshImageSecurityInfo (PrivateData); + HiiSetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData, + NULL); + GetBrowserDataResult = FALSE; + break; + } + case KEY_REMOVE_HASH_FROM_DB: + { + PrivateData->VariableName = Variable_DB; + Status = RemoveImageHashFromDatabase (PrivateData); + RefreshImageSecurityInfo (PrivateData); + HiiSetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData, + NULL); + GetBrowserDataResult = FALSE; + break; + } + case KEY_REMOVE_HASH_FROM_DBX: + { + PrivateData->VariableName = Variable_DBX; + Status = RemoveImageHashFromDatabase (PrivateData); + RefreshImageSecurityInfo (PrivateData); + HiiSetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData, + NULL); + GetBrowserDataResult = FALSE; + break; + } + case KEY_REMOVE_ALL_IMAGE_DATA: + { + Status = RemoveImageDataFromDbx (PrivateData); + Status |= RemoveImageDataFromDb (PrivateData); + RefreshImageSecurityInfo (PrivateData); + HiiSetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData, + NULL); + GetBrowserDataResult = FALSE; + break; + } + case KEY_SOVEREIGN_BOOT_BL_OPTION: + if (!mBootloadersInitted) { + Status = GetBootOptions (PrivateData); + if (!EFI_ERROR (Status)) { + mBootloadersInitted = TRUE; + } else { + if (Status != EFI_NOT_FOUND) { + PrivateData->FormData.BootloaderCount = 0; + break; + } + } + } + PrivateData->FormData.BlCertView = TRUE; + LoadBootloaders (PrivateData); + Status = EFI_SUCCESS; + break; + + case KEY_SOVEREIGN_BOOT_DB_OPTION: + PrivateData->VariableName = Variable_DB; + LoadSignatureList ( + PrivateData, + LABEL_DB_CERTS_DATA_START, + FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM, + OPTION_DB_LIST_QUESTION_ID + ); + + Status = EFI_SUCCESS; + break; + + case KEY_SOVEREIGN_BOOT_DBX_OPTION: + PrivateData->VariableName = Variable_DBX; + LoadSignatureList ( + PrivateData, + LABEL_DBX_CERTS_DATA_START, + FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM, + OPTION_DBX_LIST_QUESTION_ID + ); + + Status = EFI_SUCCESS; + break; + + case KEY_ENROLL_SIGNATURE_TO_DB: + // Refresh selected file. + PrivateData->FormData.FileEnrollType = UNKNOWN_FILE_TYPE; + PrivateData->FormData.CertificateFormat = HASHALG_SHA256; + CloseEnrolledFile (PrivateData->FileContext); + CleanUpPage ( + SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB, + LABEL_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB, + PrivateData); + Status = EFI_SUCCESS; + break; + + case KEY_ENROLL_SIGNATURE_TO_DBX: + // Refresh selected file. + PrivateData->FormData.FileEnrollType = UNKNOWN_FILE_TYPE; + PrivateData->FormData.CertificateFormat = HASHALG_SHA256; + CloseEnrolledFile (PrivateData->FileContext); + CleanUpPage ( + SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX, + LABEL_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX, + PrivateData); + Status = EFI_SUCCESS; + break; + + case KEY_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB: + mAltAccessMode = FALSE; + ChooseFile (NULL, NULL, UpdateDBFromFile, &File); + Status = EFI_SUCCESS; + break; + + case KEY_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX: + mAltAccessMode = FALSE; + ChooseFile (NULL, NULL, UpdateDBXFromFile, &File); + + if (PrivateData->FileContext->FHandle != NULL) { + // + // Parse the file's postfix. + // + NameLength = StrLen (PrivateData->FileContext->FileName); + if (NameLength <= 4) { + return FALSE; + } + + FilePostFix = PrivateData->FileContext->FileName + NameLength - 4; + + if (IsDerEncodeCertificate (FilePostFix)) { + // + // Supports DER-encoded X509 certificate. + // + PrivateData->FormData.FileEnrollType = X509_CERT_FILE_TYPE; + PrivateData->FormData.CertificateFormat = HASHALG_RAW; + } else if (IsAuthentication2Format (PrivateData->FileContext->FHandle)) { + PrivateData->FormData.FileEnrollType = AUTHENTICATION_2_FILE_TYPE; + PrivateData->FormData.CertificateFormat = HASHALG_RAW; + } else { + PrivateData->FormData.FileEnrollType = PE_IMAGE_FILE_TYPE; + PrivateData->FormData.CertificateFormat = HASHALG_SHA256; + } + + PrivateData->FileContext->FileType = PrivateData->FormData.FileEnrollType; + } + + Status = EFI_SUCCESS; + break; + + case KEY_SOVEREIGN_BOOT_DELETE_SIGNATURE_FROM_DB: + mAltAccessMode = FALSE; + UpdateDeletePage ( + PrivateData, + EFI_IMAGE_SECURITY_DATABASE, + &gEfiImageSecurityDatabaseGuid, + LABEL_DB_DELETE, + SOVEREIGN_BOOT_DELETE_SIGNATURE_FROM_DB, + OPTION_DEL_DB_QUESTION_ID + ); + Status = EFI_SUCCESS; + break; + + // + // From DBX option to the level-1 form, display signature list. + // + case KEY_VALUE_FROM_DBX_TO_LIST_FORM: + mAltAccessMode = FALSE; + PrivateData->VariableName = Variable_DBX; + LoadSignatureList ( + PrivateData, + LABEL_SIGNATURE_LIST_START, + SOVEREIGN_BOOT_DELETE_SIGNATURE_LIST_FORM, + OPTION_SIGNATURE_LIST_QUESTION_ID + ); + Status = EFI_SUCCESS; + break; + + // + // Delete all signature list and reload. + // + case KEY_SOVEREIGN_BOOT_DELETE_ALL_LIST: + mAltAccessMode = FALSE; + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Press 'Y' to delete signature list.", + L"Press other key to cancel and exit.", + NULL + ); + + if ((Key.UnicodeChar == L'Y') || (Key.UnicodeChar == L'y')) { + DeleteSignatureEx (PrivateData, Delete_Signature_List_All, PrivateData->FormData.CheckedDataCount); + } + + LoadSignatureList ( + PrivateData, + LABEL_SIGNATURE_LIST_START, + SOVEREIGN_BOOT_DELETE_SIGNATURE_LIST_FORM, + OPTION_SIGNATURE_LIST_QUESTION_ID + ); + PrivateData->FormData.ListCount = PrivateData->ListCount; + Status = EFI_SUCCESS; + break; + + // + // Delete one signature list and reload. + // + case KEY_SOVEREIGN_BOOT_DELETE_ALL_DATA: + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Press 'Y' to delete signature data.", + L"Press other key to cancel and exit.", + NULL + ); + + if ((Key.UnicodeChar == L'Y') || (Key.UnicodeChar == L'y')) { + DeleteSignatureEx ( + PrivateData, + Delete_Signature_List_One, + mAltAccessMode ? 1 : PrivateData->FormData.CheckedDataCount); + } + + if (!mAltAccessMode) { + Value->ref.FormId = SOVEREIGN_BOOT_DELETE_SIGNATURE_LIST_FORM; + CleanUpPage (Value->ref.FormId, LABEL_SIGNATURE_LIST_START, PrivateData); + LoadSignatureList ( + PrivateData, + LABEL_SIGNATURE_LIST_START, + Value->ref.FormId, + OPTION_SIGNATURE_LIST_QUESTION_ID + ); + } else { + if (PrivateData->VariableName == Variable_DB) { + Value->ref.FormId = FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM; + CleanUpPage (Value->ref.FormId, LABEL_DB_CERTS_DATA_START, PrivateData); + LoadSignatureList ( + PrivateData, + LABEL_DB_CERTS_DATA_START, + Value->ref.FormId, + OPTION_DB_LIST_QUESTION_ID + ); + } else if (PrivateData->VariableName == Variable_DBX) { + Value->ref.FormId = FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM; + CleanUpPage (Value->ref.FormId, LABEL_DBX_CERTS_DATA_START, PrivateData); + LoadSignatureList ( + PrivateData, + LABEL_DBX_CERTS_DATA_START, + Value->ref.FormId, + OPTION_DBX_LIST_QUESTION_ID + ); + } else { + Value->ref.FormId = SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID; + } + } + PrivateData->FormData.ListCount = PrivateData->ListCount; + Status = EFI_SUCCESS; + break; + + // + // Delete checked signature data and reload. + // + case KEY_SOVEREIGN_BOOT_DELETE_CHECK_DATA: + mAltAccessMode = FALSE; + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Press 'Y' to delete signature data.", + L"Press other key to cancel and exit.", + NULL + ); + + if ((Key.UnicodeChar == L'Y') || (Key.UnicodeChar == L'y')) { + DeleteSignatureEx (PrivateData, Delete_Signature_Data, PrivateData->FormData.CheckedDataCount); + } + + LoadSignatureList ( + PrivateData, + LABEL_SIGNATURE_LIST_START, + SOVEREIGN_BOOT_DELETE_SIGNATURE_LIST_FORM, + OPTION_SIGNATURE_LIST_QUESTION_ID + ); + PrivateData->FormData.ListCount = PrivateData->ListCount; + Status = EFI_SUCCESS; + break; + + case KEY_REMOVE_HASH_FROM_DATABASE: + case KEY_REMOVE_KEY_FROM_DATABASE: + case KEY_REMOVE_CERT_FROM_DATABASE: + mAltAccessMode = TRUE; + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Press 'Y' to delete signature data.", + L"Press other key to cancel and exit.", + NULL + ); + + if ((Key.UnicodeChar == L'Y') || (Key.UnicodeChar == L'y')) { + DeleteSignatureEx (PrivateData, Delete_Signature_Data, 1); + } + + if (PrivateData->DataCount == 1) { + if (PrivateData->VariableName == Variable_DB) { + Value->ref.FormId = FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM; + CleanUpPage (Value->ref.FormId, LABEL_DB_CERTS_DATA_START, PrivateData); + LoadSignatureList ( + PrivateData, + LABEL_DB_CERTS_DATA_START, + Value->ref.FormId, + OPTION_DB_LIST_QUESTION_ID + ); + PrivateData->FormData.ListCount = PrivateData->ListCount; + } else if (PrivateData->VariableName == Variable_DBX) { + Value->ref.FormId = FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM; + CleanUpPage (Value->ref.FormId, LABEL_DBX_CERTS_DATA_START, PrivateData); + LoadSignatureList ( + PrivateData, + LABEL_DBX_CERTS_DATA_START, + Value->ref.FormId, + OPTION_DBX_LIST_QUESTION_ID + ); + PrivateData->FormData.ListCount = PrivateData->ListCount; + } else { + Value->ref.FormId = SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID; + } + } else { + Value->ref.FormId = SOVEREIGN_BOOT_DELETE_SIGNATURE_DATA_FORM; + CleanUpPage (Value->ref.FormId, LABEL_SIGNATURE_DATA_START, PrivateData); + if (PrivateData->VariableName == Variable_DB) { + LoadSignatureData ( + PrivateData, + LABEL_SIGNATURE_DATA_START, + Value->ref.FormId, + OPTION_DB_ENTRIES_QUESTION_ID, + PrivateData->ListIndex + ); + } else if (PrivateData->VariableName == Variable_DBX) { + LoadSignatureData ( + PrivateData, + LABEL_SIGNATURE_DATA_START, + Value->ref.FormId, + OPTION_DBX_ENTRIES_QUESTION_ID, + PrivateData->ListIndex + ); + } + } + + Status = EFI_SUCCESS; + break; + + case KEY_VALUE_SAVE_AND_EXIT_DB: + Status = EnrollSignatureDatabase (PrivateData, 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 + ); + } else { + CleanUpPage ( + FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM, + LABEL_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB, + PrivateData); + LoadSignatureList ( + PrivateData, + LABEL_DB_CERTS_DATA_START, + FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM, + OPTION_DB_LIST_QUESTION_ID + ); + PrivateData->FormData.ListCount = PrivateData->ListCount; + } + Status = EFI_SUCCESS; + break; + + case KEY_VALUE_SAVE_AND_EXIT_DBX: + if (IsX509CertInDbx (PrivateData)) { + 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 (PrivateData->FileContext); + Status = EFI_SUCCESS; + break; + } + + if (PrivateData->FormData.CertificateFormat < HASHALG_MAX) { + Status = EnrollX509HashtoSigDB ( + PrivateData, + PrivateData->FormData.CertificateFormat, + &PrivateData->FormData.RevocationDate, + &PrivateData->FormData.RevocationTime, + PrivateData->FormData.AlwaysRevocation + ); + PrivateData->FormData.CertificateFormat = HASHALG_RAW; + } else { + Status = EnrollSignatureDatabase (PrivateData, 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 + ); + } else { + CleanUpPage ( + FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM, + LABEL_DBX_CERTS_DATA_START, + PrivateData); + LoadSignatureList ( + PrivateData, + LABEL_DBX_CERTS_DATA_START, + FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM, + OPTION_DBX_LIST_QUESTION_ID + ); + PrivateData->FormData.ListCount = PrivateData->ListCount; + } + + break; + + case KEY_VALUE_NO_SAVE_AND_EXIT_DB: + case KEY_VALUE_NO_SAVE_AND_EXIT_DBX: + CloseEnrolledFile (PrivateData->FileContext); + Status = EFI_SUCCESS; + break; + + default: + if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) && + (QuestionId < (OPTION_DEL_DB_QUESTION_ID + OPTION_CONFIG_RANGE))) + { + mAltAccessMode = FALSE; + DeleteSignature ( + PrivateData, + EFI_IMAGE_SECURITY_DATABASE, + &gEfiImageSecurityDatabaseGuid, + LABEL_DB_DELETE, + SOVEREIGN_BOOT_DELETE_SIGNATURE_FROM_DB, + OPTION_DEL_DB_QUESTION_ID, + QuestionId - OPTION_DEL_DB_QUESTION_ID + ); + // Refresh DB entries in the DB option form + LoadSignatureList ( + PrivateData, + LABEL_DB_CERTS_DATA_START, + FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM, + OPTION_DB_LIST_QUESTION_ID + ); + PrivateData->FormData.ListCount = PrivateData->ListCount; + Status = EFI_SUCCESS; + } else if ((QuestionId >= OPTION_SIGNATURE_LIST_QUESTION_ID) && + (QuestionId < (OPTION_SIGNATURE_LIST_QUESTION_ID + OPTION_CONFIG_RANGE))) + { + mAltAccessMode = FALSE; + LoadSignatureData ( + PrivateData, + LABEL_SIGNATURE_DATA_START, + SOVEREIGN_BOOT_DELETE_SIGNATURE_DATA_FORM, + OPTION_SIGNATURE_DATA_QUESTION_ID, + QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID + ); + PrivateData->ListIndex = QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID; + Status = EFI_SUCCESS; + } else if ((QuestionId >= OPTION_SIGNATURE_DATA_QUESTION_ID) && + (QuestionId < (OPTION_SIGNATURE_DATA_QUESTION_ID + OPTION_CONFIG_RANGE))) + { + mAltAccessMode = FALSE; + if (PrivateData->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID]) { + PrivateData->FormData.CheckedDataCount--; + PrivateData->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = FALSE; + } else { + PrivateData->FormData.CheckedDataCount++; + PrivateData->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = TRUE; + } + Status = EFI_SUCCESS; + } else if ((QuestionId >= OPTION_DB_LIST_QUESTION_ID) && + (QuestionId < (OPTION_DB_LIST_QUESTION_ID + OPTION_CONFIG_RANGE))) + { + mAltAccessMode = TRUE; + PrivateData->FormData.BlCertView = FALSE; + LoadSignatureData ( + PrivateData, + LABEL_SIGNATURE_DATA_START, + SOVEREIGN_BOOT_DELETE_SIGNATURE_DATA_FORM, + OPTION_DB_ENTRIES_QUESTION_ID, + QuestionId - OPTION_DB_LIST_QUESTION_ID + ); + PrivateData->ListIndex = QuestionId - OPTION_DB_LIST_QUESTION_ID; + Status = EFI_SUCCESS; + } else if ((QuestionId >= OPTION_DBX_LIST_QUESTION_ID) && + (QuestionId < (OPTION_DBX_LIST_QUESTION_ID + OPTION_CONFIG_RANGE))) + { + mAltAccessMode = TRUE; + PrivateData->FormData.BlCertView = FALSE; + LoadSignatureData ( + PrivateData, + LABEL_SIGNATURE_DATA_START, + SOVEREIGN_BOOT_DELETE_SIGNATURE_DATA_FORM, + OPTION_DBX_ENTRIES_QUESTION_ID, + QuestionId - OPTION_DBX_LIST_QUESTION_ID + ); + PrivateData->ListIndex = QuestionId - OPTION_DBX_LIST_QUESTION_ID; + Status = EFI_SUCCESS; + } else if ((QuestionId >= OPTION_DB_ENTRIES_QUESTION_ID) && + (QuestionId < (OPTION_DB_ENTRIES_QUESTION_ID + OPTION_CONFIG_RANGE))) + { + mAltAccessMode = TRUE; + PrivateData->FormData.BlCertView = FALSE; + LoadSignatureDataStrings ( + PrivateData, + QuestionId - OPTION_DB_ENTRIES_QUESTION_ID, + PrivateData->ListIndex + ); + PrivateData->DataIndex = QuestionId - OPTION_DB_ENTRIES_QUESTION_ID; + PrivateData->CheckArray[PrivateData->DataIndex] = TRUE; + Status = EFI_SUCCESS; + } else if ((QuestionId >= OPTION_DBX_ENTRIES_QUESTION_ID) && + (QuestionId < (OPTION_DBX_ENTRIES_QUESTION_ID + OPTION_CONFIG_RANGE))) + { + mAltAccessMode = TRUE; + PrivateData->FormData.BlCertView = FALSE; + LoadSignatureDataStrings ( + PrivateData, + QuestionId - OPTION_DBX_ENTRIES_QUESTION_ID, + PrivateData->ListIndex + ); + PrivateData->DataIndex = QuestionId - OPTION_DBX_ENTRIES_QUESTION_ID; + PrivateData->CheckArray[PrivateData->DataIndex] = TRUE; + Status = EFI_SUCCESS; + } else if ((QuestionId >= OPTION_BL_QUESTION_ID) && + (QuestionId < (OPTION_BL_QUESTION_ID + OPTION_CONFIG_RANGE))) + { + mAltAccessMode = TRUE; + PrivateData->FormData.BlCertView = TRUE; + mBootloaderIndex = QuestionId - OPTION_BL_QUESTION_ID; + Status = UpdateBootloaderPage (PrivateData); + if (!EFI_ERROR (Status)) { + Status = LoadBootloaderCertificates (PrivateData); + } else { + DEBUG ((DEBUG_ERROR, "Failed to update bootloader page: %r", Status)); + } + } else if ((QuestionId >= OPTION_BL_CERT_QUESTION_ID) && + (QuestionId < (OPTION_BL_CERT_QUESTION_ID + OPTION_CONFIG_RANGE))) + { + mAltAccessMode = TRUE; + PrivateData->FormData.BlCertView = TRUE; + mCertIndex = QuestionId - OPTION_BL_CERT_QUESTION_ID; + Status = UpdateCertDetails (PrivateData); + } else { + Status = EFI_UNSUPPORTED; + } + break; + } + + break; + case EFI_BROWSER_ACTION_CHANGED: + { + switch (QuestionId) { + case KEY_EXIT_FORM1: + case KEY_EXIT_FORM2: + case KEY_EXIT_FORM3: + case KEY_EXIT_FORM5: + if (PrivateData->ConfigData.AppLaunchCause == SV_BOOT_LAUNCH_VIA_SETUP) { + Scope = FormSetLevel; + } else { + Scope = SystemLevel; + } + PrivateData->FormBrowserEx2->SetScope (Scope); + Status = PrivateData->FormBrowserEx2->ExecuteAction(BROWSER_ACTION_EXIT, 0); + + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; + break; default: break; } @@ -711,30 +1391,67 @@ Callback ( case EFI_BROWSER_ACTION_FORM_OPEN: { switch (QuestionId) { - case DO_NOT_TRUST_KEY_FORM2_QUESTION_ID: + case KEY_DO_NOT_TRUST_KEY_FORM2: // When the trust form opens during image authentication failure // the PrepareBootloaders is not called, because Sovereign Boot // welcome form is skipped and SV Boto option never selected. PrepareBootloaders (PrivateData); Status = EFI_SUCCESS; break; + case KEY_SOVEREIGN_BOOT_DB_OPTION: + case KEY_SOVEREIGN_BOOT_DBX_OPTION: + CloseEnrolledFile (PrivateData->FileContext); + Status = EFI_SUCCESS; + break; default: + Status = EFI_UNSUPPORTED; break; } break; } + case EFI_BROWSER_ACTION_FORM_CLOSE: + { + switch (QuestionId) { + case KEY_SOVEREIGN_BOOT_DELETE_ALL_DATA: + // + // Free memory when exit from the SOVEREIGN_BOOT_DELETE_SIGNATURE_DATA_FORM form. + // + if (!mAltAccessMode) { + FREE_NON_NULL (PrivateData->CheckArray); + PrivateData->FormData.CheckedDataCount = 0; + } + Status = EFI_SUCCESS; + break; + case KEY_REMOVE_HASH_FROM_DATABASE: + case KEY_REMOVE_KEY_FROM_DATABASE: + case KEY_REMOVE_CERT_FROM_DATABASE: + FREE_NON_NULL (PrivateData->CheckArray); + PrivateData->FormData.CheckedDataCount = 0; + Status = EFI_SUCCESS; + break; + default: + Status = EFI_UNSUPPORTED; + break; + } + } default: Status = EFI_UNSUPPORTED; break; } - HiiSetBrowserData ( - &gSovereignBootWizardFormSetGuid, - mVarStoreName, - sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), - (CONST UINT8 *)&PrivateData->FormData, - NULL); + if (!EFI_ERROR (Status) && GetBrowserDataResult) { + HiiSetBrowserData ( + &gSovereignBootWizardFormSetGuid, + mVarStoreName, + sizeof (SOVEREIGN_BOOT_WIZARD_FORM_DATA), + (UINT8 *)&PrivateData->FormData, + NULL); + } + +EXIT: + + FREE_NON_NULL (File); return Status; } @@ -916,6 +1633,12 @@ SovereignBootWizardInit ( mPrivateData->HiiHandle = HiiHandle; + Status = InstallInteractiveModeForm (mPrivateData); + if (EFI_ERROR (Status)) { + SovereignBootWizardUnload (ImageHandle); + return Status; + } + SvConfig = &mPrivateData->NvConfig; ZeroMem (SvConfig, sizeof (SOVEREIGN_BOOT_WIZARD_NV_CONFIG)); @@ -1102,8 +1825,6 @@ SovereignBootWizardUnload ( IN EFI_HANDLE ImageHandle ) { - UINTN Index; - ASSERT (mPrivateData != NULL); if (mPrivateData->HiiHandle != NULL) { @@ -1122,12 +1843,9 @@ SovereignBootWizardUnload ( mPrivateData->AppHandle = NULL; } - for (Index = 0; Index < NAME_VALUE_NAME_NUMBER; Index++) { - FREE_NON_NULL (mPrivateData->NameValueName[Index]); - } - // Free all pools from certificate, bootloader contexts and entries FreeBootMenuEntries (); + UninstallInteractiveModeForm (mPrivateData); FREE_NON_NULL (mPrivateData); mPrivateData = NULL; diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h index e9d036db1e..0b9f10059d 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.h @@ -24,6 +24,7 @@ Revision History #include #include +#include #include #include #include @@ -46,6 +47,7 @@ Revision History #include #include #include +#include #include #include #include @@ -75,7 +77,7 @@ typedef struct { extern CONST UINTN MicrosoftCertificatesArraySize; extern CONST CERT_PTR MicrosoftCertificates[]; -#define NAME_VALUE_NAME_NUMBER 3 +#define SV_BOOT_VARSTORE_NAME L"SvBootFormData" #define DEFAULT_CLASS_MANUFACTURING_VALUE 0xFF #define DEFAULT_CLASS_STANDARD_VALUE 0x0 @@ -96,17 +98,39 @@ extern CONST CERT_PTR MicrosoftCertificates[]; } \ } while(FALSE) +#define FREE_NON_OPCODE(Handle) \ + do{ \ + if ((Handle) != NULL) { \ + HiiFreeOpCodeHandle((Handle)); \ + } \ + } while (FALSE) + +#define BUFFER_MAX_SIZE 100 + +#define WIN_CERT_UEFI_RSA2048_SIZE 256 +#define WIN_CERT_UEFI_RSA3072_SIZE 384 +#define WIN_CERT_UEFI_RSA4096_SIZE 512 + +typedef enum { + Variable_NONE, + Variable_DB, + Variable_DBX, + Variable_MAX +} CURRENT_VARIABLE_NAME; + +typedef struct { + EFI_FILE_HANDLE FHandle; + UINT16 *FileName; + UINT8 FileType; +} SOVEREIGNBOOT_FILE_CONTEXT; + typedef struct { UINT32 Signature; EFI_HANDLE AppHandle; EFI_HII_HANDLE HiiHandle; - SOVEREIGN_BOOT_WIZARD_CONFIG_DATA ConfigData; - SOVEREIGN_BOOT_WIZARD_NV_CONFIG NvConfig; - SOVEREIGN_BOOT_WIZARD_FORM_DATA FormData; - EFI_STRING_ID NameStringId[NAME_VALUE_NAME_NUMBER]; - EFI_STRING NameValueName[NAME_VALUE_NAME_NUMBER]; + EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; EFI_HII_DATABASE_PROTOCOL *HiiDatabase; EFI_HII_STRING_PROTOCOL *HiiString; @@ -114,16 +138,29 @@ typedef struct { EFI_CONFIG_KEYWORD_HANDLER_PROTOCOL *HiiKeywordHandler; EFI_HII_POPUP_PROTOCOL *HiiPopup; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; + EFI_FORM_BROWSER2_PROTOCOL *FormBrowser2; EDKII_FORM_BROWSER_EXTENSION2_PROTOCOL *FormBrowserEx2; - EFI_HII_CONFIG_ACCESS_PROTOCOL ConfigAccess; + SOVEREIGN_BOOT_WIZARD_CONFIG_DATA ConfigData; + SOVEREIGN_BOOT_WIZARD_NV_CONFIG NvConfig; + SOVEREIGN_BOOT_WIZARD_FORM_DATA FormData; - EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText; + SOVEREIGNBOOT_FILE_CONTEXT *FileContext; + + CURRENT_VARIABLE_NAME VariableName; // The variable name we are processing. + UINT32 ListCount; // Record current variable has how many signature list. + UINTN ListIndex; // Record which signature list is processing. + UINT32 DataCount; // Record current list has how many signature data. + UINTN DataIndex; // Record which signature data is processing. + BOOLEAN *CheckArray; // Record which signature data checked. } SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA; #define SOVEREIGN_BOOT_WIZARD_PRIVATE_FROM_THIS(a) CR (a, SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA, ConfigAccess, SOVEREIGN_BOOT_PRIVATE_SIGNATURE) +extern SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *gPrivateData; + #pragma pack(1) typedef struct { @@ -224,6 +261,7 @@ typedef struct { BOOLEAN CertIsValid; BOOLEAN CertIsMicrosoft; BOOLEAN CertIsCA; + BOOLEAN CertIsForbidden; UINT8 CertDigest[MAX_DIGEST_SIZE]; UINTN CertDigestSize; @@ -237,8 +275,12 @@ typedef struct { } SV_CERT_ENTRY; typedef struct { - UINT8 ImageDigest[MAX_DIGEST_SIZE]; + UINT8 ImageDigest[SHA256_DIGEST_SIZE]; UINTN ImageDigestSize; + UINT8 ImageSha384Digest[SHA384_DIGEST_SIZE]; + UINTN ImageSha384DigestSize; + UINT8 ImageSha512Digest[SHA512_DIGEST_SIZE]; + UINTN ImageSha512DigestSize; BOOLEAN ImageIsInDbx; BOOLEAN ImageIsInDb; @@ -253,10 +295,11 @@ typedef struct { LIST_ENTRY Certs; } SV_SECURITY_CONTEXT; -extern SV_MENU_OPTION BootOptionMenu; +extern SV_MENU_OPTION mBootOptionMenu; extern UINTN mBootloaderIndex; extern UINTN mCertIndex; extern INTN mFirstTrustedBootloader; +extern BOOLEAN mAltAccessMode; EFI_STATUS GetBootOptions ( @@ -293,6 +336,13 @@ GetMenuEntry ( UINTN MenuNumber ); +EFI_STATUS +ParseHashValue ( + IN UINT8 *Digest, + IN UINTN DigestSize, + OUT CHAR16 **BufferToReturn + ); + VOID FreeBootMenuEntry ( SV_MENU_ENTRY *BootloaderEntry @@ -325,6 +375,19 @@ UpdateCertDetails ( IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private ); +VOID +FillCertStrings ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN SV_CERT_ENTRY *CertificateEntry + ); + +VOID +FillKeyHashStrings ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *Private, + IN EFI_SIGNATURE_LIST *List, + IN EFI_SIGNATURE_DATA *Data + ); + EFI_STATUS RestoreSecureBootDefaults ( VOID @@ -337,8 +400,9 @@ PrepareSbVariablesForSvBoot ( EFI_STATUS AddKeyOrHashAsTrustedOrUntrusted ( - SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, - BOOLEAN Trust + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData, + IN BOOLEAN Trust, + IN BOOLEAN EnrollImageHash ); EFI_STATUS @@ -346,6 +410,12 @@ FinalizeSvBootProvisioning ( VOID ); +CHAR16 * +UiDevicePathToStr ( + IN EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *DevPathToText, + IN EFI_DEVICE_PATH_PROTOCOL *DevPath + ); + BOOLEAN Asn1TimeToEfiTime ( IN OPENSSL_ASN1_TIME *Asn1Time, @@ -379,4 +449,9 @@ FreeSecurityContext ( SV_SECURITY_CONTEXT *SecCtx ); +VOID +RefreshImageSecurityInfo ( + IN SOVEREIGN_BOOT_WIZARD_PRIVATE_DATA *PrivateData + ); + #endif diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf index da617ce5a2..eba4c8e6fa 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf @@ -29,6 +29,7 @@ Asn1Time.c BootOptionParsing.c BootOptionScanning.c + InteractiveModeImpl.c KeyManagement.c MicrosoftCerts.c SignatureParsing.c @@ -65,15 +66,30 @@ SecureBootVariableLib SecureBootVariableProvisionLib DxeImageVerificationLib + FileExplorerLib [Guids] - gSovereignBootWizardFormSetGuid gEfiCertRsa2048Guid + gEfiCertRsa2048Sha256Guid + gEfiCertX509Guid + gEfiCertSha1Guid + gEfiCertSha224Guid + gEfiCertSha256Guid + gEfiCertSha384Guid + gEfiCertSha512Guid + gEfiCertSm3Guid gEfiCertPkcs7Guid + gEfiCertTypeRsa2048Sha256Guid + gEfiFileSystemVolumeLabelInfoIdGuid gEfiCertX509Sha256Guid + gEfiCertX509Sha384Guid + gEfiCertX509Sha512Guid + gEfiCertX509Sm3Guid + gSovereignBootWizardFormSetGuid gEfiImageSecurityDatabaseGuid gEfiGlobalVariableGuid gEfiPartTypeSystemPartGuid + gEfiIfrTianoGuid [Protocols] ## PRODUCES # SovereignBootWizardFormSet diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h index be5f426788..68a0e53380 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardHii.h @@ -24,42 +24,184 @@ Revision History: #include #include -#define SOVEREIGN_BOOT_WIZARD_FORM_DATA_VARSTORE_ID 0x0001 - -#define SOVEREIGN_BOOT_WIZARD_WELCOME_FORM_ID 1 -#define SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID 2 -#define SOVEREIGN_BOOT_WIZARD_MS_SECURE_BOOT_FORM_ID 3 -#define SOVEREIGN_BOOT_WIZARD_KEY_DETAILS_FORM_ID 4 -#define SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID 9 +#define SOVEREIGN_BOOT_WIZARD_FORM_DATA_VARSTORE_ID 0x0001 + +#define SOVEREIGN_BOOT_WIZARD_WELCOME_FORM_ID 0x1 +#define SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID 0x2 +#define SOVEREIGN_BOOT_WIZARD_MS_SECURE_BOOT_FORM_ID 0x3 +#define SOVEREIGN_BOOT_WIZARD_KEY_DETAILS_FORM_ID 0x4 +#define SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID 0x5 +#define FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM 0x6 +#define FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM 0x7 +#define SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB 0x8 +#define SOVEREIGN_BOOT_DELETE_SIGNATURE_FROM_DB 0x9 +#define SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX 0xa +#define SOVEREIGN_BOOT_DELETE_SIGNATURE_LIST_FORM 0xb +#define SOVEREIGN_BOOT_DELETE_SIGNATURE_DATA_FORM 0xc +#define SOVEREIGN_BOOT_WIZARD_HASH_DETAILS_FORM_ID 0xd +#define FORMID_SOVEREIGN_BOOT_BL_OPTION_FORM 0xe +#define SOVEREIGN_BOOT_WIZARD_BL_DETAILS_FORM_ID 0xf // Question IDs // Each form will reserve 0x100 IDs -#define SOVEREIGN_BOOT_WIZARD_FORM_QUESTION_ID_BASE 0x1000 +#define SOVEREIGN_BOOT_WIZARD_FORM_QUESTION_ID_BASE 0x1000 + // Welcome form #define WELCOME_FORM_QUESTION_ID_BASE 0x1100 #define SELECT_SOVEREIGN_BOOT_QUESTION_ID 0x1101 #define SELECT_DEFAULT_SECURE_BOOT_QUESTION_ID 0x1102 -// Configuration form -#define CONFIG_FORM_QUESTION_ID_BASE 0x1200 -#define DO_NOT_TRUST_KEY_FORM2_QUESTION_ID 0x1201 -#define TRUST_KEY_AND_BOOT_FORM2_QUESTION_ID 0x1202 -#define TRUST_KEY_FORM2_QUESTION_ID 0x1203 -#define SHOW_KEY_DETAILS_FORM2_QUESTION_ID 0x1204 -#define SKIP_KEY_FORM2_QUESTION_ID 0x1205 - #define EXIT_FORM_QUESTION_ID_BASE 0x1F00 -#define EXIT_FORM1_QUESTION_ID 0x1F01 -#define EXIT_FORM2_QUESTION_ID 0x1F02 -#define EXIT_FORM3_QUESTION_ID 0x1F03 -#define EXIT_FORM9_QUESTION_ID 0x1F09 - +#define KEY_EXIT_FORM1 0x1F01 +#define KEY_EXIT_FORM2 0x1F02 +#define KEY_EXIT_FORM3 0x1F03 +#define KEY_EXIT_FORM5 0x1F05 +// Configuration form +#define CONFIG_FORM_QUESTION_ID_BASE 0x1200 +#define KEY_DO_NOT_TRUST_KEY_FORM2 0x1201 +#define KEY_TRUST_KEY_AND_BOOT_FORM2 0x1202 +#define KEY_TRUST_KEY_FORM2 0x1203 +#define KEY_SHOW_KEY_DETAILS_FORM2 0x1204 +#define KEY_SKIP_KEY_FORM2 0x1205 + + +// Interactive form + +#define KEY_REMOVE_KEY_FROM_DATABASE 0x1D01 +#define KEY_REMOVE_HASH_FROM_DATABASE 0x1D02 +#define KEY_REMOVE_CERT_FROM_DATABASE 0x1D03 + +#define KEY_SOVEREIGN_BOOT_DELETE_SIGNATURE_FROM_DB 0x1D04 +#define KEY_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB 0x1D05 +#define KEY_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX 0x1D06 + +#define SIGNATURE_TYPE_QUESTION_ID 0x1D10 + +#define KEY_VALUE_SAVE_AND_EXIT_DB 0x1F0A +#define KEY_VALUE_NO_SAVE_AND_EXIT_DB 0x1F0B +#define KEY_VALUE_SAVE_AND_EXIT_DBX 0x1F0C +#define KEY_VALUE_NO_SAVE_AND_EXIT_DBX 0x1F0D +#define KEY_VALUE_FROM_DBX_TO_LIST_FORM 0x1F0E + +#define KEY_SOVEREIGN_BOOT_DB_OPTION 0x1306 +#define KEY_SOVEREIGN_BOOT_DBX_OPTION 0x1307 +#define KEY_SOVEREIGN_BOOT_SIGNATURE_GUID_DB 0x1308 +#define KEY_SOVEREIGN_BOOT_SIGNATURE_GUID_DBX 0x1309 +#define KEY_SOVEREIGN_BOOT_DELETE_ALL_LIST 0x130a +#define KEY_SOVEREIGN_BOOT_DELETE_ALL_DATA 0x130b +#define KEY_SOVEREIGN_BOOT_DELETE_CHECK_DATA 0x130c +#define KEY_ENROLL_SIGNATURE_TO_DB 0x130d +#define KEY_ENROLL_SIGNATURE_TO_DBX 0x130e +#define KEY_SOVEREIGN_BOOT_BL_OPTION 0x130f +#define KEY_REMOVE_CERT_FROM_DB 0x1310 +#define KEY_REMOVE_CERT_FROM_DBX 0x1311 +#define KEY_ADD_CERT_TO_DB 0x1312 +#define KEY_ADD_CERT_TO_DBX 0x1313 +#define KEY_REMOVE_HASH_FROM_DB 0x1314 +#define KEY_REMOVE_HASH_FROM_DBX 0x1315 +#define KEY_ADD_HASH_TO_DB 0x1316 +#define KEY_ADD_HASH_TO_DBX 0x1317 +#define KEY_REMOVE_ALL_IMAGE_DATA 0x1318 + +#define LABEL_DB_DELETE 0x1400 +#define LABEL_SIGNATURE_LIST_START 0x1410 +#define LABEL_SIGNATURE_DATA_START 0x1420 +#define LABEL_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB 0x1430 +#define LABEL_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX 0x1440 +#define LABEL_DELETE_ALL_LIST_BUTTON 0x1500 +#define LABEL_DB_CERTS_DATA_START 0x1600 +#define LABEL_DBX_CERTS_DATA_START 0x1700 +#define LABEL_BOOTLOADER_LIST_START 0x1800 +#define LABEL_BOOTLOADER_CERT_LIST_START 0x1900 +#define LABEL_END 0xffff + +#define OPTION_CONFIG_RANGE 0x1000 + +// +// Question ID 0x2000 ~ 0x2FFF is for bootloaders +// +#define OPTION_BL_QUESTION_ID 0x2000 +// +// Question ID 0x3000 ~ 0x3FFF is for bootloader certificates +// +#define OPTION_BL_CERT_QUESTION_ID 0x3000 +// +// Question ID 0x4000 ~ 0x4FFF is for DB +// +#define OPTION_DEL_DB_QUESTION_ID 0x4000 +// +// Question ID 0x5000 ~ 0x5FFF is for signature list. +// +#define OPTION_SIGNATURE_LIST_QUESTION_ID 0x5000 +// +// Question ID 0x6000 ~ 0x6FFF is for signature data. +// +#define OPTION_SIGNATURE_DATA_QUESTION_ID 0x6000 +// +// Question ID 0x7000 ~ 0x7FFF is for DB list +// +#define OPTION_DB_LIST_QUESTION_ID 0x7000 +// +// Question ID 0x8000 ~ 0x8FFF is for DBX list +// +#define OPTION_DBX_LIST_QUESTION_ID 0x8000 +// +// Question ID 0x7000 ~ 0x7FFF is for DB list entries +// +#define OPTION_DB_ENTRIES_QUESTION_ID 0x9000 +// +// Question ID 0x8000 ~ 0x8FFF is for DBX list entries +// +#define OPTION_DBX_ENTRIES_QUESTION_ID 0xA000 + +#define SIGNATURE_TYPE_RSA2048_SHA256 0 +#define SIGNATURE_TYPE_RSA2048 1 +#define SIGNATURE_TYPE_X509 2 +#define SIGNATURE_TYPE_SHA1 3 +#define SIGNATURE_TYPE_SHA224 4 +#define SIGNATURE_TYPE_SHA256 5 +#define SIGNATURE_TYPE_SHA384 6 +#define SIGNATURE_TYPE_SHA512 7 +#define SIGNATURE_TYPE_SM3 8 +#define SIGNATURE_TYPE_X509_SHA256 9 +#define SIGNATURE_TYPE_X509_SHA384 10 +#define SIGNATURE_TYPE_X509_SHA512 11 +#define SIGNATURE_TYPE_X509_SM3 12 +#define SIGNATURE_TYPE_UNKNOWN 13 + +#define IMAGE_STATE_UNDECIDED 0 +#define IMAGE_STATE_UNTRUSTED 1 +#define IMAGE_STATE_TRUSTED 2 + +// Keep the form data packed to workaround the storage size calculation +// difference in C and IFR for EFI_HII_TIME #pragma pack(1) - // Form Data typedef struct { - BOOLEAN ImageUnsigned; + UINT8 ImageUnsigned; // If the image is unsigned. + BOOLEAN AlwaysRevocation; // If the certificate is always revoked. Revocation time is hidden + UINT8 CertificateFormat; // The type of the certificate + EFI_HII_DATE RevocationDate; // The revocation date of the certificate + EFI_HII_TIME RevocationTime; // The revocation time of the certificate + UINT8 FileEnrollType; // File type of signature enroll + UINT32 ListCount; // The count of signature list. + UINT32 CheckedDataCount; // The count of checked signature data. + UINT8 SignatureType; // Type of signature to be displayed + BOOLEAN IsCertHash; // If the signature data is certificate hash + UINT8 SignatureRemove; // If the signature data should be modified + UINT32 BootloaderCount; // The count of bootloaders. + UINT8 BlCertView; // Controls data displayed in the certificate details + UINT8 SignedByMs; // If current bootloader is signed by MS certs. + UINT8 SignedByMsOnly; // If current bootloader is signed by MS certs only. + UINT8 ImageHashIsInDb; // If current bootloader hash is present in DB. + UINT8 ImageHashIsInDbx; // If current bootloader hash is present in DBX. + UINT8 ImageTrusted; // If current bootloader is trusted. + UINT8 HasInvalidSignature; // If current bootloader contains invalid signature. + UINT8 CertInDb; // If current certificate or its hash is present in DB. + UINT8 CertInDbx; // If current certificate or its hash is present in DBX. + UINT8 CertIsValid; // If current certificate is valid. + UINT8 CertIsMicrosoft; // If current certificate is Microsoft. } SOVEREIGN_BOOT_WIZARD_FORM_DATA; #pragma pack() diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr index 6a1bba1b7f..424ed1526b 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfr.vfr @@ -85,7 +85,7 @@ formset help = STRING_TOKEN(STR_EMPTY_STRING), text = STRING_TOKEN(STR_EXIT_TEXT), flags = INTERACTIVE, - key = EXIT_FORM1_QUESTION_ID; + key = KEY_EXIT_FORM1; endform; @@ -95,50 +95,66 @@ formset form formid = SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID, title = STRING_TOKEN(STR_FORM2_TITLE); - disableif ideqval SvBootData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED; - subtitle text = STRING_TOKEN(STR_CONFIG_SUBTITLE); - subtitle text = STRING_TOKEN(STR_EMPTY_STRING); - endif; - disableif NOT ideqval SvBootData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED; - subtitle text = STRING_TOKEN(STR_LAUNCH_REASON); - endif; + disableif ideqval SvBootData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED; + subtitle text = STRING_TOKEN(STR_CONFIG_SUBTITLE); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + endif; + disableif NOT ideqval SvBootData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED; + subtitle text = STRING_TOKEN(STR_LAUNCH_REASON); + endif; subtitle text = STRING_TOKEN(STR_BOOTOPT_DESCRIPTION); subtitle text = STRING_TOKEN(STR_HW_PATH); subtitle text = STRING_TOKEN(STR_FILE_PATH); subtitle text = STRING_TOKEN(STR_EMPTY_STRING); - subtitle text = STRING_TOKEN(STR_KEY_FINGERPRINT); + suppressif ideqval SvBootFormData.ImageUnsigned == 0; + subtitle text = STRING_TOKEN(STR_BOOTLOADER_HASH); + endif; + suppressif ideqval SvBootFormData.ImageUnsigned == 1; + subtitle text = STRING_TOKEN(STR_KEY_FINGERPRINT); + endif; subtitle text = STRING_TOKEN(STR_KEY_FINGERPRINT_HASH); + + suppressif ideqval SvBootFormData.ImageUnsigned == 0; + subtitle text = STRING_TOKEN(STR_IMAGE_UNSIGNED); + endif; + suppressif ideqval SvBootFormData.SignedByMs == 0; + subtitle text = STRING_TOKEN(STR_CERT_BELONGS_TO_MICROSOFT); + endif; + suppressif ideqval SvBootFormData.HasInvalidSignature == 0; + subtitle text = STRING_TOKEN(STR_SIGNATURE_INVALID); + endif; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); subtitle text = STRING_TOKEN(STR_TRUST_QUESTION); subtitle text = STRING_TOKEN(STR_EMPTY_STRING); - text + goto SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID, + prompt = STRING_TOKEN(STR_DO_NOT_TRUST_KEY), help = STRING_TOKEN(STR_EMPTY_STRING), - text = STRING_TOKEN(STR_DO_NOT_TRUST_KEY), flags = INTERACTIVE, - key = DO_NOT_TRUST_KEY_FORM2_QUESTION_ID; + key = KEY_DO_NOT_TRUST_KEY_FORM2; - text + goto SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID, + prompt = STRING_TOKEN(STR_TRUST_KEY_AND_BOOT), help = STRING_TOKEN(STR_EMPTY_STRING), - text = STRING_TOKEN(STR_TRUST_KEY_AND_BOOT), flags = INTERACTIVE, - key = TRUST_KEY_AND_BOOT_FORM2_QUESTION_ID; + key = KEY_TRUST_KEY_AND_BOOT_FORM2; disableif ideqval SvBootData.AppLaunchCause == SV_BOOT_LAUNCH_IMAGE_VERIFICATION_FAILED; - text + goto SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID, + prompt = STRING_TOKEN(STR_TRUST_KEY), help = STRING_TOKEN(STR_EMPTY_STRING), - text = STRING_TOKEN(STR_TRUST_KEY), flags = INTERACTIVE, - key = TRUST_KEY_FORM2_QUESTION_ID; + key = KEY_TRUST_KEY_FORM2; - text + goto SOVEREIGN_BOOT_WIZARD_CONFIG_FORM_ID, + prompt = STRING_TOKEN(STR_SKIP_KEY), help = STRING_TOKEN(STR_EMPTY_STRING), - text = STRING_TOKEN(STR_SKIP_KEY), flags = INTERACTIVE, - key = SKIP_KEY_FORM2_QUESTION_ID; + key = KEY_SKIP_KEY_FORM2; endif; subtitle text = STRING_TOKEN(STR_EMPTY_STRING); @@ -148,7 +164,7 @@ formset prompt = STRING_TOKEN(STR_SHOW_KEY_DETAILS), help = STRING_TOKEN(STR_EMPTY_STRING), flags = INTERACTIVE, - key = SHOW_KEY_DETAILS_FORM2_QUESTION_ID; + key = KEY_SHOW_KEY_DETAILS_FORM2; subtitle text = STRING_TOKEN(STR_EMPTY_STRING); endif; @@ -157,7 +173,7 @@ formset help = STRING_TOKEN(STR_EMPTY_STRING), text = STRING_TOKEN(STR_EXIT_TEXT), flags = INTERACTIVE, - key = EXIT_FORM2_QUESTION_ID; + key = KEY_EXIT_FORM2; endform; @@ -171,7 +187,7 @@ formset form formid = SOVEREIGN_BOOT_WIZARD_KEY_DETAILS_FORM_ID, - title = STRING_TOKEN(STR_FORM4_TITLE); + title = STRING_TOKEN(STR_FORM_CERT_DETAILS_TITLE); grayoutif TRUE; text @@ -213,24 +229,647 @@ formset text = STRING_TOKEN(STR_CERT_KEY_EXPONENT2); endif; + + disableif ideqval SvBootFormData.BlCertView == 1; + disableif ideqval SvBootFormData.SignatureRemove == 0; + + grayoutif TRUE; + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_KEY_FINGERPRINT); + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_KEY_FINGERPRINT_HASH); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + endif; + + // Empty text field so that none of the options are + // highlighted/selected by default. + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_EMPTY_STRING); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + // No form ID here, will be updated dynamically + goto + prompt = STRING_TOKEN(STR_REMOVE_CERT), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_REMOVE_CERT_FROM_DATABASE; + endif; + endif; + + disableif ideqval SvBootFormData.BlCertView == 0; + grayoutif TRUE; + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_KEY_FINGERPRINT); + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_KEY_FINGERPRINT_HASH); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + oneof varid = SvBootFormData.CertIsValid, + prompt = STRING_TOKEN(STR_CERT_VALID), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_NO), value = 0x0, flags = DEFAULT; + option text = STRING_TOKEN(STR_YES), value = 0x1, flags = 0; + endoneof; + + oneof varid = SvBootFormData.CertIsMicrosoft, + prompt = STRING_TOKEN(STR_CERT_IS_MICROSOFT), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_NO), value = 0x0, flags = DEFAULT; + option text = STRING_TOKEN(STR_YES), value = 0x1, flags = 0; + endoneof; + + oneof varid = SvBootFormData.CertInDb, + prompt = STRING_TOKEN(STR_CERT_IN_DB), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_NO), value = 0x0, flags = 0; + option text = STRING_TOKEN(STR_YES), value = 0x1, flags = 0; + endoneof; + + oneof varid = SvBootFormData.CertInDbx, + prompt = STRING_TOKEN(STR_CERT_IN_DBX), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_NO), value = 0x0, flags = DEFAULT; + option text = STRING_TOKEN(STR_YES), value = 0x1, flags = 0; + endoneof; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + // Empty text field so that none of the options are + // highlighted/selected by default. + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_EMPTY_STRING); + + suppressif ideqval SvBootFormData.CertInDb == 0; + goto SOVEREIGN_BOOT_WIZARD_KEY_DETAILS_FORM_ID, + prompt = STRING_TOKEN(STR_REMOVE_CERT_FROM_TRUSTED), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_REMOVE_CERT_FROM_DB; + endif; + + suppressif ideqval SvBootFormData.CertInDbx == 0; + goto SOVEREIGN_BOOT_WIZARD_KEY_DETAILS_FORM_ID, + prompt = STRING_TOKEN(STR_REMOVE_CERT_FROM_UNTRUSTED), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_REMOVE_CERT_FROM_DBX; + endif; + + suppressif ideqval SvBootFormData.CertInDb == 1; + goto SOVEREIGN_BOOT_WIZARD_KEY_DETAILS_FORM_ID, + prompt = STRING_TOKEN(STR_ADD_CERT_TO_TRUSTED), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_ADD_CERT_TO_DB; + endif; + + suppressif ideqval SvBootFormData.CertInDbx == 1; + goto SOVEREIGN_BOOT_WIZARD_KEY_DETAILS_FORM_ID, + prompt = STRING_TOKEN(STR_ADD_CERT_TO_UNTRUSTED), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_ADD_CERT_TO_DBX; + endif; + + endif; + endform; + form formid = SOVEREIGN_BOOT_WIZARD_HASH_DETAILS_FORM_ID, + title = STRING_TOKEN(STR_FORM_HASH_DETAILS_TITLE); + + grayoutif TRUE; + oneof varid = SvBootFormData.SignatureType, + questionid = SIGNATURE_TYPE_QUESTION_ID, + prompt = STRING_TOKEN(STR_SIGNATURE_TYPE), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + + option text = STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256), value = SIGNATURE_TYPE_RSA2048_SHA256, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_RSA2048), value = SIGNATURE_TYPE_RSA2048, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_X509), value = SIGNATURE_TYPE_X509, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_SHA1), value = SIGNATURE_TYPE_SHA1, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_SHA224), value = SIGNATURE_TYPE_SHA224, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_SHA256), value = SIGNATURE_TYPE_SHA256, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_SHA384), value = SIGNATURE_TYPE_SHA384, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_SHA512), value = SIGNATURE_TYPE_SHA512, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_SM3), value = SIGNATURE_TYPE_SM3, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_X509_SHA256), value = SIGNATURE_TYPE_X509_SHA256, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_X509_SHA384), value = SIGNATURE_TYPE_X509_SHA384, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_X509_SHA512), value = SIGNATURE_TYPE_X509_SHA512, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_X509_SM3), value = SIGNATURE_TYPE_X509_SM3, flags = 0; + option text = STRING_TOKEN(STR_LIST_TYPE_UNKNOWN), value = SIGNATURE_TYPE_UNKNOWN, flags = 0; + endoneof; + endif; + + suppressif ideqval SvBootFormData.SignatureType == SIGNATURE_TYPE_RSA2048; + grayoutif TRUE; + suppressif ideqval SvBootFormData.IsCertHash == 0; + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_SIGNATURE_DATA_REVOCATION_TIME), + text = STRING_TOKEN(STR_SIGNATURE_DATA_REVOCATION_TIME2); + endif; + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_SIGNATURE_DATA_RAW); + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_SIGNATURE_DATA_RAW_HEX); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + endif; + + // Empty text field so that none of the options are + // highlighted/selected by default. + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_EMPTY_STRING); + + // No form ID here, will be updated dynamically + goto + prompt = STRING_TOKEN(STR_REMOVE_HASH), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_REMOVE_HASH_FROM_DATABASE; + + endif; + + suppressif NOT ideqval SvBootFormData.SignatureType == SIGNATURE_TYPE_RSA2048; + + grayoutif TRUE; + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_CERT_KEY_MODULUS); + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_CERT_KEY_MODULUS_HEX); + + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_CERT_KEY_EXPONENT), + text = STRING_TOKEN(STR_CERT_KEY_EXPONENT2); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + endif; + + // Empty text field so that none of the options are + // highlighted/selected by default. + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_EMPTY_STRING); + + goto + prompt = STRING_TOKEN(STR_REMOVE_KEY), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_REMOVE_KEY_FROM_DATABASE; + + endif; + + endform; // - // Advanced mode window + // Interactive mode window // form formid = SOVEREIGN_BOOT_WIZARD_INTERACTIVE_MODE_FORM_ID, - title = STRING_TOKEN(STR_FORM9_TITLE); + title = STRING_TOKEN(STR_FORM5_TITLE); subtitle text = STRING_TOKEN(STR_INTERACTIVE_MODE_SUBTITLE); subtitle text = STRING_TOKEN(STR_EMPTY_STRING); subtitle text = STRING_TOKEN(STR_LAUNCH_REASON); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto FORMID_SOVEREIGN_BOOT_BL_OPTION_FORM, + prompt = STRING_TOKEN(STR_SOVEREIGN_BOOT_BL_OPTION), + help = STRING_TOKEN(STR_SOVEREIGN_BOOT_BL_OPTION_HELP), + flags = INTERACTIVE, + key = KEY_SOVEREIGN_BOOT_BL_OPTION; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM, + prompt = STRING_TOKEN(STR_SOVEREIGN_BOOT_DB_OPTION), + help = STRING_TOKEN(STR_SOVEREIGN_BOOT_DB_OPTION_HELP), + flags = INTERACTIVE, + key = KEY_SOVEREIGN_BOOT_DB_OPTION; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM, + prompt = STRING_TOKEN(STR_SOVEREIGN_BOOT_DBX_OPTION), + help = STRING_TOKEN(STR_SOVEREIGN_BOOT_DBX_OPTION_HELP), + flags = INTERACTIVE, + key = KEY_SOVEREIGN_BOOT_DBX_OPTION; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); text help = STRING_TOKEN(STR_EMPTY_STRING), text = STRING_TOKEN(STR_EXIT_TEXT), flags = INTERACTIVE, - key = EXIT_FORM9_QUESTION_ID; + key = KEY_EXIT_FORM5; + + endform; + + form formid = FORMID_SOVEREIGN_BOOT_BL_OPTION_FORM, + title = STRING_TOKEN(STR_BOOTLOADER_LIST_FORM); + + disableif NOT ideqval SvBootFormData.BootloaderCount == 0; + grayoutif TRUE; + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_NO_BOOTLOADERS_FOUND); + endif; + endif; + + label LABEL_BOOTLOADER_LIST_START; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + endform; + + form formid = SOVEREIGN_BOOT_WIZARD_BL_DETAILS_FORM_ID, + title = STRING_TOKEN(STR_BOOTLOADER_DETAILS_FORM); + + subtitle text = STRING_TOKEN(STR_BOOTOPT_DESCRIPTION); + subtitle text = STRING_TOKEN(STR_HW_PATH); + subtitle text = STRING_TOKEN(STR_FILE_PATH); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + subtitle text = STRING_TOKEN(STR_BOOTLOADER_HASH); + subtitle text = STRING_TOKEN(STR_BOOTLOADER_HASH_HEX); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + grayoutif TRUE; + oneof varid = SvBootFormData.ImageUnsigned, + prompt = STRING_TOKEN(STR_IMAGE_IS_SIGNED), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_YES), value = 0x0, flags = DEFAULT; + option text = STRING_TOKEN(STR_NO), value = 0x1, flags = 0; + endoneof; + + suppressif ideqval SvBootFormData.ImageUnsigned == 1; + oneof varid = SvBootFormData.HasInvalidSignature, + prompt = STRING_TOKEN(STR_IMAGE_CONTAINS_INVALID_SIGNATURE), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_NO), value = 0x0, flags = DEFAULT; + option text = STRING_TOKEN(STR_YES), value = 0x1, flags = 0; + endoneof; + + oneof varid = SvBootFormData.SignedByMs, + prompt = STRING_TOKEN(STR_IMAGE_IS_SIGNED_BY_MS), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_NO), value = 0x0, flags = DEFAULT; + option text = STRING_TOKEN(STR_YES), value = 0x1, flags = 0; + endoneof; + + oneof varid = SvBootFormData.SignedByMsOnly, + prompt = STRING_TOKEN(STR_IMAGE_IS_SIGNED_BY_MS_ONLY), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_NO), value = 0x0, flags = DEFAULT; + option text = STRING_TOKEN(STR_YES), value = 0x1, flags = 0; + endoneof; + endif; + + oneof varid = SvBootFormData.ImageHashIsInDb, + prompt = STRING_TOKEN(STR_IMAGE_HASH_IN_DB), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_NO), value = 0x0, flags = DEFAULT; + option text = STRING_TOKEN(STR_YES), value = 0x1, flags = 0; + endoneof; + + oneof varid = SvBootFormData.ImageHashIsInDbx, + prompt = STRING_TOKEN(STR_IMAGE_HASH_IN_DBX), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_NO), value = 0x0, flags = DEFAULT; + option text = STRING_TOKEN(STR_YES), value = 0x1, flags = 0; + endoneof; + + oneof varid = SvBootFormData.ImageTrusted, + prompt = STRING_TOKEN(STR_IMAGE_IS_TRUSTED), + help = STRING_TOKEN(STR_EMPTY_STRING), + option text = STRING_TOKEN(STR_UNDECIDED), value = IMAGE_STATE_UNDECIDED, flags = DEFAULT; + option text = STRING_TOKEN(STR_NO), value = IMAGE_STATE_UNTRUSTED, flags = 0; + option text = STRING_TOKEN(STR_YES), value = IMAGE_STATE_TRUSTED, flags = 0; + endoneof; + endif; + + // Empty text field so that none of the options are + // highlighted/selected by default. + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_EMPTY_STRING); + + suppressif ideqval SvBootFormData.ImageHashIsInDb == 0; + goto SOVEREIGN_BOOT_WIZARD_BL_DETAILS_FORM_ID, + prompt = STRING_TOKEN(STR_REMOVE_HASH_FROM_TRUSTED), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_REMOVE_HASH_FROM_DB; + endif; + + suppressif ideqval SvBootFormData.ImageHashIsInDbx == 0; + goto SOVEREIGN_BOOT_WIZARD_BL_DETAILS_FORM_ID, + prompt = STRING_TOKEN(STR_REMOVE_HASH_FROM_UNTRUSTED), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_REMOVE_HASH_FROM_DBX; + endif; + + suppressif ideqval SvBootFormData.ImageHashIsInDb == 1; + goto SOVEREIGN_BOOT_WIZARD_BL_DETAILS_FORM_ID, + prompt = STRING_TOKEN(STR_ADD_HASH_TO_TRUSTED), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_ADD_HASH_TO_DB; + endif; + + suppressif ideqval SvBootFormData.ImageHashIsInDbx == 1; + goto SOVEREIGN_BOOT_WIZARD_BL_DETAILS_FORM_ID, + prompt = STRING_TOKEN(STR_ADD_HASH_TO_UNTRUSTED), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_ADD_HASH_TO_DBX; + endif; + + goto SOVEREIGN_BOOT_WIZARD_BL_DETAILS_FORM_ID, + prompt = STRING_TOKEN(STR_REMOVE_ALL_IMAGE_DATA), + help = STRING_TOKEN(STR_EMPTY_STRING), + flags = INTERACTIVE, + key = KEY_REMOVE_ALL_IMAGE_DATA; + + disableif ideqval SvBootFormData.ImageUnsigned == 1; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_BL_CERTIFICATE_LSIT); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + endif; + + label LABEL_BOOTLOADER_CERT_LIST_START; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + endform; + + form formid = FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM, + title = STRING_TOKEN(STR_SOVEREIGN_BOOT_DB_OPTION); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB, + prompt = STRING_TOKEN (STR_SOVEREIGN_BOOT_ENROLL_SIGNATURE), + help = STRING_TOKEN (STR_SOVEREIGN_BOOT_ENROLL_SIGNATURE), + flags = INTERACTIVE, + key = KEY_ENROLL_SIGNATURE_TO_DB; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto SOVEREIGN_BOOT_DELETE_SIGNATURE_FROM_DB, + prompt = STRING_TOKEN (STR_SOVEREIGN_BOOT_DELETE_SIGNATURE), + help = STRING_TOKEN (STR_SOVEREIGN_BOOT_DELETE_SIGNATURE), + flags = INTERACTIVE, + key = KEY_SOVEREIGN_BOOT_DELETE_SIGNATURE_FROM_DB; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_SV_BOOT_DB_INFO); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + label LABEL_DB_CERTS_DATA_START; + // goto opcodes will be generated dynamically for each cert + // enrolled in DB to point to key details form + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif NOT ideqval SvBootFormData.ListCount == 0; + grayoutif TRUE; + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_DATABASE_EMPTY); + endif; + endif; + + endform; + + form formid = FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM, + title = STRING_TOKEN(STR_SOVEREIGN_BOOT_DBX_OPTION); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX, + prompt = STRING_TOKEN (STR_SOVEREIGN_BOOT_ENROLL_SIGNATURE), + help = STRING_TOKEN (STR_SOVEREIGN_BOOT_ENROLL_SIGNATURE), + flags = INTERACTIVE, + key = KEY_ENROLL_SIGNATURE_TO_DBX; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto SOVEREIGN_BOOT_DELETE_SIGNATURE_LIST_FORM, + prompt = STRING_TOKEN (STR_SOVEREIGN_BOOT_DELETE_SIGNATURE), + help = STRING_TOKEN (STR_SOVEREIGN_BOOT_DELETE_SIGNATURE), + flags = INTERACTIVE, + key = KEY_VALUE_FROM_DBX_TO_LIST_FORM; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_SV_BOOT_DBX_INFO); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + label LABEL_DBX_CERTS_DATA_START; + // goto opcodes will be generated dynamically for each cert + // enrolled in DBX to point to key details form + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif NOT ideqval SvBootFormData.ListCount == 0; + grayoutif TRUE; + text + help = STRING_TOKEN(STR_EMPTY_STRING), + text = STRING_TOKEN(STR_DATABASE_EMPTY); + endif; + endif; + + endform; + + form formid = SOVEREIGN_BOOT_DELETE_SIGNATURE_FROM_DB, + title = STRING_TOKEN(STR_SOVEREIGN_BOOT_DELETE_SIGNATURE); + + label LABEL_DB_DELETE; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + endform; + + form formid = SOVEREIGN_BOOT_DELETE_SIGNATURE_LIST_FORM, + title = STRING_TOKEN(STR_SOVEREIGN_BOOT_DELETE_LIST_FORM); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif ideqval SvBootFormData.SignatureRemove == 1; + grayoutif ideqval SvBootFormData.ListCount == 0; + label LABEL_DELETE_ALL_LIST_BUTTON; + label LABEL_END; + endif; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + label LABEL_SIGNATURE_LIST_START; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + endform; + + form formid = SOVEREIGN_BOOT_DELETE_SIGNATURE_DATA_FORM, + title = STRING_TOKEN(STR_SOVEREIGN_BOOT_DELETE_DATA_FORM); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto + prompt = STRING_TOKEN(STR_SOVEREIGN_BOOT_DELETE_ALL_DATA), + help = STRING_TOKEN(STR_SOVEREIGN_BOOT_DELETE_ALL_DATA_HELP), + flags = INTERACTIVE, + key = KEY_SOVEREIGN_BOOT_DELETE_ALL_DATA; + + disableif ideqval SvBootFormData.SignatureRemove == 1; + grayoutif ideqval SvBootFormData.CheckedDataCount == 0; + goto SOVEREIGN_BOOT_DELETE_SIGNATURE_LIST_FORM, + prompt = STRING_TOKEN(STR_SOVEREIGN_BOOT_DELETE_CHECK_DATA), + help = STRING_TOKEN(STR_SOVEREIGN_BOOT_DELETE_CHECK_DATA_HELP), + flags = INTERACTIVE, + key = KEY_SOVEREIGN_BOOT_DELETE_CHECK_DATA; + endif; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + label LABEL_SIGNATURE_DATA_START; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + endform; + + form formid = SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB, + title = STRING_TOKEN(STR_SOVEREIGN_BOOT_ENROLL_SIGNATURE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB, + prompt = STRING_TOKEN(STR_SOVEREIGN_BOOT_ADD_SIGNATURE_FILE), + help = STRING_TOKEN(STR_SOVEREIGN_BOOT_ADD_SIGNATURE_FILE), + flags = INTERACTIVE, + key = KEY_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + label LABEL_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DB; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM, + prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + flags = INTERACTIVE | RESET_REQUIRED, + key = KEY_VALUE_SAVE_AND_EXIT_DB; + + goto FORMID_SOVEREIGN_BOOT_DB_OPTION_FORM, + prompt = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + flags = INTERACTIVE, + key = KEY_VALUE_NO_SAVE_AND_EXIT_DB; + + endform; + + form formid = SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX, + title = STRING_TOKEN(STR_SOVEREIGN_BOOT_ENROLL_SIGNATURE); + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX, + prompt = STRING_TOKEN(STR_SOVEREIGN_BOOT_ADD_SIGNATURE_FILE), + help = STRING_TOKEN(STR_SOVEREIGN_BOOT_ADD_SIGNATURE_FILE), + flags = INTERACTIVE, + key = KEY_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX; + + label LABEL_SOVEREIGN_BOOT_ENROLL_SIGNATURE_TO_DBX; + label LABEL_END; + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + disableif NOT ideqval SvBootFormData.FileEnrollType == 1; + oneof name = X509SignatureFormatInDbx, + varid = SvBootFormData.CertificateFormat, + prompt = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_PROMPT), + help = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_HELP), + disableif TRUE; // Make it depend on DISABLE_SHA1_DEPRECATED_INTERFACES? + option text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_SHA1), value = 0x0, flags = 0; + endif; + suppressif TRUE; // SHA224 not implemented + option text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_SHA224), value = 0x1, flags = 0; + endif; + option text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_SHA256), value = 0x2, flags = DEFAULT; + option text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_SHA384), value = 0x3, flags = 0; + option text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_SHA512), value = 0x4, flags = 0; + option text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_RAW), value = 0x6, flags = 0; + endoneof; + endif; + + disableif NOT ideqval SvBootFormData.FileEnrollType == 2; + text + help = STRING_TOKEN(STR_DBX_PE_IMAGE_FORMAT_HELP), // Help string + text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_PROMPT), // Prompt string + text = STRING_TOKEN(STR_DBX_PE_FORMAT_SHA256); // PE image type + endif; + + disableif NOT ideqval SvBootFormData.FileEnrollType == 3; + text + help = STRING_TOKEN(STR_DBX_AUTH_2_FORMAT_HELP), // Help string + text = STRING_TOKEN(STR_DBX_CERTIFICATE_FORMAT_PROMPT), // Prompt string + text = STRING_TOKEN(STR_DBX_AUTH_2_FORMAT); // AUTH_2 image type + endif; + + suppressif ideqval SvBootFormData.CertificateFormat == 4; + checkbox varid = SvBootFormData.AlwaysRevocation, + prompt = STRING_TOKEN(STR_ALWAYS_CERTIFICATE_REVOCATION_PROMPT), + help = STRING_TOKEN(STR_ALWAYS_CERTIFICATE_REVOCATION_HELP), + flags = INTERACTIVE, + endcheckbox; + + suppressif ideqval SvBootFormData.AlwaysRevocation == 1; + date varid = SvBootFormData.RevocationDate, + prompt = STRING_TOKEN(STR_CERTIFICATE_REVOCATION_DATE_PROMPT), + help = STRING_TOKEN(STR_CERTIFICATE_REVOCATION_DATE_HELP), + flags = STORAGE_NORMAL, + enddate; + + time varid = SvBootFormData.RevocationTime, + prompt = STRING_TOKEN(STR_CERTIFICATE_REVOCATION_TIME_PROMPT), + help = STRING_TOKEN(STR_CERTIFICATE_REVOCATION_TIME_HELP), + flags = STORAGE_NORMAL, + endtime; + endif; + endif; + + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + subtitle text = STRING_TOKEN(STR_EMPTY_STRING); + + goto FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM, + prompt = STRING_TOKEN(STR_SAVE_AND_EXIT), + help = STRING_TOKEN(STR_SAVE_AND_EXIT), + flags = INTERACTIVE | RESET_REQUIRED, + key = KEY_VALUE_SAVE_AND_EXIT_DBX; + + goto FORMID_SOVEREIGN_BOOT_DBX_OPTION_FORM, + prompt = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + help = STRING_TOKEN(STR_NO_SAVE_AND_EXIT), + flags = INTERACTIVE, + key = KEY_VALUE_NO_SAVE_AND_EXIT_DBX; endform; diff --git a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni index 15d3546355..5a8453adc7 100644 --- a/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni +++ b/DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizardVfrStrings.uni @@ -15,88 +15,255 @@ // // --*/ - -/=# - #langdef en-US "English" -#string STR_FORM_SET_TITLE #language en-US "Sovereign Boot Provisioning Wizard" -#string STR_FORM_SET_TITLE_HELP #language en-US " " -#string STR_EMPTY_STRING #language en-US " " -#string STR_EXIT_TEXT #language en-US "[ Exit ]" +#string STR_FORM_SET_TITLE #language en-US "Sovereign Boot Provisioning Wizard" +#string STR_FORM_SET_TITLE_HELP #language en-US " " +#string STR_EMPTY_STRING #language en-US " " +#string STR_EXIT_TEXT #language en-US "[ Exit ]" -#string FUNCTION_NINE_STRING #language en-US "F9=Reset to Defaults" -#string FUNCTION_TEN_STRING #language en-US "F10=Save" +#string FUNCTION_NINE_STRING #language en-US "F9=Reset to Defaults" +#string FUNCTION_TEN_STRING #language en-US "F10=Save" // Application launch causes -#string STR_LAUNCH_REASON #language en-US "\n" -#string STR_LAUNCH_CAUSE_DEFAULT_SETTINGS #language en-US "You see this window because you are booting for the first time or restored default system settings.\n\n" -#string STR_LAUNCH_CAUSE_SETUP #language en-US "You see this window because you have explicitly requested to launch the Wizard via system setup.\n" - "If you ended up here by mistake, please exit the application to avoid making changes to your system configuration.\n\n" -#string STR_LAUNCH_CAUSE_VERIFICATION_FAILED #language en-US "You see this window because the system attempted to boot an untrusted image.\n\n" +#string STR_LAUNCH_REASON #language en-US "\n" +#string STR_LAUNCH_CAUSE_DEFAULT_SETTINGS #language en-US "You see this window because you are booting for the first time or restored default system settings.\n\n" +#string STR_LAUNCH_CAUSE_SETUP #language en-US "You see this window because you have explicitly requested to launch the Wizard via system setup.\n" + "If you ended up here by mistake, please exit the application to avoid making changes to your system configuration.\n\n" +#string STR_LAUNCH_CAUSE_VERIFICATION_FAILED #language en-US "You see this window because the system attempted to boot an untrusted image.\n\n" // Welcome page strings -#string STR_FORM1_TITLE #language en-US "Sovereign Boot Provisioning Wizard" -#string STR_WELCOME_SUBTITLE #language en-US "Welcome to Sovereign Boot Provisioning Wizard!\n" -#string STR_WELCOME_PROMPT #language en-US "The Wizard will assist in setting up the UEFI Secure Boot feature. " - "Please select the UEFI Secure Boot scheme you would like to use:\n" - -#string STR_SELECT_SOVEREIGN_BOOT #language en-US "Sovereign Boot" -#string STR_SELECT_SOVEREIGN_BOOT_HELP #language en-US "" -#string STR_SOVEREIGN_BOOT_FEATURES #language en-US "* You decide which keys to trust\n" - "* No keys are initially trusted by default\n" - "* Requires a Sovereign Boot compatible operating system" -#string STR_SELECT_DEFAULT_SECURE_BOOT #language en-US "Standard Secure Boot with Microsoft certificates" -#string STR_SELECT_DEFAULT_SECURE_BOOT_HELP #language en-US "" -#string STR_MS_SECURE_BOOT_FEATURES #language en-US "* Trust firmware's default certificates\n" - "* Compatible with common operating systems\n" - "* Enrolls firmware's default Secure Boot keys" +#string STR_FORM1_TITLE #language en-US "Sovereign Boot Provisioning Wizard" +#string STR_WELCOME_SUBTITLE #language en-US "Welcome to Sovereign Boot Provisioning Wizard!\n" +#string STR_WELCOME_PROMPT #language en-US "The Wizard will assist in setting up the UEFI Secure Boot feature. " + "Please select the UEFI Secure Boot scheme you would like to use:\n" + +#string STR_SELECT_SOVEREIGN_BOOT #language en-US "Sovereign Boot" +#string STR_SELECT_SOVEREIGN_BOOT_HELP #language en-US "" +#string STR_SOVEREIGN_BOOT_FEATURES #language en-US "* You decide which keys to trust\n" + "* No keys are initially trusted by default\n" + "* Requires a Sovereign Boot compatible operating system" +#string STR_SELECT_DEFAULT_SECURE_BOOT #language en-US "Standard Secure Boot with Microsoft certificates" +#string STR_SELECT_DEFAULT_SECURE_BOOT_HELP #language en-US "" +#string STR_MS_SECURE_BOOT_FEATURES #language en-US "* Trust firmware's default certificates\n" + "* Compatible with common operating systems\n" + "* Enrolls firmware's default Secure Boot keys" // Configuration page strings -#string STR_FORM2_TITLE #language en-US "Sovereign Boot Provisioning Wizard" +#string STR_FORM2_TITLE #language en-US "Sovereign Boot Provisioning Wizard" -#string STR_CONFIG_SUBTITLE #language en-US "A new bootloader/key has been detected." +#string STR_CONFIG_SUBTITLE #language en-US "A new bootloader/key has been detected." -#string STR_BOOTOPT_DESCRIPTION #language en-US "Description: " -#string STR_HW_PATH #language en-US "Hardware path: " -#string STR_FILE_PATH #language en-US "File path: " -#string STR_KEY_FINGERPRINT #language en-US "Certificate fingerprint (SHA-256):" -#string STR_KEY_FINGERPRINT_HASH #language en-US "" +#string STR_BOOTOPT_DESCRIPTION #language en-US "Description: " +#string STR_HW_PATH #language en-US "Hardware path: " +#string STR_FILE_PATH #language en-US "File path: " +#string STR_KEY_FINGERPRINT #language en-US "Certificate fingerprint (SHA-256):" +#string STR_KEY_FINGERPRINT_HASH #language en-US "" +#string STR_BOOTLOADER_HASH #language en-US "Image hash (SHA-256):" -#string STR_TRUST_QUESTION #language en-US "Do you want to trust this key/image and continue booting?" -#string STR_SV_TRUST_KEY_POPUP #language en-US "" -#string STR_SV_TRUST_KEY_QUESTION #language en-US "Are you sure you want to trust the following" -#string STR_SV_UNTRUST_KEY_QUESTION #language en-US "Are you sure you do NOT want to trust the following" +#string STR_IMAGE_UNSIGNED #language en-US "!!! Image is unsigned !!!" +#string STR_SIGNATURE_INVALID #language en-US "!!! Signature or certificate is invalid !!!" +#string STR_CERT_BELONGS_TO_MICROSOFT #language en-US "!!! Certificate belongs to Microsoft !!!" -#string STR_DO_NOT_TRUST_KEY #language en-US "[ Do NOT trust, next bootloader ]" -#string STR_DO_NOT_TRUST_KEY2 #language en-US "[ Do NOT trust ]" -#string STR_TRUST_KEY_AND_BOOT #language en-US "[ Trust this key/image and boot ]" -#string STR_TRUST_KEY #language en-US "[ Trust this key/image, next key/bootloader ]" -#string STR_SKIP_KEY #language en-US "[ Skip this key/image, next key/bootloader ]" -#string STR_SHOW_KEY_DETAILS #language en-US "Show key/certificate details" +#string STR_TRUST_QUESTION #language en-US "Do you want to trust this key/image and continue booting?" +#string STR_SV_TRUST_KEY_POPUP #language en-US "" +#string STR_SV_TRUST_KEY_QUESTION #language en-US "Are you sure you want to trust the following" +#string STR_SV_UNTRUST_KEY_QUESTION #language en-US "Are you sure you do NOT want to trust the following" + +#string STR_DO_NOT_TRUST_KEY #language en-US "Do NOT trust, next bootloader" +#string STR_DO_NOT_TRUST_KEY2 #language en-US "Do NOT trust" +#string STR_TRUST_KEY_AND_BOOT #language en-US "Trust this key/image and boot" +#string STR_TRUST_KEY #language en-US "Trust this key/image, next key/bootloader" +#string STR_SKIP_KEY #language en-US "Skip this key/image, next key/bootloader" +#string STR_SHOW_KEY_DETAILS #language en-US "Show key/certificate details" // Configuration page strings -#string STR_FORM4_TITLE #language en-US "Certificate Details" +#string STR_FORM_CERT_DETAILS_TITLE #language en-US "Certificate Details" -#string STR_VALIDITY_BEFORE #language en-US "Valid Not Before:" -#string STR_VALIDITY_AFTER #language en-US "Valid Not After:" -#string STR_VALIDITY_BEFORE_DATE #language en-US "" -#string STR_VALIDITY_AFTER_DATE #language en-US "" +#string STR_VALIDITY_BEFORE #language en-US "Valid Not Before:" +#string STR_VALIDITY_AFTER #language en-US "Valid Not After:" +#string STR_VALIDITY_BEFORE_DATE #language en-US "" +#string STR_VALIDITY_AFTER_DATE #language en-US "" -#string STR_CERT_ISSUER #language en-US "Issuer Common Name (CN):" -#string STR_CERT_ISSUER2 #language en-US "" -#string STR_CERT_SUBJECT #language en-US "Subject Common Name (CN):" -#string STR_CERT_SUBJECT2 #language en-US "" +#string STR_CERT_ISSUER #language en-US "Issuer Common Name (CN):" +#string STR_CERT_ISSUER2 #language en-US "" +#string STR_CERT_SUBJECT #language en-US "Subject Common Name (CN):" +#string STR_CERT_SUBJECT2 #language en-US "" -#string STR_CERT_SERIAL_NUMBER #language en-US "Serial Number (HEX):" -#string STR_CERT_SERIAL_NUMBER2 #language en-US "" +#string STR_CERT_SERIAL_NUMBER #language en-US "Serial Number (HEX):" +#string STR_CERT_SERIAL_NUMBER2 #language en-US "" -#string STR_CERT_KEY_MODULUS #language en-US "Key Modulus:" -#string STR_CERT_KEY_MODULUS_HEX #language en-US "" -#string STR_CERT_KEY_EXPONENT #language en-US "Key Exponent:" -#string STR_CERT_KEY_EXPONENT2 #language en-US "" +#string STR_CERT_KEY_MODULUS #language en-US "Key Modulus:" +#string STR_CERT_KEY_MODULUS_HEX #language en-US "" +#string STR_CERT_KEY_EXPONENT #language en-US "Key Exponent:" +#string STR_CERT_KEY_EXPONENT2 #language en-US "" // Interactive mode strings -#string STR_FORM9_TITLE #language en-US "Sovereign Boot Provisioning Wizard" -#string STR_INTERACTIVE_MODE_SUBTITLE #language en-US "Sovereign Boot is already provisioned. You can use below options to modify/augment current configuration\n" +#string STR_FORM5_TITLE #language en-US "Sovereign Boot Provisioning Wizard" +#string STR_INTERACTIVE_MODE_SUBTITLE #language en-US "Sovereign Boot is already provisioned. You can use below options to modify/augment current configuration\n" + +#string STR_SOVEREIGN_BOOT_ENROLL_SIGNATURE #language en-US "Enroll Signature" +#string STR_SOVEREIGN_BOOT_DELETE_SIGNATURE #language en-US "Delete Signature" +#string STR_SOVEREIGN_BOOT_DELETE_LIST_FORM #language en-US "Delete Signature List Form" +#string STR_SOVEREIGN_BOOT_DELETE_DATA_FORM #language en-US "Delete Signature Data Form" +#string STR_SOVEREIGN_BOOT_DELETE_ALL_LIST #language en-US "Delete All Signature List" +#string STR_SOVEREIGN_BOOT_DELETE_ALL_DATA #language en-US "Delete All Signature Data" +#string STR_SOVEREIGN_BOOT_DELETE_CHECK_DATA #language en-US "Delete Checked Signature Data" +#string STR_SOVEREIGN_BOOT_DELETE_ALL_DATA_HELP #language en-US "All signature data will be deleted, no matter how many signature data have you checked." +#string STR_SOVEREIGN_BOOT_DELETE_CHECK_DATA_HELP #language en-US "All checked signature data will be deleted." +#string STR_SOVEREIGN_BOOT_ADD_SIGNATURE_FILE #language en-US "Enroll Signature Using File" + +#string STR_DBX_CERTIFICATE_FORMAT_PROMPT #language en-US "Signature Format" +#string STR_DBX_CERTIFICATE_FORMAT_HELP #language en-US "X509 DER-Cert enrolled. Select different option to enroll it into DBX." +#string STR_DBX_CERTIFICATE_FORMAT_SHA1 #language en-US "X509 CERT SHA1" +#string STR_DBX_CERTIFICATE_FORMAT_SHA224 #language en-US "X509 CERT SHA224" +#string STR_DBX_CERTIFICATE_FORMAT_SHA256 #language en-US "X509 CERT SHA256" +#string STR_DBX_CERTIFICATE_FORMAT_SHA384 #language en-US "X509 CERT SHA384" +#string STR_DBX_CERTIFICATE_FORMAT_SHA512 #language en-US "X509 CERT SHA512" +#string STR_DBX_CERTIFICATE_FORMAT_RAW #language en-US "X509 CERT" + +#string STR_DBX_PE_IMAGE_FORMAT_HELP #language en-US "PE image enrolled. Use SHA256 hash to enroll it into DBX" +#string STR_DBX_PE_FORMAT_SHA256 #language en-US "PE Image SHA256" + +#string STR_DBX_AUTH_2_FORMAT_HELP #language en-US "VARIABLE_AUTHENTICATION_2 binary enrolled. Use raw binary to enroll it into DBX" +#string STR_DBX_AUTH_2_FORMAT #language en-US "VARIABLE_AUTHENTICATION_2" + +#string STR_CERTIFICATE_REVOCATION_TIME_PROMPT #language en-US " Revocation Time" +#string STR_CERTIFICATE_REVOCATION_TIME_HELP #language en-US "Input the revocation time of the certificate" +#string STR_CERTIFICATE_REVOCATION_DATE_PROMPT #language en-US " Revocation Date" +#string STR_CERTIFICATE_REVOCATION_DATE_HELP #language en-US "Input the revocation date of the certificate" + +#string STR_ALWAYS_CERTIFICATE_REVOCATION_PROMPT #language en-US "Always Revoked" +#string STR_ALWAYS_CERTIFICATE_REVOCATION_HELP #language en-US "Indicate whether the certificate is always revoked." + +#string STR_SAVE_SIGNATURE_FILE #language en-US "Save Signature File" + +#string STR_SAVE_AND_EXIT #language en-US "Commit Changes and Exit" +#string STR_NO_SAVE_AND_EXIT #language en-US "Discard Changes and Exit" + +#string STR_FILE_EXPLORER_TITLE #language en-US "File Explorer" + +#string STR_SOVEREIGN_BOOT_BL_OPTION #language en-US "Show or modify Bootloaders" +#string STR_SOVEREIGN_BOOT_BL_OPTION_HELP #language en-US "" +#string STR_SOVEREIGN_BOOT_DB_OPTION #language en-US "Show or modify Trusted Key/Image Database" +#string STR_SOVEREIGN_BOOT_DB_OPTION_HELP #language en-US "" +#string STR_SOVEREIGN_BOOT_DBX_OPTION #language en-US "Show or modify Untrusted Key/Image Database" +#string STR_SOVEREIGN_BOOT_DBX_OPTION_HELP #language en-US "" + +#string STR_CERT_TYPE_RSA2048_SHA256_GUID #language en-US "RSA2048_SHA256_GUID" +#string STR_CERT_TYPE_PCKS7_GUID #language en-US "PKCS7_GUID" +#string STR_CERT_TYPE_SHA1_GUID #language en-US "SHA1_GUID" +#string STR_CERT_TYPE_SHA256_GUID #language en-US "SHA256_GUID" +#string STR_CERT_TYPE_X509_SHA256_GUID #language en-US "X509_SHA256_GUID" +#string STR_CERT_TYPE_X509_SHA384_GUID #language en-US "X509_SHA384_GUID" +#string STR_CERT_TYPE_X509_SHA512_GUID #language en-US "X509_SHA512_GUID" + +#string STR_LIST_TYPE_RSA2048_SHA256 #language en-US "RSA2048 signature of SHA256 hash" +#string STR_LIST_TYPE_RSA2048 #language en-US "RSA2048" +#string STR_LIST_TYPE_X509 #language en-US "X.509 Certificate" +#string STR_LIST_TYPE_SHA1 #language en-US "SHA1 hash" +#string STR_LIST_TYPE_SHA224 #language en-US "SHA224 hash" +#string STR_LIST_TYPE_SHA256 #language en-US "SHA256 hash" +#string STR_LIST_TYPE_SHA384 #language en-US "SHA384 hash" +#string STR_LIST_TYPE_SHA512 #language en-US "SHA512 hash" +#string STR_LIST_TYPE_SM3 #language en-US "SM3 hash" +#string STR_LIST_TYPE_X509_SHA256 #language en-US "X.509 Certificate SHA256 hash" +#string STR_LIST_TYPE_X509_SHA384 #language en-US "X.509 Certificate SHA384 hash" +#string STR_LIST_TYPE_X509_SHA512 #language en-US "X.509 Certificate SHA512 hash" +#string STR_LIST_TYPE_X509_SM3 #language en-US "X.509 Certificate SM3 hash" +#string STR_LIST_TYPE_UNKNOWN #language en-US "Unknown" + +#string STR_SIGNATURE_LIST_NAME_FORMAT #language en-US "Signature List, Entry-%d" +#string STR_SIGNATURE_DATA_NAME_FORMAT #language en-US "Signature Data, Entry-%d" +#string STR_SIGNATURE_LIST_HELP_FORMAT #language en-US "List Type:\n %s\n\nEntry Number:\n %d" +#string STR_SIGNATURE_DATA_HELP_FORMAT_GUID #language en-US "Owner GUID:\n%s\n" +#string STR_SIGNATURE_DATA_HELP_GUID_SVBOOT #language en-US "(Enrolled by Sovereign Boot Wizard)\n" +#string STR_SIGNATURE_DATA_HELP_GUID_FW #language en-US "(Enrolled by firmware)\n" +#string STR_SIGNATURE_DATA_HELP_GUID_MS #language en-US "(Microsoft owned)\n" + +#string STR_SIGNATURE_DATA_HELP_FORMAT_CN #language en-US "\n%s(%d bytes):\nCN = %s\n" +#string STR_SIGNATURE_DATA_HELP_FORMAT_HASH #language en-US "\n%s(%d bytes):\n%s\n" +#string STR_SIGNATURE_DATA_HELP_FORMAT_TIME #language en-US "\nRevocation Time:\n%s" + +#string STR_SIGNATURE_DATA_HASH_NAME_FORMAT #language en-US "Entry %d: Image %s" +#string STR_SIGNATURE_DATA_CERT_HASH_NAME_FORMAT #language en-US "Entry %d: %s" +#string STR_SIGNATURE_DATA_CERT_NAME_FORMAT #language en-US "Entry %d: %s" +#string STR_SIGNATURE_DATA_RSA_NAME_FORMAT #language en-US "Entry %d: %s key" +#string STR_SIGNATURE_DATA_RSA_HASH_NAME_FORMAT #language en-US "Entry %d: %s" +#string STR_SIGNATURE_DATA_UNKNOWN_NAME_FORMAT #language en-US "Entry %d: %s type" + +#string STR_SIGNATURE_LIST_HASH_NAME_FORMAT #language en-US "List %d: Image %s list" +#string STR_SIGNATURE_LIST_CERT_HASH_NAME_FORMAT #language en-US "List %d: %s list" +#string STR_SIGNATURE_LIST_CERT_NAME_FORMAT #language en-US "List %d: %s list" +#string STR_SIGNATURE_LIST_RSA_NAME_FORMAT #language en-US "List %d: %s key list" +#string STR_SIGNATURE_LIST_RSA_HASH_NAME_FORMAT #language en-US "List %d: %s list" +#string STR_SIGNATURE_LIST_UNKNOWN_NAME_FORMAT #language en-US "List %d: %s type list" + +#string STR_SIGNATURE_DELETE_ALL_CONFIRM #language en-US "Press 'Y' to delete all signature List." + +#string STR_FORM_HASH_DETAILS_TITLE #language en-US "Key and hash details" +#string STR_SV_BOOT_DB_INFO #language en-US "Below is the list of certificates and image hashes enrolled " + "to the Trusted Image and Key Database.\n\n" + "Use below options to delete entries by one with more detailed view.\n\n" + "To delete multiple entries please use Delete Signatures option above." +#string STR_SV_BOOT_DBX_INFO #language en-US "Below is the list of certificates and image hashes enrolled " + "to the Unrusted Image and Key Database.\n\n" + "Use below options to delete entries by one with more detailed view.\n\n" + "To delete multiple entries please use Delete Signatures option above." + +#string STR_DATABASE_EMPTY #language en-US "The database is empty" + +#string STR_SV_BOOT_SIG_LIST_HELP #language en-US "This signature was not added by Sovereing Boot Provisioning Wizard." + +#string STR_SV_BOOT_SIG_LIST_DEFAULT_HELP #language en-US "This signature was not added by Sovereing Boot." + +#string STR_SIGNATURE_TYPE #language en-US "Signature type:" +#string STR_SIGNATURE_DATA_RAW #language en-US "Signature data:" +#string STR_SIGNATURE_DATA_RAW_HEX #language en-US "" + +#string STR_SIGNATURE_DATA_REVOCATION_TIME #language en-US "Revocation time:" +#string STR_SIGNATURE_DATA_REVOCATION_TIME2 #language en-US "" + +#string STR_REMOVE_KEY #language en-US "Remove this key from database" +#string STR_REMOVE_HASH #language en-US "Remove this hash from database" +#string STR_REMOVE_CERT #language en-US "Remove this certificate from database" + +#string STR_BOOTLOADER_LIST_FORM #language en-US "Bootloaders" +#string STR_BOOTLOADER_NAME_FORMAT #language en-US "%s (%s)" +#string STR_BOOTLOADER_HELP_FORMAT #language en-US "%s\n\n%s\n\n%s" +#string STR_NO_BOOTLOADERS_FOUND #language en-US "No bootloaders found" + +#string STR_BOOTLOADER_DETAILS_FORM #language en-US "Bootloader details" +#string STR_BOOTLOADER_HASH_HEX #language en-US "" +#string STR_BL_CERTIFICATE_LSIT #language en-US "Certificate list:" +#string STR_CERT_NO_COMMON_NAME #language en-US "Certificate without common name" + +#string STR_IMAGE_IS_SIGNED #language en-US "Image is signed:" +#string STR_IMAGE_CONTAINS_INVALID_SIGNATURE #language en-US "Image contains invalid signature:" +#string STR_IMAGE_IS_SIGNED_BY_MS #language en-US "Image contains Microsoft signatures:" +#string STR_IMAGE_IS_SIGNED_BY_MS_ONLY #language en-US "Image is signed only by Microsoft certificates:" +#string STR_IMAGE_HASH_IN_DB #language en-US "Image hash present in Trusted Database:" +#string STR_IMAGE_HASH_IN_DBX #language en-US "Image hash present in Untrusted Database:" +#string STR_IMAGE_IS_TRUSTED #language en-US "Image is trusted:" + +#string STR_YES #language en-US "Yes" +#string STR_NO #language en-US "No" +#string STR_UNDECIDED #language en-US "Undecided" + +#string STR_CERT_VALID #language en-US "Certificate is valid:" +#string STR_CERT_IS_MICROSOFT #language en-US "Certificate belongs to Microsoft:" +#string STR_CERT_IN_DB #language en-US "Certificate present in Trusted Database:" +#string STR_CERT_IN_DBX #language en-US "Certificate present in Untrusted Database:" + +#string STR_REMOVE_CERT_FROM_TRUSTED #language en-US "Remove certificate from Trusted Database" +#string STR_REMOVE_CERT_FROM_UNTRUSTED #language en-US "Remove certificate from Untrusted Database" +#string STR_ADD_CERT_TO_TRUSTED #language en-US "Add certificate to Trusted Database" +#string STR_ADD_CERT_TO_UNTRUSTED #language en-US "Add certificate to Untrusted Database" + +#string STR_REMOVE_HASH_FROM_TRUSTED #language en-US "Remove image hash from Trusted Database" +#string STR_REMOVE_HASH_FROM_UNTRUSTED #language en-US "Remove image hash from Untrusted Database" +#string STR_ADD_HASH_TO_TRUSTED #language en-US "Add image hash to Trusted Database" +#string STR_ADD_HASH_TO_UNTRUSTED #language en-US "Add image hash to Untrusted Database" + +#string STR_REMOVE_ALL_IMAGE_DATA #language en-US "Remove all hashes and certificates of this image from all databases" diff --git a/DasharoPayloadPkg/DasharoPayloadPkg.dsc b/DasharoPayloadPkg/DasharoPayloadPkg.dsc index bfcf60bc88..a2004db81a 100644 --- a/DasharoPayloadPkg/DasharoPayloadPkg.dsc +++ b/DasharoPayloadPkg/DasharoPayloadPkg.dsc @@ -803,9 +803,11 @@ OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrd !if $(SOVEREIGN_BOOT_ENABLE) == TRUE DasharoModulePkg/Application/SovereignBootWizard/SovereignBootWizard.inf { - # For Secure Boot use OpenSSL, because MBED TLS may fail AuthenticodeVerify + # For Secure Boot use OpenSSL, because MBED TLS may fail AuthenticodeVerify BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf + # Using FileExplorerLib directly causes form browsing problems.^M + FileExplorerLib|MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.inf } !endif !endif @@ -894,6 +896,7 @@ OrderedCollectionLib|MdePkg/Library/BaseOrderedCollectionRedBlackTreeLib/BaseOrd MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + MdeModulePkg/Universal/FileExplorerDxe/FileExplorerDxe.inf DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.inf CrScreenshotDxe/CrScreenshotDxe.inf { diff --git a/DasharoPayloadPkg/DasharoPayloadPkg.fdf b/DasharoPayloadPkg/DasharoPayloadPkg.fdf index e85a6b66cc..d49aa33944 100644 --- a/DasharoPayloadPkg/DasharoPayloadPkg.fdf +++ b/DasharoPayloadPkg/DasharoPayloadPkg.fdf @@ -152,6 +152,7 @@ INF MdeModulePkg/Universal/MemoryTest/NullMemoryTestDxe/NullMemoryTestDxe.inf INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +INF MdeModulePkg/Universal/FileExplorerDxe/FileExplorerDxe.inf INF DasharoPayloadPkg/BlSupportDxe/BlSupportDxe.inf INF MdeModulePkg/Universal/SmbiosDxe/SmbiosDxe.inf diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 2c9e0c04df..cda50a0099 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -1017,6 +1017,7 @@ MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf + MdeModulePkg/Universal/FileExplorerDxe/FileExplorerDxe.inf OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf OvmfPkg/QemuRamfbDxe/QemuRamfbDxe.inf @@ -1105,6 +1106,8 @@ # For Secure Boot use OpenSSL, because MBED TLS may fail AuthenticodeVerify BaseCryptLib|CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLibCrypto.inf + # Using FileExplorerLib directly causes form browsing problems. + FileExplorerLib|MdeModulePkg/Library/DxeFileExplorerProtocol/DxeFileExplorerProtocol.inf } !endif diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index 390747c290..7fd674e61c 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -348,6 +348,7 @@ INF MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf INF MdeModulePkg/Universal/HiiDatabaseDxe/HiiDatabaseDxe.inf INF MdeModulePkg/Universal/SetupBrowserDxe/SetupBrowserDxe.inf INF MdeModulePkg/Universal/DisplayEngineDxe/DisplayEngineDxe.inf +INF MdeModulePkg/Universal/FileExplorerDxe/FileExplorerDxe.inf INF OvmfPkg/SioBusDxe/SioBusDxe.inf !if $(SOURCE_DEBUG_ENABLE) == FALSE diff --git a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c index 903020ea80..59ceaae6ff 100644 --- a/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c +++ b/SecurityPkg/Library/DxeImageVerificationLib/DxeImageVerificationLib.c @@ -781,6 +781,7 @@ IsCertHashFoundInDbx ( { EFI_STATUS Status; EFI_SIGNATURE_LIST *DbxList; + EFI_SIGNATURE_LIST *DbxWalker; UINTN DbxSize; EFI_SIGNATURE_DATA *CertHash; UINTN CertHashCount; @@ -821,19 +822,20 @@ IsCertHashFoundInDbx ( } } - while ((DbxSize > 0) && (SignatureListSize >= DbxList->SignatureListSize)) { + DbxWalker = DbxList; + while ((DbxSize > 0) && (SignatureListSize >= DbxWalker->SignatureListSize)) { // // Determine Hash Algorithm of Certificate in the forbidden database. // - if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha256Guid)) { + if (CompareGuid (&DbxWalker->SignatureType, &gEfiCertX509Sha256Guid)) { HashAlg = HASHALG_SHA256; - } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha384Guid)) { + } else if (CompareGuid (&DbxWalker->SignatureType, &gEfiCertX509Sha384Guid)) { HashAlg = HASHALG_SHA384; - } else if (CompareGuid (&DbxList->SignatureType, &gEfiCertX509Sha512Guid)) { + } else if (CompareGuid (&DbxWalker->SignatureType, &gEfiCertX509Sha512Guid)) { HashAlg = HASHALG_SHA512; } else { - DbxSize -= DbxList->SignatureListSize; - DbxList = (EFI_SIGNATURE_LIST *)((UINT8 *)DbxList + DbxList->SignatureListSize); + DbxSize -= DbxWalker->SignatureListSize; + DbxWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)DbxWalker + DbxWalker->SignatureListSize); continue; } // @@ -843,9 +845,9 @@ IsCertHashFoundInDbx ( goto Done; } - SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxList->SignatureHeaderSize; - CertHash = (EFI_SIGNATURE_DATA *)((UINT8 *)DbxList + SiglistHeaderSize); - CertHashCount = (DbxList->SignatureListSize - SiglistHeaderSize) / DbxList->SignatureSize; + SiglistHeaderSize = sizeof (EFI_SIGNATURE_LIST) + DbxWalker->SignatureHeaderSize; + CertHash = (EFI_SIGNATURE_DATA *)((UINT8 *)DbxWalker + SiglistHeaderSize); + CertHashCount = (DbxWalker->SignatureListSize - SiglistHeaderSize) / DbxWalker->SignatureSize; for (Index = 0; Index < CertHashCount; Index++) { // // Iterate each Signature Data Node within this CertList for verify. @@ -867,11 +869,11 @@ IsCertHashFoundInDbx ( goto Done; } - CertHash = (EFI_SIGNATURE_DATA *)((UINT8 *)CertHash + DbxList->SignatureSize); + CertHash = (EFI_SIGNATURE_DATA *)((UINT8 *)CertHash + DbxWalker->SignatureSize); } - DbxSize -= DbxList->SignatureListSize; - DbxList = (EFI_SIGNATURE_LIST *)((UINT8 *)DbxList + DbxList->SignatureListSize); + DbxSize -= DbxWalker->SignatureListSize; + DbxWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)DbxWalker + DbxWalker->SignatureListSize); } Status = EFI_SUCCESS;