X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=SecurityPkg%2FVariableAuthenticated%2FSecureBootConfigDxe%2FSecureBootConfigImpl.c;h=f527aa32e647e86ffca8e16529a28a011ddc2930;hb=db959018b650547e9255d95a536b10e956cc5e6f;hp=a685b409e2381afb0bde84ddfd97bd3492cd2090;hpb=96832eefea1025c130979dec9b7da069f77bcd96;p=mirror_edk2.git diff --git a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c index a685b409e2..f527aa32e6 100644 --- a/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c +++ b/SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootConfigImpl.c @@ -1,18 +1,16 @@ /** @file HII Config Access protocol implementation of SecureBoot configuration module. -Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2018 Hewlett Packard Enterprise Development LP
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "SecureBootConfigImpl.h" +#include +#include +#include CHAR16 mSecureBootStorageName[] = L"SECUREBOOT_CONFIGURATION"; @@ -49,8 +47,6 @@ HII_VENDOR_DEVICE_PATH mSecureBootHiiVendorDevicePath = { BOOLEAN mIsEnterSecureBootForm = FALSE; -BOOLEAN mIsSelectedSecureBootModeForm = FALSE; -BOOLEAN mIsSecureBootModeChanged = FALSE; // // OID ASN.1 Value for Hash Algorithms @@ -65,7 +61,6 @@ UINT8 mHashOidValue[] = { }; HASH_TABLE mHash[] = { - { L"SHA1", 20, &mHashOidValue[8], 5, Sha1GetContextSize, Sha1Init, Sha1Update, Sha1Final }, { L"SHA224", 28, &mHashOidValue[13], 9, NULL, NULL, NULL, NULL }, { L"SHA256", 32, &mHashOidValue[22], 9, Sha256GetContextSize, Sha256Init, Sha256Update, Sha256Final}, { L"SHA384", 48, &mHashOidValue[31], 9, Sha384GetContextSize, Sha384Init, Sha384Update, Sha384Final}, @@ -97,6 +92,49 @@ CHAR16* mDerEncodedSuffix[] = { }; 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 +}; + +SECUREBOOT_CONFIG_PRIVATE_DATA *gSecureBootPrivateData = NULL; + +/** + This code cleans up enrolled file by closing file & free related resources attached to + enrolled file. + + @param[in] FileContext FileContext cached in SecureBootConfig driver + +**/ +VOID +CloseEnrolledFile( + IN SECUREBOOT_FILE_CONTEXT *FileContext +) +{ + if (FileContext->FHandle != NULL) { + CloseFile (FileContext->FHandle); + FileContext->FHandle = NULL; + } + + if (FileContext->FileName != NULL){ + FreePool(FileContext->FileName); + FileContext->FileName = NULL; + } + FileContext->FileType = UNKNOWN_FILE_TYPE; + +} + /** This code checks if the FileSuffix is one of the possible DER-encoded certificate suffix. @@ -120,6 +158,61 @@ IsDerEncodeCertificate ( return FALSE; } +/** + This code checks if the file content complies with EFI_VARIABLE_AUTHENTICATION_2 format +The function reads file content but won't open/close given FileHandle. + + @param[in] FileHandle The FileHandle to be checked + + @retval TRUE The content is EFI_VARIABLE_AUTHENTICATION_2 format. + @retval FALSE The content is NOT a EFI_VARIABLE_AUTHENTICATION_2 format. + +**/ +BOOLEAN +IsAuthentication2Format ( + IN EFI_FILE_HANDLE FileHandle +) +{ + EFI_STATUS Status; + EFI_VARIABLE_AUTHENTICATION_2 *Auth2; + BOOLEAN IsAuth2Format; + + IsAuth2Format = FALSE; + + // + // Read the whole file content + // + Status = ReadFileContent( + FileHandle, + (VOID **) &mImageBase, + &mImageSize, + 0 + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + Auth2 = (EFI_VARIABLE_AUTHENTICATION_2 *)mImageBase; + if (Auth2->AuthInfo.Hdr.wCertificateType != WIN_CERT_TYPE_EFI_GUID) { + goto ON_EXIT; + } + + if (CompareGuid(&gEfiCertPkcs7Guid, &Auth2->AuthInfo.CertType)) { + IsAuth2Format = TRUE; + } + +ON_EXIT: + // + // Do not close File. simply check file content + // + if (mImageBase != NULL) { + FreePool (mImageBase); + mImageBase = NULL; + } + + return IsAuth2Format; +} + /** Set Secure Boot option into variable space. @@ -147,167 +240,101 @@ SaveSecureBootVariable ( } /** - Create a time based data payload by concatenating the EFI_VARIABLE_AUTHENTICATION_2 - descriptor with the input data. NO authentication is required in this function. - - @param[in, out] DataSize On input, the size of Data buffer in bytes. - On output, the size of data returned in Data - buffer in bytes. - @param[in, out] Data On input, Pointer to data buffer to be wrapped or - pointer to NULL to wrap an empty payload. - On output, Pointer to the new payload date buffer allocated from pool, - it's caller's responsibility to free the memory when finish using it. - - @retval EFI_SUCCESS Create time based payload successfully. - @retval EFI_OUT_OF_RESOURCES There are not enough memory resourses to create time based payload. - @retval EFI_INVALID_PARAMETER The parameter is invalid. - @retval Others Unexpected error happens. + 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 -CreateTimeBasedPayload ( - IN OUT UINTN *DataSize, - IN OUT UINT8 **Data - ) +CheckX509Certificate ( + IN SECUREBOOT_FILE_CONTEXT* X509FileContext, + OUT ENROLL_KEY_ERROR* Error +) { - EFI_STATUS Status; - UINT8 *NewData; - UINT8 *Payload; - UINTN PayloadSize; - EFI_VARIABLE_AUTHENTICATION_2 *DescriptorData; - UINTN DescriptorSize; - EFI_TIME Time; - - if (Data == NULL || DataSize == NULL) { + 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; + // - // In Setup mode or Custom mode, the variable does not need to be signed but the - // parameters to the SetVariable() call still need to be prepared as authenticated - // variable. So we create EFI_VARIABLE_AUTHENTICATED_2 descriptor without certificate - // data in it. + // Parse the file's postfix. Only support DER encoded X.509 certificate files. // - Payload = *Data; - PayloadSize = *DataSize; - - DescriptorSize = OFFSET_OF (EFI_VARIABLE_AUTHENTICATION_2, AuthInfo) + OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); - NewData = (UINT8*) AllocateZeroPool (DescriptorSize + PayloadSize); - if (NewData == NULL) { - return EFI_OUT_OF_RESOURCES; + NameLength = StrLen (X509FileContext->FileName); + if (NameLength <= 4) { + DEBUG ((DEBUG_ERROR, "Wrong X509 NameLength\n")); + *Error = Unsupported_Type; + return EFI_INVALID_PARAMETER; } - - if ((Payload != NULL) && (PayloadSize != 0)) { - CopyMem (NewData + DescriptorSize, Payload, PayloadSize); + 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)); - DescriptorData = (EFI_VARIABLE_AUTHENTICATION_2 *) (NewData); - - ZeroMem (&Time, sizeof (EFI_TIME)); - Status = gRT->GetTime (&Time, NULL); + // + // Read the certificate file content + // + Status = ReadFileContent (X509FileContext->FHandle, (VOID**) &X509Data, &X509DataSize, 0); if (EFI_ERROR (Status)) { - FreePool(NewData); - return Status; + DEBUG ((DEBUG_ERROR, "Error occured while reading the file.\n")); + goto ON_EXIT; } - Time.Pad1 = 0; - Time.Nanosecond = 0; - Time.TimeZone = 0; - Time.Daylight = 0; - Time.Pad2 = 0; - CopyMem (&DescriptorData->TimeStamp, &Time, sizeof (EFI_TIME)); - - DescriptorData->AuthInfo.Hdr.dwLength = OFFSET_OF (WIN_CERTIFICATE_UEFI_GUID, CertData); - DescriptorData->AuthInfo.Hdr.wRevision = 0x0200; - DescriptorData->AuthInfo.Hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID; - CopyGuid (&DescriptorData->AuthInfo.CertType, &gEfiCertPkcs7Guid); - if (Payload != NULL) { - FreePool(Payload); + // + // Parse the public key context. + // + if (RsaGetPublicKeyFromX509 (X509Data, X509DataSize, &X509PubKey) == FALSE) { + DEBUG ((DEBUG_ERROR, "Error occured while parsing the pubkey from certificate.\n")); + Status = EFI_INVALID_PARAMETER; + *Error = Unsupported_Type; + goto ON_EXIT; } - *DataSize = DescriptorSize + PayloadSize; - *Data = NewData; - return EFI_SUCCESS; -} - -/** - Internal helper function to delete a Variable given its name and GUID, NO authentication - required. - - @param[in] VariableName Name of the Variable. - @param[in] VendorGuid GUID of the Variable. - - @retval EFI_SUCCESS Variable deleted successfully. - @retval Others The driver failed to start the device. - -**/ -EFI_STATUS -DeleteVariable ( - IN CHAR16 *VariableName, - IN EFI_GUID *VendorGuid - ) -{ - EFI_STATUS Status; - VOID* Variable; - UINT8 *Data; - UINTN DataSize; - UINT32 Attr; - - GetVariable2 (VariableName, VendorGuid, &Variable, NULL); - if (Variable == NULL) { - return EFI_SUCCESS; + // + // 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); } - FreePool (Variable); - - Data = NULL; - DataSize = 0; - Attr = EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS - | EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS; - Status = CreateTimeBasedPayload (&DataSize, &Data); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Fail to create time-based data payload: %r", Status)); - return Status; + ON_EXIT: + if (X509Data != NULL) { + FreePool (X509Data); } - Status = gRT->SetVariable ( - VariableName, - VendorGuid, - Attr, - DataSize, - Data - ); - if (Data != NULL) { - FreePool (Data); - } return Status; } -/** - - Set the platform secure boot mode into "Custom" or "Standard" mode. - - @param[in] SecureBootMode New secure boot mode: STANDARD_SECURE_BOOT_MODE or - CUSTOM_SECURE_BOOT_MODE. - - @return EFI_SUCCESS The platform has switched to the special mode successfully. - @return other Fail to operate the secure boot mode. - -**/ -EFI_STATUS -SetSecureBootMode ( - IN UINT8 SecureBootMode - ) -{ - return gRT->SetVariable ( - EFI_CUSTOM_MODE_NAME, - &gEfiCustomModeEnableGuid, - EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, - sizeof (UINT8), - &SecureBootMode - ); -} - /** Generate the PK signature list from the X509 Certificate storing file (.cer) @@ -315,7 +342,7 @@ SetSecureBootMode ( @param[out] PkCert Point to the data buffer to store the signature list. @return EFI_UNSUPPORTED Unsupported Key Length. - @return EFI_OUT_OF_RESOURCES There are not enough memory resourses to form the signature list. + @return EFI_OUT_OF_RESOURCES There are not enough memory resources to form the signature list. **/ EFI_STATUS @@ -402,12 +429,6 @@ EnrollPlatformKey ( UINT32 Attr; UINTN DataSize; EFI_SIGNATURE_LIST *PkCert; - UINT16* FilePostFix; - UINTN NameLength; - - if (Private->FileContext->FileName == NULL) { - return EFI_INVALID_PARAMETER; - } PkCert = NULL; @@ -417,22 +438,7 @@ EnrollPlatformKey ( } // - // Parse the file's postfix. Only support DER encoded X.509 certificate files. - // - NameLength = StrLen (Private->FileContext->FileName); - if (NameLength <= 4) { - return EFI_INVALID_PARAMETER; - } - FilePostFix = Private->FileContext->FileName + NameLength - 4; - if (!IsDerEncodeCertificate(FilePostFix)) { - DEBUG ((EFI_D_ERROR, "Unsupported file type, only DER encoded certificate (%s) is supported.", mSupportX509Suffix)); - return EFI_INVALID_PARAMETER; - } - DEBUG ((EFI_D_INFO, "FileName= %s\n", Private->FileContext->FileName)); - DEBUG ((EFI_D_INFO, "FilePostFix = %s\n", FilePostFix)); - - // - // Prase the selected PK file and generature PK certificate list. + // Prase the selected PK file and generate PK certificate list. // Status = CreatePkX509SignatureList ( Private->FileContext->FHandle, @@ -475,37 +481,8 @@ ON_EXIT: FreePool(PkCert); } - if (Private->FileContext->FHandle != NULL) { - CloseFile (Private->FileContext->FHandle); - Private->FileContext->FHandle = NULL; - } - - return Status; -} - -/** - Remove the PK variable. - - @retval EFI_SUCCESS Delete PK successfully. - @retval Others Could not allow to delete PK. - -**/ -EFI_STATUS -DeletePlatformKey ( - VOID -) -{ - EFI_STATUS Status; - - Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); - if (EFI_ERROR (Status)) { - return Status; - } + CloseEnrolledFile(Private->FileContext); - Status = DeleteVariable ( - EFI_PLATFORM_KEY_NAME, - &gEfiGlobalVariableGuid - ); return Status; } @@ -655,9 +632,7 @@ EnrollRsa2048ToKek ( ON_EXIT: - CloseFile (Private->FileContext->FHandle); - Private->FileContext->FHandle = NULL; - Private->FileContext->FileName = NULL; + CloseEnrolledFile(Private->FileContext); if (Private->SignatureGUID != NULL) { FreePool (Private->SignatureGUID); @@ -778,9 +753,7 @@ EnrollX509ToKek ( ON_EXIT: - CloseFile (Private->FileContext->FHandle); - Private->FileContext->FileName = NULL; - Private->FileContext->FHandle = NULL; + CloseEnrolledFile(Private->FileContext); if (Private->SignatureGUID != NULL) { FreePool (Private->SignatureGUID); @@ -814,7 +787,7 @@ EnrollKeyExchangeKey ( EFI_STATUS Status; UINTN NameLength; - if ((Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) { + if ((Private->FileContext->FHandle == NULL) || (Private->FileContext->FileName == NULL) || (Private->SignatureGUID == NULL)) { return EFI_INVALID_PARAMETER; } @@ -837,6 +810,11 @@ EnrollKeyExchangeKey ( } else if (CompareMem (FilePostFix, L".pbk",4) == 0) { return EnrollRsa2048ToKek (Private); } else { + // + // File type is wrong, simply close it + // + CloseEnrolledFile(Private->FileContext); + return EFI_INVALID_PARAMETER; } } @@ -948,9 +926,7 @@ EnrollX509toSigDB ( ON_EXIT: - CloseFile (Private->FileContext->FHandle); - Private->FileContext->FileName = NULL; - Private->FileContext->FHandle = NULL; + CloseEnrolledFile(Private->FileContext); if (Private->SignatureGUID != NULL) { FreePool (Private->SignatureGUID); @@ -1017,7 +993,7 @@ IsSignatureFoundInDatabase ( } // - // Enumerate all signature data in SigDB to check if executable's signature exists. + // Enumerate all signature data in SigDB to check if signature exists for executable. // CertList = (EFI_SIGNATURE_LIST *) Data; while ((DataSize > 0) && (DataSize >= CertList->SignatureListSize)) { @@ -1241,7 +1217,7 @@ Done: /** Check whether the signature list exists in given variable data. - It searches the signature list for the ceritificate hash by CertType. + 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. @@ -1508,9 +1484,8 @@ EnrollX509HashtoSigDB ( } ON_EXIT: - CloseFile (Private->FileContext->FHandle); - Private->FileContext->FileName = NULL; - Private->FileContext->FHandle = NULL; + + CloseEnrolledFile(Private->FileContext); if (Private->SignatureGUID != NULL) { FreePool (Private->SignatureGUID); @@ -1593,6 +1568,54 @@ ON_EXIT: return IsFound; } +/** + Reads contents of a PE/COFF image in memory buffer. + + Caution: This function may receive untrusted input. + PE/COFF image is external input, so this function will make sure the PE/COFF image content + read is within the image buffer. + + @param FileHandle Pointer to the file handle to read the PE/COFF image. + @param FileOffset Offset into the PE/COFF image to begin the read operation. + @param ReadSize On input, the size in bytes of the requested read operation. + On output, the number of bytes actually read. + @param Buffer Output buffer that contains the data read from the PE/COFF image. + + @retval EFI_SUCCESS The specified portion of the PE/COFF image was read and the size +**/ +EFI_STATUS +EFIAPI +SecureBootConfigImageRead ( + IN VOID *FileHandle, + IN UINTN FileOffset, + IN OUT UINTN *ReadSize, + OUT VOID *Buffer + ) +{ + UINTN EndPosition; + + if (FileHandle == NULL || ReadSize == NULL || Buffer == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (MAX_ADDRESS - FileOffset < *ReadSize) { + return EFI_INVALID_PARAMETER; + } + + EndPosition = FileOffset + *ReadSize; + if (EndPosition > mImageSize) { + *ReadSize = (UINT32)(mImageSize - FileOffset); + } + + if (FileOffset >= mImageSize) { + *ReadSize = 0; + } + + CopyMem (Buffer, (UINT8 *)((UINTN) FileHandle + FileOffset), *ReadSize); + + return EFI_SUCCESS; +} + /** Load PE/COFF image information into internal buffer and check its validity. @@ -1609,9 +1632,28 @@ LoadPeImage ( EFI_IMAGE_DOS_HEADER *DosHdr; EFI_IMAGE_NT_HEADERS32 *NtHeader32; EFI_IMAGE_NT_HEADERS64 *NtHeader64; + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext; + EFI_STATUS Status; NtHeader32 = NULL; NtHeader64 = NULL; + + ZeroMem (&ImageContext, sizeof (ImageContext)); + ImageContext.Handle = (VOID *) mImageBase; + ImageContext.ImageRead = (PE_COFF_LOADER_READ_FILE) SecureBootConfigImageRead; + + // + // Get information about the image being loaded + // + Status = PeCoffLoaderGetImageInfo (&ImageContext); + if (EFI_ERROR (Status)) { + // + // The information can't be got from the invalid PeImage + // + DEBUG ((DEBUG_INFO, "SecureBootConfigDxe: PeImage invalid. \n")); + return Status; + } + // // Read the Dos header // @@ -1673,6 +1715,9 @@ LoadPeImage ( Calculate hash of Pe/Coff image based on the authenticode image hashing in PE/COFF Specification 8.0 Appendix A + Notes: PE/COFF image has been checked by BasePeCoffLib PeCoffLoaderGetImageInfo() in + the function LoadPeImage (). + @param[in] HashAlg Hash algorithm type. @retval TRUE Successfully hash image. @@ -1685,7 +1730,6 @@ HashPeImage ( ) { BOOLEAN Status; - UINT16 Magic; EFI_IMAGE_SECTION_HEADER *Section; VOID *HashCtx; UINTN CtxSize; @@ -1700,7 +1744,7 @@ HashPeImage ( SectionHeader = NULL; Status = FALSE; - if ((HashAlg != HASHALG_SHA1) && (HashAlg != HASHALG_SHA256)) { + if (HashAlg != HASHALG_SHA256) { return FALSE; } @@ -1709,13 +1753,8 @@ HashPeImage ( // ZeroMem (mImageDigest, MAX_DIGEST_SIZE); - if (HashAlg == HASHALG_SHA1) { - mImageDigestSize = SHA1_DIGEST_SIZE; - mCertType = gEfiCertSha1Guid; - } else if (HashAlg == HASHALG_SHA256) { - mImageDigestSize = SHA256_DIGEST_SIZE; - mCertType = gEfiCertSha256Guid; - } + mImageDigestSize = SHA256_DIGEST_SIZE; + mCertType = gEfiCertSha256Guid; CtxSize = mHash[HashAlg].GetContextSize(); @@ -1733,36 +1772,22 @@ HashPeImage ( // Measuring PE/COFF Image Header; // But CheckSum field and SECURITY data directory (certificate) are excluded // - if (mNtHeader.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { - // - // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value - // in the PE/COFF Header. If the MachineType is Itanium(IA64) and the - // Magic value in the OptionalHeader is EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - // then override the magic value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - // - Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC; - } else { - // - // Get the magic value from the PE/COFF Optional Header - // - Magic = mNtHeader.Pe32->OptionalHeader.Magic; - } // // 3. Calculate the distance from the base of the image header to the image checksum address. // 4. Hash the image header from its base to beginning of the image checksum. // HashBase = mImageBase; - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset. // - HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - HashBase); + HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.CheckSum) - (UINTN) HashBase; } else { // // Use PE32+ offset. // - HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - HashBase); + HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.CheckSum) - (UINTN) HashBase; } Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); @@ -1774,18 +1799,18 @@ HashPeImage ( // 6. Get the address of the beginning of the Cert Directory. // 7. Hash everything from the end of the checksum to the start of the Cert Directory. // - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset. // HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.CheckSum + sizeof (UINT32); - HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); + HashSize = (UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase; } else { // // Use PE32+ offset. // HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.CheckSum + sizeof (UINT32); - HashSize = (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - HashBase); + HashSize = (UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY]) - (UINTN) HashBase; } Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); @@ -1796,18 +1821,18 @@ HashPeImage ( // 8. Skip over the Cert Directory. (It is sizeof(IMAGE_DATA_DIRECTORY) bytes.) // 9. Hash everything from the end of the Cert Directory to the end of image header. // - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset // HashBase = (UINT8 *) &mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; - HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase); + HashSize = mNtHeader.Pe32->OptionalHeader.SizeOfHeaders - ((UINTN) (&mNtHeader.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN) mImageBase); } else { // // Use PE32+ offset. // HashBase = (UINT8 *) &mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]; - HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - (UINTN) ((UINT8 *) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - mImageBase); + HashSize = mNtHeader.Pe32Plus->OptionalHeader.SizeOfHeaders - ((UINTN) (&mNtHeader.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_SECURITY + 1]) - (UINTN) mImageBase); } Status = mHash[HashAlg].HashUpdate(HashCtx, HashBase, HashSize); @@ -1817,7 +1842,7 @@ HashPeImage ( // // 10. Set the SUM_OF_BYTES_HASHED to the size of the header. // - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset. // @@ -1891,7 +1916,7 @@ HashPeImage ( // if (mImageSize > SumOfBytesHashed) { HashBase = mImageBase + SumOfBytesHashed; - if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { + if (mNtHeader.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) { // // Use PE32 offset. // @@ -1987,7 +2012,7 @@ HashPeImageByType ( } /** - Enroll a new executable's signature into Signature Database. + 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 @@ -2001,36 +2026,25 @@ HashPeImageByType ( **/ EFI_STATUS -EnrollImageSignatureToSigDB ( +EnrollAuthentication2Descriptor ( IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, IN CHAR16 *VariableName ) { EFI_STATUS Status; - EFI_SIGNATURE_LIST *SigDBCert; - EFI_SIGNATURE_DATA *SigDBCertData; VOID *Data; UINTN DataSize; - UINTN SigDBSize; UINT32 Attr; - WIN_CERTIFICATE_UEFI_GUID *GuidCertData; Data = NULL; - GuidCertData = NULL; + // + // DBT only support DER-X509 Cert Enrollment + // if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) { return EFI_UNSUPPORTED; } - // - // Form the SigDB certificate list. - // Format the data item into EFI_SIGNATURE_LIST type. - // - // We need to parse executable's signature data from specified signed executable file. - // In current implementation, we simply trust the pass-in signed executable file. - // In reality, it's OS's responsibility to verify the signed executable file. - // - // // Read the whole file content // @@ -2045,16 +2059,128 @@ EnrollImageSignatureToSigDB ( } ASSERT (mImageBase != NULL); - Status = LoadPeImage (); - if (EFI_ERROR (Status)) { + 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; } - if (mSecDataDir->SizeOfCert == 0) { - if (!HashPeImage (HASHALG_SHA256)) { - Status = EFI_SECURITY_VIOLATION; - 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); + + if (Data != NULL) { + FreePool (Data); + } + + if (mImageBase != NULL) { + FreePool (mImageBase); + mImageBase = NULL; + } + + 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 SECUREBOOT_CONFIG_PRIVATE_DATA *Private, + IN CHAR16 *VariableName + ) +{ + EFI_STATUS Status; + EFI_SIGNATURE_LIST *SigDBCert; + EFI_SIGNATURE_DATA *SigDBCertData; + VOID *Data; + UINTN DataSize; + UINTN SigDBSize; + UINT32 Attr; + WIN_CERTIFICATE_UEFI_GUID *GuidCertData; + + Data = NULL; + GuidCertData = NULL; + + if (StrCmp (VariableName, EFI_IMAGE_SECURITY_DATABASE2) == 0) { + return EFI_UNSUPPORTED; + } + + // + // Form the SigDB certificate list. + // Format the data item into EFI_SIGNATURE_LIST type. + // + // We need to parse 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 = ReadFileContent( + Private->FileContext->FHandle, + (VOID **) &mImageBase, + &mImageSize, + 0 + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + ASSERT (mImageBase != NULL); + + Status = LoadPeImage (); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + if (mSecDataDir->SizeOfCert == 0) { + if (!HashPeImage (HASHALG_SHA256)) { + Status = EFI_SECURITY_VIOLATION; + goto ON_EXIT; + } } else { // @@ -2155,9 +2281,7 @@ EnrollImageSignatureToSigDB ( ON_EXIT: - CloseFile (Private->FileContext->FHandle); - Private->FileContext->FHandle = NULL; - Private->FileContext->FileName = NULL; + CloseEnrolledFile(Private->FileContext); if (Private->SignatureGUID != NULL) { FreePool (Private->SignatureGUID); @@ -2221,9 +2345,11 @@ EnrollSignatureDatabase ( // Supports DER-encoded X509 certificate. // return EnrollX509toSigDB (Private, VariableName); + } else if (IsAuthentication2Format(Private->FileContext->FHandle)){ + return EnrollAuthentication2Descriptor(Private, VariableName); + } else { + return EnrollImageSignatureToSigDB (Private, VariableName); } - - return EnrollImageSignatureToSigDB (Private, VariableName); } /** @@ -2610,7 +2736,7 @@ ON_EXIT: } /** - Delete a signature entry from siganture database. + 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. @@ -2620,7 +2746,7 @@ ON_EXIT: @param[in] QuestionIdBase Base question id of the signature list. @param[in] DeleteIndex Signature index to delete. - @retval EFI_SUCCESS Delete siganture successfully. + @retval EFI_SUCCESS Delete signature successfully. @retval EFI_NOT_FOUND Can't find the signature item, @retval EFI_OUT_OF_RESOURCES Could not allocate needed resources. **/ @@ -2811,275 +2937,244 @@ ON_EXIT: } /** - Perform secure boot mode transition from User Mode by setting AuditMode - or DeployedMode variable. + This function to delete signature list or data, according by DelType. - @param[in] NewMode New secure boot mode. + @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 Secure Boot mode transition is successful. + @retval EFI_SUCCESS Success to update the signature list page + @retval EFI_OUT_OF_RESOURCES Unable to allocate required resources. **/ EFI_STATUS -TransitionFromUserMode( - IN UINT8 NewMode +DeleteSignatureEx ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData, + IN SIGNATURE_DELETE_TYPE DelType, + IN UINT32 CheckedCount ) { - UINT8 Data; - EFI_STATUS Status; - - if (NewMode == SECURE_BOOT_MODE_AUDIT_MODE) { - Data = 1; - Status = gRT->SetVariable( - EFI_AUDIT_MODE_NAME, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - sizeof(UINT8), - &Data - ); - return Status; - } else if (NewMode == SECURE_BOOT_MODE_DEPLOYED_MODE) { - Data = 1; - Status = gRT->SetVariable( - EFI_DEPLOYED_MODE_NAME, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - sizeof(UINT8), - &Data - ); - return Status; + 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; + + 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 if (PrivateData->VariableName == Variable_DBT) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2); + } else { + goto ON_EXIT; } - // - // Other case do nothing here. May Goto enroll PK page. - // - return EFI_SUCCESS; -} - -/** - Perform secure boot mode transition from Setup Mode by setting AuditMode - variable. + Status = gRT->GetVariable ( + VariableName, + &gEfiImageSecurityDatabaseGuid, + &VariableAttr, + &VariableDataSize, + VariableData + ); + if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { + goto ON_EXIT; + } - @param[in] NewMode New secure boot mode. + VariableData = AllocateZeroPool (VariableDataSize); + if (VariableData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } - @retval EFI_SUCCESS Secure Boot mode transition is successful. -**/ -EFI_STATUS -TransitionFromSetupMode( - IN UINT8 NewMode - ) -{ - UINT8 Data; - EFI_STATUS Status; - - Status = EFI_INVALID_PARAMETER; - - if (NewMode == SECURE_BOOT_MODE_AUDIT_MODE) { - Data = 1; - Status = gRT->SetVariable( - EFI_AUDIT_MODE_NAME, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - sizeof(UINT8), - &Data - ); - return Status; + Status = gRT->GetVariable ( + VariableName, + &gEfiImageSecurityDatabaseGuid, + &VariableAttr, + &VariableDataSize, + VariableData + ); + if (EFI_ERROR (Status)) { + goto ON_EXIT; } - // - // Other case do nothing here. May Goto enroll PK page. - // - return EFI_SUCCESS; -} + Status = SetSecureBootMode (CUSTOM_SECURE_BOOT_MODE); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } -/** - Perform secure boot mode transition from Audit Mode. Nothing is done here, - should goto enroll PK page. + NewVariableData = AllocateZeroPool (VariableDataSize); + if (NewVariableData == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto ON_EXIT; + } - @param[in] NewMode New secure boot mode. + 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; - @retval EFI_SUCCESS Secure Boot mode transition is successful. -**/ -EFI_STATUS -TransitionFromAuditMode( - IN UINT8 NewMode - ) -{ - // - // Other case do nothing here. Should Goto enroll PK page. - // - return EFI_SUCCESS; -} + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + ListIndex++; + } -/** - Perform secure boot mode transition from Deployed Mode by setting Deployed Mode - variable to 0. + // + // 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; - @param[in] NewMode New secure boot mode. + 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); + } + } - @retval EFI_SUCCESS Secure Boot mode transition is successful. -**/ -EFI_STATUS -TransitionFromDeployedMode( - IN UINT8 NewMode - ) -{ - UINT8 Data; - EFI_STATUS Status; - - // - // Platform specific logic. when physical presence, Allow to set DeployedMode =:0 - // to switch back to UserMode - // - if (NewMode == SECURE_BOOT_MODE_USER_MODE) { - Data = 0; - Status = gRT->SetVariable( - EFI_DEPLOYED_MODE_NAME, - &gEfiGlobalVariableGuid, - EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS, - sizeof(UINT8), - &Data - ); - DEBUG((EFI_D_INFO, "DeployedMode Status %x\n", Status)); - return Status; - } - return EFI_SUCCESS; -} + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); -/** - Perform main secure boot mode transition. + // + // Copy remaining data, maybe 0. + // + CopyMem((UINT8 *)NewVariableData + Offset, ListWalker, RemainingSize); + Offset += RemainingSize; - @param[in] CurMode New secure boot mode. - @param[in] NewMode New secure boot mode. + VariableDataSize = Offset; + } - @retval EFI_SUCCESS Secure Boot mode transition is successful. -**/ -EFI_STATUS -SecureBootModeTransition( - IN UINT8 CurMode, - IN UINT8 NewMode - ) -{ - EFI_STATUS Status; + if ((VariableAttr & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) { + Status = CreateTimeBasedPayload (&VariableDataSize, &NewVariableData); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Fail to create time-based data payload: %r", Status)); + goto ON_EXIT; + } + } - // - // Set platform to be customized mode to ensure platform specific mode switch sucess - // - Status = SetSecureBootMode(CUSTOM_SECURE_BOOT_MODE); + Status = gRT->SetVariable ( + VariableName, + &gEfiImageSecurityDatabaseGuid, + VariableAttr, + VariableDataSize, + NewVariableData + ); if (EFI_ERROR (Status)) { - return Status; + DEBUG ((DEBUG_ERROR, "Failed to set variable, Status = %r", Status)); + goto ON_EXIT; } - // - // SecureBootMode transition - // - switch (CurMode) { - case SECURE_BOOT_MODE_USER_MODE: - Status = TransitionFromUserMode(NewMode); - break; - - case SECURE_BOOT_MODE_SETUP_MODE: - Status = TransitionFromSetupMode(NewMode); - break; - - case SECURE_BOOT_MODE_AUDIT_MODE: - Status = TransitionFromAuditMode(NewMode); - break; - - case SECURE_BOOT_MODE_DEPLOYED_MODE: - Status = TransitionFromDeployedMode(NewMode); - break; - - default: - Status = EFI_INVALID_PARAMETER; - ASSERT(FALSE); - } +ON_EXIT: + SECUREBOOT_FREE_NON_NULL (VariableData); + SECUREBOOT_FREE_NON_NULL (NewVariableData); return Status; } /** - Get current secure boot mode by retrieve data from SetupMode/AuditMode/DeployedMode. - @param[out] SecureBootMode Current secure boot mode. + Update SecureBoot strings based on new Secure Boot Mode State. String includes STR_SECURE_BOOT_STATE_CONTENT + and STR_CUR_SECURE_BOOT_MODE_CONTENT. + + @param[in] PrivateData Module's private data. + + @return EFI_SUCCESS Update secure boot strings successfully. + @return other Fail to update secure boot strings. **/ -VOID -ExtractSecureBootModeFromVariable( - OUT UINT8 *SecureBootMode +EFI_STATUS +UpdateSecureBootString( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private ) { - UINT8 *SetupMode; - UINT8 *AuditMode; - UINT8 *DeployedMode; + UINT8 *SecureBoot; - SetupMode = NULL; - AuditMode = NULL; - DeployedMode = NULL; + SecureBoot = NULL; // - // Get AuditMode/DeployedMode from variable + // Get current secure boot state. // - GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL); - GetVariable2 (EFI_AUDIT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&AuditMode, NULL); - GetVariable2 (EFI_DEPLOYED_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&DeployedMode, NULL); - if (SetupMode != NULL && AuditMode != NULL && DeployedMode != NULL) { - if (*SetupMode == 0 && *AuditMode == 0 && *DeployedMode == 0) { - // - // User Mode - // - *SecureBootMode = SECURE_BOOT_MODE_USER_MODE; - } else if (*SetupMode == 1 && *AuditMode == 0 && *DeployedMode == 0) { - // - // Setup Mode - // - *SecureBootMode = SECURE_BOOT_MODE_SETUP_MODE; - } else if (*SetupMode == 1 && *AuditMode == 1 && *DeployedMode == 0) { - // - // Audit Mode - // - *SecureBootMode = SECURE_BOOT_MODE_AUDIT_MODE; - } else if (*SetupMode == 0 && *AuditMode == 0 && *DeployedMode == 1) { - // - // Deployed Mode - // - *SecureBootMode = SECURE_BOOT_MODE_DEPLOYED_MODE; - } else { - ASSERT(FALSE); - } - }else { - ASSERT(FALSE); + GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL); + if (SecureBoot == NULL) { + return EFI_NOT_FOUND; } - if (SetupMode != NULL) { - FreePool (SetupMode); - } - if (DeployedMode != NULL) { - FreePool (DeployedMode); - } - if (AuditMode != NULL) { - FreePool (AuditMode); + if (*SecureBoot == SECURE_BOOT_MODE_ENABLE) { + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL); + } else { + HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL); } + + FreePool(SecureBoot); + + return EFI_SUCCESS; } /** This function extracts configuration from variable. + @param[in] Private Point to SecureBoot configuration driver private data. @param[in, out] ConfigData Point to SecureBoot configuration private data. **/ VOID SecureBootExtractConfigFromVariable ( + IN SECUREBOOT_CONFIG_PRIVATE_DATA *Private, IN OUT SECUREBOOT_CONFIGURATION *ConfigData ) { UINT8 *SecureBootEnable; + UINT8 *SetupMode; UINT8 *SecureBootMode; EFI_TIME CurrTime; SecureBootEnable = NULL; + SetupMode = NULL; SecureBootMode = NULL; // - // Initilize the Date and Time using system time. + // Initialize the Date and Time using system time. // ConfigData->CertificateFormat = HASHALG_RAW; ConfigData->AlwaysRevocation = TRUE; @@ -3090,20 +3185,10 @@ SecureBootExtractConfigFromVariable ( ConfigData->RevocationTime.Hour = CurrTime.Hour; ConfigData->RevocationTime.Minute = CurrTime.Minute; ConfigData->RevocationTime.Second = 0; - - // - // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable - // Checkbox. - // - ConfigData->AttemptSecureBoot = FALSE; - GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL); - if (SecureBootEnable == NULL) { - ConfigData->HideSecureBoot = TRUE; + if (Private->FileContext->FHandle != NULL) { + ConfigData->FileEnrollType = Private->FileContext->FileType; } else { - ConfigData->HideSecureBoot = FALSE; - if ((*SecureBootEnable) == SECURE_BOOT_ENABLE) { - ConfigData->AttemptSecureBoot = TRUE; - } + ConfigData->FileEnrollType = UNKNOWN_FILE_TYPE; } // @@ -3116,33 +3201,51 @@ SecureBootExtractConfigFromVariable ( } // - // Get the SecureBootMode from CustomMode variable. + // If there is no PK then the Delete Pk button will be gray. // - GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL); - if (SecureBootMode == NULL) { - ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE; - } else { - ConfigData->SecureBootMode = *(SecureBootMode); + GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL); + if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) { + ConfigData->HasPk = FALSE; + } else { + ConfigData->HasPk = TRUE; } // - // Extact current Secure Boot Mode + // Check SecureBootEnable & Pk status, fix the inconsistency. + // If the SecureBootEnable Variable doesn't exist, hide the SecureBoot Enable/Disable + // Checkbox. // - ExtractSecureBootModeFromVariable(&ConfigData->CurSecureBootMode); + ConfigData->AttemptSecureBoot = FALSE; + GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL); // - // If there is no PK then the Delete Pk button will be gray. + // Fix Pk and SecureBootEnable inconsistency // - if (ConfigData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE || ConfigData->CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE) { - ConfigData->HasPk = FALSE; - } else { - ConfigData->HasPk = TRUE; + if ((SetupMode != NULL) && (*SetupMode) == USER_MODE) { + ConfigData->HideSecureBoot = FALSE; + if ((SecureBootEnable != NULL) && (*SecureBootEnable == SECURE_BOOT_ENABLE)) { + ConfigData->AttemptSecureBoot = TRUE; + } + } else { + ConfigData->HideSecureBoot = TRUE; + } + + // + // Get the SecureBootMode from CustomMode variable. + // + GetVariable2 (EFI_CUSTOM_MODE_NAME, &gEfiCustomModeEnableGuid, (VOID**)&SecureBootMode, NULL); + if (SecureBootMode == NULL) { + ConfigData->SecureBootMode = STANDARD_SECURE_BOOT_MODE; + } else { + ConfigData->SecureBootMode = *(SecureBootMode); } if (SecureBootEnable != NULL) { FreePool (SecureBootEnable); } - + if (SetupMode != NULL) { + FreePool (SetupMode); + } if (SecureBootMode != NULL) { FreePool (SecureBootMode); } @@ -3191,7 +3294,6 @@ SecureBootExtractConfig ( EFI_STRING ConfigRequestHdr; SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData; BOOLEAN AllocatedRequest; - UINT8 *SecureBoot; if (Progress == NULL || Results == NULL) { return EFI_INVALID_PARAMETER; @@ -3201,7 +3303,6 @@ SecureBootExtractConfig ( ConfigRequestHdr = NULL; ConfigRequest = NULL; Size = 0; - SecureBoot = NULL; ZeroMem (&Configuration, sizeof (Configuration)); PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); @@ -3211,35 +3312,12 @@ SecureBootExtractConfig ( return EFI_NOT_FOUND; } - // - // Get Configuration from Variable. - // - SecureBootExtractConfigFromVariable (&Configuration); - - // - // Get current secure boot state. - // - GetVariable2 (EFI_SECURE_BOOT_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SecureBoot, NULL); - - if (SecureBoot != NULL && *SecureBoot == SECURE_BOOT_MODE_ENABLE) { - HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Enabled", NULL); - } else { - HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SECURE_BOOT_STATE_CONTENT), L"Disabled", NULL); - } + ZeroMem(&Configuration, sizeof(SECUREBOOT_CONFIGURATION)); // - // Get current secure boot mode + // Get Configuration from Variable. // - DEBUG((EFI_D_INFO, "Configuration.CurSecureBootMode %d\n", Configuration.CurSecureBootMode)); - if (Configuration.CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE) { - HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"UserMode", NULL); - } else if (Configuration.CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE) { - HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"SetupMode", NULL); - } else if (Configuration.CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE) { - HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"AuditMode", NULL); - } else if (Configuration.CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE) { - HiiSetString (PrivateData->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"DeployedMode", NULL); - } + SecureBootExtractConfigFromVariable (PrivateData, &Configuration); BufferSize = sizeof (SECUREBOOT_CONFIGURATION); ConfigRequest = Request; @@ -3285,10 +3363,6 @@ SecureBootExtractConfig ( *Progress = Request + StrLen (Request); } - if (SecureBoot != NULL) { - FreePool (SecureBoot); - } - return Status; } @@ -3318,10 +3392,10 @@ SecureBootRouteConfig ( OUT EFI_STRING *Progress ) { - UINT8 *SecureBootEnable; - SECUREBOOT_CONFIGURATION IfrNvData; - UINTN BufferSize; - EFI_STATUS Status; + SECUREBOOT_CONFIGURATION IfrNvData; + UINTN BufferSize; + SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData; + EFI_STATUS Status; if (Configuration == NULL || Progress == NULL) { return EFI_INVALID_PARAMETER; @@ -3332,10 +3406,12 @@ SecureBootRouteConfig ( return EFI_NOT_FOUND; } + PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); + // // Get Configuration from Variable. // - SecureBootExtractConfigFromVariable (&IfrNvData); + SecureBootExtractConfigFromVariable (PrivateData, &IfrNvData); // // Map the Configuration to the configuration block. @@ -3355,10 +3431,7 @@ SecureBootRouteConfig ( // // Store Buffer Storage back to EFI variable if needed // - SecureBootEnable = NULL; - GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL); - if (NULL != SecureBootEnable) { - FreePool (SecureBootEnable); + if (!IfrNvData.HideSecureBoot) { Status = SaveSecureBootVariable (IfrNvData.AttemptSecureBoot); if (EFI_ERROR (Status)) { return Status; @@ -3369,6 +3442,719 @@ SecureBootRouteConfig ( return EFI_SUCCESS; } +/** + 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 SECUREBOOT_CONFIG_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 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]; + + Status = EFI_SUCCESS; + FormatNameString = NULL; + FormatHelpString = NULL; + StartOpCodeHandle = NULL; + EndOpCodeHandle = NULL; + StartGotoHandle = NULL; + EndGotoHandle = NULL; + Index = 0; + VariableData = 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; + } + + 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; + + 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_SECURE_BOOT_DB_OPTION_FORM; + } else if (PrivateData->VariableName == Variable_DBX) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE1); + DstFormId = FORMID_SECURE_BOOT_DBX_OPTION_FORM; + } else if (PrivateData->VariableName == Variable_DBT) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2); + DstFormId = FORMID_SECURE_BOOT_DBT_OPTION_FORM; + } else { + goto ON_EXIT; + } + + HiiCreateGotoOpCode ( + StartGotoHandle, + DstFormId, + STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST), + STRING_TOKEN (STR_SECURE_BOOT_DELETE_ALL_LIST), + EFI_IFR_FLAG_CALLBACK, + KEY_SECURE_BOOT_DELETE_ALL_LIST + ); + + // + // 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; + } + + FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_NAME_FORMAT), NULL); + FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_LIST_HELP_FORMAT), NULL); + if (FormatNameString == NULL || FormatHelpString == NULL) { + goto ON_EXIT; + } + + RemainingSize = DataSize; + ListWalker = (EFI_SIGNATURE_LIST *)VariableData; + while ((RemainingSize > 0) && (RemainingSize >= ListWalker->SignatureListSize)) { + if (CompareGuid (&ListWalker->SignatureType, &gEfiCertRsa2048Guid)) { + ListType = STRING_TOKEN (STR_LIST_TYPE_RSA2048_SHA256); + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Guid)) { + ListType = STRING_TOKEN (STR_LIST_TYPE_X509); + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha1Guid)) { + ListType = STRING_TOKEN (STR_LIST_TYPE_SHA1); + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertSha256Guid)) { + ListType = STRING_TOKEN (STR_LIST_TYPE_SHA256); + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha256Guid)) { + ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA256); + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha384Guid)) { + ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA384); + } else if (CompareGuid (&ListWalker->SignatureType, &gEfiCertX509Sha512Guid)) { + ListType = STRING_TOKEN (STR_LIST_TYPE_X509_SHA512); + } else { + ListType = STRING_TOKEN (STR_LIST_TYPE_UNKNOWN); + } + FormatTypeString = HiiGetString (PrivateData->HiiHandle, ListType, NULL); + if (FormatTypeString == NULL) { + goto ON_EXIT; + } + + ZeroMem (NameBuffer, sizeof (NameBuffer)); + UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1); + + ZeroMem (HelpBuffer, sizeof (HelpBuffer)); + UnicodeSPrint (HelpBuffer, + sizeof (HelpBuffer), + FormatHelpString, + FormatTypeString, + SIGNATURE_DATA_COUNTS (ListWalker) + ); + SECUREBOOT_FREE_NON_NULL (FormatTypeString); + FormatTypeString = NULL; + + HiiCreateGotoOpCode ( + StartOpCodeHandle, + SECUREBOOT_DELETE_SIGNATURE_DATA_FORM, + HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL), + HiiSetString (PrivateData->HiiHandle, 0, HelpBuffer, NULL), + EFI_IFR_FLAG_CALLBACK, + QuestionIdBase + Index++ + ); + + RemainingSize -= ListWalker->SignatureListSize; + ListWalker = (EFI_SIGNATURE_LIST *)((UINT8 *)ListWalker + ListWalker->SignatureListSize); + } + +ON_EXIT: + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSecureBootConfigFormSetGuid, + FormId, + StartOpCodeHandle, + EndOpCodeHandle + ); + + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSecureBootConfigFormSetGuid, + FormId, + StartGotoHandle, + EndGotoHandle + ); + + SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle); + SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle); + SECUREBOOT_FREE_NON_OPCODE (StartGotoHandle); + SECUREBOOT_FREE_NON_OPCODE (EndGotoHandle); + + SECUREBOOT_FREE_NON_NULL (VariableData); + SECUREBOOT_FREE_NON_NULL (FormatNameString); + SECUREBOOT_FREE_NON_NULL (FormatHelpString); + + 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 +ParseHashValue ( + 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: + SECUREBOOT_FREE_NON_NULL (CNBuffer); + + return Status; +} + +/** + Format the help info for the signature data, each help info contain 3 parts. + 1. Onwer 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 SECUREBOOT_CONFIG_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; + BOOLEAN IsCert; + + Status = EFI_SUCCESS; + Time = NULL; + FormatTypeString = NULL; + HelpInfoIndex = 0; + DataString = NULL; + HelpInfoString = NULL; + IsCert = FALSE; + + if (CompareGuid(&ListEntry->SignatureType, &gEfiCertRsa2048Guid)) { + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_RSA2048_SHA256); + DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID); + IsCert = TRUE; + } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertX509Guid)) { + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_X509); + DataSize = ListEntry->SignatureSize - sizeof(EFI_GUID); + IsCert = TRUE; + } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertSha1Guid)) { + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA1); + DataSize = 20; + } else if (CompareGuid(&ListEntry->SignatureType, &gEfiCertSha256Guid)) { + ListTypeId = STRING_TOKEN(STR_LIST_TYPE_SHA256); + 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 { + 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 + ); + SECUREBOOT_FREE_NON_NULL (FormatHelpString); + FormatHelpString = NULL; + + // + // Format content part, it depends on the type of signature list, hash value or CN. + // + if (IsCert) { + GetCommonNameFromX509 (ListEntry, DataEntry, &DataString); + FormatHelpString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_HELP_FORMAT_CN), NULL); + } else { + // + // Format hash value for each signature data entry. + // + ParseHashValue (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 + ); + SECUREBOOT_FREE_NON_NULL (FormatHelpString); + FormatHelpString = NULL; + + // + // Format revocation time part. + // + if (Time != NULL) { + ZeroMem (TimeString, sizeof (TimeString)); + UnicodeSPrint ( + TimeString, + sizeof (TimeString), + L"%d-%d-%d %d:%d:%d", + Time->Year, + Time->Month, + Time->Day, + 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 + ); + SECUREBOOT_FREE_NON_NULL (FormatHelpString); + FormatHelpString = NULL; + } + + *StringId = HiiSetString (PrivateData->HiiHandle, 0, HelpInfoString, NULL); +ON_EXIT: + SECUREBOOT_FREE_NON_NULL (DataString); + SECUREBOOT_FREE_NON_NULL (HelpInfoString); + + SECUREBOOT_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 SECUREBOOT_CONFIG_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 FormatNameString; + VOID *StartOpCodeHandle; + VOID *EndOpCodeHandle; + UINTN DataSize; + UINTN RemainingSize; + UINT16 Index; + UINT8 *VariableData; + CHAR16 VariableName[BUFFER_MAX_SIZE]; + CHAR16 NameBuffer[BUFFER_MAX_SIZE]; + + Status = EFI_SUCCESS; + FormatNameString = NULL; + StartOpCodeHandle = NULL; + EndOpCodeHandle = NULL; + Index = 0; + VariableData = 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 = 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 if (PrivateData->VariableName == Variable_DBT) { + UnicodeSPrint (VariableName, sizeof (VariableName), EFI_IMAGE_SECURITY_DATABASE2); + } 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); + } + + FormatNameString = HiiGetString (PrivateData->HiiHandle, STRING_TOKEN (STR_SIGNATURE_DATA_NAME_FORMAT), NULL); + if (FormatNameString == NULL) { + goto ON_EXIT; + } + + 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)); + UnicodeSPrint (NameBuffer, sizeof (NameBuffer), FormatNameString, Index + 1); + + // + // Format help info buffer. + // + Status = FormatHelpInfo (PrivateData, ListWalker, DataWalker, &HelpStringId); + if (EFI_ERROR (Status)) { + goto ON_EXIT; + } + + HiiCreateCheckBoxOpCode ( + StartOpCodeHandle, + (EFI_QUESTION_ID)(QuestionIdBase + Index), + 0, + 0, + HiiSetString (PrivateData->HiiHandle, 0, NameBuffer, NULL), + HelpStringId, + EFI_IFR_FLAG_CALLBACK, + 0, + NULL + ); + + ZeroMem(NameBuffer, 100); + DataWalker = (EFI_SIGNATURE_DATA *)((UINT8 *)DataWalker + ListWalker->SignatureSize); + } + + // + // Allocate a buffer to record which signature data will be checked. + // This memory buffer will be freed when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form. + // + PrivateData->CheckArray = AllocateZeroPool (SIGNATURE_DATA_COUNTS (ListWalker) * sizeof (BOOLEAN)); +ON_EXIT: + HiiUpdateForm ( + PrivateData->HiiHandle, + &gSecureBootConfigFormSetGuid, + FormId, + StartOpCodeHandle, + EndOpCodeHandle + ); + + SECUREBOOT_FREE_NON_OPCODE (StartOpCodeHandle); + SECUREBOOT_FREE_NON_OPCODE (EndOpCodeHandle); + + SECUREBOOT_FREE_NON_NULL (VariableData); + SECUREBOOT_FREE_NON_NULL (FormatNameString); + + return Status; +} + /** This function is called to provide results data to the driver. @@ -3404,24 +4190,38 @@ SecureBootCallback ( { EFI_INPUT_KEY Key; EFI_STATUS Status; + RETURN_STATUS RStatus; SECUREBOOT_CONFIG_PRIVATE_DATA *Private; UINTN BufferSize; SECUREBOOT_CONFIGURATION *IfrNvData; UINT16 LabelId; UINT8 *SecureBootEnable; + UINT8 *Pk; UINT8 *SecureBootMode; + UINT8 *SetupMode; CHAR16 PromptString[100]; - UINT8 CurSecureBootMode; - - Status = EFI_SUCCESS; - SecureBootEnable = NULL; - SecureBootMode = NULL; + EFI_DEVICE_PATH_PROTOCOL *File; + UINTN NameLength; + UINT16 *FilePostFix; + SECUREBOOT_CONFIG_PRIVATE_DATA *PrivateData; + BOOLEAN GetBrowserDataResult; + ENROLL_KEY_ERROR EnrollKeyErrorCode; + + Status = EFI_SUCCESS; + SecureBootEnable = NULL; + SecureBootMode = NULL; + SetupMode = NULL; + File = NULL; + EnrollKeyErrorCode = None_Error; if ((This == NULL) || (Value == NULL) || (ActionRequest == NULL)) { return EFI_INVALID_PARAMETER; } + Private = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); + gSecureBootPrivateData = Private; + // // Retrieve uncommitted data from Browser // @@ -3431,18 +4231,35 @@ SecureBootCallback ( return EFI_OUT_OF_RESOURCES; } - HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData); + GetBrowserDataResult = HiiGetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8 *) IfrNvData); if (Action == EFI_BROWSER_ACTION_FORM_OPEN) { if (QuestionId == KEY_SECURE_BOOT_MODE) { + // + // Update secure boot strings when opening this form + // + Status = UpdateSecureBootString(Private); + SecureBootExtractConfigFromVariable (Private, IfrNvData); mIsEnterSecureBootForm = TRUE; - } else if (QuestionId == KEY_TRANS_SECURE_BOOT_MODE){ + } else { // - // Secure Boot Policy variable changes after tranistion. Re-sync CurSecureBootMode + // When entering SecureBoot OPTION Form + // always close opened file & free resource // - ExtractSecureBootModeFromVariable(&IfrNvData->CurSecureBootMode); - mIsSelectedSecureBootModeForm = TRUE; - mIsSecureBootModeChanged = FALSE; + if ((QuestionId == KEY_SECURE_BOOT_PK_OPTION) || + (QuestionId == KEY_SECURE_BOOT_KEK_OPTION) || + (QuestionId == KEY_SECURE_BOOT_DB_OPTION) || + (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) || + (QuestionId == KEY_SECURE_BOOT_DBT_OPTION)) { + CloseEnrolledFile(Private->FileContext); + } else if (QuestionId == KEY_SECURE_BOOT_DELETE_ALL_LIST) { + // + // Update ListCount field in varstore + // Button "Delete All Signature List" is + // enable when ListCount is greater than 0. + // + IfrNvData->ListCount = Private->ListCount; + } } goto EXIT; } @@ -3454,11 +4271,6 @@ SecureBootCallback ( Value->u8 = SECURE_BOOT_MODE_STANDARD; Status = EFI_SUCCESS; } - } else if (QuestionId == KEY_TRANS_SECURE_BOOT_MODE) { - if (mIsSelectedSecureBootModeForm) { - Value->u8 = IfrNvData->CurSecureBootMode; - Status = EFI_SUCCESS; - } } goto EXIT; } @@ -3497,15 +4309,11 @@ SecureBootCallback ( } break; - case KEY_SECURE_BOOT_OPTION: - FreeMenu (&DirectoryMenu); - FreeMenu (&FsOptionMenu); - break; - case KEY_SECURE_BOOT_KEK_OPTION: case KEY_SECURE_BOOT_DB_OPTION: case KEY_SECURE_BOOT_DBX_OPTION: case KEY_SECURE_BOOT_DBT_OPTION: + PrivateData = SECUREBOOT_CONFIG_PRIVATE_FROM_THIS (This); // // Clear Signature GUID. // @@ -3517,6 +4325,11 @@ SecureBootCallback ( } } + // + // Cleanup VFRData once leaving PK/KEK/DB/DBX/DBT enroll/delete page + // + SecureBootExtractConfigFromVariable (PrivateData, IfrNvData); + if (QuestionId == KEY_SECURE_BOOT_DB_OPTION) { LabelId = SECUREBOOT_ENROLL_SIGNATURE_TO_DB; } else if (QuestionId == KEY_SECURE_BOOT_DBX_OPTION) { @@ -3532,28 +4345,64 @@ SecureBootCallback ( // CleanUpPage (LabelId, Private); break; + case KEY_SECURE_BOOT_PK_OPTION: + LabelId = FORMID_ENROLL_PK_FORM; + // + // Refresh selected file. + // + CleanUpPage (LabelId, Private); + break; + + case FORMID_ENROLL_PK_FORM: + ChooseFile (NULL, NULL, UpdatePKFromFile, &File); + break; - case SECUREBOOT_ADD_PK_FILE_FORM_ID: case FORMID_ENROLL_KEK_FORM: + ChooseFile (NULL, NULL, UpdateKEKFromFile, &File); + break; + case SECUREBOOT_ENROLL_SIGNATURE_TO_DB: + ChooseFile (NULL, NULL, UpdateDBFromFile, &File); + break; + case SECUREBOOT_ENROLL_SIGNATURE_TO_DBX: - case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT: - if (QuestionId == SECUREBOOT_ADD_PK_FILE_FORM_ID) { - Private->FeCurrentState = FileExplorerStateEnrollPkFile; - } else if (QuestionId == FORMID_ENROLL_KEK_FORM) { - Private->FeCurrentState = FileExplorerStateEnrollKekFile; - } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DB) { - Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDb; - } else if (QuestionId == SECUREBOOT_ENROLL_SIGNATURE_TO_DBX) { - Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbx; - IfrNvData->CertificateFormat = HASHALG_SHA256; - } else { - Private->FeCurrentState = FileExplorerStateEnrollSignatureFileToDbt; + ChooseFile (NULL, NULL, UpdateDBXFromFile, &File); + + if (Private->FileContext->FHandle != NULL) { + // + // Parse the file's postfix. + // + NameLength = StrLen (Private->FileContext->FileName); + if (NameLength <= 4) { + return FALSE; + } + FilePostFix = Private->FileContext->FileName + NameLength - 4; + + if (IsDerEncodeCertificate (FilePostFix)) { + // + // Supports DER-encoded X509 certificate. + // + IfrNvData->FileEnrollType = X509_CERT_FILE_TYPE; + } else if (IsAuthentication2Format(Private->FileContext->FHandle)){ + IfrNvData->FileEnrollType = AUTHENTICATION_2_FILE_TYPE; + } else { + IfrNvData->FileEnrollType = PE_IMAGE_FILE_TYPE; + } + Private->FileContext->FileType = IfrNvData->FileEnrollType; + + // + // Clean up Certificate Format if File type is not X509 DER + // + if (IfrNvData->FileEnrollType != X509_CERT_FILE_TYPE) { + IfrNvData->CertificateFormat = HASHALG_RAW; + } + DEBUG((DEBUG_ERROR, "IfrNvData->FileEnrollType %d\n", Private->FileContext->FileType)); } - Private->FeDisplayContext = FileExplorerDisplayUnknown; - CleanUpPage (FORM_FILE_EXPLORER_ID, Private); - UpdateFileExplorer (Private, 0); + break; + + case SECUREBOOT_ENROLL_SIGNATURE_TO_DBT: + ChooseFile (NULL, NULL, UpdateDBTFromFile, &File); break; case KEY_SECURE_BOOT_DELETE_PK: @@ -3601,16 +4450,89 @@ SecureBootCallback ( ); break; - case SECUREBOOT_DELETE_SIGNATURE_FROM_DBX: - UpdateDeletePage ( + // + // From DBX option to the level-1 form, display signature list. + // + case KEY_VALUE_FROM_DBX_TO_LIST_FORM: + Private->VariableName = Variable_DBX; + LoadSignatureList ( Private, - EFI_IMAGE_SECURITY_DATABASE1, - &gEfiImageSecurityDatabaseGuid, - LABEL_DBX_DELETE, - SECUREBOOT_DELETE_SIGNATURE_FROM_DBX, - OPTION_DEL_DBX_QUESTION_ID - ); + LABEL_SIGNATURE_LIST_START, + SECUREBOOT_DELETE_SIGNATURE_LIST_FORM, + OPTION_SIGNATURE_LIST_QUESTION_ID + ); + break; + + // + // Delete all signature list and reload. + // + case KEY_SECURE_BOOT_DELETE_ALL_LIST: + 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 (Private, Delete_Signature_List_All, IfrNvData->CheckedDataCount); + } + + LoadSignatureList ( + Private, + LABEL_SIGNATURE_LIST_START, + SECUREBOOT_DELETE_SIGNATURE_LIST_FORM, + OPTION_SIGNATURE_LIST_QUESTION_ID + ); + break; + // + // Delete one signature list and reload. + // + case KEY_SECURE_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 (Private, Delete_Signature_List_One, IfrNvData->CheckedDataCount); + } + + LoadSignatureList ( + Private, + LABEL_SIGNATURE_LIST_START, + SECUREBOOT_DELETE_SIGNATURE_LIST_FORM, + OPTION_SIGNATURE_LIST_QUESTION_ID + ); + break; + + // + // Delete checked signature data and reload. + // + case KEY_SECURE_BOOT_DELETE_CHECK_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 (Private, Delete_Signature_Data, IfrNvData->CheckedDataCount); + } + + LoadSignatureList ( + Private, + LABEL_SIGNATURE_LIST_START, + SECUREBOOT_DELETE_SIGNATURE_LIST_FORM, + OPTION_SIGNATURE_LIST_QUESTION_ID + ); break; case SECUREBOOT_DELETE_SIGNATURE_FROM_DBT: @@ -3659,7 +4581,12 @@ SecureBootCallback ( L"Enrollment failed! Same certificate had already been in the dbx!", NULL ); - break; + + // + // Cert already exists in DBX. Close opened file before exit. + // + CloseEnrolledFile(Private->FileContext); + break; } if ((IfrNvData != NULL) && (IfrNvData->CertificateFormat < HASHALG_MAX)) { @@ -3670,6 +4597,7 @@ SecureBootCallback ( &IfrNvData->RevocationTime, IfrNvData->AlwaysRevocation ); + IfrNvData->CertificateFormat = HASHALG_RAW; } else { Status = EnrollSignatureDatabase (Private, EFI_IMAGE_SECURITY_DATABASE1); } @@ -3678,7 +4606,7 @@ SecureBootCallback ( EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, L"ERROR: Unsupported file type!", - L"Only supports DER-encoded X509 certificate and executable EFI image", + L"Only supports DER-encoded X509 certificate, AUTH_2 format data & executable EFI image", NULL ); } @@ -3696,71 +4624,43 @@ SecureBootCallback ( ); } break; - case KEY_TRANS_SECURE_BOOT_MODE: + case KEY_VALUE_SAVE_AND_EXIT_PK: // - // Pop up to alert user want to change secure boot mode + // Check the suffix, encode type and the key strength of PK certificate. // - if ((IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE && - (Value->u8 == SECURE_BOOT_MODE_AUDIT_MODE || Value->u8 == SECURE_BOOT_MODE_DEPLOYED_MODE)) - ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE && - Value->u8 == SECURE_BOOT_MODE_AUDIT_MODE) - ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE && - Value->u8 == SECURE_BOOT_MODE_USER_MODE && IfrNvData->PhysicalPresent == 1)){ - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"Are you sure you want to switch secure boot mode?", - L"Press 'Y' to switch secure boot mode, 'N' to discard change and return", - NULL - ); - if (Key.UnicodeChar != 'y' && Key.UnicodeChar != 'Y') { - // - // If not 'Y'/''y' restore to defualt secure boot mode - // - Value->u8 = IfrNvData->CurSecureBootMode; - goto EXIT; + Status = CheckX509Certificate (Private->FileContext, &EnrollKeyErrorCode); + if (EFI_ERROR (Status)) { + if (EnrollKeyErrorCode != None_Error && EnrollKeyErrorCode < Enroll_Error_Max) { + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + mX509EnrollPromptTitle[EnrollKeyErrorCode], + mX509EnrollPromptString[EnrollKeyErrorCode], + NULL + ); + break; } - } else if ((IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE && Value->u8 == SECURE_BOOT_MODE_USER_MODE) - ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE && Value->u8 == SECURE_BOOT_MODE_SETUP_MODE) - ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE && Value->u8 == SECURE_BOOT_MODE_DEPLOYED_MODE) - ||(IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE && Value->u8 == SECURE_BOOT_MODE_SETUP_MODE)) { + } else { + Status = EnrollPlatformKey (Private); + } + if (EFI_ERROR (Status)) { + UnicodeSPrint ( + PromptString, + sizeof (PromptString), + L"Error status: %x.", + Status + ); CreatePopUp ( EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, &Key, - L"Secure boot mode tranistion requires PK change", - L"Please go to link below to update PK", + L"ERROR: Enrollment failed!", + PromptString, NULL ); - } else { - Status = EFI_INVALID_PARAMETER; - goto EXIT; - } - - Status = SecureBootModeTransition(IfrNvData->CurSecureBootMode, Value->u8); - // - // Secure Boot Policy variable may change after tranistion. Re-sync CurSecureBootMode - // - ExtractSecureBootModeFromVariable(&CurSecureBootMode); - if (IfrNvData->CurSecureBootMode != CurSecureBootMode) { - IfrNvData->CurSecureBootMode = CurSecureBootMode; - mIsSecureBootModeChanged = TRUE; - - if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE) { - HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"UserMode", NULL); - } else if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_SETUP_MODE) { - HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"SetupMode", NULL); - } else if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_AUDIT_MODE) { - HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"AuditMode", NULL); - } else if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE) { - HiiSetString (Private->HiiHandle, STRING_TOKEN (STR_CUR_SECURE_BOOT_MODE_CONTENT), L"DeployedMode", NULL); - } } break; - default: - if (QuestionId >= FILE_OPTION_GOTO_OFFSET) { - UpdateFileExplorer (Private, QuestionId); - } else if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) && + if ((QuestionId >= OPTION_DEL_KEK_QUESTION_ID) && (QuestionId < (OPTION_DEL_KEK_QUESTION_ID + OPTION_CONFIG_RANGE))) { DeleteKeyExchangeKey (Private, QuestionId); } else if ((QuestionId >= OPTION_DEL_DB_QUESTION_ID) && @@ -3774,17 +4674,25 @@ SecureBootCallback ( OPTION_DEL_DB_QUESTION_ID, QuestionId - OPTION_DEL_DB_QUESTION_ID ); - } else if ((QuestionId >= OPTION_DEL_DBX_QUESTION_ID) && - (QuestionId < (OPTION_DEL_DBX_QUESTION_ID + OPTION_CONFIG_RANGE))) { - DeleteSignature ( + } else if ((QuestionId >= OPTION_SIGNATURE_LIST_QUESTION_ID) && + (QuestionId < (OPTION_SIGNATURE_LIST_QUESTION_ID + OPTION_CONFIG_RANGE))) { + LoadSignatureData ( Private, - EFI_IMAGE_SECURITY_DATABASE1, - &gEfiImageSecurityDatabaseGuid, - LABEL_DBX_DELETE, - SECUREBOOT_DELETE_SIGNATURE_FROM_DBX, - OPTION_DEL_DBX_QUESTION_ID, - QuestionId - OPTION_DEL_DBX_QUESTION_ID - ); + LABEL_SIGNATURE_DATA_START, + SECUREBOOT_DELETE_SIGNATURE_DATA_FORM, + OPTION_SIGNATURE_DATA_QUESTION_ID, + QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID + ); + Private->ListIndex = QuestionId - OPTION_SIGNATURE_LIST_QUESTION_ID; + } else if ((QuestionId >= OPTION_SIGNATURE_DATA_QUESTION_ID) && + (QuestionId < (OPTION_SIGNATURE_DATA_QUESTION_ID + OPTION_CONFIG_RANGE))) { + if (Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID]) { + IfrNvData->CheckedDataCount--; + Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = FALSE; + } else { + IfrNvData->CheckedDataCount++; + Private->CheckArray[QuestionId - OPTION_SIGNATURE_DATA_QUESTION_ID] = TRUE; + } } else if ((QuestionId >= OPTION_DEL_DBT_QUESTION_ID) && (QuestionId < (OPTION_DEL_DBT_QUESTION_ID + OPTION_CONFIG_RANGE))) { DeleteSignature ( @@ -3798,80 +4706,44 @@ SecureBootCallback ( ); } break; - } - } else if (Action == EFI_BROWSER_ACTION_CHANGED) { - switch (QuestionId) { - case KEY_SECURE_BOOT_ENABLE: - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; - break; - case KEY_VALUE_SAVE_AND_EXIT_PK: - Status = EnrollPlatformKey (Private); - if (EFI_ERROR (Status)) { - UnicodeSPrint ( - PromptString, - sizeof (PromptString), - L"Only DER encoded certificate file (%s) is supported.", - mSupportX509Suffix - ); - CreatePopUp ( - EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, - &Key, - L"ERROR: Unsupported file type!", - PromptString, - NULL - ); - } else { - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET; - } - break; case KEY_VALUE_NO_SAVE_AND_EXIT_PK: case KEY_VALUE_NO_SAVE_AND_EXIT_KEK: case KEY_VALUE_NO_SAVE_AND_EXIT_DB: case KEY_VALUE_NO_SAVE_AND_EXIT_DBX: case KEY_VALUE_NO_SAVE_AND_EXIT_DBT: - if (Private->FileContext->FHandle != NULL) { - CloseFile (Private->FileContext->FHandle); - Private->FileContext->FHandle = NULL; - Private->FileContext->FileName = NULL; - } + CloseEnrolledFile(Private->FileContext); if (Private->SignatureGUID != NULL) { FreePool (Private->SignatureGUID); Private->SignatureGUID = NULL; } - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; break; - + } + } else if (Action == EFI_BROWSER_ACTION_CHANGED) { + switch (QuestionId) { + case KEY_SECURE_BOOT_ENABLE: + *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; + break; case KEY_SECURE_BOOT_MODE: mIsEnterSecureBootForm = FALSE; break; - case KEY_TRANS_SECURE_BOOT_MODE: - mIsSelectedSecureBootModeForm = FALSE; - if (mIsSecureBootModeChanged) { - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_RESET; - } - mIsSecureBootModeChanged = FALSE; - break; case KEY_SECURE_BOOT_KEK_GUID: case KEY_SECURE_BOOT_SIGNATURE_GUID_DB: case KEY_SECURE_BOOT_SIGNATURE_GUID_DBX: case KEY_SECURE_BOOT_SIGNATURE_GUID_DBT: ASSERT (Private->SignatureGUID != NULL); - Status = StringToGuid ( - IfrNvData->SignatureGuid, - StrLen (IfrNvData->SignatureGuid), - Private->SignatureGUID - ); - if (EFI_ERROR (Status)) { + RStatus = StrToGuid (IfrNvData->SignatureGuid, Private->SignatureGUID); + if (RETURN_ERROR (RStatus) || (IfrNvData->SignatureGuid[GUID_STRING_LENGTH] != L'\0')) { + Status = EFI_INVALID_PARAMETER; break; } *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; break; - case KEY_SECURE_BOOT_DELETE_PK: - if (IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_USER_MODE || IfrNvData->CurSecureBootMode == SECURE_BOOT_MODE_DEPLOYED_MODE) { + GetVariable2 (EFI_SETUP_MODE_NAME, &gEfiGlobalVariableGuid, (VOID**)&SetupMode, NULL); + if (SetupMode == NULL || (*SetupMode) == SETUP_MODE) { IfrNvData->DeletePk = TRUE; IfrNvData->HasPk = FALSE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_SUBMIT; @@ -3880,22 +4752,20 @@ SecureBootCallback ( IfrNvData->HasPk = TRUE; *ActionRequest = EFI_BROWSER_ACTION_REQUEST_FORM_APPLY; } + if (SetupMode != NULL) { + FreePool (SetupMode); + } break; default: - if (QuestionId >= FILE_OPTION_OFFSET && QuestionId < FILE_OPTION_GOTO_OFFSET) { - if (UpdateFileExplorer (Private, QuestionId)) { - *ActionRequest = EFI_BROWSER_ACTION_REQUEST_EXIT; - } - } break; } } else if (Action == EFI_BROWSER_ACTION_DEFAULT_STANDARD) { if (QuestionId == KEY_HIDE_SECURE_BOOT) { - GetVariable2 (EFI_SECURE_BOOT_ENABLE_NAME, &gEfiSecureBootEnableDisableGuid, (VOID**)&SecureBootEnable, NULL); - if (SecureBootEnable == NULL) { + GetVariable2 (EFI_PLATFORM_KEY_NAME, &gEfiGlobalVariableGuid, (VOID**)&Pk, NULL); + if (Pk == NULL) { IfrNvData->HideSecureBoot = TRUE; } else { - FreePool (SecureBootEnable); + FreePool (Pk); IfrNvData->HideSecureBoot = FALSE; } Value->b = IfrNvData->HideSecureBoot; @@ -3912,17 +4782,30 @@ SecureBootCallback ( if (SecureBootMode != NULL) { FreePool (SecureBootMode); } + + if (QuestionId == KEY_SECURE_BOOT_DELETE_ALL_DATA) { + // + // Free memory when exit from the SECUREBOOT_DELETE_SIGNATURE_DATA_FORM form. + // + SECUREBOOT_FREE_NON_NULL (Private->CheckArray); + IfrNvData->CheckedDataCount = 0; + } } EXIT: - if (!EFI_ERROR (Status)) { + if (!EFI_ERROR (Status) && GetBrowserDataResult) { BufferSize = sizeof (SECUREBOOT_CONFIGURATION); HiiSetBrowserData (&gSecureBootConfigFormSetGuid, mSecureBootStorageName, BufferSize, (UINT8*) IfrNvData, NULL); } FreePool (IfrNvData); + if (File != NULL){ + FreePool(File); + File = NULL; + } + return EFI_SUCCESS; } @@ -3987,19 +4870,12 @@ InstallSecureBootConfigForm ( PrivateData->HiiHandle = HiiHandle; PrivateData->FileContext = AllocateZeroPool (sizeof (SECUREBOOT_FILE_CONTEXT)); - PrivateData->MenuEntry = AllocateZeroPool (sizeof (SECUREBOOT_MENU_ENTRY)); - if (PrivateData->FileContext == NULL || PrivateData->MenuEntry == NULL) { + if (PrivateData->FileContext == NULL) { UninstallSecureBootConfigForm (PrivateData); return EFI_OUT_OF_RESOURCES; } - PrivateData->FeCurrentState = FileExplorerStateInActive; - PrivateData->FeDisplayContext = FileExplorerDisplayUnknown; - - InitializeListHead (&FsOptionMenu.Head); - InitializeListHead (&DirectoryMenu.Head); - // // Init OpCode Handle and Allocate space for creation of Buffer // @@ -4079,19 +4955,12 @@ UninstallSecureBootConfigForm ( FreePool (PrivateData->SignatureGUID); } - if (PrivateData->MenuEntry != NULL) { - FreePool (PrivateData->MenuEntry); - } - if (PrivateData->FileContext != NULL) { FreePool (PrivateData->FileContext); } FreePool (PrivateData); - FreeMenu (&DirectoryMenu); - FreeMenu (&FsOptionMenu); - if (mStartOpCodeHandle != NULL) { HiiFreeOpCodeHandle (mStartOpCodeHandle); }